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:
parent
918f4affd5
commit
15de2eda2b
72 changed files with 2394 additions and 1998 deletions
35
Libraries/LibJS/Tests/classes/class-advanced-extends.js
Normal file
35
Libraries/LibJS/Tests/classes/class-advanced-extends.js
Normal 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");
|
||||
});
|
|
@ -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);
|
||||
});
|
||||
|
|
67
Libraries/LibJS/Tests/classes/class-constructor.js
Normal file
67
Libraries/LibJS/Tests/classes/class-constructor.js
Normal 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);
|
||||
});
|
95
Libraries/LibJS/Tests/classes/class-errors.js
Normal file
95
Libraries/LibJS/Tests/classes/class-errors.js
Normal 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();
|
||||
});
|
||||
});
|
69
Libraries/LibJS/Tests/classes/class-expressions.js
Normal file
69
Libraries/LibJS/Tests/classes/class-expressions.js
Normal 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");
|
||||
});
|
68
Libraries/LibJS/Tests/classes/class-getters.js
Normal file
68
Libraries/LibJS/Tests/classes/class-getters.js
Normal 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);
|
||||
});
|
133
Libraries/LibJS/Tests/classes/class-inheritance.js
Normal file
133
Libraries/LibJS/Tests/classes/class-inheritance.js
Normal 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);
|
||||
});
|
51
Libraries/LibJS/Tests/classes/class-methods.js
Normal file
51
Libraries/LibJS/Tests/classes/class-methods.js
Normal 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);
|
||||
});
|
100
Libraries/LibJS/Tests/classes/class-setters.js
Normal file
100
Libraries/LibJS/Tests/classes/class-setters.js
Normal 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);
|
||||
});
|
80
Libraries/LibJS/Tests/classes/class-static-getters.js
Normal file
80
Libraries/LibJS/Tests/classes/class-static-getters.js
Normal 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();
|
||||
});
|
||||
});
|
104
Libraries/LibJS/Tests/classes/class-static-setters.js
Normal file
104
Libraries/LibJS/Tests/classes/class-static-setters.js
Normal 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();
|
||||
});
|
||||
});
|
72
Libraries/LibJS/Tests/classes/class-static.js
Normal file
72
Libraries/LibJS/Tests/classes/class-static.js
Normal 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);
|
||||
});
|
19
Libraries/LibJS/Tests/classes/class-strict-mode.js
Normal file
19
Libraries/LibJS/Tests/classes/class-strict-mode.js
Normal 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();
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue