1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 01:37:36 +00:00

LibJS: Convert all remaining non-Array tests to the new system :)

This commit is contained in:
Matthew Olsson 2020-07-05 17:26:26 -07:00 committed by Andreas Kling
parent 918f4affd5
commit 15de2eda2b
72 changed files with 2394 additions and 1998 deletions

View file

@ -0,0 +1,35 @@
test("extending function", () => {
class A extends function () {
this.foo = 10;
} {}
expect(new A().foo).toBe(10);
});
test("extending null", () => {
class A extends null {}
expect(Object.getPrototypeOf(A.prototype)).toBeNull();
expect(() => {
new A();
}).toThrowWithMessage(ReferenceError, "|this| has not been initialized");
});
test("extending String", () => {
class MyString extends String {}
const ms = new MyString("abc");
expect(ms).toBeInstanceOf(MyString);
expect(ms).toBeInstanceOf(String);
expect(ms.charAt(1)).toBe("b");
class MyString2 extends MyString {
charAt(i) {
return `#${super.charAt(i)}`;
}
}
const ms2 = new MyString2("abc");
expect(ms2.charAt(1)).toBe("#b");
});

View file

@ -1,269 +1,5 @@
load("test-common.js");
try {
class X {
constructor() {
this.x = 3;
}
getX() {
return 3;
}
init() {
this.y = 3;
}
}
assert(X.name === "X");
assert(X.length === 0);
class Y extends X {
init() {
super.init();
this.y += 3;
}
}
assert(new Y().getX() === 3);
assert(new Y().x === 3);
let x = new X();
assert(x.x === 3);
assert(x.getX() === 3);
let y = new Y();
assert(y.x === 3);
assert(y.y === undefined);
y.init();
assert(y.y === 6);
assert(y.hasOwnProperty("y"));
class Foo {
constructor(x) {
this.x = x;
}
}
assert(Foo.length === 1);
class Bar extends Foo {
constructor() {
super(5);
}
}
class Baz {
constructor() {
this.foo = 55;
this._bar = 33;
}
get bar() {
return this._bar;
}
set bar(value) {
this._bar = value;
}
["get" + "Foo"]() {
return this.foo;
}
static get staticFoo() {
assert(this === Baz);
return 11;
}
}
let barPropertyDescriptor = Object.getOwnPropertyDescriptor(Baz.prototype, "bar");
assert(barPropertyDescriptor.get.name === "get bar");
assert(barPropertyDescriptor.set.name === "set bar");
let baz = new Baz();
assert(baz.foo === 55);
assert(baz.bar === 33);
baz.bar = 22;
assert(baz.bar === 22);
assert(baz.getFoo() === 55);
assert(Baz.staticFoo === 11);
assert(new Bar().x === 5);
class ExtendsFunction extends function () {
this.foo = 22;
} {}
assert(new ExtendsFunction().foo === 22);
class ExtendsString extends String {}
assert(new ExtendsString() instanceof String);
assert(new ExtendsString() instanceof ExtendsString);
assert(new ExtendsString("abc").charAt(1) === "b");
class MyWeirdString extends ExtendsString {
charAt(i) {
return "#" + super.charAt(i);
}
}
assert(new MyWeirdString("abc").charAt(1) === "#b");
class ExtendsNull extends null {}
assertThrowsError(
() => {
new ExtendsNull();
},
{
error: ReferenceError,
}
);
assert(Object.getPrototypeOf(ExtendsNull.prototype) === null);
class ExtendsClassExpression extends class {
constructor(x) {
this.x = x;
}
} {
constructor(y) {
super(5);
this.y = 6;
}
}
let extendsClassExpression = new ExtendsClassExpression();
assert(extendsClassExpression.x === 5);
assert(extendsClassExpression.y === 6);
class InStrictMode {
constructor() {
assert(isStrictMode());
}
method() {
assert(isStrictMode());
}
}
let resultOfAnExpression = new (class {
constructor(x) {
this.x = x;
}
getX() {
return this.x + 10;
}
})(55);
assert(resultOfAnExpression.x === 55);
assert(resultOfAnExpression.getX() === 65);
let ClassExpression = class Foo {};
assert(ClassExpression.name === "Foo");
new InStrictMode().method();
assert(!isStrictMode());
assertIsSyntaxError(`
class GetterWithArgument {
get foo(bar) {
return 0;
}
}
`);
assertIsSyntaxError(`
class SetterWithNoArgumetns {
set foo() {
}
}
`);
assertIsSyntaxError(`
class SetterWithMoreThanOneArgument {
set foo(bar, baz) {
}
}
`);
assertIsSyntaxError(`
class FooBase {}
class IsASyntaxError extends FooBase {
bar() {
function f() { super.baz; }
}
}
`);
assertIsSyntaxError(`
class NoBaseSuper {
constructor() {
super();
}
}
`);
assertThrowsError(
() => {
class BadExtends extends 3 {}
},
{
error: TypeError,
}
);
assertThrowsError(
() => {
class BadExtends extends undefined {}
},
{
error: TypeError,
}
);
class SuperNotASyntaxError {
bar() {
() => {
super.baz;
};
}
}
class SuperNoBasePropertyLookup {
constructor() {
super.foo;
}
}
assertThrowsError(
() => {
class Base {}
class DerivedDoesntCallSuper extends Base {
constructor() {
this;
}
}
new DerivedDoesntCallSuper();
},
{
error: ReferenceError,
}
);
assertThrowsError(
() => {
class Base {}
class CallsSuperTwice extends Base {
constructor() {
super();
super();
}
}
new CallsSuperTwice();
},
{
error: ReferenceError,
}
);
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}
test("class properties", () => {
class A {}
expect(A.name).toBe("A");
expect(A).toHaveLength(0);
});

