summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Olsson <matthewcolsson@gmail.com>2020-07-05 17:26:26 -0700
committerAndreas Kling <kling@serenityos.org>2020-07-06 23:40:35 +0200
commit15de2eda2b8c06a59053d6a7144ea9eaf07e2210 (patch)
tree191d9459dc71e270def1ca69a02406a9498005b9
parent918f4affd51cdd285272770465d4d875f4ae5aa2 (diff)
downloadserenity-15de2eda2b8c06a59053d6a7144ea9eaf07e2210.zip
LibJS: Convert all remaining non-Array tests to the new system :)
-rw-r--r--Libraries/LibJS/Tests/.prettierignore3
-rw-r--r--Libraries/LibJS/Tests/builtins/BigInt/BigInt.asIntN.js9
-rw-r--r--Libraries/LibJS/Tests/builtins/BigInt/BigInt.asUintN.js9
-rw-r--r--Libraries/LibJS/Tests/builtins/BigInt/BigInt.js122
-rw-r--r--Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toLocaleString.js31
-rw-r--r--Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.toString.js31
-rw-r--r--Libraries/LibJS/Tests/builtins/BigInt/BigInt.prototype.valueOf.js33
-rw-r--r--Libraries/LibJS/Tests/builtins/BigInt/bigint-basic.js134
-rw-r--r--Libraries/LibJS/Tests/builtins/BigInt/bigint-number-mix-errors.js141
-rw-r--r--Libraries/LibJS/Tests/builtins/Symbol/Symbol.for.js50
-rw-r--r--Libraries/LibJS/Tests/builtins/Symbol/Symbol.js34
-rw-r--r--Libraries/LibJS/Tests/builtins/Symbol/Symbol.keyFor.js54
-rw-r--r--Libraries/LibJS/Tests/builtins/Symbol/Symbol.prototype.toString.js50
-rw-r--r--Libraries/LibJS/Tests/builtins/Symbol/Symbol.prototype.valueOf.js40
-rw-r--r--Libraries/LibJS/Tests/classes/class-advanced-extends.js35
-rw-r--r--Libraries/LibJS/Tests/classes/class-basic.js274
-rw-r--r--Libraries/LibJS/Tests/classes/class-constructor.js67
-rw-r--r--Libraries/LibJS/Tests/classes/class-errors.js95
-rw-r--r--Libraries/LibJS/Tests/classes/class-expressions.js69
-rw-r--r--Libraries/LibJS/Tests/classes/class-getters.js68
-rw-r--r--Libraries/LibJS/Tests/classes/class-inheritance.js133
-rw-r--r--Libraries/LibJS/Tests/classes/class-methods.js51
-rw-r--r--Libraries/LibJS/Tests/classes/class-setters.js100
-rw-r--r--Libraries/LibJS/Tests/classes/class-static-getters.js80
-rw-r--r--Libraries/LibJS/Tests/classes/class-static-setters.js104
-rw-r--r--Libraries/LibJS/Tests/classes/class-static.js72
-rw-r--r--Libraries/LibJS/Tests/classes/class-strict-mode.js19
-rw-r--r--Libraries/LibJS/Tests/const-reassignment.js1
-rw-r--r--Libraries/LibJS/Tests/functions/arrow-functions.js134
-rw-r--r--Libraries/LibJS/Tests/functions/constructor-basic.js18
-rw-r--r--Libraries/LibJS/Tests/functions/function-TypeError.js100
-rw-r--r--Libraries/LibJS/Tests/functions/function-default-parameters.js189
-rw-r--r--Libraries/LibJS/Tests/functions/function-hoisting.js36
-rw-r--r--Libraries/LibJS/Tests/functions/function-length.js36
-rw-r--r--Libraries/LibJS/Tests/functions/function-missing-arg.js23
-rw-r--r--Libraries/LibJS/Tests/functions/function-name.js85
-rw-r--r--Libraries/LibJS/Tests/functions/function-rest-params.js74
-rw-r--r--Libraries/LibJS/Tests/functions/function-spread.js34
-rw-r--r--Libraries/LibJS/Tests/functions/function-strict-mode.js99
-rw-r--r--Libraries/LibJS/Tests/functions/function-this-in-arguments.js21
-rw-r--r--Libraries/LibJS/Tests/loops/continue-basic.js13
-rw-r--r--Libraries/LibJS/Tests/loops/do-while-basic.js20
-rw-r--r--Libraries/LibJS/Tests/loops/for-basic.js29
-rw-r--r--Libraries/LibJS/Tests/loops/for-head-errors.js58
-rw-r--r--Libraries/LibJS/Tests/loops/for-in-basic.js78
-rw-r--r--Libraries/LibJS/Tests/loops/for-no-curlies.js17
-rw-r--r--Libraries/LibJS/Tests/loops/for-of-basic.js89
-rw-r--r--Libraries/LibJS/Tests/loops/for-scopes.js30
-rw-r--r--Libraries/LibJS/Tests/loops/while-basic.js24
-rw-r--r--Libraries/LibJS/Tests/new-expression.js16
-rw-r--r--Libraries/LibJS/Tests/operators/assignment-operators.js64
-rw-r--r--Libraries/LibJS/Tests/operators/binary-bitwise-left-shift.js123
-rw-r--r--Libraries/LibJS/Tests/operators/binary-bitwise-or.js123
-rw-r--r--Libraries/LibJS/Tests/operators/binary-bitwise-right-shift.js125
-rw-r--r--Libraries/LibJS/Tests/operators/binary-bitwise-unsigned-right-shift.js125
-rw-r--r--Libraries/LibJS/Tests/operators/binary-relational.js18
-rw-r--r--Libraries/LibJS/Tests/operators/comma-operator.js38
-rw-r--r--Libraries/LibJS/Tests/operators/delete-basic.js108
-rw-r--r--Libraries/LibJS/Tests/operators/delete-global-variable.js24
-rw-r--r--Libraries/LibJS/Tests/operators/delete-globalThis-property-crash.js16
-rw-r--r--Libraries/LibJS/Tests/operators/in-operator-basic.js64
-rw-r--r--Libraries/LibJS/Tests/operators/instanceof-basic.js22
-rw-r--r--Libraries/LibJS/Tests/operators/logical-and.js50
-rw-r--r--Libraries/LibJS/Tests/operators/logical-expressions-basic.js118
-rw-r--r--Libraries/LibJS/Tests/operators/logical-expressions-short-circuit.js16
-rw-r--r--Libraries/LibJS/Tests/operators/logical-nullish-coalescing.js50
-rw-r--r--Libraries/LibJS/Tests/operators/logical-or.js50
-rw-r--r--Libraries/LibJS/Tests/operators/modulo-basic.js32
-rw-r--r--Libraries/LibJS/Tests/operators/ternary-basic.js31
-rw-r--r--Libraries/LibJS/Tests/operators/typeof-basic.js34
-rw-r--r--Libraries/LibJS/Tests/operators/void-basic.js34
-rw-r--r--Userland/test-js.cpp65
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",