1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 06:07:44 +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]);
});