mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 16:18:12 +00:00
LibJS: Add tests for symbol object integration
This commit is contained in:
parent
7a1d485b19
commit
119386ffb0
13 changed files with 198 additions and 13 deletions
|
@ -1,5 +1,7 @@
|
||||||
describe("normal functionality", () => {
|
describe("normal functionality", () => {
|
||||||
test("non-configurable property", () => {
|
let s = Symbol("foo");
|
||||||
|
|
||||||
|
test("non-configurable string property", () => {
|
||||||
let o = {};
|
let o = {};
|
||||||
Object.defineProperty(o, "foo", { value: 1, writable: false, enumerable: false });
|
Object.defineProperty(o, "foo", { value: 1, writable: false, enumerable: false });
|
||||||
|
|
||||||
|
@ -13,6 +15,20 @@ describe("normal functionality", () => {
|
||||||
expect(o).toHaveValueProperty("foo", 1);
|
expect(o).toHaveValueProperty("foo", 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("non-configurable symbol property", () => {
|
||||||
|
let o = {};
|
||||||
|
Object.defineProperty(o, s, { value: 1, writable: false, enumerable: false });
|
||||||
|
|
||||||
|
expect(o[s]).toBe(1);
|
||||||
|
o[s] = 2;
|
||||||
|
expect(o[s]).toBe(1);
|
||||||
|
|
||||||
|
expect(o).not.toHaveConfigurableProperty(s);
|
||||||
|
expect(o).not.toHaveEnumerableProperty(s);
|
||||||
|
expect(o).not.toHaveWritableProperty(s);
|
||||||
|
expect(o).toHaveValueProperty(s, 1);
|
||||||
|
});
|
||||||
|
|
||||||
test("array index getter", () => {
|
test("array index getter", () => {
|
||||||
let o = {};
|
let o = {};
|
||||||
Object.defineProperty(o, 2, {
|
Object.defineProperty(o, 2, {
|
||||||
|
@ -23,7 +39,17 @@ describe("normal functionality", () => {
|
||||||
expect(o[2]).toBe(10);
|
expect(o[2]).toBe(10);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("configurable property", () => {
|
test("symbol property getter", () => {
|
||||||
|
let o = {};
|
||||||
|
Object.defineProperty(o, s, {
|
||||||
|
get() {
|
||||||
|
return 10;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(o[s]).toBe(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("configurable string property", () => {
|
||||||
let o = {};
|
let o = {};
|
||||||
Object.defineProperty(o, "foo", { value: "hi", writable: true, enumerable: true });
|
Object.defineProperty(o, "foo", { value: "hi", writable: true, enumerable: true });
|
||||||
|
|
||||||
|
@ -37,7 +63,21 @@ describe("normal functionality", () => {
|
||||||
expect(o).toHaveValueProperty("foo", "ho");
|
expect(o).toHaveValueProperty("foo", "ho");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("reconfigure configurable property", () => {
|
test("configurable symbol property", () => {
|
||||||
|
let o = {};
|
||||||
|
Object.defineProperty(o, s, { value: "hi", writable: true, enumerable: true });
|
||||||
|
|
||||||
|
expect(o[s]).toBe("hi");
|
||||||
|
o[s] = "ho";
|
||||||
|
expect(o[s]).toBe("ho");
|
||||||
|
|
||||||
|
expect(o).not.toHaveConfigurableProperty(s);
|
||||||
|
expect(o).toHaveEnumerableProperty(s);
|
||||||
|
expect(o).toHaveWritableProperty(s);
|
||||||
|
expect(o).toHaveValueProperty(s, "ho");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("reconfigure configurable string property", () => {
|
||||||
let o = {};
|
let o = {};
|
||||||
Object.defineProperty(o, "foo", { value: 9, configurable: true, writable: false });
|
Object.defineProperty(o, "foo", { value: 9, configurable: true, writable: false });
|
||||||
Object.defineProperty(o, "foo", { configurable: true, writable: true });
|
Object.defineProperty(o, "foo", { configurable: true, writable: true });
|
||||||
|
@ -48,7 +88,18 @@ describe("normal functionality", () => {
|
||||||
expect(o).toHaveValueProperty("foo", 9);
|
expect(o).toHaveValueProperty("foo", 9);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("define accessor", () => {
|
test("reconfigure configurable symbol property", () => {
|
||||||
|
let o = {};
|
||||||
|
Object.defineProperty(o, s, { value: 9, configurable: true, writable: false });
|
||||||
|
Object.defineProperty(o, s, { configurable: true, writable: true });
|
||||||
|
|
||||||
|
expect(o).toHaveConfigurableProperty(s);
|
||||||
|
expect(o).toHaveWritableProperty(s);
|
||||||
|
expect(o).not.toHaveEnumerableProperty(s);
|
||||||
|
expect(o).toHaveValueProperty(s, 9);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("define string accessor", () => {
|
||||||
let o = {};
|
let o = {};
|
||||||
|
|
||||||
Object.defineProperty(o, "foo", {
|
Object.defineProperty(o, "foo", {
|
||||||
|
@ -72,6 +123,31 @@ describe("normal functionality", () => {
|
||||||
expect((o.foo = 5)).toBe(5);
|
expect((o.foo = 5)).toBe(5);
|
||||||
expect((o.foo = 4)).toBe(4);
|
expect((o.foo = 4)).toBe(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("define symbol accessor", () => {
|
||||||
|
let o = {};
|
||||||
|
|
||||||
|
Object.defineProperty(o, s, {
|
||||||
|
configurable: true,
|
||||||
|
get() {
|
||||||
|
return o.secret_foo + 1;
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
this.secret_foo = value + 1;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
o[s] = 10;
|
||||||
|
expect(o[s]).toBe(12);
|
||||||
|
o[s] = 20;
|
||||||
|
expect(o[s]).toBe(22);
|
||||||
|
|
||||||
|
Object.defineProperty(o, s, { configurable: true, value: 4 });
|
||||||
|
|
||||||
|
expect(o[s]).toBe(4);
|
||||||
|
expect((o[s] = 5)).toBe(5);
|
||||||
|
expect((o[s] = 4)).toBe(4);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("errors", () => {
|
describe("errors", () => {
|
||||||
|
@ -87,6 +163,19 @@ describe("errors", () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("redefine non-configurable symbol property", () => {
|
||||||
|
let o = {};
|
||||||
|
let s = Symbol("foo");
|
||||||
|
Object.defineProperty(o, s, { value: 1, writable: true, enumerable: true });
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
Object.defineProperty(o, s, { value: 2, writable: false, enumerable: true });
|
||||||
|
}).toThrowWithMessage(
|
||||||
|
TypeError,
|
||||||
|
"Cannot change attributes of non-configurable property 'Symbol(foo)'"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test("cannot define 'value' and 'get' in the same descriptor", () => {
|
test("cannot define 'value' and 'get' in the same descriptor", () => {
|
||||||
let o = {};
|
let o = {};
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,15 @@ describe("basic functionality", () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("entries with objects with symbol keys", () => {
|
||||||
|
let entries = Object.entries({ foo: 1, [Symbol("bar")]: 2, baz: 3 });
|
||||||
|
|
||||||
|
expect(entries).toEqual([
|
||||||
|
["foo", 1],
|
||||||
|
["baz", 3],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
test("entries with array", () => {
|
test("entries with array", () => {
|
||||||
entries = Object.entries(["a", "b", "c"]);
|
entries = Object.entries(["a", "b", "c"]);
|
||||||
expect(entries).toEqual([
|
expect(entries).toEqual([
|
||||||
|
|
|
@ -9,6 +9,18 @@ test("plain property", () => {
|
||||||
expect(o).not.toHaveSetterProperty("foo");
|
expect(o).not.toHaveSetterProperty("foo");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("symbol property", () => {
|
||||||
|
let s = Symbol("foo");
|
||||||
|
let o = { [s]: "bar" };
|
||||||
|
|
||||||
|
expect(o).toHaveConfigurableProperty(s);
|
||||||
|
expect(o).toHaveEnumerableProperty(s);
|
||||||
|
expect(o).toHaveWritableProperty(s);
|
||||||
|
expect(o).toHaveValueProperty(s, "bar");
|
||||||
|
expect(o).not.toHaveGetterProperty(s);
|
||||||
|
expect(o).not.toHaveSetterProperty(s);
|
||||||
|
});
|
||||||
|
|
||||||
test("getter property", () => {
|
test("getter property", () => {
|
||||||
let o = { get foo() {} };
|
let o = { get foo() {} };
|
||||||
|
|
||||||
|
|
|
@ -7,3 +7,8 @@ test("use with object", () => {
|
||||||
let names = Object.getOwnPropertyNames({ foo: 1, bar: 2, baz: 3 });
|
let names = Object.getOwnPropertyNames({ foo: 1, bar: 2, baz: 3 });
|
||||||
expect(names).toEqual(["foo", "bar", "baz"]);
|
expect(names).toEqual(["foo", "bar", "baz"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("use with object with symbol keys", () => {
|
||||||
|
let names = Object.getOwnPropertyNames({ foo: 1, [Symbol("bar")]: 2, baz: 3 });
|
||||||
|
expect(names).toEqual(["foo", "baz"]);
|
||||||
|
});
|
||||||
|
|
|
@ -14,6 +14,11 @@ describe("correct behavior", () => {
|
||||||
expect(keys).toEqual(["foo", "bar", "baz"]);
|
expect(keys).toEqual(["foo", "bar", "baz"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("object argument with symbol keys", () => {
|
||||||
|
let keys = Object.keys({ foo: 1, [Symbol("bar")]: 2, baz: 3 });
|
||||||
|
expect(keys).toEqual(["foo", "baz"]);
|
||||||
|
});
|
||||||
|
|
||||||
test("array argument", () => {
|
test("array argument", () => {
|
||||||
let keys = Object.keys(["a", "b", "c"]);
|
let keys = Object.keys(["a", "b", "c"]);
|
||||||
expect(keys).toEqual(["0", "1", "2"]);
|
expect(keys).toEqual(["0", "1", "2"]);
|
||||||
|
|
|
@ -14,6 +14,11 @@ describe("correct behavior", () => {
|
||||||
expect(values).toEqual([1, 2, 3]);
|
expect(values).toEqual([1, 2, 3]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("object argument with symbol keys", () => {
|
||||||
|
let values = Object.values({ foo: 1, [Symbol("bar")]: 2, baz: 3 });
|
||||||
|
expect(values).toEqual([1, 3]);
|
||||||
|
});
|
||||||
|
|
||||||
test("array argument", () => {
|
test("array argument", () => {
|
||||||
let values = Object.values(["a", "b", "c"]);
|
let values = Object.values(["a", "b", "c"]);
|
||||||
expect(values).toEqual(["a", "b", "c"]);
|
expect(values).toEqual(["a", "b", "c"]);
|
||||||
|
|
|
@ -18,6 +18,8 @@ test("name", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("extended name syntax", () => {
|
test("extended name syntax", () => {
|
||||||
|
const s = Symbol("foo");
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
get "method with space"() {
|
get "method with space"() {
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -30,12 +32,17 @@ test("extended name syntax", () => {
|
||||||
get [`he${"llo"}`]() {
|
get [`he${"llo"}`]() {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get [s]() {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const a = new A();
|
const a = new A();
|
||||||
expect(a["method with space"]).toBe(1);
|
expect(a["method with space"]).toBe(1);
|
||||||
expect(a[12]).toBe(2);
|
expect(a[12]).toBe(2);
|
||||||
expect(a.hello).toBe(3);
|
expect(a.hello).toBe(3);
|
||||||
|
expect(a[s]).toBe(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("inherited getter", () => {
|
test("inherited getter", () => {
|
||||||
|
|
|
@ -29,6 +29,8 @@ test("name", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("extended name syntax", () => {
|
test("extended name syntax", () => {
|
||||||
|
const s = Symbol("foo");
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
set "method with space"(value) {
|
set "method with space"(value) {
|
||||||
this.a = value;
|
this.a = value;
|
||||||
|
@ -41,15 +43,21 @@ test("extended name syntax", () => {
|
||||||
set [`he${"llo"}`](value) {
|
set [`he${"llo"}`](value) {
|
||||||
this.c = value;
|
this.c = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set [s](value) {
|
||||||
|
this.d = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const a = new A();
|
const a = new A();
|
||||||
a["method with space"] = 1;
|
a["method with space"] = 1;
|
||||||
a[12] = 2;
|
a[12] = 2;
|
||||||
a.hello = 3;
|
a.hello = 3;
|
||||||
|
a[s] = 4;
|
||||||
expect(a.a).toBe(1);
|
expect(a.a).toBe(1);
|
||||||
expect(a.b).toBe(2);
|
expect(a.b).toBe(2);
|
||||||
expect(a.c).toBe(3);
|
expect(a.c).toBe(3);
|
||||||
|
expect(a.d).toBe(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("inherited setter", () => {
|
test("inherited setter", () => {
|
||||||
|
|
|
@ -20,6 +20,8 @@ describe("correct behavior", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("extended name syntax", () => {
|
test("extended name syntax", () => {
|
||||||
|
const s = Symbol("foo");
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
static get "method with space"() {
|
static get "method with space"() {
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -32,11 +34,16 @@ describe("correct behavior", () => {
|
||||||
static get [`he${"llo"}`]() {
|
static get [`he${"llo"}`]() {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get [s]() {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(A["method with space"]).toBe(1);
|
expect(A["method with space"]).toBe(1);
|
||||||
expect(A[12]).toBe(2);
|
expect(A[12]).toBe(2);
|
||||||
expect(A.hello).toBe(3);
|
expect(A.hello).toBe(3);
|
||||||
|
expect(A[s]).toBe(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("inherited static getter", () => {
|
test("inherited static getter", () => {
|
||||||
|
|
|
@ -27,6 +27,8 @@ describe("correct behavior", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("extended name syntax", () => {
|
test("extended name syntax", () => {
|
||||||
|
const s = Symbol("foo");
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
static set "method with space"(value) {
|
static set "method with space"(value) {
|
||||||
this.a = value;
|
this.a = value;
|
||||||
|
@ -39,14 +41,20 @@ describe("correct behavior", () => {
|
||||||
static set [`he${"llo"}`](value) {
|
static set [`he${"llo"}`](value) {
|
||||||
this.c = value;
|
this.c = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static set [s](value) {
|
||||||
|
this.d = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
A["method with space"] = 1;
|
A["method with space"] = 1;
|
||||||
A[12] = 2;
|
A[12] = 2;
|
||||||
A.hello = 3;
|
A.hello = 3;
|
||||||
|
A[s] = 4;
|
||||||
expect(A.a).toBe(1);
|
expect(A.a).toBe(1);
|
||||||
expect(A.b).toBe(2);
|
expect(A.b).toBe(2);
|
||||||
expect(A.c).toBe(3);
|
expect(A.c).toBe(3);
|
||||||
|
expect(A.d).toBe(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("inherited static setter", () => {
|
test("inherited static setter", () => {
|
||||||
|
|
|
@ -31,6 +31,14 @@ describe("correct behavior", () => {
|
||||||
expect(o["hello"]).toBe("friends");
|
expect(o["hello"]).toBe("friends");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("symbol keys", () => {
|
||||||
|
let object = {};
|
||||||
|
let symbol = Symbol("foo");
|
||||||
|
|
||||||
|
object[symbol] = 2;
|
||||||
|
expect(object[symbol]).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
test("computed properties", () => {
|
test("computed properties", () => {
|
||||||
const foo = "bar";
|
const foo = "bar";
|
||||||
const computed = "computed";
|
const computed = "computed";
|
||||||
|
|
|
@ -37,3 +37,14 @@ test("computed property method shorthand", () => {
|
||||||
};
|
};
|
||||||
expect(o[14]()).toBe("bar");
|
expect(o[14]()).toBe("bar");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("symbol computed property shorthand", () => {
|
||||||
|
const s = Symbol("foo");
|
||||||
|
const o = {
|
||||||
|
foo: "bar",
|
||||||
|
[s]() {
|
||||||
|
return this.foo;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(o[s]()).toBe("bar");
|
||||||
|
});
|
||||||
|
|
|
@ -12,7 +12,7 @@ const testObjStrSpread = obj => {
|
||||||
};
|
};
|
||||||
|
|
||||||
test("spread object literal inside object literal", () => {
|
test("spread object literal inside object literal", () => {
|
||||||
let obj = {
|
const obj = {
|
||||||
foo: 0,
|
foo: 0,
|
||||||
...{ bar: 1, baz: 2 },
|
...{ bar: 1, baz: 2 },
|
||||||
qux: 3,
|
qux: 3,
|
||||||
|
@ -21,19 +21,19 @@ test("spread object literal inside object literal", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("spread object with assigned property inside object literal", () => {
|
test("spread object with assigned property inside object literal", () => {
|
||||||
obj = { foo: 0, bar: 1, baz: 2 };
|
const obj = { foo: 0, bar: 1, baz: 2 };
|
||||||
obj.qux = 3;
|
obj.qux = 3;
|
||||||
testObjSpread({ ...obj });
|
testObjSpread({ ...obj });
|
||||||
});
|
});
|
||||||
|
|
||||||
test("spread object inside object literal", () => {
|
test("spread object inside object literal", () => {
|
||||||
let a = { bar: 1, baz: 2 };
|
let a = { bar: 1, baz: 2 };
|
||||||
obj = { foo: 0, ...a, qux: 3 };
|
const obj = { foo: 0, ...a, qux: 3 };
|
||||||
testObjSpread(obj);
|
testObjSpread(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("complex nested object spreading", () => {
|
test("complex nested object spreading", () => {
|
||||||
obj = {
|
const obj = {
|
||||||
...{},
|
...{},
|
||||||
...{
|
...{
|
||||||
...{ foo: 0, bar: 1, baz: 2 },
|
...{ foo: 0, bar: 1, baz: 2 },
|
||||||
|
@ -44,31 +44,42 @@ test("complex nested object spreading", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("spread string in object literal", () => {
|
test("spread string in object literal", () => {
|
||||||
obj = { ..."abcd" };
|
const obj = { ..."abcd" };
|
||||||
testObjStrSpread(obj);
|
testObjStrSpread(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("spread array in object literal", () => {
|
test("spread array in object literal", () => {
|
||||||
obj = { ...["a", "b", "c", "d"] };
|
const obj = { ...["a", "b", "c", "d"] };
|
||||||
testObjStrSpread(obj);
|
testObjStrSpread(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("spread string object in object literal", () => {
|
test("spread string object in object literal", () => {
|
||||||
obj = { ...String("abcd") };
|
const obj = { ...String("abcd") };
|
||||||
testObjStrSpread(obj);
|
testObjStrSpread(obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("spread object with non-enumerable property", () => {
|
test("spread object with non-enumerable property", () => {
|
||||||
a = { foo: 0 };
|
const a = { foo: 0 };
|
||||||
Object.defineProperty(a, "bar", {
|
Object.defineProperty(a, "bar", {
|
||||||
value: 1,
|
value: 1,
|
||||||
enumerable: false,
|
enumerable: false,
|
||||||
});
|
});
|
||||||
obj = { ...a };
|
const obj = { ...a };
|
||||||
expect(obj.foo).toBe(0);
|
expect(obj.foo).toBe(0);
|
||||||
expect(obj).not.toHaveProperty("bar");
|
expect(obj).not.toHaveProperty("bar");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("spread object with symbol keys", () => {
|
||||||
|
const s = Symbol("baz");
|
||||||
|
const a = {
|
||||||
|
foo: "bar",
|
||||||
|
[s]: "qux",
|
||||||
|
};
|
||||||
|
const obj = { ...a };
|
||||||
|
expect(obj.foo).toBe("bar");
|
||||||
|
expect(obj[s]).toBe("qux");
|
||||||
|
});
|
||||||
|
|
||||||
test("spreading non-spreadable values", () => {
|
test("spreading non-spreadable values", () => {
|
||||||
let empty = {
|
let empty = {
|
||||||
...undefined,
|
...undefined,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue