1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 10:47:35 +00:00

Libraries: Move to Userland/Libraries/

This commit is contained in:
Andreas Kling 2021-01-12 12:17:30 +01:00
parent dc28c07fa5
commit 13d7c09125
1857 changed files with 266 additions and 274 deletions

View file

@ -0,0 +1,69 @@
test("length is 1", () => {
expect(Array.from).toHaveLength(1);
});
describe("normal behavior", () => {
test("empty array", () => {
var a = Array.from([]);
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(0);
});
test("empty string", () => {
var a = Array.from("");
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(0);
});
test("non-empty array", () => {
var a = Array.from([5, 8, 1]);
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(3);
expect(a[0]).toBe(5);
expect(a[1]).toBe(8);
expect(a[2]).toBe(1);
});
test("non-empty string", () => {
var a = Array.from("what");
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(4);
expect(a[0]).toBe("w");
expect(a[1]).toBe("h");
expect(a[2]).toBe("a");
expect(a[3]).toBe("t");
});
test("shallow array copy", () => {
var a = [1, 2, 3];
var b = Array.from([a]);
expect(b instanceof Array).toBeTrue();
expect(b).toHaveLength(1);
b[0][0] = 4;
expect(a[0]).toBe(4);
});
test("from iterator", () => {
function rangeIterator(begin, end) {
return {
[Symbol.iterator]() {
let value = begin - 1;
return {
next() {
if (value < end) {
value += 1;
}
return { value: value, done: value >= end };
},
};
},
};
}
var a = Array.from(rangeIterator(8, 10));
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(2);
expect(a[0]).toBe(8);
expect(a[1]).toBe(9);
});
});

View file

@ -0,0 +1,26 @@
test("length is 1", () => {
expect(Array.isArray).toHaveLength(1);
});
test("arguments that evaluate to false", () => {
expect(Array.isArray()).toBeFalse();
expect(Array.isArray("1")).toBeFalse();
expect(Array.isArray("foo")).toBeFalse();
expect(Array.isArray(1)).toBeFalse();
expect(Array.isArray(1, 2, 3)).toBeFalse();
expect(Array.isArray(undefined)).toBeFalse();
expect(Array.isArray(null)).toBeFalse();
expect(Array.isArray(Infinity)).toBeFalse();
expect(Array.isArray({})).toBeFalse();
});
test("arguments that evaluate to true", () => {
expect(Array.isArray([])).toBeTrue();
expect(Array.isArray([1])).toBeTrue();
expect(Array.isArray([1, 2, 3])).toBeTrue();
expect(Array.isArray(new Array())).toBeTrue();
expect(Array.isArray(new Array(10))).toBeTrue();
expect(Array.isArray(new Array("a", "b", "c"))).toBeTrue();
// FIXME: Array.prototype is supposed to be an array!
// expect(Array.isArray(Array.prototype)).toBeTrue();
});

View file

@ -0,0 +1,53 @@
test("constructor properties", () => {
expect(Array).toHaveLength(1);
expect(Array.name).toBe("Array");
expect(Array.prototype.length).toBe(0);
});
describe("errors", () => {
test("invalid array length", () => {
[-1, -100, -0.1, 0.1, 1.23, Infinity, -Infinity, NaN].forEach(value => {
expect(() => {
new Array(value);
}).toThrowWithMessage(RangeError, "Invalid array length");
});
});
});
describe("normal behavior", () => {
test("typeof", () => {
expect(typeof Array()).toBe("object");
expect(typeof new Array()).toBe("object");
});
test("constructor with single numeric argument", () => {
var a = new Array(5);
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(5);
});
test("constructor with single non-numeric argument", () => {
var a = new Array("5");
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(1);
expect(a[0]).toBe("5");
});
test("constructor with multiple numeric arguments", () => {
var a = new Array(1, 2, 3);
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(3);
expect(a[0]).toBe(1);
expect(a[1]).toBe(2);
expect(a[2]).toBe(3);
});
test("constructor with single array argument", () => {
var a = new Array([1, 2, 3]);
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(1);
expect(a[0][0]).toBe(1);
expect(a[0][1]).toBe(2);
expect(a[0][2]).toBe(3);
});
});

View file

@ -0,0 +1,59 @@
test("length is 0", () => {
expect(Array.of).toHaveLength(0);
});
describe("normal behavior", () => {
test("single numeric argument", () => {
var a = Array.of(5);
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(1);
expect(a[0]).toBe(5);
});
test("single non-numeric argument", () => {
var a = Array.of("5");
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(1);
expect(a[0]).toBe("5");
});
test("single infinite numeric argument", () => {
var a = Array.of(Infinity);
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(1);
expect(a[0]).toBe(Infinity);
});
test("multiple numeric arguments", () => {
var a = Array.of(1, 2, 3);
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(3);
expect(a[0]).toBe(1);
expect(a[1]).toBe(2);
expect(a[2]).toBe(3);
});
test("single array argument", () => {
var a = Array.of([1, 2, 3]);
expect(a instanceof Array).toBeTrue();
expect(a).toHaveLength(1);
expect(a[0][0]).toBe(1);
expect(a[0][1]).toBe(2);
expect(a[0][2]).toBe(3);
});
test("getter property is included in returned array", () => {
var t = [1, 2, 3];
Object.defineProperty(t, 3, {
get() {
return 4;
},
});
var a = Array.of(...t);
expect(a).toHaveLength(4);
expect(a[0]).toBe(1);
expect(a[1]).toBe(2);
expect(a[2]).toBe(3);
expect(a[3]).toBe(4);
});
});

View file

@ -0,0 +1,150 @@
describe("ability to work with generic non-array objects", () => {
test("push, pop", () => {
[undefined, "foo", -42, 0].forEach(length => {
const o = { length };
expect(Array.prototype.push.call(o, "foo")).toBe(1);
expect(o).toHaveLength(1);
expect(o[0]).toBe("foo");
expect(Array.prototype.push.call(o, "bar", "baz")).toBe(3);
expect(o).toHaveLength(3);
expect(o[0]).toBe("foo");
expect(o[1]).toBe("bar");
expect(o[2]).toBe("baz");
expect(Array.prototype.pop.call(o)).toBe("baz");
expect(o).toHaveLength(2);
expect(Array.prototype.pop.call(o)).toBe("bar");
expect(o).toHaveLength(1);
expect(Array.prototype.pop.call(o)).toBe("foo");
expect(o).toHaveLength(0);
expect(Array.prototype.pop.call(o)).toBeUndefined();
expect(o).toHaveLength(0);
o.length = length;
expect(Array.prototype.pop.call(o)).toBeUndefined();
expect(o).toHaveLength(0);
});
});
test("splice", () => {
const o = { length: 3, 0: "hello", 2: "serenity" };
const removed = Array.prototype.splice.call(o, 0, 2, "hello", "friends");
expect(o).toHaveLength(3);
expect(o[0]).toBe("hello");
expect(o[1]).toBe("friends");
expect(o[2]).toBe("serenity");
expect(removed).toHaveLength(2);
expect(removed[0]).toBe("hello");
expect(removed[1]).toBeUndefined();
});
test("join", () => {
expect(Array.prototype.join.call({})).toBe("");
expect(Array.prototype.join.call({ length: "foo" })).toBe("");
expect(Array.prototype.join.call({ length: 3 })).toBe(",,");
expect(Array.prototype.join.call({ length: 2, 0: "foo", 1: "bar" })).toBe("foo,bar");
expect(Array.prototype.join.call({ length: 2, 0: "foo", 1: "bar", 2: "baz" })).toBe(
"foo,bar"
);
expect(Array.prototype.join.call({ length: 3, 1: "bar" }, "~")).toBe("~bar~");
expect(Array.prototype.join.call({ length: 3, 0: "foo", 1: "bar", 2: "baz" }, "~")).toBe(
"foo~bar~baz"
);
});
// FIXME: test-js asserts when this is just called "toString" ಠ_ಠ
test("toString (FIXME)", () => {
expect(Array.prototype.toString.call({})).toBe("[object Object]");
expect(Array.prototype.toString.call({ join: "foo" })).toBe("[object Object]");
expect(Array.prototype.toString.call({ join: () => "foo" })).toBe("foo");
});
test("indexOf", () => {
expect(Array.prototype.indexOf.call({})).toBe(-1);
expect(Array.prototype.indexOf.call({ 0: undefined })).toBe(-1);
expect(Array.prototype.indexOf.call({ length: 1, 0: undefined })).toBe(0);
expect(Array.prototype.indexOf.call({ length: 1, 2: "foo" }, "foo")).toBe(-1);
expect(Array.prototype.indexOf.call({ length: 5, 2: "foo" }, "foo")).toBe(2);
expect(Array.prototype.indexOf.call({ length: 5, 2: "foo", 4: "foo" }, "foo", 3)).toBe(4);
});
test("lastIndexOf", () => {
expect(Array.prototype.lastIndexOf.call({})).toBe(-1);
expect(Array.prototype.lastIndexOf.call({ 0: undefined })).toBe(-1);
expect(Array.prototype.lastIndexOf.call({ length: 1, 0: undefined })).toBe(0);
expect(Array.prototype.lastIndexOf.call({ length: 1, 2: "foo" }, "foo")).toBe(-1);
expect(Array.prototype.lastIndexOf.call({ length: 5, 2: "foo" }, "foo")).toBe(2);
expect(Array.prototype.lastIndexOf.call({ length: 5, 2: "foo", 4: "foo" }, "foo")).toBe(4);
expect(Array.prototype.lastIndexOf.call({ length: 5, 2: "foo", 4: "foo" }, "foo", -2)).toBe(
2
);
});
test("includes", () => {
expect(Array.prototype.includes.call({})).toBeFalse();
expect(Array.prototype.includes.call({ 0: undefined })).toBeFalse();
expect(Array.prototype.includes.call({ length: 1, 0: undefined })).toBeTrue();
expect(Array.prototype.includes.call({ length: 1, 2: "foo" }, "foo")).toBeFalse();
expect(Array.prototype.includes.call({ length: 5, 2: "foo" }, "foo")).toBeTrue();
});
const o = { length: 5, 0: "foo", 1: "bar", 3: "baz" };
test("every", () => {
const visited = [];
Array.prototype.every.call(o, value => {
visited.push(value);
return true;
});
expect(visited).toEqual(["foo", "bar", "baz"]);
});
test("find, findIndex", () => {
["find", "findIndex"].forEach(name => {
const visited = [];
Array.prototype[name].call(o, value => {
visited.push(value);
return false;
});
expect(visited).toEqual(["foo", "bar", undefined, "baz", undefined]);
});
});
test("filter, forEach, map, some", () => {
["filter", "forEach", "map", "some"].forEach(name => {
const visited = [];
Array.prototype[name].call(o, value => {
visited.push(value);
return false;
});
expect(visited).toEqual(["foo", "bar", "baz"]);
});
});
test("reduce", () => {
const visited = [];
Array.prototype.reduce.call(
o,
(_, value) => {
visited.push(value);
return false;
},
"initial"
);
expect(visited).toEqual(["foo", "bar", "baz"]);
});
test("reduceRight", () => {
const visited = [];
Array.prototype.reduceRight.call(
o,
(_, value) => {
visited.push(value);
return false;
},
"initial"
);
expect(visited).toEqual(["baz", "bar", "foo"]);
});
});

View file

@ -0,0 +1,43 @@
test("length is 1", () => {
expect(Array.prototype.concat).toHaveLength(1);
});
describe("normal behavior", () => {
var array = ["hello"];
test("no arguments", () => {
var concatenated = array.concat();
expect(array).toHaveLength(1);
expect(concatenated).toHaveLength(1);
});
test("single argument", () => {
var concatenated = array.concat("friends");
expect(array).toHaveLength(1);
expect(concatenated).toHaveLength(2);
expect(concatenated[0]).toBe("hello");
expect(concatenated[1]).toBe("friends");
});
test("single array argument", () => {
var concatenated = array.concat([1, 2, 3]);
expect(array).toHaveLength(1);
expect(concatenated).toHaveLength(4);
expect(concatenated[0]).toBe("hello");
expect(concatenated[1]).toBe(1);
expect(concatenated[2]).toBe(2);
expect(concatenated[3]).toBe(3);
});
test("multiple arguments", () => {
var concatenated = array.concat(false, "serenity", { name: "libjs" }, [1, [2, 3]]);
expect(array).toHaveLength(1);
expect(concatenated).toHaveLength(6);
expect(concatenated[0]).toBe("hello");
expect(concatenated[1]).toBeFalse();
expect(concatenated[2]).toBe("serenity");
expect(concatenated[3]).toEqual({ name: "libjs" });
expect(concatenated[4]).toBe(1);
expect(concatenated[5]).toEqual([2, 3]);
});
});

View file

@ -0,0 +1,55 @@
test("length is 1", () => {
expect(Array.prototype.every).toHaveLength(1);
});
describe("errors", () => {
test("requires at least one argument", () => {
expect(() => {
[].every();
}).toThrowWithMessage(TypeError, "Array.prototype.every() requires at least one argument");
});
test("callback must be a function", () => {
expect(() => {
[].every(undefined);
}).toThrowWithMessage(TypeError, "undefined is not a function");
});
});
describe("normal behavior", () => {
test("basic functionality", () => {
var arrayOne = ["serenity", { test: "serenity" }];
var arrayTwo = [true, false, 1, 2, 3, "3"];
expect(arrayOne.every(value => value === "hello")).toBeFalse();
expect(arrayOne.every(value => value === "serenity")).toBeFalse();
expect(arrayOne.every((value, index, arr) => index < 2)).toBeTrue();
expect(arrayOne.every(value => typeof value === "string")).toBeFalse();
expect(arrayOne.every(value => arrayOne.pop())).toBeTrue();
expect(arrayTwo.every((value, index, arr) => index > 0)).toBeFalse();
expect(arrayTwo.every((value, index, arr) => index >= 0)).toBeTrue();
expect(arrayTwo.every(value => typeof value !== "string")).toBeFalse();
expect(arrayTwo.every(value => typeof value === "number")).toBeFalse();
expect(arrayTwo.every(value => value > 0)).toBeFalse();
expect(arrayTwo.every(value => value >= 0 && value < 4)).toBeTrue();
expect(arrayTwo.every(value => arrayTwo.pop())).toBeTrue();
expect(["", "hello", "friends", "serenity"].every(value => value.length >= 0)).toBeTrue();
});
test("empty array", () => {
expect([].every(value => value === 1)).toBeTrue();
});
test("elements past the initial array size are ignored", () => {
var array = [1, 2, 3, 4, 5];
expect(
arrayTwo.every((value, index, arr) => {
arr.push(6);
return value <= 5;
})
).toBeTrue();
});
});

View file

@ -0,0 +1,20 @@
test("length is 1", () => {
expect(Array.prototype.fill).toHaveLength(1);
});
test("basic functionality", () => {
var array = [1, 2, 3, 4];
expect(array.fill(0, 2, 4)).toEqual([1, 2, 0, 0]);
expect(array.fill(5, 1)).toEqual([1, 5, 5, 5]);
expect(array.fill(6)).toEqual([6, 6, 6, 6]);
expect([1, 2, 3].fill(4)).toEqual([4, 4, 4]);
expect([1, 2, 3].fill(4, 1)).toEqual([1, 4, 4]);
expect([1, 2, 3].fill(4, 1, 2)).toEqual([1, 4, 3]);
expect([1, 2, 3].fill(4, 3, 3)).toEqual([1, 2, 3]);
expect([1, 2, 3].fill(4, -3, -2)).toEqual([4, 2, 3]);
expect([1, 2, 3].fill(4, NaN, NaN)).toEqual([1, 2, 3]);
expect([1, 2, 3].fill(4, 3, 5)).toEqual([1, 2, 3]);
expect(Array(3).fill(4)).toEqual([4, 4, 4]);
});

View file

@ -0,0 +1,68 @@
test("length is 1", () => {
expect(Array.prototype.filter).toHaveLength(1);
});
describe("errors", () => {
test("requires at least one argument", () => {
expect(() => {
[].filter();
}).toThrowWithMessage(TypeError, "Array.prototype.filter() requires at least one argument");
});
test("callback must be a function", () => {
expect(() => {
[].filter(undefined);
}).toThrowWithMessage(TypeError, "undefined is not a function");
});
});
describe("normal behavior", () => {
test("never calls callback with empty array", () => {
var callbackCalled = 0;
expect(
[].filter(() => {
callbackCalled++;
})
).toEqual([]);
expect(callbackCalled).toBe(0);
});
test("calls callback once for every item", () => {
var callbackCalled = 0;
expect(
[1, 2, 3].filter(() => {
callbackCalled++;
})
).toEqual([]);
expect(callbackCalled).toBe(3);
});
test("can filter based on callback return value", () => {
var evenNumbers = [0, 1, 2, 3, 4, 5, 6, 7].filter(x => x % 2 === 0);
expect(evenNumbers).toEqual([0, 2, 4, 6]);
var fruits = [
"Apple",
"Banana",
"Blueberry",
"Grape",
"Mango",
"Orange",
"Peach",
"Pineapple",
"Raspberry",
"Watermelon",
];
const filterItems = (arr, query) => {
return arr.filter(el => el.toLowerCase().indexOf(query.toLowerCase()) !== -1);
};
expect(filterItems(fruits, "Berry")).toEqual(["Blueberry", "Raspberry"]);
expect(filterItems(fruits, "P")).toEqual([
"Apple",
"Grape",
"Peach",
"Pineapple",
"Raspberry",
]);
});
});

View file

@ -0,0 +1,65 @@
test("length is 1", () => {
expect(Array.prototype.find).toHaveLength(1);
});
describe("errors", () => {
test("requires at least one argument", () => {
expect(() => {
[].find();
}).toThrowWithMessage(TypeError, "Array.prototype.find() requires at least one argument");
});
test("callback must be a function", () => {
expect(() => {
[].find(undefined);
}).toThrowWithMessage(TypeError, "undefined is not a function");
});
});
describe("normal behavior", () => {
test("basic functionality", () => {
var array = ["hello", "friends", 1, 2, false];
expect(array.find(value => value === "hello")).toBe("hello");
expect(array.find((value, index, arr) => index === 1)).toBe("friends");
expect(array.find(value => value == "1")).toBe(1);
expect(array.find(value => value === 1)).toBe(1);
expect(array.find(value => typeof value !== "string")).toBe(1);
expect(array.find(value => typeof value === "boolean")).toBeFalse();
expect(array.find(value => value > 1)).toBe(2);
expect(array.find(value => value > 1 && value < 3)).toBe(2);
expect(array.find(value => value > 100)).toBeUndefined();
expect([].find(value => value === 1)).toBeUndefined();
});
test("never calls callback with empty array", () => {
var callbackCalled = 0;
expect(
[].find(() => {
callbackCalled++;
})
).toBeUndefined();
expect(callbackCalled).toBe(0);
});
test("calls callback once for every item", () => {
var callbackCalled = 0;
expect(
[1, 2, 3].find(() => {
callbackCalled++;
})
).toBeUndefined();
expect(callbackCalled).toBe(3);
});
test("empty slots are treated as undefined", () => {
var callbackCalled = 0;
expect(
[1, , , "foo", , undefined, , ,].find(value => {
callbackCalled++;
return value === undefined;
})
).toBeUndefined();
expect(callbackCalled).toBe(2);
});
});

View file

@ -0,0 +1,68 @@
test("length is 1", () => {
expect(Array.prototype.findIndex).toHaveLength(1);
});
describe("errors", () => {
test("requires at least one argument", () => {
expect(() => {
[].findIndex();
}).toThrowWithMessage(
TypeError,
"Array.prototype.findIndex() requires at least one argument"
);
});
test("callback must be a function", () => {
expect(() => {
[].findIndex(undefined);
}).toThrowWithMessage(TypeError, "undefined is not a function");
});
});
describe("normal behavior", () => {
test("basic functionality", () => {
var array = ["hello", "friends", 1, 2, false];
expect(array.findIndex(value => value === "hello")).toBe(0);
expect(array.findIndex((value, index, arr) => index === 1)).toBe(1);
expect(array.findIndex(value => value == "1")).toBe(2);
expect(array.findIndex(value => value === 1)).toBe(2);
expect(array.findIndex(value => typeof value !== "string")).toBe(2);
expect(array.findIndex(value => typeof value === "boolean")).toBe(4);
expect(array.findIndex(value => value > 1)).toBe(3);
expect(array.findIndex(value => value > 1 && value < 3)).toBe(3);
expect(array.findIndex(value => value > 100)).toBe(-1);
expect([].findIndex(value => value === 1)).toBe(-1);
});
test("never calls callback with empty array", () => {
var callbackCalled = 0;
expect(
[].findIndex(() => {
callbackCalled++;
})
).toBe(-1);
expect(callbackCalled).toBe(0);
});
test("calls callback once for every item", () => {
var callbackCalled = 0;
expect(
[1, 2, 3].findIndex(() => {
callbackCalled++;
})
).toBe(-1);
expect(callbackCalled).toBe(3);
});
test("empty slots are treated as undefined", () => {
var callbackCalled = 0;
expect(
[1, , , "foo", , undefined, , ,].findIndex(value => {
callbackCalled++;
return value === undefined;
})
).toBe(1);
expect(callbackCalled).toBe(2);
});
});

View file

@ -0,0 +1,70 @@
test("length is 1", () => {
expect(Array.prototype.forEach).toHaveLength(1);
});
describe("errors", () => {
test("requires at least one argument", () => {
expect(() => {
[].forEach();
}).toThrowWithMessage(
TypeError,
"Array.prototype.forEach() requires at least one argument"
);
});
test("callback must be a function", () => {
expect(() => {
[].forEach(undefined);
}).toThrowWithMessage(TypeError, "undefined is not a function");
});
});
describe("normal behavior", () => {
test("never calls callback with empty array", () => {
var callbackCalled = 0;
expect(
[].forEach(() => {
callbackCalled++;
})
).toBeUndefined();
expect(callbackCalled).toBe(0);
});
test("calls callback once for every item", () => {
var callbackCalled = 0;
expect(
[1, 2, 3].forEach(() => {
callbackCalled++;
})
).toBeUndefined();
expect(callbackCalled).toBe(3);
});
test("callback receives value and index", () => {
var a = [1, 2, 3];
a.forEach((value, index) => {
expect(value).toBe(a[index]);
expect(index).toBe(a[index] - 1);
});
});
test("callback receives array", () => {
var callbackCalled = 0;
var a = [1, 2, 3];
a.forEach((_, __, array) => {
callbackCalled++;
expect(a).toEqual(array);
a.push("test");
});
expect(callbackCalled).toBe(3);
expect(a).toEqual([1, 2, 3, "test", "test", "test"]);
});
test("this value can be modified", () => {
var t = [];
[1, 2, 3].forEach(function (value) {
this.push(value);
}, t);
expect(t).toEqual([1, 2, 3]);
});
});

View file

@ -0,0 +1,18 @@
test("length is 1", () => {
expect(Array.prototype.includes).toHaveLength(1);
});
test("basic functionality", () => {
var array = ["hello", "friends", 1, 2, false];
expect([].includes()).toBeFalse();
expect([undefined].includes()).toBeTrue();
expect(array.includes("hello")).toBeTrue();
expect(array.includes(1)).toBeTrue();
expect(array.includes(1, -3)).toBeTrue();
expect(array.includes("serenity")).toBeFalse();
expect(array.includes(false, -1)).toBeTrue();
expect(array.includes(2, -1)).toBeFalse();
expect(array.includes(2, -100)).toBeTrue();
expect(array.includes("friends", 100)).toBeFalse();
});

View file

@ -0,0 +1,25 @@
test("length is 1", () => {
expect(Array.prototype.indexOf).toHaveLength(1);
});
test("basic functionality", () => {
var array = ["hello", "friends", 1, 2, false];
expect(array.indexOf("hello")).toBe(0);
expect(array.indexOf("friends")).toBe(1);
expect(array.indexOf(false)).toBe(4);
expect(array.indexOf(false, 2)).toBe(4);
expect(array.indexOf(false, -2)).toBe(4);
expect(array.indexOf(1)).toBe(2);
expect(array.indexOf(1, 1000)).toBe(-1);
expect(array.indexOf(1, -1000)).toBe(2);
expect(array.indexOf("serenity")).toBe(-1);
expect(array.indexOf(false, -1)).toBe(4);
expect(array.indexOf(2, -1)).toBe(-1);
expect(array.indexOf(2, -2)).toBe(3);
expect([].indexOf("serenity")).toBe(-1);
expect([].indexOf("serenity", 10)).toBe(-1);
expect([].indexOf("serenity", -10)).toBe(-1);
expect([].indexOf()).toBe(-1);
expect([undefined].indexOf()).toBe(0);
});

View file

@ -0,0 +1,24 @@
test("length is 1", () => {
expect(Array.prototype.join).toHaveLength(1);
});
test("basic functionality", () => {
expect(["hello", "friends"].join()).toBe("hello,friends");
expect(["hello", "friends"].join(undefined)).toBe("hello,friends");
expect(["hello", "friends"].join(" ")).toBe("hello friends");
expect(["hello", "friends", "foo"].join("~", "#")).toBe("hello~friends~foo");
expect([].join()).toBe("");
expect([null].join()).toBe("");
expect([undefined].join()).toBe("");
expect([undefined, null, ""].join()).toBe(",,");
expect([1, null, 2, undefined, 3].join()).toBe("1,,2,,3");
expect(Array(3).join()).toBe(",,");
});
test("circular references", () => {
const a = ["foo", [], [1, 2, []], ["bar"]];
a[1] = a;
a[2][2] = a;
// [ "foo", <circular>, [ 1, 2, <circular> ], [ "bar" ] ]
expect(a.join()).toBe("foo,,1,2,,bar");
});

View file

@ -0,0 +1,22 @@
test("length is 1", () => {
expect(Array.prototype.lastIndexOf).toHaveLength(1);
});
test("basic functionality", () => {
var array = [1, 2, 3, 1, "hello"];
expect(array.lastIndexOf("hello")).toBe(4);
expect(array.lastIndexOf("hello", 1000)).toBe(4);
expect(array.lastIndexOf(1)).toBe(3);
expect(array.lastIndexOf(1, -1)).toBe(3);
expect(array.lastIndexOf(1, -2)).toBe(3);
expect(array.lastIndexOf(2)).toBe(1);
expect(array.lastIndexOf(2, -3)).toBe(1);
expect(array.lastIndexOf(2, -4)).toBe(1);
expect([].lastIndexOf("hello")).toBe(-1);
expect([].lastIndexOf("hello", 10)).toBe(-1);
expect([].lastIndexOf("hello", -10)).toBe(-1);
expect([].lastIndexOf()).toBe(-1);
expect([undefined].lastIndexOf()).toBe(0);
expect([undefined, undefined, undefined].lastIndexOf()).toBe(2);
});

View file

@ -0,0 +1,57 @@
test("length is 1", () => {
expect(Array.prototype.map).toHaveLength(1);
});
describe("errors", () => {
test("requires at least one argument", () => {
expect(() => {
[].map();
}).toThrowWithMessage(TypeError, "Array.prototype.map() requires at least one argument");
});
test("callback must be a function", () => {
expect(() => {
[].map(undefined);
}).toThrowWithMessage(TypeError, "undefined is not a function");
});
});
describe("normal behavior", () => {
test("never calls callback with empty array", () => {
var callbackCalled = 0;
expect(
[].map(() => {
callbackCalled++;
})
).toEqual([]);
expect(callbackCalled).toBe(0);
});
test("calls callback once for every item", () => {
var callbackCalled = 0;
expect(
[1, 2, 3].map(() => {
callbackCalled++;
})
).toEqual([undefined, undefined, undefined]);
expect(callbackCalled).toBe(3);
});
test("can map based on callback return value", () => {
expect(
[undefined, null, true, "foo", 42, {}].map(
(value, index) => "" + index + " -> " + value
)
).toEqual([
"0 -> undefined",
"1 -> null",
"2 -> true",
"3 -> foo",
"4 -> 42",
"5 -> [object Object]",
]);
var squaredNumbers = [0, 1, 2, 3, 4].map(x => x ** 2);
expect(squaredNumbers).toEqual([0, 1, 4, 9, 16]);
});
});

View file

@ -0,0 +1,29 @@
test("length is 0", () => {
expect(Array.prototype.pop).toHaveLength(0);
});
describe("normal behavior", () => {
test("array with elements", () => {
var a = [1, 2, 3];
expect(a.pop()).toBe(3);
expect(a).toEqual([1, 2]);
expect(a.pop()).toBe(2);
expect(a).toEqual([1]);
expect(a.pop()).toBe(1);
expect(a).toEqual([]);
expect(a.pop()).toBeUndefined();
expect(a).toEqual([]);
});
test("empty array", () => {
var a = [];
expect(a.pop()).toBeUndefined();
expect(a).toEqual([]);
});
test("array with empty slot", () => {
var a = [,];
expect(a.pop()).toBeUndefined();
expect(a).toEqual([]);
});
});

View file

@ -0,0 +1,23 @@
test("length is 1", () => {
expect(Array.prototype.push).toHaveLength(1);
});
describe("normal behavior", () => {
test("no argument", () => {
var a = ["hello"];
expect(a.push()).toBe(1);
expect(a).toEqual(["hello"]);
});
test("single argument", () => {
var a = ["hello"];
expect(a.push("friends")).toBe(2);
expect(a).toEqual(["hello", "friends"]);
});
test("multiple arguments", () => {
var a = ["hello", "friends"];
expect(a.push(1, 2, 3)).toBe(5);
expect(a).toEqual(["hello", "friends", 1, 2, 3]);
});
});

View file

@ -0,0 +1,113 @@
test("length is 1", () => {
expect(Array.prototype.reduce).toHaveLength(1);
});
describe("errors", () => {
test("requires at least one argument", () => {
expect(() => {
[].reduce();
}).toThrowWithMessage(TypeError, "Array.prototype.reduce() requires at least one argument");
});
test("callback must be a function", () => {
expect(() => {
[].reduce(undefined);
}).toThrowWithMessage(TypeError, "undefined is not a function");
});
test("reduce of empty array with no initial value", () => {
expect(() => {
[].reduce((a, x) => x);
}).toThrowWithMessage(TypeError, "Reduce of empty array with no initial value");
});
test("reduce of array with only empty slots and no initial value", () => {
expect(() => {
[, ,].reduce((a, x) => x);
}).toThrowWithMessage(TypeError, "Reduce of empty array with no initial value");
});
});
describe("normal behavior", () => {
test("basic functionality", () => {
[1, 2].reduce(function () {
expect(this).toBeUndefined();
});
var callbackCalled = 0;
var callback = () => {
callbackCalled++;
return true;
};
expect([1].reduce(callback)).toBe(1);
expect(callbackCalled).toBe(0);
expect([, 1].reduce(callback)).toBe(1);
expect(callbackCalled).toBe(0);
callbackCalled = 0;
expect([1, 2, 3].reduce(callback)).toBeTrue();
expect(callbackCalled).toBe(2);
callbackCalled = 0;
expect([, , 1, 2, 3].reduce(callback)).toBeTrue();
expect(callbackCalled).toBe(2);
callbackCalled = 0;
expect([1, , , 10, , 100, , ,].reduce(callback)).toBeTrue();
expect(callbackCalled).toBe(2);
var constantlySad = () => ":^(";
var result = [].reduce(constantlySad, ":^)");
expect(result).toBe(":^)");
result = [":^0"].reduce(constantlySad, ":^)");
expect(result).toBe(":^(");
result = [":^0"].reduce(constantlySad);
expect(result).toBe(":^0");
result = [5, 4, 3, 2, 1].reduce((accum, elem) => accum + elem);
expect(result).toBe(15);
result = [1, 2, 3, 4, 5, 6].reduce((accum, elem) => accum + elem, 100);
expect(result).toBe(121);
result = [6, 5, 4, 3, 2, 1].reduce((accum, elem) => {
return accum + elem;
}, 100);
expect(result).toBe(121);
var indexes = [];
result = ["foo", 1, true].reduce((a, v, i) => {
indexes.push(i);
});
expect(result).toBeUndefined();
expect(indexes.length).toBe(2);
expect(indexes[0]).toBe(1);
expect(indexes[1]).toBe(2);
indexes = [];
result = ["foo", 1, true].reduce((a, v, i) => {
indexes.push(i);
}, "foo");
expect(result).toBeUndefined();
expect(indexes).toEqual([0, 1, 2]);
var mutable = { prop: 0 };
result = ["foo", 1, true].reduce((a, v) => {
a.prop = v;
return a;
}, mutable);
expect(result).toBe(mutable);
expect(result.prop).toBeTrue();
var a1 = [1, 2];
var a2 = null;
a1.reduce((a, v, i, t) => {
a2 = t;
});
expect(a1).toBe(a2);
});
});

View file

@ -0,0 +1,118 @@
test("length is 1", () => {
expect(Array.prototype.reduceRight).toHaveLength(1);
});
describe("errors", () => {
test("requires at least one argument", () => {
expect(() => {
[].reduceRight();
}).toThrowWithMessage(
TypeError,
"Array.prototype.reduceRight() requires at least one argument"
);
});
test("callback must be a function", () => {
expect(() => {
[].reduceRight(undefined);
}).toThrowWithMessage(TypeError, "undefined is not a function");
});
test("reduce of empty array with no initial value", () => {
expect(() => {
[].reduceRight((a, x) => x);
}).toThrowWithMessage(TypeError, "Reduce of empty array with no initial value");
});
test("reduce of array with only empty slots and no initial value", () => {
expect(() => {
[, ,].reduceRight((a, x) => x);
}).toThrowWithMessage(TypeError, "Reduce of empty array with no initial value");
});
});
describe("normal behavior", () => {
test("basic functionality", () => {
[1, 2].reduceRight(function () {
expect(this).toBeUndefined();
});
var callbackCalled = 0;
var callback = () => {
callbackCalled++;
return true;
};
expect([1].reduceRight(callback)).toBe(1);
expect(callbackCalled).toBe(0);
expect([1].reduceRight(callback)).toBe(1);
expect(callbackCalled).toBe(0);
callbackCalled = 0;
expect([1, 2, 3].reduceRight(callback)).toBe(true);
expect(callbackCalled).toBe(2);
callbackCalled = 0;
expect([1, 2, 3, ,].reduceRight(callback)).toBe(true);
expect(callbackCalled).toBe(2);
callbackCalled = 0;
expect([, , , 1, , , 10, , 100, , ,].reduceRight(callback)).toBe(true);
expect(callbackCalled).toBe(2);
var constantlySad = () => ":^(";
var result = [].reduceRight(constantlySad, ":^)");
expect(result).toBe(":^)");
result = [":^0"].reduceRight(constantlySad, ":^)");
expect(result).toBe(":^(");
result = [":^0"].reduceRight(constantlySad);
expect(result).toBe(":^0");
result = [5, 4, 3, 2, 1].reduceRight((accum, elem) => "" + accum + elem);
expect(result).toBe("12345");
result = [1, 2, 3, 4, 5, 6].reduceRight((accum, elem) => {
return "" + accum + elem;
}, 100);
expect(result).toBe("100654321");
result = [6, 5, 4, 3, 2, 1].reduceRight((accum, elem) => {
return "" + accum + elem;
}, 100);
expect(result).toBe("100123456");
var indexes = [];
result = ["foo", 1, true].reduceRight((a, v, i) => {
indexes.push(i);
});
expect(result).toBeUndefined();
expect(indexes.length).toBe(2);
expect(indexes[0]).toBe(1);
expect(indexes[1]).toBe(0);
indexes = [];
result = ["foo", 1, true].reduceRight((a, v, i) => {
indexes.push(i);
}, "foo");
expect(result).toBeUndefined();
expect(indexes).toEqual([2, 1, 0]);
var mutable = { prop: 0 };
result = ["foo", 1, true].reduceRight((a, v) => {
a.prop = v;
return a;
}, mutable);
expect(result).toBe(mutable);
expect(result.prop).toBe("foo");
var a1 = [1, 2];
var a2 = null;
a1.reduceRight((a, v, i, t) => {
a2 = t;
});
expect(a1).toBe(a2);
});
});

View file

@ -0,0 +1,9 @@
test("length is 0", () => {
expect(Array.prototype.reverse).toHaveLength(0);
});
test("basic functionality", () => {
var array = [1, 2, 3];
expect(array.reverse()).toEqual([3, 2, 1]);
expect(array).toEqual([3, 2, 1]);
});

View file

@ -0,0 +1,23 @@
test("length is 0", () => {
expect(Array.prototype.shift).toHaveLength(0);
});
describe("normal behavior", () => {
test("array with elements", () => {
var a = [1, 2, 3];
expect(a.shift()).toBe(1);
expect(a).toEqual([2, 3]);
});
test("empty array", () => {
var a = [];
expect(a.shift()).toBeUndefined();
expect(a).toEqual([]);
});
test("array with empty slot", () => {
var a = [,];
expect(a.shift()).toBeUndefined();
expect(a).toEqual([]);
});
});

View file

@ -0,0 +1,39 @@
test("length is 0", () => {
expect(Array.prototype.slice).toHaveLength(2);
});
test("basic functionality", () => {
var array = ["hello", "friends", "serenity", 1];
var slice = array.slice();
expect(array).toEqual(["hello", "friends", "serenity", 1]);
expect(slice).toEqual(["hello", "friends", "serenity", 1]);
slice = array.slice(1);
expect(array).toEqual(["hello", "friends", "serenity", 1]);
expect(slice).toEqual(["friends", "serenity", 1]);
slice = array.slice(0, 2);
expect(array).toEqual(["hello", "friends", "serenity", 1]);
expect(slice).toEqual(["hello", "friends"]);
slice = array.slice(-1);
expect(array).toEqual(["hello", "friends", "serenity", 1]);
expect(slice).toEqual([1]);
slice = array.slice(1, 1);
expect(array).toEqual(["hello", "friends", "serenity", 1]);
expect(slice).toEqual([]);
slice = array.slice(1, -1);
expect(array).toEqual(["hello", "friends", "serenity", 1]);
expect(slice).toEqual(["friends", "serenity"]);
slice = array.slice(2, -1);
expect(array).toEqual(["hello", "friends", "serenity", 1]);
expect(slice).toEqual(["serenity"]);
slice = array.slice(0, 100);
expect(array).toEqual(["hello", "friends", "serenity", 1]);
expect(slice).toEqual(["hello", "friends", "serenity", 1]);
});

View file

@ -0,0 +1,37 @@
test("length is 1", () => {
expect(Array.prototype.some).toHaveLength(1);
});
describe("errors", () => {
test("requires at least one argument", () => {
expect(() => {
[].some();
}).toThrowWithMessage(TypeError, "Array.prototype.some() requires at least one argument");
});
test("callback must be a function", () => {
expect(() => {
[].some(undefined);
}).toThrowWithMessage(TypeError, "undefined is not a function");
});
});
test("basic functionality", () => {
var array = ["hello", "friends", 1, 2, false, -42, { name: "serenityos" }];
expect(array.some(value => value === "hello")).toBeTrue();
expect(array.some(value => value === "serenity")).toBeFalse();
expect(array.some((value, index, arr) => index === 1)).toBeTrue();
expect(array.some(value => value == "1")).toBeTrue();
expect(array.some(value => value === 1)).toBeTrue();
expect(array.some(value => value === 13)).toBeFalse();
expect(array.some(value => typeof value !== "string")).toBeTrue();
expect(array.some(value => typeof value === "boolean")).toBeTrue();
expect(array.some(value => value > 1)).toBeTrue();
expect(array.some(value => value > 1 && value < 3)).toBeTrue();
expect(array.some(value => value > 100)).toBeFalse();
expect(array.some(value => value < 0)).toBeTrue();
expect(array.some(value => array.pop())).toBeTrue();
expect(["", "hello", "friends", "serenity"].some(value => value.length === 0)).toBeTrue();
expect([].some(value => value === 1)).toBeFalse();
});

View file

@ -0,0 +1,204 @@
describe("Array.prototype.sort", () => {
test("basic functionality", () => {
expect(Array.prototype.sort).toHaveLength(1);
var arr = ["c", "b", "d", "a"];
expect(arr.sort()).toEqual(arr);
expect(arr).toEqual(["a", "b", "c", "d"]);
arr = ["aa", "a"];
expect(arr.sort()).toEqual(arr);
expect(arr).toEqual(["a", "aa"]);
arr = [1, 0];
expect(arr.sort()).toBe(arr); // should be exactly same object
expect(arr).toEqual([0, 1]);
// numbers are sorted as strings
arr = [205, -123, 22, 200, 3, -20, -2, -1, 25, 2, 0, 1];
expect(arr.sort()).toEqual([-1, -123, -2, -20, 0, 1, 2, 200, 205, 22, 25, 3]);
// mix of data, including empty slots and undefined
arr = ["2", Infinity, null, null, , undefined, 5, , undefined, null, 54, "5"];
expect(arr.sort()).toEqual([
"2",
5,
"5",
54,
Infinity,
null,
null,
null,
undefined,
undefined,
,
,
]);
expect(arr.length).toEqual(12);
// undefined compare function
arr = ["2", Infinity, null, null, , undefined, 5n, , undefined, null, 54, "5"];
expect(arr.sort(undefined)).toEqual([
"2",
5n,
"5",
54,
Infinity,
null,
null,
null,
undefined,
undefined,
,
,
]);
expect(arr.length).toEqual(12);
// numeric data with compare function to sort numerically
arr = [50, 500, 5, Infinity, -Infinity, 0, 10, -10, 1, -1, 5, 0, 15, Infinity];
expect(arr.sort((a, b) => a - b)).toEqual([
-Infinity,
-10,
-1,
0,
0,
1,
5,
5,
10,
15,
50,
500,
Infinity,
Infinity,
]);
expect(arr.length).toEqual(14);
// numeric data with compare function to sort reverse numerically
arr = [50, 500, 5, Infinity, -Infinity, 0, 10, -10, 1, -1, 5, 0, 15, Infinity];
expect(arr.sort((a, b) => b - a)).toEqual([
Infinity,
Infinity,
500,
50,
15,
10,
5,
5,
1,
0,
0,
-1,
-10,
-Infinity,
]);
// small/edge cases
expect([].sort()).toEqual([]);
expect([5].sort()).toEqual([5]);
expect([5, 5].sort()).toEqual([5, 5]);
expect([undefined].sort()).toEqual([undefined]);
expect([undefined, undefined].sort()).toEqual([undefined, undefined]);
expect([,].sort()).toEqual([,]);
expect([, ,].sort()).toEqual([, ,]);
expect([5, ,].sort()).toEqual([5, ,]);
expect([, , 5].sort()).toEqual([5, , ,]);
// sorting should be stable
arr = [
{ sorted_key: 2, other_property: 1 },
{ sorted_key: 2, other_property: 2 },
{ sorted_key: 1, other_property: 3 },
];
arr.sort((a, b) => a.sorted_key - b.sorted_key);
expect(arr[1].other_property == 1);
expect(arr[2].other_property == 2);
});
test("that it makes no unnecessary calls to compare function", () => {
expectNoCallCompareFunction = function (a, b) {
expect().fail();
};
expect([].sort(expectNoCallCompareFunction)).toEqual([]);
expect([1].sort(expectNoCallCompareFunction)).toEqual([1]);
expect([1, undefined].sort(expectNoCallCompareFunction)).toEqual([1, undefined]);
expect([undefined, undefined].sort(expectNoCallCompareFunction)).toEqual([
undefined,
undefined,
]);
expect([, , 1, ,].sort(expectNoCallCompareFunction)).toEqual([1, , , ,]);
expect([undefined, , 1, , undefined, ,].sort(expectNoCallCompareFunction)).toEqual([
1,
undefined,
undefined,
,
,
,
]);
});
test("that it works on non-arrays", () => {
var obj = { length: 0 };
expect(Array.prototype.sort.call(obj)).toBe(obj);
expect(obj).toEqual({ length: 0 });
obj = { 0: 1, length: 0 };
expect(Array.prototype.sort.call(obj, undefined)).toBe(obj);
expect(obj).toEqual({ 0: 1, length: 0 });
obj = { 0: 3, 1: 2, 2: 1, 3: 0, length: 2 };
expect(Array.prototype.sort.call(obj)).toBe(obj);
expect(obj).toEqual({ 0: 2, 1: 3, 2: 1, 3: 0, length: 2 });
obj = { 0: 3, 1: 2, 2: 1, a: "b", hello: "friends!", length: 2 };
expect(Array.prototype.sort.call(obj)).toBe(obj);
expect(obj).toEqual({ 0: 2, 1: 3, 2: 1, 3: 0, a: "b", hello: "friends!", length: 2 });
obj = { 0: 2, 1: 3, 2: 1, a: "b", hello: "friends!", length: 2 };
expect(
Array.prototype.sort.call(obj, (a, b) => {
expect(a == 2 || a == 3).toBeTrue();
expect(b == 2 || b == 3).toBeTrue();
return b - a;
})
).toBe(obj);
expect(obj).toEqual({ 0: 3, 1: 2, 2: 1, 3: 0, a: "b", hello: "friends!", length: 2 });
});
test("that it handles abrupt completions correctly", () => {
class TestError extends Error {
constructor() {
super();
this.name = "TestError";
}
}
arr = [1, 2, 3];
expect(() =>
arr.sort((a, b) => {
throw new TestError();
})
).toThrow(TestError);
class DangerousToString {
toString() {
throw new TestError();
}
}
arr = [new DangerousToString(), new DangerousToString()];
expect(() => arr.sort()).toThrow(TestError);
});
test("that it does not use deleteProperty unnecessarily", () => {
var obj = new Proxy(
{ 0: 5, 1: 4, 2: 3, length: 3 },
{
deleteProperty: function (target, property) {
expect().fail();
},
}
);
Array.prototype.sort.call(obj);
});
});

View file

@ -0,0 +1,49 @@
test("length is 2", () => {
expect(Array.prototype.splice).toHaveLength(2);
});
test("basic functionality", () => {
var array = ["hello", "friends", "serenity", 1, 2];
var removed = array.splice(3);
expect(array).toEqual(["hello", "friends", "serenity"]);
expect(removed).toEqual([1, 2]);
array = ["hello", "friends", "serenity", 1, 2];
removed = array.splice(-2);
expect(array).toEqual(["hello", "friends", "serenity"]);
expect(removed).toEqual([1, 2]);
array = ["hello", "friends", "serenity", 1, 2];
removed = array.splice(-2, 1);
expect(array).toEqual(["hello", "friends", "serenity", 2]);
expect(removed).toEqual([1]);
array = ["serenity"];
removed = array.splice(0, 0, "hello", "friends");
expect(array).toEqual(["hello", "friends", "serenity"]);
expect(removed).toEqual([]);
array = ["goodbye", "friends", "serenity"];
removed = array.splice(0, 1, "hello");
expect(array).toEqual(["hello", "friends", "serenity"]);
expect(removed).toEqual(["goodbye"]);
array = ["foo", "bar", "baz"];
removed = array.splice();
expect(array).toEqual(["foo", "bar", "baz"]);
expect(removed).toEqual([]);
removed = array.splice(0, 123);
expect(array).toEqual([]);
expect(removed).toEqual(["foo", "bar", "baz"]);
array = ["foo", "bar", "baz"];
removed = array.splice(123, 123);
expect(array).toEqual(["foo", "bar", "baz"]);
expect(removed).toEqual([]);
array = ["foo", "bar", "baz"];
removed = array.splice(-123, 123);
expect(array).toEqual([]);
expect(removed).toEqual(["foo", "bar", "baz"]);
});

View file

@ -0,0 +1,62 @@
test("length is 0", () => {
expect(Array.prototype.toLocaleString).toHaveLength(0);
});
describe("normal behavior", () => {
test("array with no elements", () => {
expect([].toLocaleString()).toBe("");
});
test("array with one element", () => {
expect(["foo"].toLocaleString()).toBe("foo");
});
test("array with multiple elements", () => {
expect(["foo", "bar", "baz"].toLocaleString()).toBe("foo,bar,baz");
});
test("null and undefined result in empty strings", () => {
expect([null].toLocaleString()).toBe("");
expect([undefined].toLocaleString()).toBe("");
expect([undefined, null].toLocaleString()).toBe(",");
});
test("empty values result in empty strings", () => {
expect(new Array(1).toLocaleString()).toBe("");
expect(new Array(3).toLocaleString()).toBe(",,");
var a = new Array(5);
a[2] = "foo";
a[4] = "bar";
expect(a.toLocaleString()).toBe(",,foo,,bar");
});
test("getter property is included in returned string", () => {
var a = ["foo"];
Object.defineProperty(a, 1, {
get() {
return "bar";
},
});
expect(a.toLocaleString()).toBe("foo,bar");
});
test("array with elements that have a custom toString() function", () => {
var toStringCalled = 0;
var o = {
toString() {
toStringCalled++;
return "o";
},
};
expect([o, undefined, o, null, o].toLocaleString()).toBe("o,,o,,o");
expect(toStringCalled).toBe(3);
});
test("array with circular references", () => {
const a = ["foo", [], [1, 2, []], ["bar"]];
a[1] = a;
a[2][2] = a;
// [ "foo", <circular>, [ 1, 2, <circular> ], [ "bar" ] ]
expect(a.toLocaleString()).toBe("foo,,1,2,,bar");
});
});

View file

@ -0,0 +1,66 @@
test("length is 0", () => {
expect(Array.prototype.toString).toHaveLength(0);
});
describe("normal behavior", () => {
test("array with no elements", () => {
expect([].toString()).toBe("");
});
test("array with one element", () => {
expect([1].toString()).toBe("1");
});
test("array with multiple elements", () => {
expect([1, 2, 3].toString()).toBe("1,2,3");
});
test("string and array concatenation", () => {
expect("rgb(" + [10, 11, 12] + ")").toBe("rgb(10,11,12)");
});
test("null and undefined result in empty strings", () => {
expect([null].toString()).toBe("");
expect([undefined].toString()).toBe("");
expect([undefined, null].toString()).toBe(",");
});
test("empty values result in empty strings", () => {
expect(new Array(1).toString()).toBe("");
expect(new Array(3).toString()).toBe(",,");
var a = new Array(5);
a[2] = "foo";
a[4] = "bar";
expect(a.toString()).toBe(",,foo,,bar");
});
test("getter property is included in returned string", () => {
var a = [1, 2, 3];
Object.defineProperty(a, 3, {
get() {
return 10;
},
});
expect(a.toString()).toBe("1,2,3,10");
});
test("array with elements that have a custom toString() function", () => {
var toStringCalled = 0;
var o = {
toString() {
toStringCalled++;
return "o";
},
};
expect([o, undefined, o, null, o].toString()).toBe("o,,o,,o");
expect(toStringCalled).toBe(3);
});
test("array with circular references", () => {
const a = ["foo", [], [1, 2, []], ["bar"]];
a[1] = a;
a[2][2] = a;
// [ "foo", <circular>, [ 1, 2, <circular> ], [ "bar" ] ]
expect(a.toString()).toBe("foo,,1,2,,bar");
});
});

View file

@ -0,0 +1,23 @@
test("length is 1", () => {
expect(Array.prototype.unshift).toHaveLength(1);
});
describe("normal behavior", () => {
test("no argument", () => {
var a = ["hello"];
expect(a.unshift()).toBe(1);
expect(a).toEqual(["hello"]);
});
test("single argument", () => {
var a = ["hello"];
expect(a.unshift("friends")).toBe(2);
expect(a).toEqual(["friends", "hello"]);
});
test("multiple arguments", () => {
var a = ["friends", "hello"];
expect(a.unshift(1, 2, 3)).toBe(5);
expect(a).toEqual([1, 2, 3, "friends", "hello"]);
});
});

View file

@ -0,0 +1,44 @@
test("length", () => {
expect(Array.prototype.values.length).toBe(0);
});
test("basic functionality", () => {
const a = [1, 2, 3];
const it = a.values();
expect(it.next()).toEqual({ value: 1, done: false });
expect(it.next()).toEqual({ value: 2, done: false });
expect(it.next()).toEqual({ value: 3, done: false });
expect(it.next()).toEqual({ value: undefined, done: true });
expect(it.next()).toEqual({ value: undefined, done: true });
expect(it.next()).toEqual({ value: undefined, done: true });
});
test("works when applied to non-object", () => {
[true, false, 9, 2n, Symbol()].forEach(primitive => {
const it = [].values.call(primitive);
expect(it.next()).toEqual({ value: undefined, done: true });
expect(it.next()).toEqual({ value: undefined, done: true });
expect(it.next()).toEqual({ value: undefined, done: true });
});
});
test("item added to array before exhaustion is accessible", () => {
const a = [1, 2];
const it = a.values();
expect(it.next()).toEqual({ value: 1, done: false });
expect(it.next()).toEqual({ value: 2, done: false });
a.push(3);
expect(it.next()).toEqual({ value: 3, done: false });
expect(it.next()).toEqual({ value: undefined, done: true });
expect(it.next()).toEqual({ value: undefined, done: true });
});
test("item added to array after exhaustion is inaccessible", () => {
const a = [1, 2];
const it = a.values();
expect(it.next()).toEqual({ value: 1, done: false });
expect(it.next()).toEqual({ value: 2, done: false });
expect(it.next()).toEqual({ value: undefined, done: true });
a.push(3);
expect(it.next()).toEqual({ value: undefined, done: true });
});

View file

@ -0,0 +1,57 @@
test("basic functionality", () => {
var a = [1, 2, 3];
expect(typeof a).toBe("object");
expect(a).toHaveLength(3);
expect(a[0]).toBe(1);
expect(a[1]).toBe(2);
expect(a[2]).toBe(3);
a[1] = 5;
expect(a[1]).toBe(5);
expect(a).toHaveLength(3);
a.push(7);
expect(a[3]).toBe(7);
expect(a).toHaveLength(4);
a = [,];
expect(a).toHaveLength(1);
expect(a.toString()).toBe("");
expect(a[0]).toBeUndefined();
a = [, , , ,];
expect(a).toHaveLength(4);
expect(a.toString()).toBe(",,,");
expect(a[0]).toBeUndefined();
expect(a[1]).toBeUndefined();
expect(a[2]).toBeUndefined();
expect(a[3]).toBeUndefined();
a = [1, , 2, , , 3];
expect(a).toHaveLength(6);
expect(a.toString()).toBe("1,,2,,,3");
expect(a[0]).toBe(1);
expect(a[1]).toBeUndefined();
expect(a[2]).toBe(2);
expect(a[3]).toBeUndefined();
expect(a[4]).toBeUndefined();
expect(a[5]).toBe(3);
a = [1, , 2, , , 3];
Object.defineProperty(a, 1, {
get() {
return this.getterSetterValue;
},
set(value) {
this.getterSetterValue = value;
},
});
expect(a).toHaveLength(6);
expect(a.toString()).toBe("1,,2,,,3");
expect(a.getterSetterValue).toBeUndefined();
a[1] = 20;
expect(a).toHaveLength(6);
expect(a.toString()).toBe("1,20,2,,,3");
expect(a.getterSetterValue).toBe(20);
});

View file

@ -0,0 +1,37 @@
describe("errors", () => {
test("invalid array length value", () => {
var a = [1, 2, 3];
[undefined, "foo", -1, Infinity, -Infinity, NaN].forEach(value => {
expect(() => {
a.length = value;
}).toThrowWithMessage(RangeError, "Invalid array length");
expect(a).toHaveLength(3);
});
});
});
describe("normal behavior", () => {
test("extend array by setting length", () => {
var a = [1, 2, 3];
a.length = 5;
expect(a).toEqual([1, 2, 3, undefined, undefined]);
});
test("truncate array by setting length", () => {
var a = [1, 2, 3];
a.length = 2;
expect(a).toEqual([1, 2]);
a.length = 0;
expect(a).toEqual([]);
});
test("length value is coerced to number if possible", () => {
var a = [1, 2, 3];
a.length = "42";
expect(a).toHaveLength(42);
a.length = [];
expect(a).toHaveLength(0);
a.length = true;
expect(a).toHaveLength(1);
});
});

View file

@ -0,0 +1,19 @@
test("Issue #1992, shrinking array during find() iteration", () => {
var a, callbackCalled;
callbackCalled = 0;
a = [1, 2, 3, 4, 5];
a.find(() => {
callbackCalled++;
a.pop();
});
expect(callbackCalled).toBe(5);
callbackCalled = 0;
a = [1, 2, 3, 4, 5];
a.findIndex(() => {
callbackCalled++;
a.pop();
});
expect(callbackCalled).toBe(5);
});

View file

@ -0,0 +1,15 @@
describe("Issue #3382", () => {
test("Creating an array with simple storage (<= 200 initial elements)", () => {
var a = Array(200);
expect(a).toHaveLength(200);
expect(a.push("foo")).toBe(201);
expect(a).toHaveLength(201);
});
test("Creating an array with generic storage (> 200 initial elements)", () => {
var a = Array(201);
expect(a).toHaveLength(201);
expect(a.push("foo")).toBe(202);
expect(a).toHaveLength(202);
});
});

View file

@ -0,0 +1,25 @@
describe("errors", () => {
test("cannot spread number in array", () => {
expect(() => {
[...1];
}).toThrowWithMessage(TypeError, "1 is not iterable");
});
test("cannot spread object in array", () => {
expect(() => {
[...{}];
}).toThrowWithMessage(TypeError, "[object Object] is not iterable");
});
});
test("basic functionality", () => {
expect([1, ...[2, 3], 4]).toEqual([1, 2, 3, 4]);
let a = [2, 3];
expect([1, ...a, 4]).toEqual([1, 2, 3, 4]);
let obj = { a: [2, 3] };
expect([1, ...obj.a, 4]).toEqual([1, 2, 3, 4]);
expect([...[], ...[...[1, 2, 3]], 4]).toEqual([1, 2, 3, 4]);
});

View file

@ -0,0 +1,27 @@
// Update when more typed arrays get added
const TYPED_ARRAYS = [
Uint8Array,
Uint16Array,
Uint32Array,
Int8Array,
Int16Array,
Int32Array,
Float32Array,
Float64Array,
];
test("basic functionality", () => {
expect(ArrayBuffer.isView).toHaveLength(1);
expect(ArrayBuffer.isView()).toBeFalse();
expect(ArrayBuffer.isView(null)).toBeFalse();
expect(ArrayBuffer.isView(undefined)).toBeFalse();
expect(ArrayBuffer.isView([])).toBeFalse();
expect(ArrayBuffer.isView({})).toBeFalse();
expect(ArrayBuffer.isView(123)).toBeFalse();
expect(ArrayBuffer.isView("foo")).toBeFalse();
expect(ArrayBuffer.isView(new ArrayBuffer())).toBeFalse();
TYPED_ARRAYS.forEach(T => {
expect(ArrayBuffer.isView(new T())).toBeTrue();
});
});

View file

@ -0,0 +1,13 @@
test("basic functionality", () => {
expect(ArrayBuffer).toHaveLength(1);
expect(ArrayBuffer.name).toBe("ArrayBuffer");
expect(ArrayBuffer.prototype.constructor).toBe(ArrayBuffer);
expect(new ArrayBuffer()).toBeInstanceOf(ArrayBuffer);
expect(typeof new ArrayBuffer()).toBe("object");
});
test("ArrayBuffer constructor must be invoked with 'new'", () => {
expect(() => {
ArrayBuffer();
}).toThrowWithMessage(TypeError, "ArrayBuffer constructor must be called with 'new'");
});

View file

@ -0,0 +1,6 @@
test("basic functionality", () => {
expect(new ArrayBuffer().byteLength).toBe(0);
expect(new ArrayBuffer(1).byteLength).toBe(1);
expect(new ArrayBuffer(64).byteLength).toBe(64);
expect(new ArrayBuffer(123).byteLength).toBe(123);
});

View file

@ -0,0 +1,68 @@
describe("correct behavior", () => {
test("basic functionality", () => {
expect(BigInt).toHaveLength(1);
expect(BigInt.name).toBe("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);
});
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
);
});
test("constructor with objects", () => {
expect(BigInt([])).toBe(0n);
});
});
describe("errors", () => {
test('cannot be constructed with "new"', () => {
expect(() => {
new BigInt();
}).toThrowWithMessage(TypeError, "BigInt is not a constructor");
});
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);
}).toThrowWithMessage(SyntaxError, `Invalid value for BigInt: ${value}`);
});
});
test("invalid numeric arguments", () => {
[1.23, Infinity, -Infinity, NaN].forEach(value => {
expect(() => {
BigInt(value);
}).toThrowWithMessage(RangeError, "BigInt argument must be an integer");
});
});
});

View file

@ -0,0 +1,3 @@
test("basic functionality", () => {
expect(BigInt.prototype[Symbol.toStringTag]).toBe("BigInt");
});

View file

@ -0,0 +1,10 @@
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");
});

View file

@ -0,0 +1,10 @@
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");
});

View file

@ -0,0 +1,12 @@
test("basic functionality", () => {
expect(BigInt.prototype.valueOf).toHaveLength(0);
expect(typeof BigInt(123).valueOf()).toBe("bigint");
// FIXME: Uncomment once we support Object() with argument
// 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");
});

View file

@ -0,0 +1,80 @@
describe("correct behavior", () => {
test("typeof bigint", () => {
expect(typeof 1n).toBe("bigint");
});
test("bigint string coercion", () => {
expect("" + 123n).toBe("123");
});
test("arithmetic operators", () => {
let bigint = 123n;
expect(-bigint).toBe(-123n);
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);
});
test("bitwise operators", () => {
expect(12n & 5n).toBe(4n);
expect(1n | 2n).toBe(3n);
expect(5n ^ 3n).toBe(6n);
expect(~1n).toBe(-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);
});
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();
expect(1n != 1n).toBeFalse();
expect(1n != 1).toBeFalse();
expect(1 != 1n).toBeFalse();
expect(1n != 1.23).toBeTrue();
expect(1.23 != 1n).toBeTrue();
});
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();
expect(1n !== 1n).toBeFalse();
expect(1n !== 1).toBeTrue();
expect(1 !== 1n).toBeTrue();
expect(1n !== 1.23).toBeTrue();
expect(1.23 !== 1n).toBeTrue();
});
});
describe("errors", () => {
test("conversion to number", () => {
expect(() => {
+123n;
}).toThrowWithMessage(TypeError, "Cannot convert BigInt to number");
});
});

View file

@ -0,0 +1,8 @@
describe("minus behavior", () => {
test("the basics", () => {
expect(3n - 4n).toBe(-1n);
expect(3n - -4n).toBe(7n);
expect(-3n - -4n).toBe(-1n);
expect(-3n - 4n).toBe(-7n);
});
});

View file

@ -0,0 +1,31 @@
const doTest = (operatorName, executeOperation) => {
[1, null, undefined].forEach(value => {
const messageSuffix = operatorName === "unsigned right-shift" ? "" : " and other type";
expect(() => {
executeOperation(1n, value);
}).toThrowWithMessage(
TypeError,
`Cannot use ${operatorName} operator with BigInt${messageSuffix}`
);
});
};
[
["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]);
});
});

View file

@ -0,0 +1,32 @@
test("constructor properties", () => {
expect(Boolean).toHaveLength(1);
expect(Boolean.name).toBe("Boolean");
});
test("typeof", () => {
expect(typeof new Boolean()).toBe("object");
expect(typeof Boolean()).toBe("boolean");
expect(typeof Boolean(true)).toBe("boolean");
});
test("basic functionality", () => {
var foo = new Boolean(true);
var bar = new Boolean(true);
expect(foo).not.toBe(bar);
expect(foo.valueOf()).toBe(bar.valueOf());
expect(Boolean()).toBeFalse();
expect(Boolean(false)).toBeFalse();
expect(Boolean(null)).toBeFalse();
expect(Boolean(undefined)).toBeFalse();
expect(Boolean(NaN)).toBeFalse();
expect(Boolean("")).toBeFalse();
expect(Boolean(0.0)).toBeFalse();
expect(Boolean(-0.0)).toBeFalse();
expect(Boolean(true)).toBeTrue();
expect(Boolean("0")).toBeTrue();
expect(Boolean({})).toBeTrue();
expect(Boolean([])).toBeTrue();
expect(Boolean(1)).toBeTrue();
});

View file

@ -0,0 +1,5 @@
test("basic functionality", () => {
expect(typeof Boolean.prototype).toBe("object");
expect(Boolean.prototype.valueOf()).toBeFalse();
expect(Boolean.prototype).not.toHaveProperty("length");
});

View file

@ -0,0 +1,17 @@
test("basic functionality", () => {
var foo = true;
expect(foo.toString()).toBe("true");
expect(true.toString()).toBe("true");
expect(Boolean.prototype.toString.call(true)).toBe("true");
expect(Boolean.prototype.toString.call(false)).toBe("false");
expect(new Boolean(true).toString()).toBe("true");
expect(new Boolean(false).toString()).toBe("false");
});
test("errors on non-boolean |this|", () => {
expect(() => {
Boolean.prototype.toString.call("foo");
}).toThrowWithMessage(TypeError, "Not a Boolean object");
});

View file

@ -0,0 +1,16 @@
test("basic functionality", () => {
var foo = true;
expect(foo.valueOf()).toBeTrue();
expect(true.valueOf()).toBeTrue();
expect(Boolean.prototype.valueOf.call(true)).toBeTrue();
expect(Boolean.prototype.valueOf.call(false)).toBeFalse();
expect(new Boolean().valueOf()).toBeFalse();
});
test("errors on non-boolean |this|", () => {
expect(() => {
Boolean.prototype.valueOf.call("foo");
}).toThrowWithMessage(TypeError, "Not a Boolean object");
});