View file

@ -0,0 +1,67 @@
test("property initialization", () => {
class A {
constructor() {
this.x = 3;
}
}
expect(new A().x).toBe(3);
});
test("method initialization", () => {
class A {
constructor() {
this.x = () => 10;
}
}
expect(new A().x()).toBe(10);
});
test("initialize to class method", () => {
class A {
constructor() {
this.x = this.method;
}
method() {
return 10;
}
}
expect(new A().x()).toBe(10);
});
test("constructor length affects class length", () => {
class A {
constructor() {}
}
expect(A).toHaveLength(0);
class B {
constructor(a, b, c = 2) {}
}
expect(B).toHaveLength(2);
});
test.skip("must be invoked with 'new'", () => {
class A {
constructor() {}
}
expect(() => {
A();
}).toThrow(TypeError); // FIXME: Add message when this test works
expect(() => {
A.prototype.constructor();
}).toThrow(TypeError); // FIXME: Add message when this test works
});
test("implicit constructor", () => {
class A {}
expect(new A()).toBeInstanceOf(A);
});

View file

@ -0,0 +1,95 @@
describe("non-syntax errors", () => {
test("super reference inside nested-but-same |this| scope with no base class", () => {
expect(`
class A {
foo() {
() => { super.bar; }
}
}`).toEval();
});
test("super reference property lookup with no base class", () => {
expect(`
class A {
constructor() {
super.foo;
}
}`).toEval();
});
});
describe("reference errors", () => {
test("derived class doesn't call super in constructor before using this", () => {
class Parent {}
class Child extends Parent {
constructor() {
this;
}
}
expect(() => {
new Child();
}).toThrowWithMessage(ReferenceError, "|this| has not been initialized");
});
test("derived class calls super twice in constructor", () => {
class Parent {}
class Child extends Parent {
constructor() {
super();
super();
}
}
expect(() => {
new Child();
}).toThrowWithMessage(ReferenceError, "|this| is already initialized");
});
});
describe("syntax errors", () => {
test("getter with argument", () => {
expect(`
class A {
get foo(v) {
return 0;
}
}`).not.toEval();
});
test("setter with no arguments", () => {
expect(`
class A {
set foo() {
}
}`).not.toEval();
});
test("setter with more than one argument", () => {
expect(`
class A {
set foo(bar, baz) {
}
}`).not.toEval();
});
test("super reference inside different |this| scope", () => {
expect(`
class Parent {}
class Child extends Parent {
foo() {
function f() { super.foo; }
}
}`).not.toEval();
});
test("super reference call with no base class", () => {
expect(`
class A {
constructor() {
super();
}
}`).not.toEval();
});
});

