157 lines
3.8 KiB
JavaScript
157 lines
3.8 KiB
JavaScript
import assert from "node:assert";
|
|
import { describe, test } from "node:test";
|
|
import { ObjectTree, Tree } from "../../src/internal.js";
|
|
import * as symbols from "../../src/symbols.js";
|
|
|
|
describe("ObjectTree", () => {
|
|
test("can get the keys of the tree", async () => {
|
|
const fixture = createFixture();
|
|
assert.deepEqual(Array.from(await fixture.keys()), [
|
|
"Alice.md",
|
|
"Bob.md",
|
|
"Carol.md",
|
|
]);
|
|
});
|
|
|
|
test("can get the value for a key", async () => {
|
|
const fixture = createFixture();
|
|
const alice = await fixture.get("Alice.md");
|
|
assert.equal(alice, "Hello, **Alice**.");
|
|
});
|
|
|
|
test("getting an unsupported key returns undefined", async () => {
|
|
const fixture = createFixture();
|
|
assert.equal(await fixture.get("xyz"), undefined);
|
|
});
|
|
|
|
test("getting a null/undefined key throws an exception", async () => {
|
|
const fixture = createFixture();
|
|
await assert.rejects(async () => {
|
|
await fixture.get(null);
|
|
});
|
|
await assert.rejects(async () => {
|
|
await fixture.get(undefined);
|
|
});
|
|
});
|
|
|
|
test("can set a value", async () => {
|
|
const tree = new ObjectTree({
|
|
a: 1,
|
|
b: 2,
|
|
c: 3,
|
|
});
|
|
|
|
// Update existing key
|
|
await tree.set("a", 4);
|
|
|
|
// Delete key
|
|
await tree.set("b", undefined);
|
|
|
|
// Overwrite key with trailing slash
|
|
await tree.set("c/", {});
|
|
|
|
// New key
|
|
await tree.set("d", 5);
|
|
|
|
assert.deepEqual(await Tree.entries(tree), [
|
|
["a", 4],
|
|
["c/", {}],
|
|
["d", 5],
|
|
]);
|
|
});
|
|
|
|
test("can wrap a class instance", async () => {
|
|
class Foo {
|
|
constructor() {
|
|
this.a = 1;
|
|
}
|
|
|
|
get prop() {
|
|
return this._prop;
|
|
}
|
|
set prop(prop) {
|
|
this._prop = prop;
|
|
}
|
|
}
|
|
class Bar extends Foo {
|
|
method() {}
|
|
}
|
|
const bar = new Bar();
|
|
/** @type {any} */ (bar).extra = "Hello";
|
|
const fixture = new ObjectTree(bar);
|
|
assert.deepEqual(await Tree.entries(fixture), [
|
|
["a", 1],
|
|
["extra", "Hello"],
|
|
["prop", undefined],
|
|
]);
|
|
assert.equal(await fixture.get("a"), 1);
|
|
await fixture.set("prop", "Goodbye");
|
|
assert.equal(bar.prop, "Goodbye");
|
|
assert.equal(await fixture.get("prop"), "Goodbye");
|
|
});
|
|
|
|
test("sets parent symbol on subobjects", async () => {
|
|
const fixture = new ObjectTree({
|
|
sub: {},
|
|
});
|
|
const sub = await fixture.get("sub");
|
|
assert.equal(sub[symbols.parent], fixture);
|
|
});
|
|
|
|
test("sets parent on subtrees", async () => {
|
|
const fixture = new ObjectTree({
|
|
a: 1,
|
|
more: new ObjectTree({
|
|
b: 2,
|
|
}),
|
|
});
|
|
const more = await fixture.get("more");
|
|
assert.equal(more.parent, fixture);
|
|
});
|
|
|
|
test("adds trailing slashes to keys for subtrees", async () => {
|
|
const tree = new ObjectTree({
|
|
a1: 1,
|
|
a2: new ObjectTree({
|
|
b1: 2,
|
|
}),
|
|
a3: 3,
|
|
a4: new ObjectTree({
|
|
b2: 4,
|
|
}),
|
|
});
|
|
const keys = Array.from(await tree.keys());
|
|
assert.deepEqual(keys, ["a1", "a2/", "a3", "a4/"]);
|
|
});
|
|
|
|
test("can retrieve values with optional trailing slash", async () => {
|
|
const subtree = {
|
|
async get(key) {},
|
|
async keys() {},
|
|
};
|
|
const tree = new ObjectTree({
|
|
a: 1,
|
|
subtree,
|
|
});
|
|
assert.equal(await tree.get("a"), 1);
|
|
assert.equal(await tree.get("a/"), 1);
|
|
assert.equal(await tree.get("subtree"), subtree);
|
|
assert.equal(await tree.get("subtree/"), subtree);
|
|
});
|
|
|
|
test("method on an object is bound to the object", async () => {
|
|
const n = new Number(123);
|
|
const tree = new ObjectTree(n);
|
|
const method = await tree.get("toString");
|
|
assert.equal(method(), "123");
|
|
});
|
|
});
|
|
|
|
function createFixture() {
|
|
return new ObjectTree({
|
|
"Alice.md": "Hello, **Alice**.",
|
|
"Bob.md": "Hello, **Bob**.",
|
|
"Carol.md": "Hello, **Carol**.",
|
|
});
|
|
}
|