View file

@ -0,0 +1,51 @@
test("basic functionality", () => {
expect(Date.UTC(2020)).toBe(1577836800000);
expect(Date.UTC(2000, 10)).toBe(973036800000);
expect(Date.UTC(1980, 5, 30)).toBe(331171200000);
expect(Date.UTC(1980, 5, 30, 13)).toBe(331218000000);
expect(Date.UTC(1970, 5, 30, 13, 30)).toBe(15600600000);
expect(Date.UTC(1970, 0, 1, 0, 0, 59)).toBe(59000);
expect(Date.UTC(1970, 0, 1, 0, 0, 0, 999)).toBe(999);
expect(Date.UTC(1969, 11, 31, 23, 59, 59, 817)).toBe(-183);
expect(Date.UTC(1799, 0)).toBe(-5396198400000);
expect(Date.UTC(1800, 0)).toBe(-5364662400000);
expect(Date.UTC(1801, 0)).toBe(-5333126400000);
expect(Date.UTC(1802, 0)).toBe(-5301590400000);
expect(Date.UTC(1803, 0)).toBe(-5270054400000);
expect(Date.UTC(1804, 0)).toBe(-5238518400000);
expect(Date.UTC(1999, 0)).toBe(915148800000);
expect(Date.UTC(2000, 0)).toBe(946684800000);
expect(Date.UTC(2001, 0)).toBe(978307200000);
expect(Date.UTC(2002, 0)).toBe(1009843200000);
expect(Date.UTC(2003, 0)).toBe(1041379200000);
expect(Date.UTC(2004, 0)).toBe(1072915200000);
expect(Date.UTC(20000, 0)).toBe(568971820800000);
});
test("leap year", () => {
expect(Date.UTC(2020, 2, 1)).toBe(1583020800000);
});
test("out of range", () => {
expect(Date.UTC(2020, -20)).toBe(1525132800000);
expect(Date.UTC(2020, 20)).toBe(1630454400000);
expect(Date.UTC(2020, 1, -10)).toBe(1579564800000);
expect(Date.UTC(2020, 1, 40)).toBe(1583884800000);
expect(Date.UTC(2020, 1, 15, -50)).toBe(1581544800000);
expect(Date.UTC(2020, 1, 15, 50)).toBe(1581904800000);
expect(Date.UTC(2020, 1, 15, 12, -123)).toBe(1581760620000);
expect(Date.UTC(2020, 1, 15, 12, 123)).toBe(1581775380000);
expect(Date.UTC(2020, 1, 15, 12, 30, -123)).toBe(1581769677000);
expect(Date.UTC(2020, 1, 15, 12, 30, 123)).toBe(1581769923000);
expect(Date.UTC(2020, 1, 15, 12, 30, 30, -2345)).toBe(1581769827655);
expect(Date.UTC(2020, 1, 15, 12, 30, 30, 2345)).toBe(1581769832345);
});

View file

@ -0,0 +1,77 @@
test("basic functionality", () => {
expect(Date).toHaveLength(7);
expect(Date.name === "Date");
expect(Date.prototype).not.toHaveProperty("length");
});
test("string constructor", () => {
// The string constructor is the same as calling the timestamp constructor with the result of Date.parse(arguments).
// Since that has exhaustive tests in Date.parse.js, just do some light smoke testing here.
expect(new Date("2017-09-07T21:08:59.001Z").toISOString()).toBe("2017-09-07T21:08:59.001Z");
});
test("timestamp constructor", () => {
// The timestamp constructor takes a timestamp in milliseconds since the start of the epoch, in UTC.
// 50 days and 1234 milliseconds after the start of the epoch.
// Most Date methods return values in local time, but since timezone offsets are less than 17 days,
// these checks will pass in all timezones.
let timestamp = 50 * 24 * 60 * 60 * 1000 + 1234;
let date = new Date(timestamp);
expect(date.getTime()).toBe(timestamp); // getTime() returns the timestamp in UTC.
expect(date.getMilliseconds()).toBe(234);
expect(date.getSeconds()).toBe(1);
expect(date.getFullYear()).toBe(1970);
expect(date.getMonth()).toBe(1); // Feb
});
test("tuple constructor", () => {
// The tuple constructor takes a date in local time.
expect(new Date(2019, 11).getFullYear()).toBe(2019);
expect(new Date(2019, 11).getMonth()).toBe(11);
expect(new Date(2019, 11).getDate()).toBe(1); // getDay() returns day of week, getDate() returns day in month
expect(new Date(2019, 11).getHours()).toBe(0);
expect(new Date(2019, 11).getMinutes()).toBe(0);
expect(new Date(2019, 11).getSeconds()).toBe(0);
expect(new Date(2019, 11).getMilliseconds()).toBe(0);
expect(new Date(2019, 11).getDay()).toBe(0);
let date = new Date(2019, 11, 15, 9, 16, 14, 123); // Note: Month is 0-based.
expect(date.getFullYear()).toBe(2019);
expect(date.getMonth()).toBe(11);
expect(date.getDate()).toBe(15);
expect(date.getHours()).toBe(9);
expect(date.getMinutes()).toBe(16);
expect(date.getSeconds()).toBe(14);
expect(date.getMilliseconds()).toBe(123);
expect(date.getDay()).toBe(0);
// getTime() returns a time stamp in UTC, but we can at least check it's in the right interval, which will be true independent of the local timezone if the range is big enough.
let timestamp_lower_bound = 1575072000000; // 2019-12-01T00:00:00Z
let timestamp_upper_bound = 1577750400000; // 2019-12-31T00:00:00Z
expect(date.getTime()).toBeGreaterThan(timestamp_lower_bound);
expect(date.getTime()).toBeLessThan(timestamp_upper_bound);
});
test("tuple constructor overflow", () => {
let date = new Date(2019, 13, 33, 30, 70, 80, 2345);
expect(date.getFullYear()).toBe(2020);
expect(date.getMonth()).toBe(2);
expect(date.getDate()).toBe(5);
expect(date.getHours()).toBe(7);
expect(date.getMinutes()).toBe(11);
expect(date.getSeconds()).toBe(22);
expect(date.getMilliseconds()).toBe(345);
expect(date.getDay()).toBe(4);
let date = new Date(2019, -13, -33, -30, -70, -80, -2345);
expect(date.getFullYear()).toBe(2017);
expect(date.getMonth()).toBe(9);
expect(date.getDate()).toBe(26);
expect(date.getHours()).toBe(16);
expect(date.getMinutes()).toBe(48);
expect(date.getSeconds()).toBe(37);
expect(date.getMilliseconds()).toBe(655);
expect(date.getDay()).toBe(4);
});

View file

@ -0,0 +1,10 @@
test("basic functionality", () => {
var last = 0;
for (var i = 0; i < 100; ++i) {
var now = Date.now();
expect(now).not.toBeNaN();
expect(now).toBeGreaterThan(1580000000000);
expect(now).toBeGreaterThanOrEqual(last);
last = now;
}
});

View file

@ -0,0 +1,32 @@
test("basic functionality", () => {
expect(Date.parse("2020")).toBe(1577836800000);
expect(Date.parse("2000-11")).toBe(973036800000);
expect(Date.parse("1980-06-30")).toBe(331171200000);
expect(Date.parse("1970-06-30T13:30Z")).toBe(15600600000);
expect(Date.parse("1970-01-01T00:00:59Z")).toBe(59000);
expect(Date.parse("1970-01-01T00:00:00.999Z")).toBe(999);
expect(Date.parse("2020T13:14+15:16")).toBe(1577829480000);
expect(Date.parse("2020T13:14-15:16")).toBe(1577939400000);
expect(Date.parse("2020T23:59Z")).toBe(1577923140000);
expect(Date.parse("+020000")).toBe(568971820800000);
expect(Date.parse("+020000-01")).toBe(568971820800000);
expect(Date.parse("+020000-01T00:00:00.000Z")).toBe(568971820800000);
expect(Date.parse(2020)).toBe(1577836800000);
expect(Date.parse("+1980")).toBe(NaN);
expect(Date.parse("1980-")).toBe(NaN);
expect(Date.parse("1980-05-")).toBe(NaN);
expect(Date.parse("1980-05-00T")).toBe(NaN);
expect(Date.parse("1980-05-00T15:15:")).toBe(NaN);
expect(Date.parse("1980-05-00T15:15:15.")).toBe(NaN);
expect(Date.parse("1980-5-30")).toBe(NaN);
expect(Date.parse("1980-05-30T13")).toBe(NaN);
expect(Date.parse("1980-05-30T13:4")).toBe(NaN);
expect(Date.parse("1980-05-30T13:40+")).toBe(NaN);
expect(Date.parse("1980-05-30T13:40+1")).toBe(NaN);
expect(Date.parse("1980-05-30T13:40+1:10")).toBe(NaN);
expect(Date.parse("1970-06-30T13:30Zoo")).toBe(NaN);
expect(Date.parse("2020T13:30.40:")).toBe(NaN);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
let d = new Date();
expect(d.getDate()).toBe(d.getDate());
expect(d.getDate()).not.toBeNaN();
expect(d.getDate()).toBeGreaterThanOrEqual(1);
expect(d.getDate()).toBeLessThanOrEqual(31);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getDay()).toBe(d.getDay());
expect(d.getDay()).not.toBeNaN();
expect(d.getDay()).toBeGreaterThanOrEqual(0);
expect(d.getDay()).toBeLessThanOrEqual(6);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getFullYear()).toBe(d.getFullYear());
expect(d.getFullYear()).not.toBeNaN();
expect(d.getFullYear()).toBe(d.getFullYear());
expect(d.getFullYear()).toBeGreaterThanOrEqual(2020);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getHours()).toBe(d.getHours());
expect(d.getHours()).not.toBeNaN();
expect(d.getHours()).toBeGreaterThanOrEqual(0);
expect(d.getHours()).toBeLessThanOrEqual(23);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getMilliseconds()).toBe(d.getMilliseconds());
expect(d.getMilliseconds()).not.toBeNaN();
expect(d.getMilliseconds()).toBeGreaterThanOrEqual(0);
expect(d.getMilliseconds()).toBeLessThanOrEqual(999);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getMinutes()).toBe(d.getMinutes());
expect(d.getMinutes()).not.toBeNaN();
expect(d.getMinutes()).toBeGreaterThanOrEqual(0);
expect(d.getMinutes()).toBeLessThanOrEqual(59);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getMonth()).toBe(d.getMonth());
expect(d.getMonth()).not.toBeNaN();
expect(d.getMonth()).toBeGreaterThanOrEqual(0);
expect(d.getMonth()).toBeLessThanOrEqual(11);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getSeconds()).toBe(d.getSeconds());
expect(d.getSeconds()).not.toBeNaN();
expect(d.getSeconds()).toBeGreaterThanOrEqual(0);
expect(d.getSeconds()).toBeLessThanOrEqual(59);
});

View file

@ -0,0 +1,6 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getTime()).toBe(d.getTime());
expect(d.getTime()).not.toBeNaN();
expect(d.getTime()).toBeGreaterThanOrEqual(1580000000000);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
let d = new Date();
expect(d.getUTCDate()).toBe(d.getUTCDate());
expect(d.getUTCDate()).not.toBeNaN();
expect(d.getUTCDate()).toBeGreaterThanOrEqual(1);
expect(d.getUTCDate()).toBeLessThanOrEqual(31);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getUTCDay()).toBe(d.getUTCDay());
expect(d.getUTCDay()).not.toBeNaN();
expect(d.getUTCDay()).toBeGreaterThanOrEqual(0);
expect(d.getUTCDay()).toBeLessThanOrEqual(6);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getUTCFullYear()).toBe(d.getUTCFullYear());
expect(d.getUTCFullYear()).not.toBeNaN();
expect(d.getUTCFullYear()).toBe(d.getUTCFullYear());
expect(d.getUTCFullYear()).toBeGreaterThanOrEqual(2020);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getUTCHours()).toBe(d.getUTCHours());
expect(d.getUTCHours()).not.toBeNaN();
expect(d.getUTCHours()).toBeGreaterThanOrEqual(0);
expect(d.getUTCHours()).toBeLessThanOrEqual(23);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getUTCMilliseconds()).toBe(d.getUTCMilliseconds());
expect(d.getUTCMilliseconds()).not.toBeNaN();
expect(d.getUTCMilliseconds()).toBeGreaterThanOrEqual(0);
expect(d.getUTCMilliseconds()).toBeLessThanOrEqual(999);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getUTCMinutes()).toBe(d.getUTCMinutes());
expect(d.getUTCMinutes()).not.toBeNaN();
expect(d.getUTCMinutes()).toBeGreaterThanOrEqual(0);
expect(d.getUTCMinutes()).toBeLessThanOrEqual(59);
});

View file

@ -0,0 +1,26 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getUTCMonth()).toBe(d.getUTCMonth());
expect(d.getUTCMonth()).not.toBeNaN();
expect(d.getUTCMonth()).toBeGreaterThanOrEqual(0);
expect(d.getUTCMonth()).toBeLessThanOrEqual(11);
expect(new Date(Date.UTC(2020, 11)).getUTCMonth()).toBe(11);
});
test("leap years", () => {
expect(new Date(Date.UTC(2019, 1, 29)).getUTCDate()).toBe(1);
expect(new Date(Date.UTC(2019, 1, 29)).getUTCMonth()).toBe(2);
expect(new Date(Date.UTC(2100, 1, 29)).getUTCDate()).toBe(1);
expect(new Date(Date.UTC(2100, 1, 29)).getUTCMonth()).toBe(2);
expect(new Date(Date.UTC(2000, 1, 29)).getUTCDate()).toBe(29);
expect(new Date(Date.UTC(2000, 1, 29)).getUTCMonth()).toBe(1);
expect(new Date(Date.UTC(2020, 1, 29)).getUTCDate()).toBe(29);
expect(new Date(Date.UTC(2020, 1, 29)).getUTCMonth()).toBe(1);
expect(new Date(Date.UTC(2019, 2, 1)).getUTCDate()).toBe(1);
expect(new Date(Date.UTC(2019, 2, 1)).getUTCMonth()).toBe(2);
expect(new Date(Date.UTC(2020, 2, 1)).getUTCDate()).toBe(1);
expect(new Date(Date.UTC(2020, 2, 1)).getUTCMonth()).toBe(2);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
var d = new Date();
expect(d.getUTCSeconds()).toBe(d.getUTCSeconds());
expect(d.getUTCSeconds()).not.toBeNaN();
expect(d.getUTCSeconds()).toBeGreaterThanOrEqual(0);
expect(d.getUTCSeconds()).toBeLessThanOrEqual(59);
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
expect(new Date(1597955034555).toISOString()).toBe("2020-08-20T20:23:54.555Z");
expect(new Date(Date.UTC(22020)).toISOString()).toBe("+022020-01-01T00:00:00.000Z");
expect(new Date(Date.UTC(1950)).toISOString()).toBe("1950-01-01T00:00:00.000Z");
expect(new Date(Date.UTC(1800)).toISOString()).toBe("1800-01-01T00:00:00.000Z");
expect(new Date(Date.UTC(-100)).toISOString()).toBe("-000100-01-01T00:00:00.000Z");
});

View file

@ -0,0 +1,18 @@
test("basic functionality", () => {
expect(Error).toHaveLength(1);
expect(Error.name).toBe("Error");
});
test("name", () => {
[Error(), Error(undefined), Error("test"), Error(42), Error(null)].forEach(error => {
expect(error.name).toBe("Error");
});
});
test("message", () => {
expect(Error().message).toBe("");
expect(Error(undefined).message).toBe("");
expect(Error("test").message).toBe("test");
expect(Error(42).message).toBe("42");
expect(Error(null).message).toBe("null");
});

View file

@ -0,0 +1,10 @@
test("basic functionality", () => {
expect(Error.prototype).not.toHaveProperty("length");
var changedInstance = new Error("");
changedInstance.name = "NewCustomError";
expect(changedInstance.name).toBe("NewCustomError");
var normalInstance = new Error("");
expect(normalInstance.name).toBe("Error");
});

View file

@ -0,0 +1,7 @@
test("basic functionality", () => {
expect(Error().toString()).toBe("Error");
expect(Error(undefined).toString()).toBe("Error");
expect(Error(null).toString()).toBe("Error: null");
expect(Error("test").toString()).toBe("Error: test");
expect(Error(42).toString()).toBe("Error: 42");
});

View file

@ -0,0 +1,53 @@
describe("correct behavior", () => {
test("constructor properties", () => {
expect(Function).toHaveLength(1);
expect(Function.name).toBe("Function");
expect(Function.prototype).toHaveLength(0);
expect(Function.prototype.name).toBe("");
});
test("typeof", () => {
expect(typeof Function()).toBe("function");
expect(typeof new Function()).toBe("function");
});
test("basic functionality", () => {
expect(Function()()).toBeUndefined();
expect(new Function()()).toBeUndefined();
expect(Function("return 42")()).toBe(42);
expect(new Function("return 42")()).toBe(42);
expect(new Function("foo", "return foo")(42)).toBe(42);
expect(new Function("foo,bar", "return foo + bar")(1, 2)).toBe(3);
expect(new Function("foo", "bar", "return foo + bar")(1, 2)).toBe(3);
expect(new Function("foo", "bar,baz", "return foo + bar + baz")(1, 2, 3)).toBe(6);
expect(new Function("foo", "bar", "baz", "return foo + bar + baz")(1, 2, 3)).toBe(6);
expect(new Function("foo", "if (foo) { return 42; } else { return 'bar'; }")(true)).toBe(
42
);
expect(new Function("foo", "if (foo) { return 42; } else { return 'bar'; }")(false)).toBe(
"bar"
);
expect(new Function("return typeof Function()")()).toBe("function");
expect(new Function("x", "return function (y) { return x + y };")(1)(2)).toBe(3);
expect(new Function("-->")()).toBeUndefined();
expect(new Function().name).toBe("anonymous");
expect(new Function().toString()).toBe("function anonymous() {\n ???\n}");
});
});
describe("errors", () => {
test("syntax error", () => {
expect(() => {
new Function("[");
})
// This might be confusing at first but keep in mind it's actually parsing
// function anonymous() { [ }
// This is in line with what other engines are reporting.
.toThrowWithMessage(
SyntaxError,
"Unexpected token CurlyClose. Expected BracketClose (line: 4, column: 1)"
);
});
});

View file

@ -0,0 +1,8 @@
test("basic functionality", () => {
expect(Function.prototype[Symbol.hasInstance]).toHaveLength(1);
function Foo() {}
const foo = new Foo();
expect(Function.prototype[Symbol.hasInstance].call(Foo, foo)).toBeTrue();
});

View file

@ -0,0 +1,51 @@
test("basic functionality", () => {
function Foo(arg) {
this.foo = arg;
}
function Bar(arg) {
this.bar = arg;
}
function FooBar(arg) {
Foo.apply(this, [arg]);
Bar.apply(this, [arg]);
}
function FooBarBaz(arg) {
Foo.apply(this, [arg]);
Bar.apply(this, [arg]);
this.baz = arg;
}
expect(Function.prototype.apply).toHaveLength(2);
var foo = new Foo("test");
expect(foo.foo).toBe("test");
expect(foo.bar).toBeUndefined();
expect(foo.baz).toBeUndefined();
var bar = new Bar("test");
expect(bar.foo).toBeUndefined();
expect(bar.bar).toBe("test");
expect(bar.baz).toBeUndefined();
var foobar = new FooBar("test");
expect(foobar.foo).toBe("test");
expect(foobar.bar).toBe("test");
expect(foobar.baz).toBeUndefined();
var foobarbaz = new FooBarBaz("test");
expect(foobarbaz.foo).toBe("test");
expect(foobarbaz.bar).toBe("test");
expect(foobarbaz.baz).toBe("test");
expect(Math.abs.apply(null, [-1])).toBe(1);
var add = (x, y) => x + y;
expect(add.apply(null, [1, 2])).toBe(3);
var multiply = function (x, y) {
return x * y;
};
expect(multiply.apply(null, [3, 4])).toBe(12);
expect((() => this).apply("foo")).toBe(globalThis);
});

View file

@ -0,0 +1,149 @@
describe("basic behavior", () => {
test("basic binding", () => {
expect(Function.prototype.bind).toHaveLength(1);
var charAt = String.prototype.charAt.bind("bar");
expect(charAt(0) + charAt(1) + charAt(2)).toBe("bar");
function getB() {
return this.toUpperCase().charAt(0);
}
expect(getB.bind("bar")()).toBe("B");
});
test("bound functions work with array functions", () => {
var Make3 = Number.bind(null, 3);
expect([55].map(Make3)[0]).toBe(3);
var MakeTrue = Boolean.bind(null, true);
expect([1, 2, 3].filter(MakeTrue)).toHaveLength(3);
expect(
[1, 2, 3].reduce(
function (acc, x) {
return acc + x;
}.bind(null, 4, 5)
)
).toBe(9);
expect(
[1, 2, 3].reduce(
function (acc, x) {
return acc + x + this;
}.bind(3)
)
).toBe(12);
});
});
describe("bound function arguments", () => {
function sum(a, b, c) {
return a + b + c;
}
var boundSum = sum.bind(null, 10, 5);
test("arguments are bound to the function", () => {
expect(boundSum()).toBeNaN();
expect(boundSum(5)).toBe(20);
expect(boundSum(5, 6, 7)).toBe(20);
});
test("arguments are appended to a BoundFunction's bound arguments", () => {
expect(boundSum.bind(null, 5)()).toBe(20);
});
test("binding a constructor's arguments", () => {
var Make5 = Number.bind(null, 5);
expect(Make5()).toBe(5);
expect(new Make5().valueOf()).toBe(5);
});
test("length property", () => {
expect(sum).toHaveLength(3);
expect(boundSum).toHaveLength(1);
expect(boundSum.bind(null, 5)).toHaveLength(0);
expect(boundSum.bind(null, 5, 6, 7, 8)).toHaveLength(0);
});
});
describe("bound function |this|", () => {
function identity() {
return this;
}
test("captures global object as |this| if |this| is null or undefined", () => {
expect(identity.bind()()).toBe(globalThis);
expect(identity.bind(null)()).toBe(globalThis);
expect(identity.bind(undefined)()).toBe(globalThis);
function Foo() {
expect(identity.bind()()).toBe(globalThis);
expect(identity.bind(this)()).toBe(this);
}
new Foo();
});
test("does not capture global object as |this| if |this| is null or undefined in strict mode", () => {
"use strict";
function strictIdentity() {
return this;
}
expect(strictIdentity.bind()()).toBeUndefined();
expect(strictIdentity.bind(null)()).toBeNull();
expect(strictIdentity.bind(undefined)()).toBeUndefined();
});
test("primitive |this| values are converted to objects", () => {
expect(identity.bind("foo")()).toBeInstanceOf(String);
expect(identity.bind(123)()).toBeInstanceOf(Number);
expect(identity.bind(true)()).toBeInstanceOf(Boolean);
});
test("bound functions retain |this| values passed to them", () => {
var obj = { foo: "bar" };
expect(identity.bind(obj)()).toBe(obj);
});
test("bound |this| cannot be changed after being set", () => {
expect(identity.bind("foo").bind(123)()).toBeInstanceOf(String);
});
test("arrow functions cannot be bound", () => {
expect((() => this).bind("foo")()).toBe(globalThis);
});
});
describe("bound function constructors", () => {
function Bar() {
this.x = 3;
this.y = 4;
}
Bar.prototype.baz = "baz";
var BoundBar = Bar.bind({ u: 5, v: 6 });
var bar = new BoundBar();
test("bound |this| value does not affect constructor", () => {
expect(bar.x).toBe(3);
expect(bar.y).toBe(4);
expect(typeof bar.u).toBe("undefined");
expect(typeof bar.v).toBe("undefined");
});
test("bound functions retain original prototype", () => {
expect(bar.baz).toBe("baz");
});
test("bound functions do not have a prototype property", () => {
expect(BoundBar).not.toHaveProperty("prototype");
});
});
describe("errors", () => {
test("does not accept non-function values", () => {
expect(() => {
Function.prototype.bind.call("foo");
}).toThrowWithMessage(TypeError, "Not a Function object");
});
});

View file

@ -0,0 +1,53 @@
test("length", () => {
expect(Function.prototype.call).toHaveLength(1);
});
test("basic functionality", () => {
function Foo(arg) {
this.foo = arg;
}
function Bar(arg) {
this.bar = arg;
}
function FooBar(arg) {
Foo.call(this, arg);
Bar.call(this, arg);
}
function FooBarBaz(arg) {
Foo.call(this, arg);
Bar.call(this, arg);
this.baz = arg;
}
var foo = new Foo("test");
expect(foo.foo).toBe("test");
expect(foo.bar).toBeUndefined();
expect(foo.baz).toBeUndefined();
var bar = new Bar("test");
expect(bar.foo).toBeUndefined();
expect(bar.bar).toBe("test");
expect(bar.baz).toBeUndefined();
var foobar = new FooBar("test");
expect(foobar.foo).toBe("test");
expect(foobar.bar).toBe("test");
expect(foobar.baz).toBeUndefined();
var foobarbaz = new FooBarBaz("test");
expect(foobarbaz.foo).toBe("test");
expect(foobarbaz.bar).toBe("test");
expect(foobarbaz.baz).toBe("test");
expect(Math.abs.call(null, -1)).toBe(1);
var add = (x, y) => x + y;
expect(add.call(null, 1, 2)).toBe(3);
var multiply = function (x, y) {
return x * y;
};
expect(multiply.call(null, 3, 4)).toBe(12);
expect((() => this).call("foo")).toBe(globalThis);
});

View file

@ -0,0 +1,17 @@
test("basic functionality", () => {
expect(function () {}.toString()).toBe("function () {\n ???\n}");
expect(function (foo) {}.toString()).toBe("function (foo) {\n ???\n}");
expect(function (foo, bar, baz) {}.toString()).toBe("function (foo, bar, baz) {\n ???\n}");
expect(
function (foo, bar, baz) {
if (foo) {
return baz;
} else if (bar) {
return foo;
}
return bar + 42;
}.toString()
).toBe("function (foo, bar, baz) {\n ???\n}");
expect(console.debug.toString()).toBe("function debug() {\n [NativeFunction]\n}");
expect(Function.toString()).toBe("function Function() {\n [FunctionConstructor]\n}");
});

View file

@ -0,0 +1,22 @@
test("basic functionality", () => {
expect(Infinity + "").toBe("Infinity");
expect(-Infinity + "").toBe("-Infinity");
expect(Infinity).toBe(Infinity);
expect(Infinity - 1).toBe(Infinity);
expect(Infinity + 1).toBe(Infinity);
expect(-Infinity).toBe(-Infinity);
expect(-Infinity - 1).toBe(-Infinity);
expect(-Infinity + 1).toBe(-Infinity);
expect(1 / Infinity).toBe(0);
expect(1 / -Infinity).toBe(-0);
expect(1 / 0).toBe(Infinity);
expect(-1 / 0).toBe(-Infinity);
expect(-100).toBeLessThan(Infinity);
expect(0).toBeLessThan(Infinity);
expect(100).toBeLessThan(Infinity);
expect(-Infinity).toBeLessThan(Infinity);
expect(-100).toBeGreaterThan(-Infinity);
expect(0).toBeGreaterThan(-Infinity);
expect(100).toBeGreaterThan(-Infinity);
expect(Infinity).toBeGreaterThan(-Infinity);
});

View file

@ -0,0 +1,4 @@
test("basic functionality", () => {
expect(JSON[Symbol.toStringTag]).toBe("JSON");
expect(JSON.toString()).toBe("[object JSON]");
});

View file

@ -0,0 +1,11 @@
test("basic functionality", () => {
let string = `{"var1":10,"var2":"hello","var3":{"nested":5}}`;
let object = JSON.parse(string, (key, value) =>
typeof value === "number" ? value * 2 : value
);
expect(object).toEqual({ var1: 20, var2: "hello", var3: { nested: 10 } });
object = JSON.parse(string, (key, value) => (typeof value === "number" ? undefined : value));
expect(object).toEqual({ var2: "hello", var3: {} });
});

View file

@ -0,0 +1,37 @@
test("basic functionality", () => {
expect(JSON.parse).toHaveLength(2);
const properties = [
["5", 5],
["null", null],
["true", true],
["false", false],
['"test"', "test"],
['[1,2,"foo"]', [1, 2, "foo"]],
['{"foo":1,"bar":"baz"}', { foo: 1, bar: "baz" }],
];
properties.forEach(testCase => {
expect(JSON.parse(testCase[0])).toEqual(testCase[1]);
});
});
test("syntax errors", () => {
[
undefined,
NaN,
-NaN,
Infinity,
-Infinity,
'{ "foo" }',
'{ foo: "bar" }',
"[1,2,3,]",
"[1,2,3, ]",
'{ "foo": "bar",}',
'{ "foo": "bar", }',
].forEach(test => {
expect(() => {
JSON.parse(test);
}).toThrow(SyntaxError);
});
});

View file

@ -0,0 +1,10 @@
test("Issue #3548, exception in property getter with replacer function", () => {
const o = {
get foo() {
throw Error();
},
};
expect(() => {
JSON.stringify(o, (_, value) => value);
}).toThrow(Error);
});

View file

@ -0,0 +1,30 @@
test("basic functionality", () => {
let o = {
key1: "key1",
key2: "key2",
key3: "key3",
};
Object.defineProperty(o, "defined", {
enumerable: true,
get() {
o.prop = "prop";
return "defined";
},
});
o.key4 = "key4";
o[2] = 2;
o[0] = 0;
o[1] = 1;
delete o.key1;
delete o.key3;
o.key1 = "key1";
expect(JSON.stringify(o)).toBe(
'{"0":0,"1":1,"2":2,"key2":"key2","defined":"defined","key4":"key4","key1":"key1"}'
);
});

View file

@ -0,0 +1,11 @@
test("basic functionality", () => {
let p = new Proxy([], {
get(_, key) {
if (key === "length") return 3;
return Number(key);
},
});
expect(JSON.stringify(p)).toBe("[0,1,2]");
expect(JSON.stringify([[new Proxy(p, {})]])).toBe("[[[0,1,2]]]");
});

View file

@ -0,0 +1,38 @@
test("basic functionality", () => {
let o = {
var1: "foo",
var2: 42,
arr: [
1,
2,
{
nested: {
hello: "world",
},
get x() {
return 10;
},
},
],
obj: {
subarr: [3],
},
};
let string = JSON.stringify(o, (key, value) => {
if (key === "hello") return undefined;
if (value === 10) return 20;
if (key === "subarr") return [3, 4, 5];
return value;
});
expect(string).toBe(
'{"var1":"foo","var2":42,"arr":[1,2,{"nested":{},"x":20}],"obj":{"subarr":[3,4,5]}}'
);
string = JSON.stringify(o, ["var1", "var1", "var2", "obj"]);
expect(string).toBe('{"var1":"foo","var2":42,"obj":{}}');
string = JSON.stringify(o, ["var1", "var1", "var2", "obj", "subarr"]);
expect(string).toBe('{"var1":"foo","var2":42,"obj":{"subarr":[3]}}');
});

View file

@ -0,0 +1,47 @@
test("basic functionality", () => {
let o = {
foo: 1,
bar: "baz",
qux: {
get x() {
return 10;
},
y() {
return 20;
},
arr: [1, 2, 3],
},
};
let string = JSON.stringify(o, null, 4);
let expected = `{
"foo": 1,
"bar": "baz",
"qux": {
"x": 10,
"arr": [
1,
2,
3
]
}
}`;
expect(string).toBe(expected);
string = JSON.stringify(o, null, "abcd");
expected = `{
abcd"foo": 1,
abcd"bar": "baz",
abcd"qux": {
abcdabcd"x": 10,
abcdabcd"arr": [
abcdabcdabcd1,
abcdabcdabcd2,
abcdabcdabcd3
abcdabcd]
abcd}
}`;
expect(string).toBe(expected);
});

View file

@ -0,0 +1,71 @@
describe("correct behavior", () => {
test("length", () => {
expect(JSON.stringify).toHaveLength(3);
});
test("basic functionality", () => {
[
[5, "5"],
[undefined, undefined],
[null, "null"],
[NaN, "null"],
[-NaN, "null"],
[Infinity, "null"],
[-Infinity, "null"],
[true, "true"],
[false, "false"],
["test", '"test"'],
[new Number(5), "5"],
[new Boolean(false), "false"],
[new String("test"), '"test"'],
[() => {}, undefined],
[[1, 2, "foo"], '[1,2,"foo"]'],
[{ foo: 1, bar: "baz", qux() {} }, '{"foo":1,"bar":"baz"}'],
[
{
var1: 1,
var2: 2,
toJSON(key) {
let o = this;
o.var2 = 10;
return o;
},
},
'{"var1":1,"var2":10}',
],
].forEach(testCase => {
expect(JSON.stringify(testCase[0])).toEqual(testCase[1]);
});
});
test("ignores non-enumerable properties", () => {
let o = { foo: "bar" };
Object.defineProperty(o, "baz", { value: "qux", enumerable: false });
expect(JSON.stringify(o)).toBe('{"foo":"bar"}');
});
});
describe("errors", () => {
test("cannot serialize BigInt", () => {
expect(() => {
JSON.stringify(5n);
}).toThrow(TypeError, "Cannot serialize BigInt value to JSON");
});
test("cannot serialize circular structures", () => {
let bad1 = {};
bad1.foo = bad1;
let bad2 = [];
bad2[5] = [[[bad2]]];
let bad3a = { foo: "bar" };
let bad3b = [1, 2, bad3a];
bad3a.bad = bad3b;
[bad1, bad2, bad3a].forEach(bad => {
expect(() => {
JSON.stringify(bad);
}).toThrow(TypeError, "Cannot stringify circular object");
});
});
});

View file

@ -0,0 +1,10 @@
test("basic functionality", () => {
expect(Math.E).toBeCloseTo(2.718281);
expect(Math.LN2).toBeCloseTo(0.693147);
expect(Math.LN10).toBeCloseTo(2.302585);
expect(Math.LOG2E).toBeCloseTo(1.442695);
expect(Math.LOG10E).toBeCloseTo(0.434294);
expect(Math.PI).toBeCloseTo(3.1415926);
expect(Math.SQRT1_2).toBeCloseTo(0.707106);
expect(Math.SQRT2).toBeCloseTo(1.414213);
});

View file

@ -0,0 +1,4 @@
test("basic functionality", () => {
expect(Math[Symbol.toStringTag]).toBe("Math");
expect(Math.toString()).toBe("[object Math]");
});

View file

@ -0,0 +1,14 @@
test("basic functionality", () => {
expect(Math.abs).toHaveLength(1);
expect(Math.abs("-1")).toBe(1);
expect(Math.abs(-2)).toBe(2);
expect(Math.abs(null)).toBe(0);
expect(Math.abs("")).toBe(0);
expect(Math.abs([])).toBe(0);
expect(Math.abs([2])).toBe(2);
expect(Math.abs([1, 2])).toBeNaN();
expect(Math.abs({})).toBeNaN();
expect(Math.abs("string")).toBeNaN();
expect(Math.abs()).toBeNaN();
});

View file

@ -0,0 +1,9 @@
test("basic functionality", () => {
expect(Math.acosh).toHaveLength(1);
expect(Math.acosh(-1)).toBeNaN();
expect(Math.acosh(0)).toBeNaN();
expect(Math.acosh(0.5)).toBeNaN();
expect(Math.acosh(1)).toBeCloseTo(0);
expect(Math.acosh(2)).toBeCloseTo(1.316957);
});

View file

@ -0,0 +1,15 @@
test("basic functionality", () => {
expect(Math.asin).toHaveLength(1);
expect(Math.asin(0)).toBe(0);
expect(Math.asin(null)).toBe(0);
expect(Math.asin("")).toBe(0);
expect(Math.asin([])).toBe(0);
// FIXME(LibM): expect(Math.asin(1)).toBeCloseTo(1.5707963267948966);
// FIXME(LibM): expect(Math.asin(-1)).toBeCloseTo(-1.5707963267948966);
expect(Math.asin()).toBeNaN();
expect(Math.asin(undefined)).toBeNaN();
expect(Math.asin([1, 2, 3])).toBeNaN();
expect(Math.asin({})).toBeNaN();
expect(Math.asin("foo")).toBeNaN();
});

View file

@ -0,0 +1,6 @@
test("basic functionality", () => {
expect(Math.asinh).toHaveLength(1);
expect(Math.asinh(0)).toBeCloseTo(0);
expect(Math.asinh(1)).toBeCloseTo(0.881373);
});

View file

@ -0,0 +1,12 @@
test("basic functionality", () => {
expect(Math.atan).toHaveLength(1);
expect(Math.atan(0)).toBe(0);
expect(Math.atan(-0)).toBe(-0);
expect(Math.atan(NaN)).toBeNaN();
expect(Math.atan(-2)).toBeCloseTo(-1.1071487177940904);
expect(Math.atan(2)).toBeCloseTo(1.1071487177940904);
expect(Math.atan(Infinity)).toBeCloseTo(Math.PI / 2);
expect(Math.atan(-Infinity)).toBeCloseTo(-Math.PI / 2);
expect(Math.atan(0.5)).toBeCloseTo(0.4636476090008061);
});

View file

@ -0,0 +1,28 @@
test("basic functionality", () => {
expect(Math.atan2).toHaveLength(2);
expect(Math.atan2(90, 15)).toBeCloseTo(1.4056476493802699);
expect(Math.atan2(15, 90)).toBeCloseTo(0.16514867741462683);
expect(Math.atan2(+0, -0)).toBeCloseTo(Math.PI);
expect(Math.atan2(-0, -0)).toBeCloseTo(-Math.PI);
expect(Math.atan2(+0, +0)).toBe(0);
expect(Math.atan2(-0, +0)).toBe(-0);
expect(Math.atan2(+0, -1)).toBeCloseTo(Math.PI);
expect(Math.atan2(-0, -1)).toBeCloseTo(-Math.PI);
expect(Math.atan2(+0, 1)).toBe(0);
expect(Math.atan2(-0, 1)).toBe(-0);
expect(Math.atan2(-1, +0)).toBeCloseTo(-Math.PI / 2);
expect(Math.atan2(-1, -0)).toBeCloseTo(-Math.PI / 2);
expect(Math.atan2(1, +0)).toBeCloseTo(Math.PI / 2);
expect(Math.atan2(1, -0)).toBeCloseTo(Math.PI / 2);
expect(Math.atan2(1, -Infinity)).toBeCloseTo(Math.PI);
expect(Math.atan2(-1, -Infinity)).toBeCloseTo(-Math.PI);
expect(Math.atan2(1, +Infinity)).toBe(0);
expect(Math.atan2(-1, +Infinity)).toBe(-0);
expect(Math.atan2(+Infinity, 1)).toBeCloseTo(Math.PI / 2);
expect(Math.atan2(-Infinity, 1)).toBeCloseTo(-Math.PI / 2);
expect(Math.atan2(+Infinity, -Infinity)).toBeCloseTo((3 * Math.PI) / 4);
expect(Math.atan2(-Infinity, -Infinity)).toBeCloseTo((-3 * Math.PI) / 4);
expect(Math.atan2(+Infinity, +Infinity)).toBeCloseTo(Math.PI / 4);
expect(Math.atan2(-Infinity, +Infinity)).toBeCloseTo(-Math.PI / 4);
});

Some files were not shown because too many files have changed in this diff Show more