View file

@ -0,0 +1,69 @@
// This file must not be formatted by prettier. Make sure your IDE
// respects the .prettierignore file!
test("basic functionality", () => {
const A = class {
constructor(x) {
this.x = x;
}
getX() {
return this.x * 2;
}
};
expect(new A(10).getX()).toBe(20);
});
test("inline instantiation", () => {
const a = new class {
constructor() {
this.x = 10;
}
getX() {
return this.x * 2;
}
};
expect(a.getX()).toBe(20);
});
test("inline instantiation with argument", () => {
const a = new class {
constructor(x) {
this.x = x;
}
getX() {
return this.x * 2;
}
}(10);
expect(a.getX()).toBe(20);
});
test("extending class expressions", () => {
class A extends class {
constructor(x) {
this.x = x;
}
} {
constructor(y) {
super(y);
this.y = y * 2;
}
};
const a = new A(10);
expect(a.x).toBe(10);
expect(a.y).toBe(20);
});
test("class expression name", () => {
let A = class {}
expect(A.name).toBe("A");
let B = class C {}
expect(B.name).toBe("C");
});

View file

@ -0,0 +1,68 @@
test("basic functionality", () => {
class A {
get x() {
return 10;
}
}
expect(A).not.toHaveProperty("x");
expect(new A().x).toBe(10);
});
test("name", () => {
class A {
get x() {}
}
const d = Object.getOwnPropertyDescriptor(A.prototype, "x");
expect(d.get.name).toBe("get x");
});
test("extended name syntax", () => {
class A {
get "method with space"() {
return 1;
}
get 12() {
return 2;
}
get [`he${"llo"}`]() {
return 3;
}
}
const a = new A();
expect(a["method with space"]).toBe(1);
expect(a[12]).toBe(2);
expect(a.hello).toBe(3);
});
test("inherited getter", () => {
class Parent {
get x() {
return 3;
}
}
class Child extends Parent {}
expect(Child).not.toHaveProperty("x");
expect(new Child().x).toBe(3);
});
test("inherited getter overriding", () => {
class Parent {
get x() {
return 3;
}
}
class Child extends Parent {
get x() {
return 10;
}
}
expect(new Child().x).toBe(10);
});

View file

@ -0,0 +1,133 @@
test("method inheritance", () => {
class Parent {
method() {
return 3;
}
}
class Child extends Parent {}
const p = new Parent();
const c = new Child();
expect(p.method()).toBe(3);
expect(c.method()).toBe(3);
});
test("method overriding", () => {
class Parent {
method() {
return 3;
}
}
class Child extends Parent {
method() {
return 10;
}
}
const p = new Parent();
const c = new Child();
expect(p.method()).toBe(3);
expect(c.method()).toBe(10);
});
test("parent method reference with super", () => {
class Parent {
method() {
return 3;
}
}
class Child extends Parent {
method() {
return super.method() * 2;
}
}
const p = new Parent();
const c = new Child();
expect(p.method()).toBe(3);
expect(c.method()).toBe(6);
});
test("child class access to parent class initialized properties", () => {
class Parent {
constructor() {
this.x = 3;
}
}
class Child extends Parent {}
const p = new Parent();
const c = new Child();
expect(p.x).toBe(3);
expect(c.x).toBe(3);
});
test("child class modification of parent class properties", () => {
class Parent {
constructor() {
this.x = 3;
}
}
class Child extends Parent {
change() {
this.x = 10;
}
}
const p = new Parent();
const c = new Child();
expect(p.x).toBe(3);
expect(c.x).toBe(3);
c.change();
expect(c.x).toBe(10);
});
test("inheritance and hasOwnProperty", () => {
class Parent {
constructor() {
this.x = 3;
}
}
class Child extends Parent {
method() {
this.y = 10;
}
}
const p = new Parent();
const c = new Child();
expect(p.hasOwnProperty("x")).toBeTrue();
expect(p.hasOwnProperty("y")).toBeFalse();
expect(c.hasOwnProperty("x")).toBeTrue();
expect(c.hasOwnProperty("y")).toBeFalse();
c.method();
expect(c.hasOwnProperty("x")).toBeTrue();
expect(c.hasOwnProperty("y")).toBeTrue();
});
test("super constructor call from child class with argument", () => {
class Parent {
constructor(x) {
this.x = x;
}
}
class Child extends Parent {
constructor() {
super(10);
}
}
const p = new Parent(3);
const c = new Child(3);
expect(p.x).toBe(3);
expect(c.x).toBe(10);
});

