run npm install to generate a package lock
This commit is contained in:
153
node_modules/@weborigami/async-tree/test/drivers/BrowserFileTree.test.js
generated
vendored
Normal file
153
node_modules/@weborigami/async-tree/test/drivers/BrowserFileTree.test.js
generated
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import BrowserFileTree from "../../src/drivers/BrowserFileTree.js";
|
||||
import { Tree } from "../../src/internal.js";
|
||||
|
||||
// Skip these tests if we're not in a browser.
|
||||
const isBrowser = typeof window !== "undefined";
|
||||
if (isBrowser) {
|
||||
describe("BrowserFileTree", async () => {
|
||||
test("can get the keys of the tree", async () => {
|
||||
const fixture = await createFixture();
|
||||
assert.deepEqual(Array.from(await fixture.keys()), [
|
||||
"Alice.md",
|
||||
"Bob.md",
|
||||
"Carol.md",
|
||||
"subfolder/",
|
||||
]);
|
||||
});
|
||||
|
||||
test("can get the value for a key", async () => {
|
||||
const fixture = await createFixture();
|
||||
const buffer = await fixture.get("Alice.md");
|
||||
assert.equal(text(buffer), "Hello, **Alice**.");
|
||||
});
|
||||
|
||||
test("getting an unsupported key returns undefined", async () => {
|
||||
const fixture = await createFixture();
|
||||
assert.equal(await fixture.get("xyz"), undefined);
|
||||
});
|
||||
|
||||
test("getting empty key returns undefined", async () => {
|
||||
const fixture = await createFixture();
|
||||
assert.equal(await fixture.get(""), undefined);
|
||||
});
|
||||
|
||||
test("getting a null/undefined key throws an exception", async () => {
|
||||
const fixture = await createFixture();
|
||||
await assert.rejects(async () => {
|
||||
await fixture.get(null);
|
||||
});
|
||||
await assert.rejects(async () => {
|
||||
await fixture.get(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
test("sets parent on subtrees", async () => {
|
||||
const fixture = await createFixture();
|
||||
const subfolder = await fixture.get("subfolder");
|
||||
assert.equal(subfolder.parent, fixture);
|
||||
});
|
||||
|
||||
test("can retrieve values with optional trailing slash", async () => {
|
||||
const fixture = await createFixture();
|
||||
assert(await fixture.get("Alice.md"));
|
||||
assert(await fixture.get("Alice.md/"));
|
||||
assert(await fixture.get("subfolder"));
|
||||
assert(await fixture.get("subfolder/"));
|
||||
});
|
||||
|
||||
test("can set a value", async () => {
|
||||
const fixture = await createFixture();
|
||||
|
||||
// Update existing key.
|
||||
await fixture.set("Alice.md", "Goodbye, **Alice**.");
|
||||
|
||||
// New key.
|
||||
await fixture.set("David.md", "Hello, **David**.");
|
||||
|
||||
// Delete key.
|
||||
await fixture.set("Bob.md", undefined);
|
||||
|
||||
// Delete non-existent key.
|
||||
await fixture.set("xyz", undefined);
|
||||
|
||||
assert.deepEqual(await strings(fixture), {
|
||||
"Alice.md": "Goodbye, **Alice**.",
|
||||
"Carol.md": "Hello, **Carol**.",
|
||||
"David.md": "Hello, **David**.",
|
||||
subfolder: {},
|
||||
});
|
||||
});
|
||||
|
||||
test("can create a subfolder via set", async () => {
|
||||
const fixture = await createFixture();
|
||||
const tree = {
|
||||
async get(key) {
|
||||
const name = key.replace(/\.md$/, "");
|
||||
return `Hello, **${name}**.`;
|
||||
},
|
||||
async keys() {
|
||||
return ["Ellen.md"];
|
||||
},
|
||||
};
|
||||
await fixture.set("more", tree);
|
||||
assert.deepEqual(await strings(fixture), {
|
||||
"Alice.md": "Hello, **Alice**.",
|
||||
"Bob.md": "Hello, **Bob**.",
|
||||
"Carol.md": "Hello, **Carol**.",
|
||||
more: {
|
||||
"Ellen.md": "Hello, **Ellen**.",
|
||||
},
|
||||
subfolder: {},
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function createFile(directory, name, contents) {
|
||||
const file = await directory.getFileHandle(name, { create: true });
|
||||
const writable = await file.createWritable();
|
||||
await writable.write(contents);
|
||||
await writable.close();
|
||||
}
|
||||
|
||||
let count = 0;
|
||||
async function createFixture() {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
const directory = await root.getDirectoryHandle("async-tree", {
|
||||
create: true,
|
||||
});
|
||||
|
||||
// Create a new subdirectory for each test.
|
||||
const subdirectoryName = `test${count++}`;
|
||||
|
||||
// Delete any pre-existing subdirectory with that name.
|
||||
try {
|
||||
await directory.removeEntry(subdirectoryName, { recursive: true });
|
||||
} catch (e) {
|
||||
// Ignore errors.
|
||||
}
|
||||
|
||||
const subdirectory = await directory.getDirectoryHandle(subdirectoryName, {
|
||||
create: true,
|
||||
});
|
||||
|
||||
await createFile(subdirectory, "Alice.md", "Hello, **Alice**.");
|
||||
await createFile(subdirectory, "Bob.md", "Hello, **Bob**.");
|
||||
await createFile(subdirectory, "Carol.md", "Hello, **Carol**.");
|
||||
|
||||
await subdirectory.getDirectoryHandle("subfolder", {
|
||||
create: true,
|
||||
});
|
||||
|
||||
return new BrowserFileTree(subdirectory);
|
||||
}
|
||||
|
||||
async function strings(tree) {
|
||||
return Tree.plain(Tree.map(tree, (value) => text(value)));
|
||||
}
|
||||
|
||||
function text(arrayBuffer) {
|
||||
return new TextDecoder().decode(arrayBuffer);
|
||||
}
|
||||
17
node_modules/@weborigami/async-tree/test/drivers/DeepMapTree.test.js
generated
vendored
Normal file
17
node_modules/@weborigami/async-tree/test/drivers/DeepMapTree.test.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import DeepMapTree from "../../src/drivers/DeepMapTree.js";
|
||||
import { Tree } from "../../src/internal.js";
|
||||
|
||||
describe("DeepMapTree", () => {
|
||||
test("returns a DeepMapTree for value that's a Map", async () => {
|
||||
const tree = new DeepMapTree([
|
||||
["a", 1],
|
||||
["map", new Map([["b", 2]])],
|
||||
]);
|
||||
const map = await tree.get("map");
|
||||
assert.equal(map instanceof DeepMapTree, true);
|
||||
assert.deepEqual(await Tree.plain(map), { b: 2 });
|
||||
assert.equal(map.parent, tree);
|
||||
});
|
||||
});
|
||||
35
node_modules/@weborigami/async-tree/test/drivers/DeepObjectTree.test.js
generated
vendored
Normal file
35
node_modules/@weborigami/async-tree/test/drivers/DeepObjectTree.test.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import { DeepObjectTree, Tree } from "../../src/internal.js";
|
||||
|
||||
describe("DeepObjectTree", () => {
|
||||
test("returns an ObjectTree for value that's a plain sub-object or sub-array", async () => {
|
||||
const tree = createFixture();
|
||||
|
||||
const object = await tree.get("object");
|
||||
assert.equal(object instanceof DeepObjectTree, true);
|
||||
assert.deepEqual(await Tree.plain(object), { b: 2 });
|
||||
assert.equal(object.parent, tree);
|
||||
|
||||
const array = await tree.get("array");
|
||||
assert.equal(array instanceof DeepObjectTree, true);
|
||||
assert.deepEqual(await Tree.plain(array), [3]);
|
||||
assert.equal(array.parent, tree);
|
||||
});
|
||||
|
||||
test("adds trailing slashes to keys for subtrees including plain objects or arrays", async () => {
|
||||
const tree = createFixture();
|
||||
const keys = Array.from(await tree.keys());
|
||||
assert.deepEqual(keys, ["a", "object/", "array/"]);
|
||||
});
|
||||
});
|
||||
|
||||
function createFixture() {
|
||||
return new DeepObjectTree({
|
||||
a: 1,
|
||||
object: {
|
||||
b: 2,
|
||||
},
|
||||
array: [3],
|
||||
});
|
||||
}
|
||||
22
node_modules/@weborigami/async-tree/test/drivers/DeferredTree.test.js
generated
vendored
Normal file
22
node_modules/@weborigami/async-tree/test/drivers/DeferredTree.test.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import DeferredTree from "../../src/drivers/DeferredTree.js";
|
||||
import { ObjectTree, Tree } from "../../src/internal.js";
|
||||
|
||||
describe("DeferredTree", () => {
|
||||
test("lazy-loads a treelike object", async () => {
|
||||
const tree = new DeferredTree(async () => ({ a: 1, b: 2, c: 3 }));
|
||||
assert.deepEqual(await Tree.plain(tree), { a: 1, b: 2, c: 3 });
|
||||
});
|
||||
|
||||
test("sets parent on subtrees", async () => {
|
||||
const object = {
|
||||
a: 1,
|
||||
};
|
||||
const parent = new ObjectTree({});
|
||||
const fixture = new DeferredTree(() => object);
|
||||
fixture.parent = parent;
|
||||
const tree = await fixture.tree();
|
||||
assert.equal(tree.parent, parent);
|
||||
});
|
||||
});
|
||||
116
node_modules/@weborigami/async-tree/test/drivers/ExplorableSiteTree.test.js
generated
vendored
Normal file
116
node_modules/@weborigami/async-tree/test/drivers/ExplorableSiteTree.test.js
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
import assert from "node:assert";
|
||||
import { beforeEach, describe, mock, test } from "node:test";
|
||||
import ExplorableSiteTree from "../../src/drivers/ExplorableSiteTree.js";
|
||||
import { Tree } from "../../src/internal.js";
|
||||
|
||||
const textDecoder = new TextDecoder();
|
||||
const textEncoder = new TextEncoder();
|
||||
|
||||
const mockHost = "https://mock";
|
||||
|
||||
const mockResponses = {
|
||||
"/.keys.json": {
|
||||
data: JSON.stringify(["about/", "index.html"]),
|
||||
},
|
||||
"/about": {
|
||||
redirected: true,
|
||||
status: 301,
|
||||
url: "https://mock/about/",
|
||||
},
|
||||
"/about/.keys.json": {
|
||||
data: JSON.stringify(["Alice.html", "Bob.html", "Carol.html"]),
|
||||
},
|
||||
"/about/Alice.html": {
|
||||
data: "Hello, Alice!",
|
||||
},
|
||||
"/about/Bob.html": {
|
||||
data: "Hello, Bob!",
|
||||
},
|
||||
"/about/Carol.html": {
|
||||
data: "Hello, Carol!",
|
||||
},
|
||||
"/index.html": {
|
||||
data: "Home page",
|
||||
},
|
||||
};
|
||||
|
||||
describe("ExplorableSiteTree", () => {
|
||||
beforeEach(() => {
|
||||
mock.method(global, "fetch", mockFetch);
|
||||
});
|
||||
|
||||
test("can get the keys of a tree", async () => {
|
||||
const fixture = new ExplorableSiteTree(mockHost);
|
||||
const keys = await fixture.keys();
|
||||
assert.deepEqual(Array.from(keys), ["about/", "index.html"]);
|
||||
});
|
||||
|
||||
test("can get a plain value for a key", async () => {
|
||||
const fixture = new ExplorableSiteTree(mockHost);
|
||||
const arrayBuffer = await fixture.get("index.html");
|
||||
const text = textDecoder.decode(arrayBuffer);
|
||||
assert.equal(text, "Home page");
|
||||
});
|
||||
|
||||
test("getting an unsupported key returns undefined", async () => {
|
||||
const fixture = new ExplorableSiteTree(mockHost);
|
||||
assert.equal(await fixture.get("xyz"), undefined);
|
||||
});
|
||||
|
||||
test("getting a null/undefined key throws an exception", async () => {
|
||||
const fixture = new ExplorableSiteTree(mockHost);
|
||||
await assert.rejects(async () => {
|
||||
await fixture.get(null);
|
||||
});
|
||||
await assert.rejects(async () => {
|
||||
await fixture.get(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
test("can return a new tree for a key that redirects", async () => {
|
||||
const fixture = new ExplorableSiteTree(mockHost);
|
||||
const about = await fixture.get("about");
|
||||
assert(about instanceof ExplorableSiteTree);
|
||||
assert.equal(about.href, "https://mock/about/");
|
||||
});
|
||||
|
||||
test("can convert a site to a plain object", async () => {
|
||||
const fixture = new ExplorableSiteTree(mockHost);
|
||||
// Convert buffers to strings.
|
||||
const strings = Tree.map(fixture, {
|
||||
deep: true,
|
||||
value: (value) => textDecoder.decode(value),
|
||||
});
|
||||
assert.deepEqual(await Tree.plain(strings), {
|
||||
about: {
|
||||
"Alice.html": "Hello, Alice!",
|
||||
"Bob.html": "Hello, Bob!",
|
||||
"Carol.html": "Hello, Carol!",
|
||||
},
|
||||
"index.html": "Home page",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function mockFetch(href) {
|
||||
if (!href.startsWith(mockHost)) {
|
||||
return { status: 404 };
|
||||
}
|
||||
const path = href.slice(mockHost.length);
|
||||
const mockedResponse = mockResponses[path];
|
||||
if (mockedResponse) {
|
||||
return Object.assign(
|
||||
{
|
||||
arrayBuffer: () => textEncoder.encode(mockedResponse.data).buffer,
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: () => mockedResponse.data,
|
||||
},
|
||||
mockedResponse
|
||||
);
|
||||
}
|
||||
return {
|
||||
ok: false,
|
||||
status: 404,
|
||||
};
|
||||
}
|
||||
192
node_modules/@weborigami/async-tree/test/drivers/FileTree.test.js
generated
vendored
Normal file
192
node_modules/@weborigami/async-tree/test/drivers/FileTree.test.js
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
import assert from "node:assert";
|
||||
import * as fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { describe, test } from "node:test";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import FileTree from "../../src/drivers/FileTree.js";
|
||||
import { ObjectTree, Tree } from "../../src/internal.js";
|
||||
|
||||
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const tempDirectory = path.join(dirname, "fixtures/temp");
|
||||
|
||||
const textDecoder = new TextDecoder();
|
||||
|
||||
describe("FileTree", async () => {
|
||||
test("can get the keys of the tree", async () => {
|
||||
const fixture = createFixture("fixtures/markdown");
|
||||
assert.deepEqual(Array.from(await fixture.keys()), [
|
||||
"Alice.md",
|
||||
"Bob.md",
|
||||
"Carol.md",
|
||||
"subfolder/",
|
||||
]);
|
||||
});
|
||||
|
||||
test("can get the value for a key", async () => {
|
||||
const fixture = createFixture("fixtures/markdown");
|
||||
const buffer = await fixture.get("Alice.md");
|
||||
const text = textDecoder.decode(buffer);
|
||||
assert.equal(text, "Hello, **Alice**.");
|
||||
});
|
||||
|
||||
test("getting an unsupported key returns undefined", async () => {
|
||||
const fixture = createFixture("fixtures/markdown");
|
||||
assert.equal(await fixture.get("xyz"), undefined);
|
||||
});
|
||||
|
||||
test("getting empty key returns undefined", async () => {
|
||||
const fixture = createFixture("fixtures/markdown");
|
||||
assert.equal(await fixture.get(""), undefined);
|
||||
});
|
||||
|
||||
test("getting a null/undefined key throws an exception", async () => {
|
||||
const fixture = createFixture("fixtures/markdown");
|
||||
await assert.rejects(async () => {
|
||||
await fixture.get(null);
|
||||
});
|
||||
await assert.rejects(async () => {
|
||||
await fixture.get(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
test("can retrieve values with optional trailing slash", async () => {
|
||||
const fixture = createFixture("fixtures/markdown");
|
||||
assert(await fixture.get("Alice.md"));
|
||||
assert(await fixture.get("Alice.md/"));
|
||||
assert(await fixture.get("subfolder"));
|
||||
assert(await fixture.get("subfolder/"));
|
||||
});
|
||||
|
||||
test("sets parent on subtrees", async () => {
|
||||
const fixture = createFixture("fixtures");
|
||||
const markdown = await fixture.get("markdown");
|
||||
assert.equal(markdown.parent, fixture);
|
||||
});
|
||||
|
||||
test("can write out a file via set()", async () => {
|
||||
await createTempDirectory();
|
||||
|
||||
// Write out a file.
|
||||
const fileName = "file1";
|
||||
const fileText = "This is the first file.";
|
||||
const tempFiles = new FileTree(tempDirectory);
|
||||
await tempFiles.set(fileName, fileText);
|
||||
|
||||
// Read it back in.
|
||||
const filePath = path.join(tempDirectory, fileName);
|
||||
const actualText = String(await fs.readFile(filePath));
|
||||
|
||||
assert.equal(fileText, actualText);
|
||||
|
||||
await removeTempDirectory();
|
||||
});
|
||||
|
||||
test("create subfolder via set() with empty object value", async () => {
|
||||
await createTempDirectory();
|
||||
|
||||
// Write out new, empty folder called "empty".
|
||||
const tempFiles = new FileTree(tempDirectory);
|
||||
await tempFiles.set("empty", {});
|
||||
|
||||
// Verify folder exists and has no contents.
|
||||
const folderPath = path.join(tempDirectory, "empty");
|
||||
const stats = await fs.stat(folderPath);
|
||||
assert(stats.isDirectory());
|
||||
const files = await fs.readdir(folderPath);
|
||||
assert.deepEqual(files, []);
|
||||
|
||||
await removeTempDirectory();
|
||||
});
|
||||
|
||||
test("create subfolder via set() with empty tree value", async () => {
|
||||
await createTempDirectory();
|
||||
|
||||
// Write out new, empty folder called "empty".
|
||||
const tempFiles = new FileTree(tempDirectory);
|
||||
await tempFiles.set("empty", new ObjectTree({}));
|
||||
|
||||
// Verify folder exists and has no contents.
|
||||
const folderPath = path.join(tempDirectory, "empty");
|
||||
const stats = await fs.stat(folderPath);
|
||||
assert(stats.isDirectory());
|
||||
const files = await fs.readdir(folderPath);
|
||||
assert.deepEqual(files, []);
|
||||
|
||||
await removeTempDirectory();
|
||||
});
|
||||
|
||||
test("can write out subfolder via set()", async () => {
|
||||
await createTempDirectory();
|
||||
|
||||
// Create a tiny set of "files".
|
||||
const obj = {
|
||||
file1: "This is the first file.",
|
||||
subfolder: {
|
||||
file2: "This is the second file.",
|
||||
},
|
||||
};
|
||||
|
||||
// Write out files as a new folder called "folder".
|
||||
const tempFiles = new FileTree(tempDirectory);
|
||||
await tempFiles.set("folder", obj);
|
||||
|
||||
// Read them back in.
|
||||
const actualFiles = await tempFiles.get("folder");
|
||||
const strings = Tree.map(actualFiles, {
|
||||
deep: true,
|
||||
value: (buffer) => textDecoder.decode(buffer),
|
||||
});
|
||||
const plain = await Tree.plain(strings);
|
||||
assert.deepEqual(plain, obj);
|
||||
|
||||
await removeTempDirectory();
|
||||
});
|
||||
|
||||
test("can delete a file via set()", async () => {
|
||||
await createTempDirectory();
|
||||
const tempFile = path.join(tempDirectory, "file");
|
||||
await fs.writeFile(tempFile, "");
|
||||
const tempFiles = new FileTree(tempDirectory);
|
||||
await tempFiles.set("file", undefined);
|
||||
let stats;
|
||||
try {
|
||||
stats = await fs.stat(tempFile);
|
||||
} catch (/** @type {any} */ error) {
|
||||
if (error.code !== "ENOENT") {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
assert(stats === undefined);
|
||||
await removeTempDirectory();
|
||||
});
|
||||
|
||||
test("can delete a folder via set()", async () => {
|
||||
await createTempDirectory();
|
||||
const folder = path.join(tempDirectory, "folder");
|
||||
await fs.mkdir(folder);
|
||||
const tempFiles = new FileTree(tempDirectory);
|
||||
await tempFiles.set("folder", undefined);
|
||||
let stats;
|
||||
try {
|
||||
stats = await fs.stat(folder);
|
||||
} catch (/** @type {any} */ error) {
|
||||
if (error.code !== "ENOENT") {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
assert(stats === undefined);
|
||||
await removeTempDirectory();
|
||||
});
|
||||
});
|
||||
|
||||
function createFixture(fixturePath) {
|
||||
return new FileTree(path.join(dirname, fixturePath));
|
||||
}
|
||||
|
||||
async function createTempDirectory() {
|
||||
await fs.mkdir(tempDirectory, { recursive: true });
|
||||
}
|
||||
|
||||
async function removeTempDirectory() {
|
||||
await fs.rm(tempDirectory, { recursive: true });
|
||||
}
|
||||
46
node_modules/@weborigami/async-tree/test/drivers/FunctionTree.test.js
generated
vendored
Normal file
46
node_modules/@weborigami/async-tree/test/drivers/FunctionTree.test.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import FunctionTree from "../../src/drivers/FunctionTree.js";
|
||||
|
||||
describe("FunctionTree", async () => {
|
||||
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 a value from function with multiple arguments curries the function", async () => {
|
||||
const fixture = new FunctionTree((a, b, c) => a + b + c);
|
||||
const fnA = await fixture.get(1);
|
||||
const fnAB = await fnA.get(2);
|
||||
const result = await fnAB.get(3);
|
||||
assert.equal(result, 6);
|
||||
});
|
||||
|
||||
test("getting an unsupported key returns undefined", async () => {
|
||||
const fixture = createFixture();
|
||||
assert.equal(await fixture.get("xyz"), undefined);
|
||||
});
|
||||
});
|
||||
|
||||
function createFixture() {
|
||||
return new FunctionTree(
|
||||
(key) => {
|
||||
if (key?.endsWith?.(".md")) {
|
||||
const name = key.slice(0, -3);
|
||||
return `Hello, **${name}**.`;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
["Alice.md", "Bob.md", "Carol.md"]
|
||||
);
|
||||
}
|
||||
59
node_modules/@weborigami/async-tree/test/drivers/MapTree.test.js
generated
vendored
Normal file
59
node_modules/@weborigami/async-tree/test/drivers/MapTree.test.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import MapTree from "../../src/drivers/MapTree.js";
|
||||
import * as symbols from "../../src/symbols.js";
|
||||
|
||||
describe("MapTree", () => {
|
||||
test("can get the keys of the tree", async () => {
|
||||
const fixture = createFixture();
|
||||
assert.deepEqual(Array.from(await fixture.keys()), ["a", "b", "c"]);
|
||||
});
|
||||
|
||||
test("can get the value for a key", async () => {
|
||||
const fixture = createFixture();
|
||||
const a = await fixture.get("a");
|
||||
assert.equal(a, 1);
|
||||
});
|
||||
|
||||
test("sets parent on subtrees", async () => {
|
||||
const map = new Map([["more", new Map([["a", 1]])]]);
|
||||
const fixture = new MapTree(map);
|
||||
const more = await fixture.get("more");
|
||||
assert.equal(more[symbols.parent], fixture);
|
||||
});
|
||||
|
||||
test("adds trailing slashes to keys for subtrees", async () => {
|
||||
const tree = new MapTree([
|
||||
["a", 1],
|
||||
["subtree", new MapTree([["b", 2]])],
|
||||
]);
|
||||
const keys = Array.from(await tree.keys());
|
||||
assert.deepEqual(keys, ["a", "subtree/"]);
|
||||
});
|
||||
|
||||
test("can retrieve values with optional trailing slash", async () => {
|
||||
const subtree = new MapTree([["b", 2]]);
|
||||
const tree = new MapTree([
|
||||
["a", 1],
|
||||
["subtree", 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("getting an unsupported key returns undefined", async () => {
|
||||
const fixture = createFixture();
|
||||
assert.equal(await fixture.get("d"), undefined);
|
||||
});
|
||||
});
|
||||
|
||||
function createFixture() {
|
||||
const map = new Map([
|
||||
["a", 1],
|
||||
["b", 2],
|
||||
["c", 3],
|
||||
]);
|
||||
return new MapTree(map);
|
||||
}
|
||||
156
node_modules/@weborigami/async-tree/test/drivers/ObjectTree.test.js
generated
vendored
Normal file
156
node_modules/@weborigami/async-tree/test/drivers/ObjectTree.test.js
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
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**.",
|
||||
});
|
||||
}
|
||||
44
node_modules/@weborigami/async-tree/test/drivers/SetTree.test.js
generated
vendored
Normal file
44
node_modules/@weborigami/async-tree/test/drivers/SetTree.test.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import SetTree from "../../src/drivers/SetTree.js";
|
||||
import { ObjectTree } from "../../src/internal.js";
|
||||
|
||||
describe("SetTree", () => {
|
||||
test("can get the keys of the tree", async () => {
|
||||
const set = new Set(["a", "b", "c"]);
|
||||
const fixture = new SetTree(set);
|
||||
assert.deepEqual(Array.from(await fixture.keys()), [0, 1, 2]);
|
||||
});
|
||||
|
||||
test("can get the value for a key", async () => {
|
||||
const set = new Set(["a", "b", "c"]);
|
||||
const fixture = new SetTree(set);
|
||||
const a = await fixture.get(0);
|
||||
assert.equal(a, "a");
|
||||
});
|
||||
|
||||
test("getting an unsupported key returns undefined", async () => {
|
||||
const set = new Set(["a", "b", "c"]);
|
||||
const fixture = new SetTree(set);
|
||||
assert.equal(await fixture.get(3), undefined);
|
||||
});
|
||||
|
||||
test("getting a null/undefined key throws an exception", async () => {
|
||||
const set = new Set(["a", "b", "c"]);
|
||||
const fixture = new SetTree(set);
|
||||
await assert.rejects(async () => {
|
||||
await fixture.get(null);
|
||||
});
|
||||
await assert.rejects(async () => {
|
||||
await fixture.get(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
test("sets parent on subtrees", async () => {
|
||||
const set = new Set();
|
||||
set.add(new ObjectTree({}));
|
||||
const fixture = new SetTree(set);
|
||||
const subtree = await fixture.get(0);
|
||||
assert.equal(subtree.parent, fixture);
|
||||
});
|
||||
});
|
||||
92
node_modules/@weborigami/async-tree/test/drivers/SiteTree.test.js
generated
vendored
Normal file
92
node_modules/@weborigami/async-tree/test/drivers/SiteTree.test.js
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
import assert from "node:assert";
|
||||
import { beforeEach, describe, mock, test } from "node:test";
|
||||
import SiteTree from "../../src/drivers/SiteTree.js";
|
||||
|
||||
const textDecoder = new TextDecoder();
|
||||
const textEncoder = new TextEncoder();
|
||||
|
||||
const mockHost = "https://mock";
|
||||
|
||||
const mockResponses = {
|
||||
"/about": {
|
||||
redirected: true,
|
||||
status: 301,
|
||||
url: "https://mock/about/",
|
||||
},
|
||||
"/about/Alice.html": {
|
||||
data: "Hello, Alice!",
|
||||
},
|
||||
"/about/Bob.html": {
|
||||
data: "Hello, Bob!",
|
||||
},
|
||||
"/about/Carol.html": {
|
||||
data: "Hello, Carol!",
|
||||
},
|
||||
"/index.html": {
|
||||
data: "Home page",
|
||||
},
|
||||
};
|
||||
|
||||
describe("SiteTree", () => {
|
||||
beforeEach(() => {
|
||||
mock.method(global, "fetch", mockFetch);
|
||||
});
|
||||
|
||||
test("returns an empty array as the keys of a tree", async () => {
|
||||
const fixture = new SiteTree(mockHost);
|
||||
const keys = await fixture.keys();
|
||||
assert.deepEqual(Array.from(keys), []);
|
||||
});
|
||||
|
||||
test("can get a plain value for a key", async () => {
|
||||
const fixture = new SiteTree(mockHost);
|
||||
const arrayBuffer = await fixture.get("index.html");
|
||||
const text = textDecoder.decode(arrayBuffer);
|
||||
assert.equal(text, "Home page");
|
||||
});
|
||||
|
||||
test("immediately return a new tree for a key with a trailing slash", async () => {
|
||||
const fixture = new SiteTree(mockHost);
|
||||
const about = await fixture.get("about/");
|
||||
assert(about instanceof SiteTree);
|
||||
assert.equal(about.href, "https://mock/about/");
|
||||
});
|
||||
|
||||
test("getting an unsupported key returns undefined", async () => {
|
||||
const fixture = new SiteTree(mockHost);
|
||||
assert.equal(await fixture.get("xyz"), undefined);
|
||||
});
|
||||
|
||||
test("getting a null/undefined key throws an exception", async () => {
|
||||
const fixture = new SiteTree(mockHost);
|
||||
await assert.rejects(async () => {
|
||||
await fixture.get(null);
|
||||
});
|
||||
await assert.rejects(async () => {
|
||||
await fixture.get(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function mockFetch(href) {
|
||||
if (!href.startsWith(mockHost)) {
|
||||
return { status: 404 };
|
||||
}
|
||||
const path = href.slice(mockHost.length);
|
||||
const mockedResponse = mockResponses[path];
|
||||
if (mockedResponse) {
|
||||
return Object.assign(
|
||||
{
|
||||
arrayBuffer: () => textEncoder.encode(mockedResponse.data).buffer,
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: () => mockedResponse.data,
|
||||
},
|
||||
mockedResponse
|
||||
);
|
||||
}
|
||||
return {
|
||||
ok: false,
|
||||
status: 404,
|
||||
};
|
||||
}
|
||||
121
node_modules/@weborigami/async-tree/test/drivers/calendarTree.test.js
generated
vendored
Normal file
121
node_modules/@weborigami/async-tree/test/drivers/calendarTree.test.js
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
import assert from "node:assert";
|
||||
import { describe, test } from "node:test";
|
||||
import calendar from "../../src/drivers/calendarTree.js";
|
||||
import { toPlainValue } from "../../src/utilities.js";
|
||||
|
||||
describe("calendarTree", () => {
|
||||
test("without a start or end, returns a tree for today", async () => {
|
||||
const tree = calendar({
|
||||
value: (year, month, day) => `${year}-${month}-${day}`,
|
||||
});
|
||||
const plain = await toPlainValue(tree);
|
||||
const today = new Date();
|
||||
const year = today.getFullYear();
|
||||
const month = (today.getMonth() + 1).toString().padStart(2, "0");
|
||||
const day = today.getDate().toString().padStart(2, "0");
|
||||
assert.deepEqual(plain, {
|
||||
[year]: {
|
||||
[month]: {
|
||||
[day]: `${year}-${month}-${day}`,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("returns a tree for a month range", async () => {
|
||||
const tree = calendar({
|
||||
start: "2025-01",
|
||||
end: "2025-02",
|
||||
value: (year, month, day) => `${year}-${month}-${day}`,
|
||||
});
|
||||
const plain = await toPlainValue(tree);
|
||||
assert.deepEqual(plain, {
|
||||
2025: {
|
||||
"01": {
|
||||
"01": "2025-01-01",
|
||||
"02": "2025-01-02",
|
||||
"03": "2025-01-03",
|
||||
"04": "2025-01-04",
|
||||
"05": "2025-01-05",
|
||||
"06": "2025-01-06",
|
||||
"07": "2025-01-07",
|
||||
"08": "2025-01-08",
|
||||
"09": "2025-01-09",
|
||||
10: "2025-01-10",
|
||||
11: "2025-01-11",
|
||||
12: "2025-01-12",
|
||||
13: "2025-01-13",
|
||||
14: "2025-01-14",
|
||||
15: "2025-01-15",
|
||||
16: "2025-01-16",
|
||||
17: "2025-01-17",
|
||||
18: "2025-01-18",
|
||||
19: "2025-01-19",
|
||||
20: "2025-01-20",
|
||||
21: "2025-01-21",
|
||||
22: "2025-01-22",
|
||||
23: "2025-01-23",
|
||||
24: "2025-01-24",
|
||||
25: "2025-01-25",
|
||||
26: "2025-01-26",
|
||||
27: "2025-01-27",
|
||||
28: "2025-01-28",
|
||||
29: "2025-01-29",
|
||||
30: "2025-01-30",
|
||||
31: "2025-01-31",
|
||||
},
|
||||
"02": {
|
||||
"01": "2025-02-01",
|
||||
"02": "2025-02-02",
|
||||
"03": "2025-02-03",
|
||||
"04": "2025-02-04",
|
||||
"05": "2025-02-05",
|
||||
"06": "2025-02-06",
|
||||
"07": "2025-02-07",
|
||||
"08": "2025-02-08",
|
||||
"09": "2025-02-09",
|
||||
10: "2025-02-10",
|
||||
11: "2025-02-11",
|
||||
12: "2025-02-12",
|
||||
13: "2025-02-13",
|
||||
14: "2025-02-14",
|
||||
15: "2025-02-15",
|
||||
16: "2025-02-16",
|
||||
17: "2025-02-17",
|
||||
18: "2025-02-18",
|
||||
19: "2025-02-19",
|
||||
20: "2025-02-20",
|
||||
21: "2025-02-21",
|
||||
22: "2025-02-22",
|
||||
23: "2025-02-23",
|
||||
24: "2025-02-24",
|
||||
25: "2025-02-25",
|
||||
26: "2025-02-26",
|
||||
27: "2025-02-27",
|
||||
28: "2025-02-28",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("returns a tree for a day range", async () => {
|
||||
const tree = calendar({
|
||||
start: "2025-02-27",
|
||||
end: "2025-03-02",
|
||||
value: (year, month, day) => `${year}-${month}-${day}`,
|
||||
});
|
||||
const plain = await toPlainValue(tree);
|
||||
assert.deepEqual(plain, {
|
||||
2025: {
|
||||
"02": {
|
||||
27: "2025-02-27",
|
||||
28: "2025-02-28",
|
||||
},
|
||||
"03": {
|
||||
"01": "2025-03-01",
|
||||
"02": "2025-03-02",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
1
node_modules/@weborigami/async-tree/test/drivers/fixtures/markdown/Alice.md
generated
vendored
Normal file
1
node_modules/@weborigami/async-tree/test/drivers/fixtures/markdown/Alice.md
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Hello, **Alice**.
|
||||
1
node_modules/@weborigami/async-tree/test/drivers/fixtures/markdown/Bob.md
generated
vendored
Normal file
1
node_modules/@weborigami/async-tree/test/drivers/fixtures/markdown/Bob.md
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Hello, **Bob**.
|
||||
1
node_modules/@weborigami/async-tree/test/drivers/fixtures/markdown/Carol.md
generated
vendored
Normal file
1
node_modules/@weborigami/async-tree/test/drivers/fixtures/markdown/Carol.md
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Hello, **Carol**.
|
||||
1
node_modules/@weborigami/async-tree/test/drivers/fixtures/markdown/subfolder/README.md
generated
vendored
Normal file
1
node_modules/@weborigami/async-tree/test/drivers/fixtures/markdown/subfolder/README.md
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
This file exists to force the creation of the parent folder.
|
||||
Reference in New Issue
Block a user