diff options
author | Matthew Olsson <matthewcolsson@gmail.com> | 2020-07-05 17:26:26 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-07-06 23:40:35 +0200 |
commit | 15de2eda2b8c06a59053d6a7144ea9eaf07e2210 (patch) | |
tree | 191d9459dc71e270def1ca69a02406a9498005b9 | |
parent | 918f4affd51cdd285272770465d4d875f4ae5aa2 (diff) | |
download | serenity-15de2eda2b8c06a59053d6a7144ea9eaf07e2210.zip |
LibJS: Convert all remaining non-Array tests to the new system :)
72 files changed, 2429 insertions, 2033 deletions
diff --git a/Libraries/LibJS/Tests/.prettierignore b/Libraries/LibJS/Tests/.prettierignore new file mode 100644 index 0000000000..dca057cb36 --- /dev/null +++ b/Libraries/LibJS/Tests/.prettierignore @@ -0,0 +1,3 @@ +classes/class-expressions.js +functions/function-strict-mode.js +new-expression.js diff --git a/Libraries/LibJS/Tests/builtins/BigInt/BigInt.asIntN.js b/Libraries/LibJS/Tests/builtins/BigInt/BigInt.asIntN.js deleted file mode 100644 index c2d78976f5..0000000000 --- a/Libraries/LibJS/Tests/builtins/BigInt/BigInt.asIntN.js +++ /dev/null @@ -1,9 +0,0 @@ -load("test-common.js"); - -try { - assert(BigInt.asIntN.length === 2); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} diff --git a/Libraries/LibJS/Tests/builtins/BigInt/BigInt.asUintN.js b/Libraries/LibJS/Tests/builtins/BigInt/BigInt.asUintN.js deleted file mode 100644 index 0255cad0ad..0000000000 --- a/Libraries/LibJS/Tests/builtins/BigInt/BigInt.asUintN.js +++ /dev/null @@ -1,9 +0,0 @@ -load("test-common.js"); - -try { - assert(BigInt.asUintN.length === 2); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} diff --git a/Libraries/LibJS/Tests/builtins/BigInt/BigInt.js b/Libraries/LibJS/Tests/builtins/BigInt/BigInt.js index eeda8fb8cc..f0fd70122d 100644 --- a/Libraries/LibJS/Tests/builtins/BigInt/BigInt.js +++ b/Libraries/LibJS/Tests/builtins/BigInt/BigInt.js @@ -1,78 +1,68 @@ -load("test-common.js"); +describe("correct behavior", () => { + test("basic functionality", () => { + expect(BigInt).toHaveLength(1); + expect(BigInt.name).toBe("BigInt"); + }); -try { - assert(BigInt.length === 1); - assert(BigInt.name === "BigInt"); + test("constructor with numbers", () => { + expect(BigInt(0)).toBe(0n); + expect(BigInt(1)).toBe(1n); + expect(BigInt(+1)).toBe(1n); + expect(BigInt(-1)).toBe(-1n); + expect(BigInt(123n)).toBe(123n); + }); - assert(BigInt(0) === 0n); - assert(BigInt(1) === 1n); - assert(BigInt(+1) === 1n); - assert(BigInt(-1) === -1n); - assert(BigInt("") === 0n); - assert(BigInt("0") === 0n); - assert(BigInt("1") === 1n); - assert(BigInt("+1") === 1n); - assert(BigInt("-1") === -1n); - assert(BigInt("-1") === -1n); - assert(BigInt([]) === 0n); - assert(BigInt("42") === 42n); - assert(BigInt(" \n 00100 \n ") === 100n); - assert(BigInt(123n) === 123n); - assert( - BigInt("3323214327642987348732109829832143298746432437532197321") === + test("constructor with strings", () => { + expect(BigInt("")).toBe(0n); + expect(BigInt("0")).toBe(0n); + expect(BigInt("1")).toBe(1n); + expect(BigInt("+1")).toBe(1n); + expect(BigInt("-1")).toBe(-1n); + expect(BigInt("-1")).toBe(-1n); + expect(BigInt("42")).toBe(42n); + expect(BigInt(" \n 00100 \n ")).toBe(100n); + expect(BigInt("3323214327642987348732109829832143298746432437532197321")).toBe( 3323214327642987348732109829832143298746432437532197321n - ); + ); + }); - assertThrowsError( - () => { - new BigInt(); - }, - { - error: TypeError, - message: "BigInt is not a constructor", - } - ); + test("constructor with objects", () => { + expect(BigInt([])).toBe(0n); + }); +}); - [null, undefined, Symbol()].forEach(value => { - assertThrowsError( - () => { - BigInt(value); - }, - { - error: TypeError, - message: - typeof value === "symbol" - ? "Cannot convert symbol to BigInt" - : `Cannot convert ${value} to BigInt`, - } - ); +describe("errors", () => { + test('cannot be constructed with "new"', () => { + expect(() => { + new BigInt(); + }).toThrowWithMessage(TypeError, "BigInt is not a constructor"); }); - ["foo", "123n", "1+1", {}, function () {}].forEach(value => { - assertThrowsError( - () => { + test("invalid arguments", () => { + expect(() => { + BigInt(null); + }).toThrowWithMessage(TypeError, "Cannot convert null to BigInt"); + + expect(() => { + BigInt(undefined); + }).toThrowWithMessage(TypeError, "Cannot convert undefined to BigInt"); + + expect(() => { + BigInt(Symbol()); + }).toThrowWithMessage(TypeError, "Cannot convert symbol to BigInt"); + + ["foo", "123n", "1+1", {}, function () {}].forEach(value => { + expect(() => { BigInt(value); - }, - { - error: SyntaxError, - message: `Invalid value for BigInt: ${value}`, - } - ); + }).toThrowWithMessage(SyntaxError, `Invalid value for BigInt: ${value}`); + }); }); - [1.23, Infinity, -Infinity, NaN].forEach(value => { - assertThrowsError( - () => { + test("invalid numeric arguments", () => { + [1.23, Infinity, -Infinity, NaN].forEach(value => { + expect(() => { BigInt(value); - }, - { - error: RangeError, - message: "BigInt argument must be an integer", - } - ); + }).toThrowWithMessage(RangeError, "BigInt argument must be an integer"); + }); }); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +}); diff --git a/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toLocaleString.js b/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toLocaleString.js index d3d96961af..b257edab30 100644 --- a/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toLocaleString.js +++ b/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toLocaleString.js @@ -1,21 +1,10 @@ -load("test-common.js"); - -try { - assert(BigInt.prototype.toLocaleString.length === 0); - - assertThrowsError( - () => { - BigInt.prototype.toLocaleString.call("foo"); - }, - { - error: TypeError, - message: "Not a BigInt object", - } - ); - - assert(BigInt(123).toLocaleString() === "123"); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +test("basic functionality", () => { + expect(BigInt.prototype.toLocaleString).toHaveLength(0); + expect(BigInt(123).toLocaleString()).toBe("123"); +}); + +test("calling with non-BigInt |this|", () => { + expect(() => { + BigInt.prototype.toLocaleString.call("foo"); + }).toThrowWithMessage(TypeError, "Not a BigInt object"); +}); diff --git a/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toString.js b/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toString.js index 2e18260baa..d75940234a 100644 --- a/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toString.js +++ b/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toString.js @@ -1,21 +1,10 @@ -load("test-common.js"); - -try { - assert(BigInt.prototype.toString.length === 0); - - assertThrowsError( - () => { - BigInt.prototype.toString.call("foo"); - }, - { - error: TypeError, - message: "Not a BigInt object", - } - ); - - assert(BigInt(123).toString() === "123"); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +test("basic functionality", () => { + expect(BigInt.prototype.toString).toHaveLength(0); + expect(BigInt(123).toString()).toBe("123"); +}); + +test("calling with non-BigInt |this|", () => { + expect(() => { + BigInt.prototype.toString.call("foo"); + }).toThrowWithMessage(TypeError, "Not a BigInt object"); +}); diff --git a/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.valueOf.js b/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.valueOf.js index bf71fd93cd..2453de327d 100644 --- a/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.valueOf.js +++ b/Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.valueOf.js @@ -1,23 +1,12 @@ -load("test-common.js"); - -try { - assert(BigInt.prototype.valueOf.length === 0); - - assertThrowsError( - () => { - BigInt.prototype.valueOf.call("foo"); - }, - { - error: TypeError, - message: "Not a BigInt object", - } - ); - - assert(typeof BigInt(123).valueOf() === "bigint"); +test("basic functionality", () => { + expect(BigInt.prototype.valueOf).toHaveLength(0); + expect(typeof BigInt(123).valueOf()).toBe("bigint"); // FIXME: Uncomment once we support Object() with argument - // assert(typeof Object(123n).valueOf() === "bigint"); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + // expect(typeof Object(123n).valueOf()).toBe("bigint"); +}); + +test("calling with non-BigInt |this|", () => { + expect(() => { + BigInt.prototype.valueOf.call("foo"); + }).toThrowWithMessage(TypeError, "Not a BigInt object"); +}); diff --git a/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js b/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js index 841b60008f..c32681792f 100644 --- a/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js +++ b/Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js @@ -1,74 +1,80 @@ -load("test-common.js"); +describe("correct behavior", () => { + test("typeof bigint", () => { + expect(typeof 1n).toBe("bigint"); + }); -try { - var bigint = 123n; + test("bigint string coersion", () => { + expect("" + 123n).toBe("123"); + }); - assert(typeof bigint === "bigint"); - assert(-bigint === -123n); - assert("" + bigint === "123"); + test("arithmetic operators", () => { + let bigint = 123n; + expect(-bigint).toBe(-123n); - assertThrowsError( - () => { - +bigint; - }, - { - error: TypeError, - message: "Cannot convert BigInt to number", - } - ); + expect(12n + 34n).toBe(46n); + expect(12n - 34n).toBe(-22n); + expect(8n * 12n).toBe(96n); + expect(123n / 10n).toBe(12n); + expect(2n ** 3n).toBe(8n); + expect(5n % 3n).toBe(2n); + expect( + 45977665298704210987n + + (714320987142450987412098743217984576n / 4598741987421098765327980n) * 987498743n + ).toBe(199365500239020623962n); + }); - assert(12n + 34n === 46n); - assert(12n - 34n === -22n); - assert(8n * 12n === 96n); - assert(123n / 10n === 12n); - assert(2n ** 3n === 8n); - assert(5n % 3n === 2n); - assert( - 45977665298704210987n + - (714320987142450987412098743217984576n / 4598741987421098765327980n) * 987498743n === - 199365500239020623962n - ); + test("bitwise operators", () => { + expect(12n & 5n).toBe(4n); + expect(1n | 2n).toBe(3n); + expect(5n ^ 3n).toBe(6n); + expect(~1n).toBe(-2n); + }); - assert((12n & 5n) === 4n); - assert((1n | 2n) === 3n); - assert((5n ^ 3n) === 6n); - assert(~1n === -2n); + test("increment operators", () => { + let bigint = 1n; + expect(bigint++).toBe(1n); + expect(bigint).toBe(2n); + expect(bigint--).toBe(2n); + expect(bigint).toBe(1n); + expect(++bigint).toBe(2n); + expect(bigint).toBe(2n); + expect(--bigint).toBe(1n); + expect(bigint).toBe(1n); + }); - bigint = 1n; - assert(bigint++ === 1n); - assert(bigint === 2n); - assert(bigint-- === 2n); - assert(bigint === 1n); - assert(++bigint === 2n); - assert(bigint === 2n); - assert(--bigint === 1n); - assert(bigint === 1n); + test("weak equality operators", () => { + expect(1n == 1n).toBeTrue(); + expect(1n == 1).toBeTrue(); + expect(1 == 1n).toBeTrue(); + expect(1n == 1.23).toBeFalse(); + expect(1.23 == 1n).toBeFalse(); - assert((1n == 1n) === true); - assert((1n == 1) === true); - assert((1 == 1n) === true); - assert((1n == 1.23) === false); - assert((1.23 == 1n) === false); + expect(1n != 1n).toBeFalse(); + expect(1n != 1).toBeFalse(); + expect(1 != 1n).toBeFalse(); + expect(1n != 1.23).toBeTrue(); + expect(1.23 != 1n).toBeTrue(); + }); - assert((1n != 1n) === false); - assert((1n != 1) === false); - assert((1 != 1n) === false); - assert((1n != 1.23) === true); - assert((1.23 != 1n) === true); + test("strong equality operators", () => { + expect(1n === 1n).toBeTrue(); + expect(1n === 1).toBeFalse(); + expect(1 === 1n).toBeFalse(); + expect(1n === 1.23).toBeFalse(); + expect(1.23 === 1n).toBeFalse(); - assert((1n === 1n) === true); - assert((1n === 1) == false); - assert((1 === 1n) === false); - assert((1n === 1.23) === false); - assert((1.23 === 1n) === false); + expect(1n !== 1n).toBeFalse(); + expect(1n !== 1).toBeTrue(); + expect(1 !== 1n).toBeTrue(); + expect(1n !== 1.23).toBeTrue(); + expect(1.23 !== 1n).toBeTrue(); + }); +}); - assert((1n !== 1n) === false); - assert((1n !== 1) === true); - assert((1 !== 1n) === true); - assert((1n !== 1.23) === true); - assert((1.23 !== 1n) === true); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +describe("errors", () => { + test("conversion to number", () => { + expect(() => { + +123n; + }).toThrowWithMessage(TypeError, "Cannot convert BigInt to number"); + }); +}); diff --git a/Libraries/LibJS/Tests/builtins/BigInt/bigint-number-mix-errors.js b/Libraries/LibJS/Tests/builtins/BigInt/bigint-number-mix-errors.js index 8097ff0ca1..aa3eaa301d 100644 --- a/Libraries/LibJS/Tests/builtins/BigInt/bigint-number-mix-errors.js +++ b/Libraries/LibJS/Tests/builtins/BigInt/bigint-number-mix-errors.js @@ -1,118 +1,31 @@ -load("test-common.js"); - -try { +const doTest = (operatorName, executeOperation) => { [1, null, undefined].forEach(value => { - assertThrowsError( - () => { - 1n + value; - }, - { - error: TypeError, - message: "Cannot use addition operator with BigInt and other type", - } - ); - assertThrowsError( - () => { - 1n - value; - }, - { - error: TypeError, - message: "Cannot use subtraction operator with BigInt and other type", - } - ); - assertThrowsError( - () => { - 1n * value; - }, - { - error: TypeError, - message: "Cannot use multiplication operator with BigInt and other type", - } - ); - assertThrowsError( - () => { - 1n / value; - }, - { - error: TypeError, - message: "Cannot use division operator with BigInt and other type", - } - ); - assertThrowsError( - () => { - 1n % value; - }, - { - error: TypeError, - message: "Cannot use modulo operator with BigInt and other type", - } - ); - assertThrowsError( - () => { - 1n ** value; - }, - { - error: TypeError, - message: "Cannot use exponentiation operator with BigInt and other type", - } - ); - assertThrowsError( - () => { - 1n | value; - }, - { - error: TypeError, - message: "Cannot use bitwise OR operator with BigInt and other type", - } - ); - assertThrowsError( - () => { - 1n & value; - }, - { - error: TypeError, - message: "Cannot use bitwise AND operator with BigInt and other type", - } - ); - assertThrowsError( - () => { - 1n ^ value; - }, - { - error: TypeError, - message: "Cannot use bitwise XOR operator with BigInt and other type", - } - ); - assertThrowsError( - () => { - 1n << value; - }, - { - error: TypeError, - message: "Cannot use left-shift operator with BigInt and other type", - } - ); - assertThrowsError( - () => { - 1n >> value; - }, - { - error: TypeError, - message: "Cannot use right-shift operator with BigInt and other type", - } - ); - assertThrowsError( - () => { - 1n >>> value; - }, - { - error: TypeError, - message: "Cannot use unsigned right-shift operator with BigInt", - } + const messageSuffix = operatorName === "unsigned right-shift" ? "" : " and other type"; + + expect(() => { + executeOperation(1n, value); + }).toThrowWithMessage( + TypeError, + `Cannot use ${operatorName} operator with BigInt${messageSuffix}` ); }); +}; - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +[ + ["addition", (a, b) => a + b], + ["subtraction", (a, b) => a - b], + ["multiplication", (a, b) => a * b], + ["division", (a, b) => a / b], + ["modulo", (a, b) => a % b], + ["exponentiation", (a, b) => a ** b], + ["bitwise OR", (a, b) => a | b], + ["bitwise AND", (a, b) => a & b], + ["bitwise XOR", (a, b) => a ^ b], + ["left-shift", (a, b) => a << b], + ["right-shift", (a, b) => a >> b], + ["unsigned right-shift", (a, b) => a >>> b], +].forEach(testCase => { + test(`using ${testCase[0]} operator with BigInt and other type`, () => { + doTest(testCase[0], testCase[1]); + }); +}); diff --git a/Libraries/LibJS/Tests/builtins/Symbol/Symbol.for.js b/Libraries/LibJS/Tests/builtins/Symbol/Symbol.for.js index 0d581d98b6..b4e37e3c6c 100644 --- a/Libraries/LibJS/Tests/builtins/Symbol/Symbol.for.js +++ b/Libraries/LibJS/Tests/builtins/Symbol/Symbol.for.js @@ -1,33 +1,23 @@ -load("test-common.js"); +// test("basic functionality", () => { +// const localSym = Symbol("foo"); +// const globalSym = Symbol.for("foo"); -try { - const localSym = Symbol("foo"); - const globalSym = Symbol.for("foo"); +// expect(localSym).not.toBe(globalSym); +// expect(localSym).not.toBe(Symbol("foo")); +// expect(globalSym).not.toBe(Symbol("foo")); +// expect(globalSym).toBe(Symbol.for("foo")); +// expect(localSym.toString()).toBe("Symbol(foo)"); +// expect(globalSym.toString()).toBe("Symbol(foo)"); - assert(localSym !== globalSym); - assert(localSym !== Symbol("foo")); - assert(globalSym !== Symbol("foo")); - assert(globalSym === Symbol.for("foo")); - assert(localSym.toString() === "Symbol(foo)"); - assert(globalSym.toString() === "Symbol(foo)"); +// expect(Symbol.for(1).description).toBe("1"); +// expect(Symbol.for(true).description).toBe("true"); +// expect(Symbol.for({}).description).toBe("[object Object]"); +// expect(Symbol.for().description).toBe("undefined"); +// expect(Symbol.for(null).description).toBe("null"); +// }); - assert(Symbol.for(1).description === "1"); - assert(Symbol.for(true).description === "true"); - assert(Symbol.for({}).description === "[object Object]"); - assert(Symbol.for().description === "undefined"); - assert(Symbol.for(null).description === "null"); - - assertThrowsError( - () => { - Symbol.for(Symbol()); - }, - { - error: TypeError, - message: "Cannot convert symbol to string", - } - ); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +// test("symbol argument throws an error", () => { +// expect(() => { +// Symbol.for(Symbol()); +// }).toThrowWithMessage(TypeError, "Cannot convert symbol to string"); +// }); diff --git a/Libraries/LibJS/Tests/builtins/Symbol/Symbol.js b/Libraries/LibJS/Tests/builtins/Symbol/Symbol.js index f6cf02fa66..a38dcbad61 100644 --- a/Libraries/LibJS/Tests/builtins/Symbol/Symbol.js +++ b/Libraries/LibJS/Tests/builtins/Symbol/Symbol.js @@ -1,29 +1,19 @@ -load("test-common.js"); - -try { +test("basic functionality", () => { const s1 = Symbol("foo"); const s2 = Symbol("foo"); - assert(s1 !== s2); - assert(s1.description === "foo"); - assert(s2.description === "foo"); + expect(s1).not.toBe(s2); + expect(s1.description).toBe("foo"); + expect(s2.description).toBe("foo"); s1.description = "bar"; - assert(s1.description === "foo"); - - assert(typeof s1 === "symbol"); + expect(s1.description).toBe("foo"); - assertThrowsError( - () => { - Symbol(Symbol("foo")); - }, - { - error: TypeError, - message: "Cannot convert symbol to string", - } - ); + expect(typeof s1).toBe("symbol"); +}); - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +test("constructing symbol from symbol is an error", () => { + expect(() => { + Symbol(Symbol("foo")); + }).toThrowWithMessage(TypeError, "Cannot convert symbol to string"); +}); diff --git a/Libraries/LibJS/Tests/builtins/Symbol/Symbol.keyFor.js b/Libraries/LibJS/Tests/builtins/Symbol/Symbol.keyFor.js index 93311673b3..7c70f00d98 100644 --- a/Libraries/LibJS/Tests/builtins/Symbol/Symbol.keyFor.js +++ b/Libraries/LibJS/Tests/builtins/Symbol/Symbol.keyFor.js @@ -1,34 +1,24 @@ -load("test-common.js"); +// test("basic functionality", () => { +// const localSym = Symbol("bar"); +// const globalSym = Symbol.for("bar"); -try { - const localSym = Symbol("foo"); - const globalSym = Symbol.for("foo"); +// expect(Symbol.keyFor(localSym)).toBeUndefined(); +// expect(Symbol.keyFor(globalSym)).toBe("bar"); +// }); - assert(Symbol.keyFor(localSym) === undefined); - assert(Symbol.keyFor(globalSym) === "foo"); - - const testThrows = (value, str) => { - assertThrowsError( - () => { - Symbol.keyFor(value); - }, - { - error: TypeError, - message: str + " is not a symbol", - } - ); - }; - - testThrows(1, "1"); - testThrows(null, "null"); - testThrows(undefined, "undefined"); - testThrows([], "[object Array]"); - testThrows({}, "[object Object]"); - testThrows(true, "true"); - testThrows("foobar", "foobar"); - testThrows(function () {}, "[object ScriptFunction]"); // FIXME: Better function stringification - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +// test("bad argument values", () => { +// [ +// [1, "1"], +// [null, "null"], +// [undefined, "undefined"], +// [[], "[object Array]"], +// [{}, "[object Object]"], +// [true, "true"], +// ["foobar", "foobar"], +// [function () {}, "[object ScriptFunction]"], // FIXME: Better function stringification +// ].forEach(testCase => { +// expect(() => { +// Symbol.keyFor(testCase[0]); +// }).toThrowWithMessage(TypeError, `${testCase[1]} is not a symbol`); +// }); +// }); diff --git a/Libraries/LibJS/Tests/builtins/Symbol/Symbol.prototype.toString.js b/Libraries/LibJS/Tests/builtins/Symbol/Symbol.prototype.toString.js index f4dbc0bcb7..a94167b5f1 100644 --- a/Libraries/LibJS/Tests/builtins/Symbol/Symbol.prototype.toString.js +++ b/Libraries/LibJS/Tests/builtins/Symbol/Symbol.prototype.toString.js @@ -1,33 +1,23 @@ -load("test-common.js"); +describe("correct behavior", () => { + test("basic functionality", () => { + const s1 = Symbol("baz"); + // const s2 = Symbol.for("qux"); -try { - const s1 = Symbol("foo"); - const s2 = Symbol.for("bar"); + expect(s1.toString()).toBe("Symbol(baz)"); + // expect(s2.toString()).toBe("Symbol(qux)"); + }); +}); - assert(s1.toString() === "Symbol(foo)"); - assert(s2.toString() === "Symbol(bar)"); +describe("errors", () => { + test("convert to string", () => { + expect(() => { + Symbol() + ""; + }).toThrowWithMessage(TypeError, "Cannot convert symbol to string"); + }); - assertThrowsError( - () => { - s1 + ""; - }, - { - error: TypeError, - message: "Cannot convert symbol to string", - } - ); - - assertThrowsError( - () => { - s1 + 1; - }, - { - error: TypeError, - message: "Cannot convert symbol to number", - } - ); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + test("convert to number", () => { + expect(() => { + Symbol() + 1; + }).toThrowWithMessage(TypeError, "Cannot convert symbol to number"); + }); +}); diff --git a/Libraries/LibJS/Tests/builtins/Symbol/Symbol.prototype.valueOf.js b/Libraries/LibJS/Tests/builtins/Symbol/Symbol.prototype.valueOf.js index c242268c52..84a9188406 100644 --- a/Libraries/LibJS/Tests/builtins/Symbol/Symbol.prototype.valueOf.js +++ b/Libraries/LibJS/Tests/builtins/Symbol/Symbol.prototype.valueOf.js @@ -1,25 +1,15 @@ -load("test-common.js"); - -try { - let local = Symbol("foo"); - let global = Symbol.for("foo"); - assert(local.valueOf() === local); - assert(global.valueOf() === global); - - assert(Symbol.prototype.valueOf.call(local) === local); - assert(Symbol.prototype.valueOf.call(global) === global); - - assertThrowsError( - () => { - Symbol.prototype.valueOf.call("foo"); - }, - { - error: TypeError, - message: "Not a Symbol object", - } - ); - - console.log("PASS"); -} catch (err) { - console.log("FAIL: " + err); -} +test("basic functionality", () => { + const local = Symbol("foo"); + // const global = Symbol.for("foo"); + expect(local.valueOf()).toBe(local); + // expect(global.valueOf()).toBe(global); + + expect(Symbol.prototype.valueOf.call(local)).toBe(local); + // expect(Symbol.prototype.valueOf.call(global)).toBe(global); +}); + +test("|this| must be a symbol", () => { + expect(() => { + Symbol.prototype.valueOf.call("foo"); + }).toThrowWithMessage(TypeError, "Not a Symbol object"); +}); diff --git a/Libraries/LibJS/Tests/classes/class-advanced-extends.js b/Libraries/LibJS/Tests/classes/class-advanced-extends.js new file mode 100644 index 0000000000..749f65003c --- /dev/null +++ b/Libraries/LibJS/Tests/classes/class-advanced-extends.js @@ -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"); +}); diff --git a/Libraries/LibJS/Tests/classes/class-basic.js b/Libraries/LibJS/Tests/classes/class-basic.js index 2fd856ac36..844bbe68fc 100644 --- a/Libraries/LibJS/Tests/classes/class-basic.js +++ b/Libraries/LibJS/Tests/classes/class-basic.js @@ -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); +}); diff --git a/Libraries/LibJS/Tests/classes/class-constructor.js b/Libraries/LibJS/Tests/classes/class-constructor.js new file mode 100644 index 0000000000..367c1e77ea --- /dev/null +++ b/Libraries/LibJS/Tests/classes/class-constructor.js @@ -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); +}); diff --git a/Libraries/LibJS/Tests/classes/class-errors.js b/Libraries/LibJS/Tests/classes/class-errors.js new file mode 100644 index 0000000000..acef9ee3c9 --- /dev/null +++ b/Libraries/LibJS/Tests/classes/class-errors.js @@ -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(); + }); +}); diff --git a/Libraries/LibJS/Tests/classes/class-expressions.js b/Libraries/LibJS/Tests/classes/class-expressions.js new file mode 100644 index 0000000000..3dbea6d8fc --- /dev/null +++ b/Libraries/LibJS/Tests/classes/class-expressions.js @@ -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"); +}); diff --git a/Libraries/LibJS/Tests/classes/class-getters.js b/Libraries/LibJS/Tests/classes/class-getters.js new file mode 100644 index 0000000000..b1cf7ad229 --- /dev/null +++ b/Libraries/LibJS/Tests/classes/class-getters.js @@ -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); +}); diff --git a/Libraries/LibJS/Tests/classes/class-inheritance.js b/Libraries/LibJS/Tests/classes/class-inheritance.js new file mode 100644 index 0000000000..5fb273ba52 --- /dev/null +++ b/Libraries/LibJS/Tests/classes/class-inheritance.js @@ -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); +}); diff --git a/Libraries/LibJS/Tests/classes/class-methods.js b/Libraries/LibJS/Tests/classes/class-methods.js new file mode 100644 index 0000000000..4bc04ea5a5 --- /dev/null +++ b/Libraries/LibJS/Tests/classes/class-methods.js @@ -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); +}); diff --git a/Libraries/LibJS/Tests/classes/class-setters.js b/Libraries/LibJS/Tests/classes/class-setters.js new file mode 100644 index 0000000000..19dbd6ecd2 --- /dev/null +++ b/Libraries/LibJS/Tests/classes/class-setters.js @@ -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); +}); diff --git a/Libraries/LibJS/Tests/classes/class-static-getters.js b/Libraries/LibJS/Tests/classes/class-static-getters.js new file mode 100644 index 0000000000..0407bd9a48 --- /dev/null +++ b/Libraries/LibJS/Tests/classes/class-static-getters.js @@ -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(); + }); +}); diff --git a/Libraries/LibJS/Tests/classes/class-static-setters.js b/Libraries/LibJS/Tests/classes/class-static-setters.js new file mode 100644 index 0000000000..41d867a7e5 --- /dev/null +++ b/Libraries/LibJS/Tests/classes/class-static-setters.js @@ -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(); + }); +}); diff --git a/Libraries/LibJS/Tests/classes/class-static.js b/Libraries/LibJS/Tests/classes/class-static.js new file mode 100644 index 0000000000..a58cdd7f5d --- /dev/null +++ b/Libraries/LibJS/Tests/classes/class-static.js @@ -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); +}); diff --git a/Libraries/LibJS/Tests/classes/class-strict-mode.js b/Libraries/LibJS/Tests/classes/class-strict-mode.js new file mode 100644 index 0000000000..90ead4490f --- /dev/null +++ b/Libraries/LibJS/Tests/classes/class-strict-mode.js @@ -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(); +}); diff --git a/Libraries/LibJS/Tests/const-reassignment.js b/Libraries/LibJS/Tests/const-reassignment.js index 6638229738..44d9cab173 100644 --- a/Libraries/LibJS/Tests/const-reassignment.js +++ b/Libraries/LibJS/Tests/const-reassignment.js @@ -1,3 +1,4 @@ +// I'm not sure how this test passed before the refactor, but it definitely doesn't work at all test.skip("reassignment to const", () => { const constantValue = 1; expect(() => { diff --git a/Libraries/LibJS/Tests/functions/arrow-functions.js b/Libraries/LibJS/Tests/functions/arrow-functions.js index 6f9afc632d..3b3ab09ed1 100644 --- a/Libraries/LibJS/Tests/functions/arrow-functions.js +++ b/Libraries/LibJS/Tests/functions/arrow-functions.js @@ -1,69 +1,101 @@ -load("test-common.js"); +test("no arguments", () => { + let getNumber = () => { + return 42; + }; + expect(getNumber()).toBe(42); -try { - let getNumber = () => 42; - assert(getNumber() === 42); + getNumber = () => 42; + expect(getNumber()).toBe(42); + getNumber = () => { + return 99; + }; + expect(getNumber()).toBe(99); getNumber = () => 99; - assert(getNumber() === 99); + expect(getNumber()).toBe(99); +}); +test("arguments", () => { let add = (a, b) => a + b; - assert(add(2, 3) === 5); + expect(add(2, 3)).toBe(5); const addBlock = (a, b) => { let res = a + b; return res; }; - assert(addBlock(5, 4) === 9); + expect(addBlock(5, 4)).toBe(9); +}); +test("inside an array", () => { let chompy = [x => x, 2]; - assert(chompy.length === 2); - assert(chompy[0](1) === 1); + expect(chompy).toHaveLength(2); + expect(chompy[0](1)).toBe(1); +}); +test("return object literal", () => { const makeObject = (a, b) => ({ a, b }); const obj = makeObject(33, 44); - assert(typeof obj === "object"); - assert(obj.a === 33); - assert(obj.b === 44); + expect(typeof obj).toBe("object"); + expect(obj.a).toBe(33); + expect(obj.b).toBe(44); +}); +test("return undefined", () => { let returnUndefined = () => {}; - assert(typeof returnUndefined() === "undefined"); + expect(returnUndefined()).toBeUndefined(); +}); +test("return array literal", () => { const makeArray = (a, b) => [a, b]; const array = makeArray("3", { foo: 4 }); - assert(array[0] === "3"); - assert(array[1].foo === 4); + expect(array[0]).toBe("3"); + expect(array[1].foo).toBe(4); +}); +test("return numeric expression", () => { let square = x => x * x; - assert(square(3) === 9); + expect(square(3)).toBe(9); let squareBlock = x => { return x * x; }; - assert(squareBlock(4) === 16); + expect(squareBlock(4)).toBe(16); +}); +test("return called arrow function expression", () => { const message = (who => "Hello " + who)("friends!"); - assert(message === "Hello friends!"); + expect(message).toBe("Hello friends!"); const sum = ((x, y, z) => x + y + z)(1, 2, 3); - assert(sum === 6); + expect(sum).toBe(6); const product = ((x, y, z) => { let res = x * y * z; return res; })(5, 4, 2); - assert(product === 40); + expect(product).toBe(40); const half = (x => { return x / 2; })(10); - assert(half === 5); - - var foo, bar; + expect(half).toBe(5); +}); + +test("currying", () => { + let add = a => b => a + b; + expect(typeof add(1)).toBe("function"); + expect(typeof add(1, 2)).toBe("function"); + expect(add(1)(2)).toBe(3); +}); + +test("with comma operator", () => { + let foo, bar; (foo = bar), baz => {}; - assert(foo === undefined); - assert(bar === undefined); + expect(foo).toBe(undefined); + expect(bar).toBe(undefined); +}); +test("arrow functions in objects", () => { function FooBar() { this.x = { y: () => this, @@ -73,50 +105,46 @@ try { }; } - var foobar = new FooBar(); - assert(foobar.x.y() === foobar); - assert(foobar.x.z() === foobar.x); - - var Baz = () => {}; - - assert(Baz.prototype === undefined); - - assertThrowsError( - () => { - new Baz(); - }, - { - error: TypeError, - message: "Baz is not a constructor", - } - ); + const foobar = new FooBar(); + expect(foobar.x.y()).toBe(foobar); + expect(foobar.x.z()).toBe(foobar.x); +}); +test("strict mode propogation", () => { (() => { "use strict"; - assert(isStrictMode()); + expect(isStrictMode()).toBeTrue(); (() => { - assert(isStrictMode()); + expect(isStrictMode()).toBeTrue(); })(); })(); (() => { "use strict"; - assert(isStrictMode()); + expect(isStrictMode()).toBeTrue(); })(); (() => { - assert(!isStrictMode()); + expect(isStrictMode()).toBeFalse(); (() => { "use strict"; - assert(isStrictMode()); + expect(isStrictMode()).toBeTrue(); })(); - assert(!isStrictMode()); + expect(isStrictMode()).toBeFalse(); })(); - - console.log("PASS"); -} catch { - console.log("FAIL"); -} +}); + +test("no prototype", () => { + let foo = () => {}; + expect(foo).not.toHaveProperty("prototype"); +}); + +test("cannot be constructed", () => { + let foo = () => {}; + expect(() => { + new foo(); + }).toThrowWithMessage(TypeError, "foo is not a constructor"); +}); diff --git a/Libraries/LibJS/Tests/functions/constructor-basic.js b/Libraries/LibJS/Tests/functions/constructor-basic.js index 669bc77d96..c672e71529 100644 --- a/Libraries/LibJS/Tests/functions/constructor-basic.js +++ b/Libraries/LibJS/Tests/functions/constructor-basic.js @@ -1,17 +1,11 @@ -load("test-common.js"); - -try { +test("basic functionality", () => { function Foo() { this.x = 123; } - assert(Foo.prototype.constructor === Foo); - - var foo = new Foo(); - assert(foo.constructor === Foo); - assert(foo.x === 123); + expect(Foo.prototype.constructor).toBe(Foo); - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + const foo = new Foo(); + expect(foo.constructor).toBe(Foo); + expect(foo.x).toBe(123); +}); diff --git a/Libraries/LibJS/Tests/functions/function-TypeError.js b/Libraries/LibJS/Tests/functions/function-TypeError.js index 6a59534d96..289d109f6a 100644 --- a/Libraries/LibJS/Tests/functions/function-TypeError.js +++ b/Libraries/LibJS/Tests/functions/function-TypeError.js @@ -1,70 +1,44 @@ -load("test-common.js"); +test("calling non-function", () => { + expect(() => { + const a = true; + a(); + }).toThrowWithMessage(TypeError, "true is not a function (evaluated from 'a')"); +}); -try { - assertThrowsError( - () => { - var b = true; - b(); - }, - { - error: TypeError, - message: "true is not a function (evaluated from 'b')", - } - ); - - assertThrowsError( - () => { - var n = 100 + 20 + 3; - n(); - }, - { - error: TypeError, - message: "123 is not a function (evaluated from 'n')", - } - ); +test("calling number", () => { + expect(() => { + const a = 100 + 20 + 3; + a(); + }).toThrowWithMessage(TypeError, "123 is not a function (evaluated from 'a')"); +}); - assertThrowsError( - () => { - var o = {}; - o.a(); - }, - { - error: TypeError, - message: "undefined is not a function (evaluated from 'o.a')", - } - ); +test("calling undefined object key", () => { + expect(() => { + const o = {}; + o.a(); + }).toThrowWithMessage(TypeError, "undefined is not a function (evaluated from 'o.a')"); +}); - assertThrowsError( - () => { - Math(); - }, - { - error: TypeError, - message: "[object MathObject] is not a function (evaluated from 'Math')", - } - ); +test("calling object", () => { + expect(() => { + Math(); + }).toThrowWithMessage(TypeError, "[object MathObject] is not a function (evaluated from 'Math')"); +}); - assertThrowsError( - () => { - new Math(); - }, - { - error: TypeError, - message: "[object MathObject] is not a constructor (evaluated from 'Math')", - } +test("constructing object", () => { + expect(() => { + new Math(); + }).toThrowWithMessage( + TypeError, + "[object MathObject] is not a constructor (evaluated from 'Math')" ); +}); - assertThrowsError( - () => { - new isNaN(); - }, - { - error: TypeError, - message: "[object NativeFunction] is not a constructor (evaluated from 'isNaN')", - } +test("constructing native function", () => { + expect(() => { + new isNaN(); + }).toThrowWithMessage( + TypeError, + "[object NativeFunction] is not a constructor (evaluated from 'isNaN')" ); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +}); diff --git a/Libraries/LibJS/Tests/functions/function-default-parameters.js b/Libraries/LibJS/Tests/functions/function-default-parameters.js index 4e0064dacc..49d3f40a05 100644 --- a/Libraries/LibJS/Tests/functions/function-default-parameters.js +++ b/Libraries/LibJS/Tests/functions/function-default-parameters.js @@ -1,75 +1,81 @@ -load("test-common.js"); - -try { - function func1(a, b = 1) { - return a + b; +test("single default parameter", () => { + function func(a = 6) { + return typeof a; } - const arrowFunc1 = (a, b = 1) => a + b; - - assert(func1(4, 5) === 9); - assert(func1(4) === 5); - assert(func1(4, undefined) === 5); - assert(Number.isNaN(func1())); - - assert(arrowFunc1(4, 5) === 9); - assert(arrowFunc1(4) === 5); - assert(arrowFunc1(4, undefined) === 5); - assert(Number.isNaN(arrowFunc1())); - - function func2(a = 6) { - return typeof a; + const arrowFunc = (a = 6) => typeof a; + + expect(func()).toBe("number"); + expect(func(5)).toBe("number"); + expect(func(undefined)).toBe("number"); + expect(func(false)).toBe("boolean"); + expect(func(null)).toBe("object"); + expect(func({})).toBe("object"); + + expect(arrowFunc()).toBe("number"); + expect(arrowFunc(5)).toBe("number"); + expect(arrowFunc(undefined)).toBe("number"); + expect(arrowFunc(false)).toBe("boolean"); + expect(arrowFunc(null)).toBe("object"); + expect(arrowFunc({})).toBe("object"); +}); + +test("two parameters, second one is default", () => { + function func(a, b = 1) { + return a + b; } - const arrowFunc2 = (a = 6) => typeof a; + const arrowFunc = (a, b = 1) => a + b; - assert(func2() === "number"); - assert(func2(5) === "number"); - assert(func2(undefined) === "number"); - assert(func2(false) === "boolean"); - assert(func2(null) === "object"); - assert(func2({}) === "object"); + expect(func(4, 5)).toBe(9); + expect(func(4)).toBe(5); + expect(func(4, undefined)).toBe(5); + expect(func()).toBeNaN(); - assert(arrowFunc2() === "number"); - assert(arrowFunc2(5) === "number"); - assert(arrowFunc2(undefined) === "number"); - assert(arrowFunc2(false) === "boolean"); - assert(arrowFunc2(null) === "object"); - assert(arrowFunc2({}) === "object"); + expect(arrowFunc(4, 5)).toBe(9); + expect(arrowFunc(4)).toBe(5); + expect(arrowFunc(4, undefined)).toBe(5); + expect(arrowFunc()).toBeNaN(); +}); - function func3(a = 5, b) { +test("two parameters, first one is default", () => { + function func(a = 5, b) { return a + b; } - const arrowFunc3 = (a = 5, b) => a + b; + const arrowFunc = (a = 5, b) => a + b; - assert(func3(4, 5) === 9); - assert(func3(undefined, 4) === 9); - assert(Number.isNaN(func3())); + expect(func(4, 5)).toBe(9); + expect(func(undefined, 4)).toBe(9); + expect(func()).toBeNaN(); - assert(arrowFunc3(4, 5) === 9); - assert(arrowFunc3(undefined, 4) === 9); - assert(Number.isNaN(arrowFunc3())); + expect(arrowFunc(4, 5)).toBe(9); + expect(arrowFunc(undefined, 4)).toBe(9); + expect(arrowFunc()).toBeNaN(); +}); - function func4(a, b = a) { +test("default parameter references a previous parameter", () => { + function func(a, b = a) { return a + b; } - const arrowFunc4 = (a, b = a) => a + b; + const arrowFunc = (a, b = a) => a + b; - assert(func4(4, 5) === 9); - assert(func4(4) === 8); - assert(func4("hf") === "hfhf"); - assert(func4(true) === 2); - assert(Number.isNaN(func4())); + expect(func(4, 5)).toBe(9); + expect(func(4)).toBe(8); + expect(func("hf")).toBe("hfhf"); + expect(func(true)).toBe(2); + expect(func()).toBeNaN(); - assert(arrowFunc4(4, 5) === 9); - assert(arrowFunc4(4) === 8); - assert(arrowFunc4("hf") === "hfhf"); - assert(arrowFunc4(true) === 2); - assert(Number.isNaN(arrowFunc4())); + expect(arrowFunc(4, 5)).toBe(9); + expect(arrowFunc(4)).toBe(8); + expect(arrowFunc("hf")).toBe("hfhf"); + expect(arrowFunc(true)).toBe(2); + expect(arrowFunc()).toBeNaN(); +}); - function func5( +test("parameter with a function default value", () => { + function func( a = function () { return 5; } @@ -77,60 +83,61 @@ try { return a(); } - const arrowFunc5 = ( + const arrowFunc = ( a = function () { return 5; } ) => a(); - assert(func5() === 5); - assert( - func5(function () { + expect(func()).toBe(5); + expect( + func(function () { return 10; - }) === 10 - ); - assert(func5(() => 10) === 10); - assert(arrowFunc5() === 5); - assert( - arrowFunc5(function () { + }) + ).toBe(10); + expect(func(() => 10)).toBe(10); + + expect(arrowFunc()).toBe(5); + expect( + arrowFunc(function () { return 10; - }) === 10 - ); - assert(arrowFunc5(() => 10) === 10); + }) + ).toBe(10); + expect(arrowFunc(() => 10)).toBe(10); +}); - function func6(a = () => 5) { +test("parameter with an arrow function default vlaue", () => { + function func(a = () => 5) { return a(); } - const arrowFunc6 = (a = () => 5) => a(); + const arrowFunc = (a = () => 5) => a(); - assert(func6() === 5); - assert( - func6(function () { + expect(func()).toBe(5); + expect( + func(function () { return 10; - }) === 10 - ); - assert(func6(() => 10) === 10); - assert(arrowFunc6() === 5); - assert( - arrowFunc6(function () { + }) + ).toBe(10); + expect(func(() => 10)).toBe(10); + expect(arrowFunc()).toBe(5); + expect( + arrowFunc(function () { return 10; - }) === 10 - ); - assert(arrowFunc6(() => 10) === 10); + }) + ).toBe(10); + expect(arrowFunc(() => 10)).toBe(10); +}); - function func7(a = { foo: "bar" }) { +test("parameter with an object default value", () => { + function func(a = { foo: "bar" }) { return a.foo; } - const arrowFunc7 = (a = { foo: "bar" }) => a.foo; - - assert(func7() === "bar"); - assert(func7({ foo: "baz" }) === "baz"); - assert(arrowFunc7() === "bar"); - assert(arrowFunc7({ foo: "baz" }) === "baz"); + const arrowFunc = (a = { foo: "bar" }) => a.foo; - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect(func()).toBe("bar"); + expect(func({ foo: "baz" })).toBe("baz"); + expect(arrowFunc()).toBe("bar"); + expect(arrowFunc({ foo: "baz" })).toBe("baz"); +}); diff --git a/Libraries/LibJS/Tests/functions/function-hoisting.js b/Libraries/LibJS/Tests/functions/function-hoisting.js index 0df5f3ddd0..5a10f210c3 100644 --- a/Libraries/LibJS/Tests/functions/function-hoisting.js +++ b/Libraries/LibJS/Tests/functions/function-hoisting.js @@ -1,24 +1,29 @@ -load("test-common.js"); - -try { - var callHoisted = hoisted(); +test("basic functionality", () => { + let callHoisted = hoisted(); function hoisted() { - return true; + return "foo"; } - assert(hoisted() === true); - assert(callHoisted === true); + expect(hoisted()).toBe("foo"); + expect(callHoisted).toBe("foo"); +}); +// First two calls produce a ReferenceError, but the declarations should be hoisted +test.skip("functions are hoisted across non-lexical scopes", () => { + expect(scopedHoisted).toBeUndefined(); + expect(callScopedHoisted).toBeUndefined(); { var callScopedHoisted = scopedHoisted(); function scopedHoisted() { return "foo"; } - assert(scopedHoisted() === "foo"); - assert(callScopedHoisted === "foo"); + expect(scopedHoisted()).toBe("foo"); + expect(callScopedHoisted).toBe("foo"); } - assert(scopedHoisted() === "foo"); - assert(callScopedHoisted === "foo"); + expect(scopedHoisted()).toBe("foo"); + expect(callScopedHoisted).toBe("foo"); +}); +test("functions are not hoisted across lexical scopes", () => { const test = () => { var iife = (function () { return declaredLater(); @@ -28,10 +33,7 @@ try { } return iife; }; - assert(typeof declaredLater === "undefined"); - assert(test() === "yay"); - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect(() => declaredLater).toThrow(ReferenceError); + expect(test()).toBe("yay"); +}); diff --git a/Libraries/LibJS/Tests/functions/function-length.js b/Libraries/LibJS/Tests/functions/function-length.js index 481e436f10..36858526c8 100644 --- a/Libraries/LibJS/Tests/functions/function-length.js +++ b/Libraries/LibJS/Tests/functions/function-length.js @@ -1,27 +1,23 @@ -load("test-common.js"); - -try { +test("basic functionality", () => { function foo() {} - assert(foo.length === 0); - assert((foo.length = 5) === 5); - assert(foo.length === 0); + expect(foo).toHaveLength(0); + expect((foo.length = 5)).toBe(5); + expect(foo).toHaveLength(0); function bar(a, b, c) {} - assert(bar.length === 3); - assert((bar.length = 5) === 5); - assert(bar.length === 3); + expect(bar).toHaveLength(3); + expect((bar.length = 5)).toBe(5); + expect(bar).toHaveLength(3); +}); +test("functions with special parameter lists", () => { function baz(a, b = 1, c) {} - assert(baz.length === 1); - assert((baz.length = 5) === 5); - assert(baz.length === 1); + expect(baz).toHaveLength(1); + expect((baz.length = 5)).toBe(5); + expect(baz).toHaveLength(1); function qux(a, b, ...c) {} - assert(qux.length === 2); - assert((qux.length = 5) === 5); - assert(qux.length === 2); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect(qux).toHaveLength(2); + expect((qux.length = 2)).toBe(2); + expect(qux).toHaveLength(2); +}); diff --git a/Libraries/LibJS/Tests/functions/function-missing-arg.js b/Libraries/LibJS/Tests/functions/function-missing-arg.js index a9d77e7514..af4d514a6e 100644 --- a/Libraries/LibJS/Tests/functions/function-missing-arg.js +++ b/Libraries/LibJS/Tests/functions/function-missing-arg.js @@ -1,15 +1,10 @@ -load("test-common.js"); +test("basic functionality", () => { + function foo(a, b) { + return a + b; + } -function foo(a, b) { - return a + b; -} - -try { - assert(isNaN(foo()) === true); - assert(isNaN(foo(1)) === true); - assert(foo(2, 3) === 5); - assert(foo(2, 3, 4) === 5); - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect(foo()).toBeNaN(); + expect(foo(1)).toBeNaN(); + expect(foo(2, 3)).toBe(5); + expect(foo(2, 3, 4)).toBe(5); +}); diff --git a/Libraries/LibJS/Tests/functions/function-name.js b/Libraries/LibJS/Tests/functions/function-name.js index 3a8fbe7e3a..052669c3cb 100644 --- a/Libraries/LibJS/Tests/functions/function-name.js +++ b/Libraries/LibJS/Tests/functions/function-name.js @@ -1,45 +1,50 @@ -load("test-common.js"); +test("basic functionality", () => { + expect(function () {}.name).toBe(""); -try { - assert(function () {}.name === ""); - - var foo = function () {}; - assert(foo.name === "foo"); - assert((foo.name = "bar") === "bar"); - assert(foo.name === "foo"); - - var a, b; + function bar() {} + expect(bar.name).toBe("bar"); + expect((bar.name = "baz")).toBe("baz"); + expect(bar.name).toBe("bar"); +}); + +test("function assigned to variable", () => { + let foo = function () {}; + expect(foo.name).toBe("foo"); + expect((foo.name = "bar")).toBe("bar"); + expect(foo.name).toBe("foo"); + + let a, b; a = b = function () {}; - assert(a.name === "b"); - assert(b.name === "b"); - - var arr = [function () {}, function () {}, function () {}]; - assert(arr[0].name === "arr"); - assert(arr[1].name === "arr"); - assert(arr[2].name === "arr"); - - var f; - var o = { a: function () {} }; - assert(o.a.name === "a"); + expect(a.name).toBe("b"); + expect(b.name).toBe("b"); +}); + +test("functions in array assigned to variable", () => { + const arr = [function () {}, function () {}, function () {}]; + expect(arr[0].name).toBe("arr"); + expect(arr[1].name).toBe("arr"); + expect(arr[2].name).toBe("arr"); +}); + +test("functions in objects", () => { + let f; + let o = { a: function () {} }; + + expect(o.a.name).toBe("a"); f = o.a; - assert(f.name === "a"); - assert(o.a.name === "a"); + expect(f.name).toBe("a"); + expect(o.a.name).toBe("a"); + o = { ...o, b: f }; - assert(o.a.name === "a"); - assert(o.b.name === "a"); - o.c = function () {}; - assert(o.c.name === "c"); + expect(o.a.name).toBe("a"); + expect(o.b.name).toBe("a"); - function bar() {} - assert(bar.name === "bar"); - assert((bar.name = "baz") === "baz"); - assert(bar.name === "bar"); - - assert(console.log.name === "log"); - assert((console.log.name = "warn") === "warn"); - assert(console.log.name === "log"); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + o.c = function () {}; + expect(o.c.name).toBe("c"); +}); + +test("names of native functions", () => { + expect(console.debug.name).toBe("debug"); + expect((console.debug.name = "warn")).toBe("warn"); + expect(console.debug.name).toBe("debug"); +}); diff --git a/Libraries/LibJS/Tests/functions/function-rest-params.js b/Libraries/LibJS/Tests/functions/function-rest-params.js index a4a7597d68..144880e865 100644 --- a/Libraries/LibJS/Tests/functions/function-rest-params.js +++ b/Libraries/LibJS/Tests/functions/function-rest-params.js @@ -1,57 +1,47 @@ -load("test-common.js"); - -try { +test("rest parameter with no arguments", () => { function foo(...a) { - assert(a instanceof Array); - assert(a.length === 0); + expect(a).toBeInstanceOf(Array); + expect(a).toHaveLength(0); } foo(); +}); - function foo1(...a) { - assert(a instanceof Array); - assert(a.length === 4); - assert(a[0] === "foo"); - assert(a[1] === 123); - assert(a[2] === undefined); - assert(a[3].foo === "bar"); +test("rest parameter with arguments", () => { + function foo(...a) { + expect(a).toEqual(["foo", 123, undefined, { foo: "bar" }]); } - foo1("foo", 123, undefined, { foo: "bar" }); + foo("foo", 123, undefined, { foo: "bar" }); +}); - function foo2(a, b, ...c) { - assert(a === "foo"); - assert(b === 123); - assert(c instanceof Array); - assert(c.length === 0); +test("rest parameter after normal parameters with no arguments", () => { + function foo(a, b, ...c) { + expect(a).toBe("foo"); + expect(b).toBe(123); + expect(c).toEqual([]); } - foo2("foo", 123); + foo("foo", 123); +}); - function foo3(a, b, ...c) { - assert(a === "foo"); - assert(b === 123); - assert(c instanceof Array); - assert(c.length === 2); - assert(c[0] === undefined); - assert(c[1].foo === "bar"); +test("rest parameter after normal parameters with arguments", () => { + function foo(a, b, ...c) { + expect(a).toBe("foo"); + expect(b).toBe(123); + expect(c).toEqual([undefined, { foo: "bar" }]); } - foo3("foo", 123, undefined, { foo: "bar" }); + foo("foo", 123, undefined, { foo: "bar" }); +}); - var foo = (...a) => { - assert(a instanceof Array); - assert(a.length === 0); +test("basic arrow function rest parameters", () => { + let foo = (...a) => { + expect(a).toBeInstanceOf(Array); + expect(a).toHaveLength(0); }; foo(); - var foo = (a, b, ...c) => { - assert(a === "foo"); - assert(b === 123); - assert(c instanceof Array); - assert(c.length === 2); - assert(c[0] === undefined); - assert(c[1].foo === "bar"); + foo = (a, b, ...c) => { + expect(a).toBe("foo"); + expect(b).toBe(123); + expect(c).toEqual([undefined, { foo: "bar" }]); }; foo("foo", 123, undefined, { foo: "bar" }); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +}); diff --git a/Libraries/LibJS/Tests/functions/function-spread.js b/Libraries/LibJS/Tests/functions/function-spread.js index e3fe7c520f..abe3d4bc5d 100644 --- a/Libraries/LibJS/Tests/functions/function-spread.js +++ b/Libraries/LibJS/Tests/functions/function-spread.js @@ -1,30 +1,20 @@ -load("test-common.js"); - -try { +test("basic functionality", () => { const sum = (a, b, c) => a + b + c; const a = [1, 2, 3]; - assert(sum(...a) === 6); - assert(sum(1, ...a) === 4); - assert(sum(...a, 10) === 6); + expect(sum(...a)).toBe(6); + expect(sum(1, ...a)).toBe(4); + expect(sum(...a, 10)).toBe(6); const foo = (a, b, c) => c; const o = { bar: [1, 2, 3] }; - assert(foo(...o.bar) === 3); - assert(foo(..."abc") === "c"); - - assertThrowsError( - () => { - [...1]; - }, - { - error: TypeError, - message: "1 is not iterable", - } - ); + expect(foo(...o.bar)).toBe(3); + expect(foo(..."abc")).toBe("c"); +}); - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +test("spreading non iterable", () => { + expect(() => { + [...1]; + }).toThrowWithMessage(TypeError, "1 is not iterable"); +}); diff --git a/Libraries/LibJS/Tests/functions/function-strict-mode.js b/Libraries/LibJS/Tests/functions/function-strict-mode.js index 44385ec32d..46c93b1e5c 100644 --- a/Libraries/LibJS/Tests/functions/function-strict-mode.js +++ b/Libraries/LibJS/Tests/functions/function-strict-mode.js @@ -1,52 +1,53 @@ -load("test-common.js"); - -try { - (function () { - assert(!isStrictMode()); - })(); - - (function () { +// This file must not be formatted by prettier. Make sure your IDE +// respects the .prettierignore file! + +test("non strict-mode by default", () => { + expect(isStrictMode()).toBeFalse(); +}); + +test("use strict with double quotes", () => { + "use strict"; + expect(isStrictMode()).toBeTrue(); +}); + +test("use strict with single quotes", () => { + 'use strict'; + expect(isStrictMode()).toBeTrue(); +}); + +test("use strict with backticks does not yield strict mode", () => { + `use strict`; + expect(isStrictMode()).toBeFalse(); +}); + +test("use strict with single quotes after statement does not yield strict mode code", () => { + ;'use strict'; + expect(isStrictMode()).toBeFalse(); +}); + +test("use strict with double quotes after statement does not yield strict mode code", () => { + ;"use strict"; + expect(isStrictMode()).toBeFalse(); +}); + +test("strict mode propogates down the scope chain", () => { + "use strict"; + expect(isStrictMode()).toBeTrue(); + (function() { + expect(isStrictMode()).toBeTrue(); + })(); +}); + +test("strict mode does not propogate up the scope chain", () => { + expect(isStrictMode()).toBeFalse(); + (function() { "use strict"; - assert(isStrictMode()); - })(); - - (function () { - "use strict"; - assert(isStrictMode()); - })(); - - (function () { - `use strict`; - assert(!isStrictMode()); - })(); - - (function () { - ("use strict"); - assert(!isStrictMode()); - })(); - - (function () { - ("use strict"); - assert(!isStrictMode()); - })(); - - (function () { - "use strict"; - (function () { - assert(isStrictMode()); - })(); - })(); - - (function () { - assert(!isStrictMode()); - (function () { - "use strict"; - assert(isStrictMode()); - })(); - assert(!isStrictMode()); + expect(isStrictMode()).toBeTrue(); })(); + expect(isStrictMode()).toBeFalse(); +}); - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +test('only the string "use strict" yields strict mode code', () => { + "use stric"; + expect(isStrictMode()).toBeFalse(); +}); diff --git a/Libraries/LibJS/Tests/functions/function-this-in-arguments.js b/Libraries/LibJS/Tests/functions/function-this-in-arguments.js index 4fb2a3248f..69d58310d5 100644 --- a/Libraries/LibJS/Tests/functions/function-this-in-arguments.js +++ b/Libraries/LibJS/Tests/functions/function-this-in-arguments.js @@ -1,17 +1,16 @@ -load("test-common.js"); - -try { - assert(typeof this === "object"); - assert(this === globalThis); +test("basic functionality", () => { + expect(typeof this).toBe("object"); + expect(this).toBe(globalThis); +}); +test("this inside instantiated functions is not globalThis", () => { + let functionThis; function Foo() { this.x = 5; - assert(typeof this === "object"); - assert(this.x === 5); + functionThis = this; } new Foo(); - console.log("PASS"); -} catch (err) { - console.log("FAIL: " + err); -} + expect(typeof functionThis).toBe("object"); + expect(functionThis.x).toBe(5); +}); diff --git a/Libraries/LibJS/Tests/loops/continue-basic.js b/Libraries/LibJS/Tests/loops/continue-basic.js index 4a9ad656cf..73e7dce40f 100644 --- a/Libraries/LibJS/Tests/loops/continue-basic.js +++ b/Libraries/LibJS/Tests/loops/continue-basic.js @@ -1,11 +1,10 @@ -load("test-common.js"); - -try { +test("basic functionality", () => { var j = 0; for (var i = 0; i < 9; ++i) { - if (i == 3) continue; + if (i == 3) { + continue; + } ++j; } - assert(j == 8); - console.log("PASS"); -} catch {} + expect(j).toBe(8); +}); diff --git a/Libraries/LibJS/Tests/loops/do-while-basic.js b/Libraries/LibJS/Tests/loops/do-while-basic.js index b701cceb9a..943490996b 100644 --- a/Libraries/LibJS/Tests/loops/do-while-basic.js +++ b/Libraries/LibJS/Tests/loops/do-while-basic.js @@ -1,18 +1,14 @@ -load("test-common.js"); - -try { - var number = 0; +test("basic functionality", () => { + let number = 0; do { number++; } while (number < 9); - assert(number === 9); + expect(number).toBe(9); +}); - number = 0; +test("no braces", () => { + let number = 0; do number++; while (number < 3); - assert(number === 3); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect(number).toBe(3); +}); diff --git a/Libraries/LibJS/Tests/loops/for-basic.js b/Libraries/LibJS/Tests/loops/for-basic.js index d0041040d2..a6d7e85e99 100644 --- a/Libraries/LibJS/Tests/loops/for-basic.js +++ b/Libraries/LibJS/Tests/loops/for-basic.js @@ -1,24 +1,15 @@ -load("test-common.js"); - -try { - var a = []; - for (var i = 0; i < 3; ++i) { +test("basic functionality", () => { + let a = []; + for (let i = 0; i < 3; ++i) { a.push(i); } - assert(a.length === 3); - assert(a[0] === 0); - assert(a[1] === 1); - assert(a[2] === 2); + expect(a).toEqual([0, 1, 2]); +}); - for (; a.length < 6; ) { +test("only condition", () => { + let a = []; + for (; a.length < 3; ) { a.push("x"); } - assert(a.length === 6); - assert(a[3] === "x"); - assert(a[4] === "x"); - assert(a[5] === "x"); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect(a).toEqual(["x", "x", "x"]); +}); diff --git a/Libraries/LibJS/Tests/loops/for-head-errors.js b/Libraries/LibJS/Tests/loops/for-head-errors.js index a2ddecc989..94fea40f5d 100644 --- a/Libraries/LibJS/Tests/loops/for-head-errors.js +++ b/Libraries/LibJS/Tests/loops/for-head-errors.js @@ -1,45 +1,23 @@ -load("test-common.js"); +test("using undefined variable in initializer", () => { + expect(() => { + for (let i = foo; i < 100; ++i) {} + }).toThrowWithMessage(ReferenceError, "'foo' is not defined"); +}); -try { - assertThrowsError( - () => { - for (var i = foo; i < 100; ++i) { - assertNotReached(); - } - }, - { - error: ReferenceError, - message: "'foo' is not defined", - } - ); +test("using undefined variable in condition", () => { + expect(() => { + for (let i = 0; i < foo; ++i) {} + }).toThrowWithMessage(ReferenceError, "'foo' is not defined"); +}); - assertThrowsError( - () => { - for (var i = 0; i < foo; ++i) { - assertNotReached(); - } - }, - { - error: ReferenceError, - message: "'foo' is not defined", - } - ); +test("using undefined variable in updater", () => { + let loopCount = 0; - var loopCount = 0; - assertThrowsError( - () => { - for (var i = 0; i < 100; ++foo) { - loopCount++; - } - }, - { - error: ReferenceError, - message: "'foo' is not defined", + expect(() => { + for (let i = 0; i < 100; ++foo) { + loopCount++; } - ); - assert(loopCount === 1); + }).toThrowWithMessage(ReferenceError, "'foo' is not defined"); - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect(loopCount).toBe(1); +}); diff --git a/Libraries/LibJS/Tests/loops/for-in-basic.js b/Libraries/LibJS/Tests/loops/for-in-basic.js index f74382c21f..f0e4fc1f51 100644 --- a/Libraries/LibJS/Tests/loops/for-in-basic.js +++ b/Libraries/LibJS/Tests/loops/for-in-basic.js @@ -1,47 +1,45 @@ -load("test-common.js"); +test("iterate through empty string", () => { + const a = []; + for (const property in "") { + a.push(property); + } + expect(a).toEqual([]); +}); -try { - assertVisitsAll(visit => { - for (const property in "") { - visit(property); - } - }, []); +test("iterate through number", () => { + const a = []; + for (const property in 123) { + a.push(property); + } + expect(a).toEqual([]); +}); - assertVisitsAll(visit => { - for (const property in 123) { - visit(property); - } - }, []); +test("iterate through empty object", () => { + const a = []; + for (const property in {}) { + a.push(property); + } + expect(a).toEqual([]); +}); - assertVisitsAll(visit => { - for (const property in {}) { - visit(property); - } - }, []); +test("iterate through string", () => { + const a = []; + for (const property in "hello") { + a.push(property); + } + expect(a).toEqual(["0", "1", "2", "3", "4"]); +}); - assertVisitsAll( - visit => { - for (const property in "hello") { - visit(property); - } - }, - ["0", "1", "2", "3", "4"] - ); - - assertVisitsAll( - visit => { - for (const property in { a: 1, b: 2, c: 2 }) { - visit(property); - } - }, - ["a", "b", "c"] - ); +test("iterate through object", () => { + const a = []; + for (const property in { a: 1, b: 2, c: 2 }) { + a.push(property); + } + expect(a).toEqual(["a", "b", "c"]); +}); +test("use already-declared variable", () => { var property; for (property in "abc"); - assert(property === "2"); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect(property).toBe("2"); +}); diff --git a/Libraries/LibJS/Tests/loops/for-no-curlies.js b/Libraries/LibJS/Tests/loops/for-no-curlies.js index 4cae046294..a8c94ed19f 100644 --- a/Libraries/LibJS/Tests/loops/for-no-curlies.js +++ b/Libraries/LibJS/Tests/loops/for-no-curlies.js @@ -1,12 +1,5 @@ -load("test-common.js"); - -try { - var number = 0; - - for (var i = 0; i < 3; ++i) for (var j = 0; j < 3; ++j) number++; - - assert(number === 9); - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +test("basic functionality", () => { + let number = 0; + for (let i = 0; i < 3; ++i) for (let j = 0; j < 3; ++j) number++; + expect(number).toBe(9); +}); diff --git a/Libraries/LibJS/Tests/loops/for-of-basic.js b/Libraries/LibJS/Tests/loops/for-of-basic.js index 4669a6c9b6..b415f0e753 100644 --- a/Libraries/LibJS/Tests/loops/for-of-basic.js +++ b/Libraries/LibJS/Tests/loops/for-of-basic.js @@ -1,60 +1,47 @@ -load("test-common.js"); +describe("correct behavior", () => { + test("iterate through array", () => { + const a = []; + for (const num of [1, 2, 3]) { + a.push(num); + } + expect(a).toEqual([1, 2, 3]); + }); -try { - assertThrowsError( - () => { - for (const _ of 123) { - } - }, - { - error: TypeError, - message: "for..of right-hand side must be iterable", + test("iterate through string", () => { + const a = []; + for (const char of "hello") { + a.push(char); } - ); + expect(a).toEqual(["h", "e", "l", "l", "o"]); + }); - assertThrowsError( - () => { - for (const _ of { foo: 1, bar: 2 }) { - } - }, - { - error: TypeError, - message: "for..of right-hand side must be iterable", + test("iterate through string object", () => { + const a = []; + for (const char of new String("hello")) { + a.push(char); } - ); + expect(a).toEqual(["h", "e", "l", "l", "o"]); + }); - assertVisitsAll( - visit => { - for (const num of [1, 2, 3]) { - visit(num); - } - }, - [1, 2, 3] - ); + test("use already-declared variable", () => { + var char; + for (char of "abc"); + expect(char).toBe("c"); + }); +}); - assertVisitsAll( - visit => { - for (const char of "hello") { - visit(char); +describe("errors", () => { + test("right hand side is a primitive", () => { + expect(() => { + for (const _ of 123) { } - }, - ["h", "e", "l", "l", "o"] - ); + }).toThrowWithMessage(TypeError, "for..of right-hand side must be iterable"); + }); - assertVisitsAll( - visit => { - for (const char of new String("hello")) { - visit(char); + test("right hand side is an object", () => { + expect(() => { + for (const _ of { foo: 1, bar: 2 }) { } - }, - ["h", "e", "l", "l", "o"] - ); - - var char; - for (char of "abc"); - assert(char === "c"); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + }).toThrowWithMessage(TypeError, "for..of right-hand side must be iterable"); + }); +}); diff --git a/Libraries/LibJS/Tests/loops/for-scopes.js b/Libraries/LibJS/Tests/loops/for-scopes.js index 182edde831..0fae8fc501 100644 --- a/Libraries/LibJS/Tests/loops/for-scopes.js +++ b/Libraries/LibJS/Tests/loops/for-scopes.js @@ -1,22 +1,18 @@ -load("test-common.js"); - -try { +test("var in for head", () => { for (var v = 5; false; ); - assert(v == 5); - - const options = { error: ReferenceError }; + expect(v).toBe(5); +}); - assertThrowsError(() => { - for (let l = 5; false; ); +test("let in for head", () => { + for (let l = 5; false; ); + expect(() => { l; - }, options); + }).toThrowWithMessage(ReferenceError, "'l' is not defined"); +}); - assertThrowsError(() => { - for (const c = 5; false; ); +test("const in for head", () => { + for (const c = 5; false; ); + expect(() => { c; - }, options); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + }).toThrowWithMessage(ReferenceError, "'c' is not defined"); +}); diff --git a/Libraries/LibJS/Tests/loops/while-basic.js b/Libraries/LibJS/Tests/loops/while-basic.js index 4932bb830f..cd1ded3e13 100644 --- a/Libraries/LibJS/Tests/loops/while-basic.js +++ b/Libraries/LibJS/Tests/loops/while-basic.js @@ -1,21 +1,19 @@ -load("test-common.js"); - -try { - var number = 0; +test("basic functionality", () => { + let number = 0; while (number < 9) { number++; } - assert(number === 9); + expect(number).toBe(9); +}); - number = 0; +test("no braces", () => { + let number = 0; while (number < 3) number++; - assert(number === 3); + expect(number).toBe(3); +}); +test("does not loop when initially false", () => { while (false) { - assertNotReached(); + expect().fail(); } - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +}); diff --git a/Libraries/LibJS/Tests/new-expression.js b/Libraries/LibJS/Tests/new-expression.js index 7bc892ae68..eedbd671b3 100644 --- a/Libraries/LibJS/Tests/new-expression.js +++ b/Libraries/LibJS/Tests/new-expression.js @@ -1,3 +1,6 @@ +// This file must not be formatted by prettier. Make sure your IDE +// respects the .prettierignore file! + test("new-expression parsing", () => { function Foo() { this.x = 1; @@ -6,13 +9,15 @@ test("new-expression parsing", () => { let foo = new Foo(); expect(foo.x).toBe(1); - foo = new Foo(); + foo = new Foo expect(foo.x).toBe(1); - foo = new Foo(); + foo = new + Foo + (); expect(foo.x).toBe(1); - foo = new Foo() + 2; + foo = new Foo + 2 expect(foo).toBe("[object Object]2"); }); @@ -26,10 +31,11 @@ test("new-expressions with object keys", () => { foo = new a.b(); expect(foo.x).toBe(2); - foo = new a.b(); + foo = new a.b; expect(foo.x).toBe(2); - foo = new a.b(); + foo = new + a.b(); expect(foo.x).toBe(2); }); diff --git a/Libraries/LibJS/Tests/operators/assignment-operators.js b/Libraries/LibJS/Tests/operators/assignment-operators.js index ef39d3a3ac..c236f628cc 100644 --- a/Libraries/LibJS/Tests/operators/assignment-operators.js +++ b/Libraries/LibJS/Tests/operators/assignment-operators.js @@ -1,61 +1,55 @@ -load("test-common.js"); - -try { - var x; +let x; +test("basic functionality", () => { x = 1; - assert((x = 2) === 2); - assert(x === 2); + expect((x = 2)).toBe(2); + expect(x).toBe(2); x = 1; - assert((x += 2) === 3); - assert(x === 3); + expect((x += 2)).toBe(3); + expect(x).toBe(3); x = 3; - assert((x -= 2) === 1); - assert(x === 1); + expect((x -= 2)).toBe(1); + expect(x).toBe(1); x = 3; - assert((x *= 2) === 6); - assert(x === 6); + expect((x *= 2)).toBe(6); + expect(x).toBe(6); x = 6; - assert((x /= 2) === 3); - assert(x === 3); + expect((x /= 2)).toBe(3); + expect(x).toBe(3); x = 6; - assert((x %= 4) === 2); - assert(x === 2); + expect((x %= 4)).toBe(2); + expect(x).toBe(2); x = 2; - assert((x **= 3) === 8); - assert(x === 8); + expect((x **= 3)).toBe(8); + expect(x).toBe(8); x = 3; - assert((x &= 2) === 2); - assert(x === 2); + expect((x &= 2)).toBe(2); + expect(x).toBe(2); x = 3; - assert((x |= 4) === 7); - assert(x === 7); + expect((x |= 4)).toBe(7); + expect(x).toBe(7); x = 6; - assert((x ^= 2) === 4); - assert(x === 4); + expect((x ^= 2)).toBe(4); + expect(x).toBe(4); x = 2; - assert((x <<= 2) === 8); - assert(x === 8); + expect((x <<= 2)).toBe(8); + expect(x).toBe(8); x = 8; - assert((x >>= 2) === 2); - assert(x === 2); + expect((x >>= 2)).toBe(2); + expect(x).toBe(2); x = -(2 ** 32 - 10); - assert((x >>>= 2) === 2); - assert(x === 2); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect((x >>>= 2)).toBe(2); + expect(x).toBe(2); +}); diff --git a/Libraries/LibJS/Tests/operators/binary-bitwise-left-shift.js b/Libraries/LibJS/Tests/operators/binary-bitwise-left-shift.js index 713c156670..6955b7b791 100644 --- a/Libraries/LibJS/Tests/operators/binary-bitwise-left-shift.js +++ b/Libraries/LibJS/Tests/operators/binary-bitwise-left-shift.js @@ -1,63 +1,60 @@ -load("test-common.js"); - -try { - assert(0 << 0 === 0); - assert(0 << 1 === 0); - assert(0 << 2 === 0); - assert(0 << 3 === 0); - assert(0 << 4 === 0); - assert(0 << 5 === 0); - - assert(1 << 0 === 1); - assert(1 << 1 === 2); - assert(1 << 2 === 4); - assert(1 << 3 === 8); - assert(1 << 4 === 16); - assert(1 << 5 === 32); - - assert(2 << 0 === 2); - assert(2 << 1 === 4); - assert(2 << 2 === 8); - assert(2 << 3 === 16); - assert(2 << 4 === 32); - assert(2 << 5 === 64); - - assert(3 << 0 === 3); - assert(3 << 1 === 6); - assert(3 << 2 === 12); - assert(3 << 3 === 24); - assert(3 << 4 === 48); - assert(3 << 5 === 96); - - assert(4 << 0 === 4); - assert(4 << 1 === 8); - assert(4 << 2 === 16); - assert(4 << 3 === 32); - assert(4 << 4 === 64); - assert(4 << 5 === 128); - - assert(5 << 0 === 5); - assert(5 << 1 === 10); - assert(5 << 2 === 20); - assert(5 << 3 === 40); - assert(5 << 4 === 80); - assert(5 << 5 === 160); - - var x = 3; - var y = 7; - assert("42" << 6 === 2688); - assert(x << y === 384); - assert(x << [[[[12]]]] === 12288); - assert(undefined << y === 0); - assert("a" << "b" === 0); - assert(null << null === 0); - assert(undefined << undefined === 0); - assert(NaN << NaN === 0); - assert(NaN << 6 === 0); - assert(Infinity << Infinity === 0); - assert(-Infinity << Infinity === 0); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +test("basic numeric shifting", () => { + expect(0 << 0).toBe(0); + expect(0 << 1).toBe(0); + expect(0 << 2).toBe(0); + expect(0 << 3).toBe(0); + expect(0 << 4).toBe(0); + expect(0 << 5).toBe(0); + + expect(1 << 0).toBe(1); + expect(1 << 1).toBe(2); + expect(1 << 2).toBe(4); + expect(1 << 3).toBe(8); + expect(1 << 4).toBe(16); + expect(1 << 5).toBe(32); + + expect(2 << 0).toBe(2); + expect(2 << 1).toBe(4); + expect(2 << 2).toBe(8); + expect(2 << 3).toBe(16); + expect(2 << 4).toBe(32); + expect(2 << 5).toBe(64); + + expect(3 << 0).toBe(3); + expect(3 << 1).toBe(6); + expect(3 << 2).toBe(12); + expect(3 << 3).toBe(24); + expect(3 << 4).toBe(48); + expect(3 << 5).toBe(96); + + expect(4 << 0).toBe(4); + expect(4 << 1).toBe(8); + expect(4 << 2).toBe(16); + expect(4 << 3).toBe(32); + expect(4 << 4).toBe(64); + expect(4 << 5).toBe(128); + + expect(5 << 0).toBe(5); + expect(5 << 1).toBe(10); + expect(5 << 2).toBe(20); + expect(5 << 3).toBe(40); + expect(5 << 4).toBe(80); + expect(5 << 5).toBe(160); +}); + +test("shifting with non-numeric values", () => { + let x = 3; + let y = 7; + + expect("42" << 6).toBe(2688); + expect(x << y).toBe(384); + expect(x << [[[[12]]]]).toBe(12288); + expect(undefined << y).toBe(0); + expect("a" << "b").toBe(0); + expect(null << null).toBe(0); + expect(undefined << undefined).toBe(0); + expect(NaN << NaN).toBe(0); + expect(NaN << 6).toBe(0); + expect(Infinity << Infinity).toBe(0); + expect(-Infinity << Infinity).toBe(0); +}); diff --git a/Libraries/LibJS/Tests/operators/binary-bitwise-or.js b/Libraries/LibJS/Tests/operators/binary-bitwise-or.js index 2274d02217..74edcbd9ec 100644 --- a/Libraries/LibJS/Tests/operators/binary-bitwise-or.js +++ b/Libraries/LibJS/Tests/operators/binary-bitwise-or.js @@ -1,63 +1,60 @@ -load("test-common.js"); - -try { - assert((0 | 0) === 0); - assert((0 | 1) === 1); - assert((0 | 2) === 2); - assert((0 | 3) === 3); - assert((0 | 4) === 4); - assert((0 | 5) === 5); - - assert((1 | 0) === 1); - assert((1 | 1) === 1); - assert((1 | 2) === 3); - assert((1 | 3) === 3); - assert((1 | 4) === 5); - assert((1 | 5) === 5); - - assert((2 | 0) === 2); - assert((2 | 1) === 3); - assert((2 | 2) === 2); - assert((2 | 3) === 3); - assert((2 | 4) === 6); - assert((2 | 5) === 7); - - assert((3 | 0) === 3); - assert((3 | 1) === 3); - assert((3 | 2) === 3); - assert((3 | 3) === 3); - assert((3 | 4) === 7); - assert((3 | 5) === 7); - - assert((4 | 0) === 4); - assert((4 | 1) === 5); - assert((4 | 2) === 6); - assert((4 | 3) === 7); - assert((4 | 4) === 4); - assert((4 | 5) === 5); - - assert((5 | 0) === 5); - assert((5 | 1) === 5); - assert((5 | 2) === 7); - assert((5 | 3) === 7); - assert((5 | 4) === 5); - assert((5 | 5) === 5); - - var x = 3; - var y = 7; - assert(("42" | 6) === 46); - assert((x | y) === 7); - assert((x | [[[[12]]]]) === 15); - assert((undefined | y) === 7); - assert(("a" | "b") === 0); - assert((null | null) === 0); - assert((undefined | undefined) === 0); - assert((NaN | NaN) === 0); - assert((NaN | 6) === 6); - assert((Infinity | Infinity) === 0); - assert((-Infinity | Infinity) === 0); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +test("basic numeric or", () => { + expect(0 | 0).toBe(0); + expect(0 | 1).toBe(1); + expect(0 | 2).toBe(2); + expect(0 | 3).toBe(3); + expect(0 | 4).toBe(4); + expect(0 | 5).toBe(5); + + expect(1 | 0).toBe(1); + expect(1 | 1).toBe(1); + expect(1 | 2).toBe(3); + expect(1 | 3).toBe(3); + expect(1 | 4).toBe(5); + expect(1 | 5).toBe(5); + + expect(2 | 0).toBe(2); + expect(2 | 1).toBe(3); + expect(2 | 2).toBe(2); + expect(2 | 3).toBe(3); + expect(2 | 4).toBe(6); + expect(2 | 5).toBe(7); + + expect(3 | 0).toBe(3); + expect(3 | 1).toBe(3); + expect(3 | 2).toBe(3); + expect(3 | 3).toBe(3); + expect(3 | 4).toBe(7); + expect(3 | 5).toBe(7); + + expect(4 | 0).toBe(4); + expect(4 | 1).toBe(5); + expect(4 | 2).toBe(6); + expect(4 | 3).toBe(7); + expect(4 | 4).toBe(4); + expect(4 | 5).toBe(5); + + expect(5 | 0).toBe(5); + expect(5 | 1).toBe(5); + expect(5 | 2).toBe(7); + expect(5 | 3).toBe(7); + expect(5 | 4).toBe(5); + expect(5 | 5).toBe(5); +}); + +test("or with non-numeric values", () => { + let x = 3; + let y = 7; + + expect("42" | 6).toBe(46); + expect(x | y).toBe(7); + expect(x | [[[[12]]]]).toBe(15); + expect(undefined | y).toBe(7); + expect("a" | "b").toBe(0); + expect(null | null).toBe(0); + expect(undefined | undefined).toBe(0); + expect(NaN | NaN).toBe(0); + expect(NaN | 6).toBe(6); + expect(Infinity | Infinity).toBe(0); + expect(-Infinity | Infinity).toBe(0); +}); diff --git a/Libraries/LibJS/Tests/operators/binary-bitwise-right-shift.js b/Libraries/LibJS/Tests/operators/binary-bitwise-right-shift.js index 96e5cfb31d..ec8982b0ae 100644 --- a/Libraries/LibJS/Tests/operators/binary-bitwise-right-shift.js +++ b/Libraries/LibJS/Tests/operators/binary-bitwise-right-shift.js @@ -1,63 +1,62 @@ -load("test-common.js"); - -try { - assert(0 >> 0 === 0); - assert(0 >> 1 === 0); - assert(0 >> 2 === 0); - assert(0 >> 3 === 0); - assert(0 >> 4 === 0); - assert(0 >> 5 === 0); - - assert(1 >> 0 === 1); - assert(1 >> 1 === 0); - assert(1 >> 2 === 0); - assert(1 >> 3 === 0); - assert(1 >> 4 === 0); - assert(1 >> 5 === 0); - - assert(5 >> 0 === 5); - assert(5 >> 1 === 2); - assert(5 >> 2 === 1); - assert(5 >> 3 === 0); - assert(5 >> 4 === 0); - assert(5 >> 5 === 0); - - assert(42 >> 0 === 42); - assert(42 >> 1 === 21); - assert(42 >> 2 === 10); - assert(42 >> 3 === 5); - assert(42 >> 4 === 2); - assert(42 >> 5 === 1); - - assert(-1 >> 0 === -1); - assert(-1 >> 1 === -1); - assert(-1 >> 2 === -1); - assert(-1 >> 3 === -1); - assert(-1 >> 4 === -1); - assert(-1 >> 5 === -1); - - assert(-5 >> 0 === -5); - assert(-5 >> 1 === -3); - assert(-5 >> 2 === -2); - assert(-5 >> 3 === -1); - assert(-5 >> 4 === -1); - assert(-5 >> 5 === -1); - - var x = 67; - var y = 4; - assert("42" >> 3 === 5); - assert(x >> y === 4); - assert(x >> [[[[5]]]] === 2); - assert(undefined >> y === 0); - assert("a" >> "b" === 0); - assert(null >> null === 0); - assert(undefined >> undefined === 0); - assert(NaN >> NaN === 0); - assert(6 >> NaN === 6); - assert(Infinity >> Infinity === 0); - assert(-Infinity >> Infinity === 0); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +test("basic numeric shifting", () => { + expect(0 >> 0).toBe(0); + expect(0 >> 1).toBe(0); + expect(0 >> 2).toBe(0); + expect(0 >> 3).toBe(0); + expect(0 >> 4).toBe(0); + expect(0 >> 5).toBe(0); + + expect(1 >> 0).toBe(1); + expect(1 >> 1).toBe(0); + expect(1 >> 2).toBe(0); + expect(1 >> 3).toBe(0); + expect(1 >> 4).toBe(0); + expect(1 >> 5).toBe(0); + + expect(5 >> 0).toBe(5); + expect(5 >> 1).toBe(2); + expect(5 >> 2).toBe(1); + expect(5 >> 3).toBe(0); + expect(5 >> 4).toBe(0); + expect(5 >> 5).toBe(0); + + expect(42 >> 0).toBe(42); + expect(42 >> 1).toBe(21); + expect(42 >> 2).toBe(10); + expect(42 >> 3).toBe(5); + expect(42 >> 4).toBe(2); + expect(42 >> 5).toBe(1); +}); + +test("numeric shifting with negative lhs values", () => { + expect(-1 >> 0).toBe(-1); + expect(-1 >> 1).toBe(-1); + expect(-1 >> 2).toBe(-1); + expect(-1 >> 3).toBe(-1); + expect(-1 >> 4).toBe(-1); + expect(-1 >> 5).toBe(-1); + + expect(-5 >> 0).toBe(-5); + expect(-5 >> 1).toBe(-3); + expect(-5 >> 2).toBe(-2); + expect(-5 >> 3).toBe(-1); + expect(-5 >> 4).toBe(-1); + expect(-5 >> 5).toBe(-1); +}); + +test("shifting with non-numeric values", () => { + let x = 67; + let y = 4; + + expect("42" >> 3).toBe(5); + expect(x >> y).toBe(4); + expect(x >> [[[[5]]]]).toBe(2); + expect(undefined >> y).toBe(0); + expect("a" >> "b").toBe(0); + expect(null >> null).toBe(0); + expect(undefined >> undefined).toBe(0); + expect(NaN >> NaN).toBe(0); + expect(6 >> NaN).toBe(6); + expect(Infinity >> Infinity).toBe(0); + expect(-Infinity >> Infinity).toBe(0); +}); diff --git a/Libraries/LibJS/Tests/operators/binary-bitwise-unsigned-right-shift.js b/Libraries/LibJS/Tests/operators/binary-bitwise-unsigned-right-shift.js index 30303672e9..cddad0eb7a 100644 --- a/Libraries/LibJS/Tests/operators/binary-bitwise-unsigned-right-shift.js +++ b/Libraries/LibJS/Tests/operators/binary-bitwise-unsigned-right-shift.js @@ -1,63 +1,62 @@ -load("test-common.js"); - -try { - assert(0 >>> 0 === 0); - assert(0 >>> 1 === 0); - assert(0 >>> 2 === 0); - assert(0 >>> 3 === 0); - assert(0 >>> 4 === 0); - assert(0 >>> 5 === 0); - - assert(1 >>> 0 === 1); - assert(1 >>> 1 === 0); - assert(1 >>> 2 === 0); - assert(1 >>> 3 === 0); - assert(1 >>> 4 === 0); - assert(1 >>> 5 === 0); - - assert(5 >>> 0 === 5); - assert(5 >>> 1 === 2); - assert(5 >>> 2 === 1); - assert(5 >>> 3 === 0); - assert(5 >>> 4 === 0); - assert(5 >>> 5 === 0); - - assert(42 >>> 0 === 42); - assert(42 >>> 1 === 21); - assert(42 >>> 2 === 10); - assert(42 >>> 3 === 5); - assert(42 >>> 4 === 2); - assert(42 >>> 5 === 1); - - assert(-1 >>> 0 === 4294967295); - assert(-1 >>> 1 === 2147483647); - assert(-1 >>> 2 === 1073741823); - assert(-1 >>> 3 === 536870911); - assert(-1 >>> 4 === 268435455); - assert(-1 >>> 5 === 134217727); - - assert(-5 >>> 0 === 4294967291); - assert(-5 >>> 1 === 2147483645); - assert(-5 >>> 2 === 1073741822); - assert(-5 >>> 3 === 536870911); - assert(-5 >>> 4 === 268435455); - assert(-5 >>> 5 === 134217727); - - var x = -67; - var y = 4; - assert("-42" >>> 3 === 536870906); - assert(x >>> y === 268435451); - assert(x >>> [[[[5]]]] === 134217725); - assert(undefined >>> y === 0); - assert("a" >>> "b" === 0); - assert(null >>> null === 0); - assert(undefined >>> undefined === 0); - assert(NaN >>> NaN === 0); - assert(6 >>> NaN === 6); - assert(Infinity >>> Infinity === 0); - assert(-Infinity >>> Infinity === 0); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +test("basic numeric shifting", () => { + expect(0 >>> 0).toBe(0); + expect(0 >>> 1).toBe(0); + expect(0 >>> 2).toBe(0); + expect(0 >>> 3).toBe(0); + expect(0 >>> 4).toBe(0); + expect(0 >>> 5).toBe(0); + + expect(1 >>> 0).toBe(1); + expect(1 >>> 1).toBe(0); + expect(1 >>> 2).toBe(0); + expect(1 >>> 3).toBe(0); + expect(1 >>> 4).toBe(0); + expect(1 >>> 5).toBe(0); + + expect(5 >>> 0).toBe(5); + expect(5 >>> 1).toBe(2); + expect(5 >>> 2).toBe(1); + expect(5 >>> 3).toBe(0); + expect(5 >>> 4).toBe(0); + expect(5 >>> 5).toBe(0); + + expect(42 >>> 0).toBe(42); + expect(42 >>> 1).toBe(21); + expect(42 >>> 2).toBe(10); + expect(42 >>> 3).toBe(5); + expect(42 >>> 4).toBe(2); + expect(42 >>> 5).toBe(1); +}); + +test("numeric shifting with negative lhs values", () => { + expect(-1 >>> 0).toBe(4294967295); + expect(-1 >>> 1).toBe(2147483647); + expect(-1 >>> 2).toBe(1073741823); + expect(-1 >>> 3).toBe(536870911); + expect(-1 >>> 4).toBe(268435455); + expect(-1 >>> 5).toBe(134217727); + + expect(-5 >>> 0).toBe(4294967291); + expect(-5 >>> 1).toBe(2147483645); + expect(-5 >>> 2).toBe(1073741822); + expect(-5 >>> 3).toBe(536870911); + expect(-5 >>> 4).toBe(268435455); + expect(-5 >>> 5).toBe(134217727); +}); + +test("shifting with non-numeric values", () => { + let x = -67; + let y = 4; + + expect("-42" >>> 3).toBe(536870906); + expect(x >>> y).toBe(268435451); + expect(x >>> [[[[5]]]]).toBe(134217725); + expect(undefined >>> y).toBe(0); + expect("a" >>> "b").toBe(0); + expect(null >>> null).toBe(0); + expect(undefined >>> undefined).toBe(0); + expect(NaN >>> NaN).toBe(0); + expect(6 >>> NaN).toBe(6); + expect(Infinity >>> Infinity).toBe(0); + expect(-Infinity >>> Infinity).toBe(0); +}); diff --git a/Libraries/LibJS/Tests/operators/binary-relational.js b/Libraries/LibJS/Tests/operators/binary-relational.js index 719927c7a0..64336d12c1 100644 --- a/Libraries/LibJS/Tests/operators/binary-relational.js +++ b/Libraries/LibJS/Tests/operators/binary-relational.js @@ -1,6 +1,4 @@ -load("test-common.js"); - -try { +test("basic functionality", () => { const vals = [ 1, 2, @@ -723,13 +721,9 @@ try { let x = vals[test[0]]; let y = vals[test[1]]; - assert(x < y === test[2]); - assert(x > y === test[3]); - assert(x <= y === test[4]); - assert(x >= y === test[5]); + expect(x < y).toBe(test[2]); + expect(x > y).toBe(test[3]); + expect(x <= y).toBe(test[4]); + expect(x >= y).toBe(test[5]); } - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +}); diff --git a/Libraries/LibJS/Tests/operators/comma-operator.js b/Libraries/LibJS/Tests/operators/comma-operator.js index 549610dbe6..3b47757370 100644 --- a/Libraries/LibJS/Tests/operators/comma-operator.js +++ b/Libraries/LibJS/Tests/operators/comma-operator.js @@ -1,26 +1,24 @@ -load("test-common.js"); +test("inside parenthesis", () => { + expect((1, 2, 3)).toBe(3); + expect((1, 2 + 3, 4)).toBe(4); +}); -try { - assert((1, 2, 3) === 3); - assert((1, 2 + 3, 4) === 4); - - var foo = 0; +test("with post-increment operator", () => { + let foo = 0; foo = (foo++, foo); - assert(foo === 1); + expect(foo).toBe(1); +}); +test("with assignment operator", () => { var a, b, c; - assert(((a = b = 3), (c = 4)) === 4); - assert(a === 3); - assert(b === 3); - assert(c === 4); + expect(((a = b = 3), (c = 4))).toBe(4); + expect(a).toBe(3); + expect(b).toBe(3); + expect(c).toBe(4); var x, y, z; - assert((x = ((y = 5), (z = 6))) === 6); - assert(x === 6); - assert(y === 5); - assert(z === 6); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect((x = ((y = 5), (z = 6)))).toBe(6); + expect(x).toBe(6); + expect(y).toBe(5); + expect(z).toBe(6); +}); diff --git a/Libraries/LibJS/Tests/operators/delete-basic.js b/Libraries/LibJS/Tests/operators/delete-basic.js index cb763c9895..dc2345f7b2 100644 --- a/Libraries/LibJS/Tests/operators/delete-basic.js +++ b/Libraries/LibJS/Tests/operators/delete-basic.js @@ -1,60 +1,58 @@ -load("test-common.js"); - -try { - o = {}; +test("deleting object properties", () => { + const o = {}; o.x = 1; o.y = 2; o.z = 3; - assert(Object.getOwnPropertyNames(o).length === 3); - - assert(delete o.x === true); - assert(o.hasOwnProperty("x") === false); - assert(o.hasOwnProperty("y") === true); - assert(o.hasOwnProperty("z") === true); - assert(Object.getOwnPropertyNames(o).length === 2); - - assert(delete o.y === true); - assert(o.hasOwnProperty("x") === false); - assert(o.hasOwnProperty("y") === false); - assert(o.hasOwnProperty("z") === true); - assert(Object.getOwnPropertyNames(o).length === 1); - - assert(delete o.z === true); - assert(o.hasOwnProperty("x") === false); - assert(o.hasOwnProperty("y") === false); - assert(o.hasOwnProperty("z") === false); - assert(Object.getOwnPropertyNames(o).length === 0); - - a = [3, 5, 7]; - - assert(Object.getOwnPropertyNames(a).length === 4); - - assert(delete a[0] === true); - assert(a.hasOwnProperty(0) === false); - assert(a.hasOwnProperty(1) === true); - assert(a.hasOwnProperty(2) === true); - assert(Object.getOwnPropertyNames(a).length === 3); - - assert(delete a[1] === true); - assert(a.hasOwnProperty(0) === false); - assert(a.hasOwnProperty(1) === false); - assert(a.hasOwnProperty(2) === true); - assert(Object.getOwnPropertyNames(a).length === 2); - - assert(delete a[2] === true); - assert(a.hasOwnProperty(0) === false); - assert(a.hasOwnProperty(1) === false); - assert(a.hasOwnProperty(2) === false); - assert(Object.getOwnPropertyNames(a).length === 1); - - q = {}; + expect(Object.getOwnPropertyNames(o)).toHaveLength(3); + + expect(delete o.x).toBeTrue(); + expect(o.hasOwnProperty("x")).toBeFalse(); + expect(o.hasOwnProperty("y")).toBeTrue(); + expect(o.hasOwnProperty("z")).toBeTrue(); + expect(Object.getOwnPropertyNames(o)).toHaveLength(2); + + expect(delete o.y).toBeTrue(); + expect(o.hasOwnProperty("x")).toBeFalse(); + expect(o.hasOwnProperty("y")).toBeFalse(); + expect(o.hasOwnProperty("z")).toBeTrue(); + expect(Object.getOwnPropertyNames(o)).toHaveLength(1); + + expect(delete o.z).toBeTrue(); + expect(o.hasOwnProperty("x")).toBeFalse(); + expect(o.hasOwnProperty("y")).toBeFalse(); + expect(o.hasOwnProperty("z")).toBeFalse(); + expect(Object.getOwnPropertyNames(o)).toHaveLength(0); +}); + +test("deleting array indices", () => { + const a = [3, 5, 7]; + + expect(Object.getOwnPropertyNames(a)).toHaveLength(4); + + expect(delete a[0]).toBeTrue(); + expect(a.hasOwnProperty(0)).toBeFalse(); + expect(a.hasOwnProperty(1)).toBeTrue(); + expect(a.hasOwnProperty(2)).toBeTrue(); + expect(Object.getOwnPropertyNames(a)).toHaveLength(3); + + expect(delete a[1]).toBeTrue(); + expect(a.hasOwnProperty(0)).toBeFalse(); + expect(a.hasOwnProperty(1)).toBeFalse(); + expect(a.hasOwnProperty(2)).toBeTrue(); + expect(Object.getOwnPropertyNames(a)).toHaveLength(2); + + expect(delete a[2]).toBeTrue(); + expect(a.hasOwnProperty(0)).toBeFalse(); + expect(a.hasOwnProperty(1)).toBeFalse(); + expect(a.hasOwnProperty(2)).toBeFalse(); + expect(Object.getOwnPropertyNames(a)).toHaveLength(1); +}); + +test("deleting non-configurable property", () => { + const q = {}; Object.defineProperty(q, "foo", { value: 1, writable: false, enumerable: false }); - assert(q.foo === 1); - - assert(delete q.foo === false); - assert(q.hasOwnProperty("foo") === true); + expect(q.foo).toBe(1); - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect(delete q.foo).toBeFalse(); + expect(q.hasOwnProperty("foo")).toBeTrue(); +}); diff --git a/Libraries/LibJS/Tests/operators/delete-global-variable.js b/Libraries/LibJS/Tests/operators/delete-global-variable.js index a96afbe464..2c0f500169 100644 --- a/Libraries/LibJS/Tests/operators/delete-global-variable.js +++ b/Libraries/LibJS/Tests/operators/delete-global-variable.js @@ -1,19 +1,9 @@ -load("test-common.js"); +a = 1; -try { - a = 1; - assert(delete a === true); +test("basic functionality", () => { + expect(delete a).toBeTrue(); - assertThrowsError( - () => { - a; - }, - { - error: ReferenceError, - } - ); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect(() => { + a; + }).toThrowWithMessage(ReferenceError, "'a' is not defined"); +}); diff --git a/Libraries/LibJS/Tests/operators/delete-globalThis-property-crash.js b/Libraries/LibJS/Tests/operators/delete-globalThis-property-crash.js index 4738197327..1a51bd6962 100644 --- a/Libraries/LibJS/Tests/operators/delete-globalThis-property-crash.js +++ b/Libraries/LibJS/Tests/operators/delete-globalThis-property-crash.js @@ -1,10 +1,8 @@ -load("test-common.js"); +a = 1; -try { - a = 1; - assert(delete globalThis.a === true); - a = 2; - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +test("basic functionality", () => { + expect(delete globalThis.a).toBeTrue(); + expect(() => { + a = 2; + }).not.toThrow(); +}); diff --git a/Libraries/LibJS/Tests/operators/in-operator-basic.js b/Libraries/LibJS/Tests/operators/in-operator-basic.js index 0a495cd2a5..54880993e9 100644 --- a/Libraries/LibJS/Tests/operators/in-operator-basic.js +++ b/Libraries/LibJS/Tests/operators/in-operator-basic.js @@ -1,38 +1,32 @@ -load("test-common.js"); +test("in operator with objects", () => { + const o = { foo: "bar", bar: undefined }; + expect("" in o).toBeFalse(); + expect("foo" in o).toBeTrue(); + expect("bar" in o).toBeTrue(); + expect("baz" in o).toBeFalse(); + expect("toString" in o).toBeTrue(); +}); -try { - ["foo", 123, null, undefined].forEach(value => { - assertThrowsError( - () => { - "prop" in value; - }, - { - error: TypeError, - message: "'in' operator must be used on an object", - } - ); - }); - - var o = { foo: "bar", bar: undefined }; - assert("" in o === false); - assert("foo" in o === true); - assert("bar" in o === true); - assert("baz" in o === false); - assert("toString" in o === true); +test("in operator with arrays", () => { + const a = ["hello", "friends"]; + expect(0 in a).toBeTrue(); + expect(1 in a).toBeTrue(); + expect(2 in a).toBeFalse(); + expect("0" in a).toBeTrue(); + expect("hello" in a).toBeFalse(); + expect("friends" in a).toBeFalse(); + expect("length" in a).toBeTrue(); +}); - var a = ["hello", "friends"]; - assert(0 in a === true); - assert(1 in a === true); - assert(2 in a === false); - assert("0" in a === true); - assert("hello" in a === false); - assert("friends" in a === false); - assert("length" in a === true); +test("in operator with string object", () => { + const s = new String("foo"); + expect("length" in s).toBeTrue(); +}); - var s = new String("foo"); - assert("length" in s); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +test("error when used with primitives", () => { + ["foo", 123, null, undefined].forEach(value => { + expect(() => { + "prop" in value; + }).toThrowWithMessage(TypeError, "'in' operator must be used on an object"); + }); +}); diff --git a/Libraries/LibJS/Tests/operators/instanceof-basic.js b/Libraries/LibJS/Tests/operators/instanceof-basic.js index 23a1ead60c..8d9935d769 100644 --- a/Libraries/LibJS/Tests/operators/instanceof-basic.js +++ b/Libraries/LibJS/Tests/operators/instanceof-basic.js @@ -1,13 +1,13 @@ -load("test-common.js"); - -try { +test("basic functionality", () => { function Foo() { this.x = 123; } - var foo = new Foo(); - assert(foo instanceof Foo); + const foo = new Foo(); + expect(foo instanceof Foo).toBeTrue(); +}); +test("derived ES5 classes", () => { function Base() { this.is_base = true; } @@ -18,11 +18,7 @@ try { Object.setPrototypeOf(Derived.prototype, Base.prototype); - var d = new Derived(); - assert(d instanceof Derived); - assert(d instanceof Base); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + const d = new Derived(); + expect(d instanceof Derived).toBeTrue(); + expect(d instanceof Base).toBeTrue(); +}); diff --git a/Libraries/LibJS/Tests/operators/logical-and.js b/Libraries/LibJS/Tests/operators/logical-and.js new file mode 100644 index 0000000000..2ddbe1feea --- /dev/null +++ b/Libraries/LibJS/Tests/operators/logical-and.js @@ -0,0 +1,50 @@ +test("booleans", () => { + expect(true && true).toBeTrue(); + expect(false && false).toBeFalse(); + expect(true && false).toBeFalse(); + expect(false && true).toBeFalse(); +}); + +test("strings", () => { + expect("" && "").toBe(""); + expect("" && false).toBe(""); + expect("" && true).toBe(""); + expect(false && "").toBeFalse(); + expect(true && "").toBe(""); + expect("foo" && "bar").toBe("bar"); + expect("foo" && false).toBeFalse(); + expect("foo" && true).toBeTrue(); + expect(false && "bar").toBeFalse(); + expect(true && "bar").toBe("bar"); +}); + +test("numbers", () => { + expect(false && 1 === 2).toBeFalse(); + expect(true && 1 === 2).toBeFalse(); + expect(0 && false).toBe(0); + expect(0 && true).toBe(0); + expect(42 && false).toBeFalse(); + expect(42 && true).toBeTrue(); + expect(false && 0).toBeFalse(); + expect(true && 0).toBe(0); + expect(false && 42).toBeFalse(); + expect(true && 42).toBe(42); +}); + +test("objects", () => { + expect([] && false).toBeFalse(); + expect([] && true).toBeTrue(); + expect(false && []).toBeFalse(); + expect(true && []).toHaveLength(0); +}); + +test("null & undefined", () => { + expect(null && false).toBeNull(); + expect(null && true).toBeNull(); + expect(false && null).toBeFalse(); + expect(true && null).toBeNull(); + expect(undefined && false).toBeUndefined(); + expect(undefined && true).toBeUndefined(); + expect(false && undefined).toBeFalse(); + expect(true && undefined).toBeUndefined(); +}); diff --git a/Libraries/LibJS/Tests/operators/logical-expressions-basic.js b/Libraries/LibJS/Tests/operators/logical-expressions-basic.js deleted file mode 100644 index 63f27efb9e..0000000000 --- a/Libraries/LibJS/Tests/operators/logical-expressions-basic.js +++ /dev/null @@ -1,118 +0,0 @@ -load("test-common.js"); - -try { - assert((true && true) === true); - assert((false && false) === false); - assert((true && false) === false); - assert((false && true) === false); - assert((false && 1 === 2) === false); - assert((true && 1 === 2) === false); - assert(("" && "") === ""); - assert(("" && false) === ""); - assert(("" && true) === ""); - assert((false && "") === false); - assert((true && "") === ""); - assert(("foo" && "bar") === "bar"); - assert(("foo" && false) === false); - assert(("foo" && true) === true); - assert((false && "bar") === false); - assert((true && "bar") === "bar"); - assert((0 && false) === 0); - assert((0 && true) === 0); - assert((42 && false) === false); - assert((42 && true) === true); - assert((false && 0) === false); - assert((true && 0) === 0); - assert((false && 42) === false); - assert((true && 42) === 42); - assert(([] && false) === false); - assert(([] && true) === true); - assert((false && []) === false); - assert((true && []).length === 0); - assert((null && false) === null); - assert((null && true) === null); - assert((false && null) === false); - assert((true && null) === null); - assert((undefined && false) === undefined); - assert((undefined && true) === undefined); - assert((false && undefined) === false); - assert((true && undefined) === undefined); - - assert((true || true) === true); - assert((false || false) === false); - assert((true || false) === true); - assert((false || true) === true); - assert((false || 1 === 2) === false); - assert((true || 1 === 2) === true); - assert(("" || "") === ""); - assert(("" || false) === false); - assert(("" || true) === true); - assert((false || "") === ""); - assert((true || "") === true); - assert(("foo" || "bar") === "foo"); - assert(("foo" || false) === "foo"); - assert(("foo" || true) === "foo"); - assert((false || "bar") === "bar"); - assert((true || "bar") === true); - assert((0 || false) === false); - assert((0 || true) === true); - assert((42 || false) === 42); - assert((42 || true) === 42); - assert((false || 0) === 0); - assert((true || 0) === true); - assert((false || 42) === 42); - assert((true || 42) === true); - assert(([] || false).length === 0); - assert(([] || true).length === 0); - assert((false || []).length === 0); - assert((true || []) === true); - assert((null || false) === false); - assert((null || true) === true); - assert((false || null) === null); - assert((true || null) === true); - assert((undefined || false) === false); - assert((undefined || true) === true); - assert((false || undefined) === undefined); - assert((true || undefined) === true); - - assert((true ?? true) === true); - assert((false ?? false) === false); - assert((true ?? false) === true); - assert((false ?? true) === false); - assert((false ?? 1 === 2) === false); - assert((true ?? 1 === 2) === true); - assert(("" ?? "") === ""); - assert(("" ?? false) === ""); - assert(("" ?? true) === ""); - assert((false ?? "") === false); - assert((true ?? "") === true); - assert(("foo" ?? "bar") === "foo"); - assert(("foo" ?? false) === "foo"); - assert(("foo" ?? true) === "foo"); - assert((false ?? "bar") === false); - assert((true ?? "bar") === true); - assert((0 ?? false) === 0); - assert((0 ?? true) === 0); - assert((42 ?? false) === 42); - assert((42 ?? true) === 42); - assert((false ?? 0) === false); - assert((true ?? 0) === true); - assert((false ?? 42) === false); - assert((true ?? 42) === true); - assert(([] ?? false).length === 0); - assert(([] ?? true).length === 0); - assert((false ?? []) === false); - assert((true ?? []) === true); - assert((null ?? false) === false); - assert((null ?? true) === true); - assert((false ?? null) === false); - assert((true ?? null) === true); - assert((undefined ?? false) === false); - assert((undefined ?? true) === true); - assert((false ?? undefined) === false); - assert((true ?? undefined) === true); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} diff --git a/Libraries/LibJS/Tests/operators/logical-expressions-short-circuit.js b/Libraries/LibJS/Tests/operators/logical-expressions-short-circuit.js index 9e6a29dae4..a095fefd91 100644 --- a/Libraries/LibJS/Tests/operators/logical-expressions-short-circuit.js +++ b/Libraries/LibJS/Tests/operators/logical-expressions-short-circuit.js @@ -1,15 +1,13 @@ -load("test-common.js"); - -try { +test("basic functionality", () => { let foo = 1; false && (foo = 2); - assert(foo === 1); + expect(foo).toBe(1); foo = 1; true || (foo = 2); - assert(foo === 1); + expect(foo).toBe(1); - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + foo = 1; + true ?? (foo = 2); + expect(foo).toBe(1); +}); diff --git a/Libraries/LibJS/Tests/operators/logical-nullish-coalescing.js b/Libraries/LibJS/Tests/operators/logical-nullish-coalescing.js new file mode 100644 index 0000000000..9a4ad82e94 --- /dev/null +++ b/Libraries/LibJS/Tests/operators/logical-nullish-coalescing.js @@ -0,0 +1,50 @@ +test("booleans", () => { + expect(true ?? true).toBeTrue(); + expect(false ?? false).toBeFalse(); + expect(true ?? false).toBeTrue(); + expect(false ?? true).toBeFalse(); +}); + +test("strings", () => { + expect("" ?? "").toBe(""); + expect("" ?? false).toBe(""); + expect("" ?? true).toBe(""); + expect(false ?? "").toBeFalse(); + expect(true ?? "").toBeTrue(); + expect("foo" ?? "bar").toBe("foo"); + expect("foo" ?? false).toBe("foo"); + expect("foo" ?? true).toBe("foo"); + expect(false ?? "bar").toBeFalse(); + expect(true ?? "bar").toBeTrue(); +}); + +test("numbers", () => { + expect(false ?? 1 === 2).toBeFalse(); + expect(true ?? 1 === 2).toBeTrue(); + expect(0 ?? false).toBe(0); + expect(0 ?? true).toBe(0); + expect(42 ?? false).toBe(42); + expect(42 ?? true).toBe(42); + expect(false ?? 0).toBeFalse(); + expect(true ?? 0).toBeTrue(); + expect(false ?? 42).toBeFalse(); + expect(true ?? 42).toBeTrue(); +}); + +test("objects", () => { + expect([] ?? false).toHaveLength(0); + expect([] ?? true).toHaveLength(0); + expect(false ?? []).toBeFalse(); + expect(true ?? []).toBeTrue(); +}); + +test("null & undefined", () => { + expect(null ?? false).toBeFalse(); + expect(null ?? true).toBeTrue(); + expect(false ?? null).toBeFalse(); + expect(true ?? null).toBeTrue(); + expect(undefined ?? false).toBeFalse(); + expect(undefined ?? true).toBeTrue(); + expect(false ?? undefined).toBeFalse(); + expect(true ?? undefined).toBeTrue(); +}); diff --git a/Libraries/LibJS/Tests/operators/logical-or.js b/Libraries/LibJS/Tests/operators/logical-or.js new file mode 100644 index 0000000000..5499c1e4ab --- /dev/null +++ b/Libraries/LibJS/Tests/operators/logical-or.js @@ -0,0 +1,50 @@ +test("booleans", () => { + expect(true || true).toBeTrue(); + expect(false || false).toBeFalse(); + expect(true || false).toBeTrue(); + expect(false || true).toBeTrue(); +}); + +test("strings", () => { + expect("" || "").toBe(""); + expect("" || false).toBeFalse(); + expect("" || true).toBeTrue(); + expect(false || "").toBe(""); + expect(true || "").toBeTrue(); + expect("foo" || "bar").toBe("foo"); + expect("foo" || false).toBe("foo"); + expect("foo" || true).toBe("foo"); + expect(false || "bar").toBe("bar"); + expect(true || "bar").toBeTrue(); +}); + +test("numbers", () => { + expect(false || 1 === 2).toBeFalse(); + expect(true || 1 === 2).toBeTrue(); + expect(0 || false).toBeFalse(); + expect(0 || true).toBeTrue(); + expect(42 || false).toBe(42); + expect(42 || true).toBe(42); + expect(false || 0).toBe(0); + expect(true || 0).toBeTrue(); + expect(false || 42).toBe(42); + expect(true || 42).toBeTrue(); +}); + +test("objects", () => { + expect([] || false).toHaveLength(0); + expect([] || true).toHaveLength(0); + expect(false || []).toHaveLength(0); + expect(true || []).toBeTrue(); +}); + +test("null & undefined", () => { + expect(null || false).toBeFalse(); + expect(null || true).toBeTrue(); + expect(false || null).toBeNull(); + expect(true || null).toBeTrue(); + expect(undefined || false).toBeFalse(); + expect(undefined || true).toBeTrue(); + expect(false || undefined).toBeUndefined(); + expect(true || undefined).toBeTrue(); +}); diff --git a/Libraries/LibJS/Tests/operators/modulo-basic.js b/Libraries/LibJS/Tests/operators/modulo-basic.js index 21fbbeed68..b6e97bac0f 100644 --- a/Libraries/LibJS/Tests/operators/modulo-basic.js +++ b/Libraries/LibJS/Tests/operators/modulo-basic.js @@ -1,22 +1,16 @@ -load("test-common.js"); - -try { - assert(10 % 3 === 1); - assert(10.5 % 2.5 === 0.5); - assert(-0.99 % 0.99 === -0); +test("basic functionality", () => { + expect(10 % 3).toBe(1); + expect(10.5 % 2.5).toBe(0.5); + expect(-0.99 % 0.99).toBe(-0); // Examples from MDN: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators - assert(12 % 5 === 2); - assert(-1 % 2 === -1); - assert(1 % -2 === 1); - assert(isNaN(NaN % 2)); - assert(1 % 2 === 1); - assert(2 % 3 === 2); - assert(-4 % 2 === -0); - assert(5.5 % 2 === 1.5); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect(12 % 5).toBe(2); + expect(-1 % 2).toBe(-1); + expect(1 % -2).toBe(1); + expect(1 % 2).toBe(1); + expect(2 % 3).toBe(2); + expect(-4 % 2).toBe(-0); + expect(5.5 % 2).toBe(1.5); + expect(NaN % 2).toBeNaN(); +}); diff --git a/Libraries/LibJS/Tests/operators/ternary-basic.js b/Libraries/LibJS/Tests/operators/ternary-basic.js index d760ef1dec..e3b6ff7a18 100644 --- a/Libraries/LibJS/Tests/operators/ternary-basic.js +++ b/Libraries/LibJS/Tests/operators/ternary-basic.js @@ -1,21 +1,16 @@ -load("test-common.js"); +test("basic functionality", () => { + const x = 1; -try { - var x = 1; + expect(x === 1 ? true : false).toBeTrue(); + expect(x ? x : 0).toBe(x); + expect(1 < 2 ? true : false).toBeTrue(); + expect(0 ? 1 : 1 ? 10 : 20).toBe(10); + expect(0 ? (1 ? 1 : 10) : 20).toBe(20); +}); - assert(x === 1 ? true : false); - assert((x ? x : 0) === x); - assert(1 < 2 ? true : false); - assert((0 ? 1 : 1 ? 10 : 20) === 10); - assert((0 ? (1 ? 1 : 10) : 20) === 20); - - var o = {}; +test("object values", () => { + const o = {}; o.f = true; - assert(o.f ? true : false); - - assert(1 ? o.f : null); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect(o.f ? true : false).toBeTrue(); + expect(1 ? o.f : null).toBeTrue(); +}); diff --git a/Libraries/LibJS/Tests/operators/typeof-basic.js b/Libraries/LibJS/Tests/operators/typeof-basic.js index 29372ac606..0a1ab0effe 100644 --- a/Libraries/LibJS/Tests/operators/typeof-basic.js +++ b/Libraries/LibJS/Tests/operators/typeof-basic.js @@ -1,27 +1,27 @@ -load("test-common.js"); - -try { - assert(typeof "foo" === "string"); - assert(!(typeof "foo" !== "string")); - assert(typeof (1 + 2) === "number"); - assert(typeof {} === "object"); - assert(typeof null === "object"); - assert(typeof undefined === "undefined"); +test("basic functionality", () => { + expect(typeof "foo").toBe("string"); + expect(typeof (1 + 2)).toBe("number"); + expect(typeof {}).toBe("object"); + expect(typeof null).toBe("object"); + expect(typeof undefined).toBe("undefined"); + expect(typeof 1n).toBe("bigint"); + expect(typeof Symbol()).toBe("symbol"); + expect(typeof function () {}).toBe("function"); var iExist = 1; - assert(typeof iExist === "number"); - assert(typeof iDontExist === "undefined"); + expect(typeof iExist).toBe("number"); + expect(typeof iDontExist).toBe("undefined"); +}); +test("typeof calls property getter", () => { var calls = 0; Object.defineProperty(globalThis, "foo", { get() { calls++; + return 10; }, }); - assert(typeof foo === "undefined"); - assert(calls === 1); - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} + expect(typeof foo).toBe("number"); + expect(calls).toBe(1); +}); diff --git a/Libraries/LibJS/Tests/operators/void-basic.js b/Libraries/LibJS/Tests/operators/void-basic.js index a4648600d5..2d64eeb4a0 100644 --- a/Libraries/LibJS/Tests/operators/void-basic.js +++ b/Libraries/LibJS/Tests/operators/void-basic.js @@ -1,20 +1,14 @@ -load("test-common.js"); - -try { - assert(void "" === undefined); - assert(void "foo" === undefined); - assert(void 1 === undefined); - assert(void 42 === undefined); - assert(void true === undefined); - assert(void false === undefined); - assert(void null === undefined); - assert(void undefined === undefined); - assert(void function () {} === undefined); - assert(void (() => {}) === undefined); - assert(void (() => "hello friends")() === undefined); - assert((() => void "hello friends")() === undefined); - - console.log("PASS"); -} catch (e) { - console.log("FAIL: " + e); -} +test("basic functionality", () => { + expect(void "").toBeUndefined(); + expect(void "foo").toBeUndefined(); + expect(void 1).toBeUndefined(); + expect(void 42).toBeUndefined(); + expect(void true).toBeUndefined(); + expect(void false).toBeUndefined(); + expect(void null).toBeUndefined(); + expect(void undefined).toBeUndefined(); + expect(void function () {}).toBeUndefined(); + expect(void (() => {})).toBeUndefined(); + expect(void (() => "hello friends")()).toBeUndefined(); + expect((() => void "hello friends")()).toBeUndefined(); +}); diff --git a/Userland/test-js.cpp b/Userland/test-js.cpp index de1373b8ce..9f329ace8b 100644 --- a/Userland/test-js.cpp +++ b/Userland/test-js.cpp @@ -43,6 +43,12 @@ // FIXME: Will eventually not be necessary when all tests are converted Vector<String> tests_to_run = { + "builtins/BigInt/BigInt.js", + "builtins/BigInt/bigint-basic.js", + "builtins/BigInt/bigint-number-mix-errors.js", + "builtins/BigInt/BigInt.prototype.toLocaleString.js", + "builtins/BigInt/BigInt.prototype.toString.js", + "builtins/BigInt/BigInt.prototype.valueOf.js", "builtins/Boolean/Boolean.js", "builtins/Boolean/Boolean.prototype.js", "builtins/Boolean/Boolean.prototype.toString.js", @@ -169,6 +175,65 @@ Vector<String> tests_to_run = { "builtins/String/String.prototype.trim.js", "builtins/String/String.prototype.valueOf.js", "builtins/String/String.raw.js", + "builtins/Symbol/Symbol.js", + "builtins/Symbol/Symbol.for.js", + "builtins/Symbol/Symbol.keyFor.js", + "builtins/Symbol/Symbol.prototype.toString.js", + "builtins/Symbol/Symbol.prototype.valueOf.js", + "classes/class-advanced-extends.js", + "classes/class-basic.js", + "classes/class-constructor.js", + "classes/class-errors.js", + "classes/class-expressions.js", + "classes/class-getters.js", + "classes/class-inheritance.js", + "classes/class-methods.js", + "classes/class-setters.js", + "classes/class-static.js", + "classes/class-static-getters.js", + "classes/class-static-setters.js", + "classes/class-strict-mode.js", + "functions/arrow-functions.js", + "functions/constructor-basic.js", + "functions/function-default-parameters.js", + "functions/function-hoisting.js", + "functions/function-length.js", + "functions/function-missing-arg.js", + "functions/function-name.js", + "functions/function-rest-params.js", + "functions/function-spread.js", + "functions/function-strict-mode.js", + "functions/function-this-in-arguments.js", + "functions/function-TypeError.js", + "loops/continue-basic.js", + "loops/do-while-basic.js", + "loops/for-basic.js", + "loops/for-head-errors.js", + "loops/for-in-basic.js", + "loops/for-no-curlies.js", + "loops/for-of-basic.js", + "loops/for-scopes.js", + "loops/while-basic.js", + "operators/assignment-operators.js", + "operators/binary-bitwise-left-shift.js", + "operators/binary-bitwise-or.js", + "operators/binary-bitwise-right-shift.js", + "operators/binary-bitwise-unsigned-right-shift.js", + "operators/binary-relational.js", + "operators/comma-operator.js", + "operators/delete-basic.js", + "operators/delete-global-variable.js", + "operators/delete-globalThis-property-crash.js", + "operators/in-operator-basic.js", + "operators/instanceof-basic.js", + "operators/logical-and.js", + "operators/logical-expressions-short-circuit.js", + "operators/logical-nullish-coalescing.js", + "operators/logical-or.js", + "operators/modulo-basic.js", + "operators/ternary-basic.js", + "operators/typeof-basic.js", + "operators/void-basic.js", "add-values-to-primitive.js", "automatic-semicolon-insertion.js", "comments-basic.js", |