View file

@ -0,0 +1,51 @@
test("basic functionality", () => {
class A {
number() {
return 2;
}
string() {
return "foo";
}
}
const a = new A();
expect(a.number()).toBe(2);
expect(a.string()).toBe("foo");
});
test("length", () => {
class A {
method1() {}
method2(a, b, c, d) {}
method3(a, b, ...c) {}
}
const a = new A();
expect(a.method1).toHaveLength(0);
expect(a.method2).toHaveLength(4);
expect(a.method3).toHaveLength(2);
});
test("extended name syntax", () => {
class A {
"method with space"() {
return 1;
}
12() {
return 2;
}
[`he${"llo"}`]() {
return 3;
}
}
const a = new A();
expect(a["method with space"]()).toBe(1);
expect(a[12]()).toBe(2);
expect(a.hello()).toBe(3);
});

View file

@ -0,0 +1,100 @@
test("basic functionality", () => {
class A {
get x() {
return this._x;
}
set x(value) {
this._x = value * 2;
}
}
expect(A.x).toBeUndefined();
expect(A).not.toHaveProperty("_x");
const a = new A();
expect(a.x).toBeUndefined();
expect(a).not.toHaveProperty("_x");
a.x = 3;
expect(a.x).toBe(6);
expect(a).toHaveProperty("_x", 6);
});
test("name", () => {
class A {
set x(v) {}
}
const d = Object.getOwnPropertyDescriptor(A.prototype, "x");
expect(d.set.name).toBe("set x");
});
test("extended name syntax", () => {
class A {
set "method with space"(value) {
this.a = value;
}
set 12(value) {
this.b = value;
}
set [`he${"llo"}`](value) {
this.c = value;
}
}
const a = new A();
a["method with space"] = 1;
a[12] = 2;
a.hello = 3;
expect(a.a).toBe(1);
expect(a.b).toBe(2);
expect(a.c).toBe(3);
});
test("inherited setter", () => {
class Parent {
get x() {
return this._x;
}
set x(value) {
this._x = value * 2;
}
}
class Child extends Parent {}
const c = new Child();
expect(c.x).toBeUndefined();
c.x = 10;
expect(c.x).toBe(20);
});
test("inherited static setter overriding", () => {
class Parent {
get x() {
return this._x;
}
set x(value) {
this._x = value * 2;
}
}
class Child extends Parent {
get x() {
return this._x;
}
set x(value) {
this._x = value * 3;
}
}
const c = new Child();
expect(c.x).toBeUndefined();
c.x = 10;
expect(c.x).toBe(30);
});

View file

@ -0,0 +1,80 @@
describe("correct behavior", () => {
test("basic functionality", () => {
class A {
static get x() {
return 10;
}
}
expect(A.x).toBe(10);
expect(new A()).not.toHaveProperty("x");
});
test("name", () => {
class A {
static get x() {}
}
const d = Object.getOwnPropertyDescriptor(A, "x");
expect(d.get.name).toBe("get x");
});
test("extended name syntax", () => {
class A {
static get "method with space"() {
return 1;
}
static get 12() {
return 2;
}
static get [`he${"llo"}`]() {
return 3;
}
}
expect(A["method with space"]).toBe(1);
expect(A[12]).toBe(2);
expect(A.hello).toBe(3);
});
test("inherited static getter", () => {
class Parent {
static get x() {
return 3;
}
}
class Child extends Parent {}
expect(Parent.x).toBe(3);
expect(Child.x).toBe(3);
});
test("inherited static getter overriding", () => {
class Parent {
static get x() {
return 3;
}
}
class Child extends Parent {
static get x() {
return 10;
}
}
expect(Parent.x).toBe(3);
expect(Child.x).toBe(10);
});
});
describe("errors", () => {
test('"get static" is a syntax error', () => {
expect(`
class A {
get static foo() {}
}`).not.toEval();
});
});

View file

@ -0,0 +1,104 @@
describe("correct behavior", () => {
test("basic functionality", () => {
class A {
static get x() {
return this._x;
}
static set x(value) {
this._x = value * 2;
}
}
expect(A.x).toBeUndefined();
expect(A).not.toHaveProperty("_x");
A.x = 3;
expect(A.x).toBe(6);
expect(A).toHaveProperty("_x", 6);
});
test("name", () => {
class A {
static set x(v) {}
}
const d = Object.getOwnPropertyDescriptor(A, "x");
expect(d.set.name).toBe("set x");
});
test("extended name syntax", () => {
class A {
static set "method with space"(value) {
this.a = value;
}
static set 12(value) {
this.b = value;
}
static set [`he${"llo"}`](value) {
this.c = value;
}
}
A["method with space"] = 1;
A[12] = 2;
A.hello = 3;
expect(A.a).toBe(1);
expect(A.b).toBe(2);
expect(A.c).toBe(3);
});
test("inherited static setter", () => {
class Parent {
static get x() {
return this._x;
}
static set x(value) {
this._x = value * 2;
}
}
class Child extends Parent {}
expect(Child.x).toBeUndefined();
Child.x = 10;
expect(Child.x).toBe(20);
});
test("inherited static setter overriding", () => {
class Parent {
static get x() {
return this._x;
}
static set x(value) {
this._x = value * 2;
}
}
class Child extends Parent {
static get x() {
return this._x;
}
static set x(value) {
this._x = value * 3;
}
}
expect(Child.x).toBeUndefined();
Child.x = 10;
expect(Child.x).toBe(30);
});
});
describe("errors", () => {
test('"set static" is a syntax error', () => {
expect(`
class A {
set static foo(value) {}
}`).not.toEval();
});
});

View file

@ -0,0 +1,72 @@
test("basic functionality", () => {
class A {
static method() {
return 10;
}
}
expect(A.method()).toBe(10);
expect(new A().method).toBeUndefined();
});
test("extended name syntax", () => {
class A {
static method() {
return 1;
}
static 12() {
return 2;
}
static [`he${"llo"}`]() {
return 3;
}
}
expect(A.method()).toBe(1);
expect(A[12]()).toBe(2);
expect(A.hello()).toBe(3);
});
test("bound |this|", () => {
class A {
static method() {
expect(this).toBe(A);
}
}
A.method();
});
test("inherited static methods", () => {
class Parent {
static method() {
return 3;
}
}
class Child extends Parent {}
expect(Parent.method()).toBe(3);
expect(Child.method()).toBe(3);
expect(new Parent()).not.toHaveProperty("method");
expect(new Child()).not.toHaveProperty("method");
});
test("static method overriding", () => {
class Parent {
static method() {
return 3;
}
}
class Child extends Parent {
static method() {
return 10;
}
}
expect(Parent.method()).toBe(3);
expect(Child.method()).toBe(10);
});

View file

@ -0,0 +1,19 @@
test("constructors are always strict mode", () => {
class A {
constructor() {
expect(isStrictMode()).toBeTrue();
}
}
new A();
});
test("methods are always strict mode", () => {
class A {
method() {
expect(isStrictMode()).toBeTrue();
}
}
new A().method();
});