/// import { expect, test } from "@playwright/test"; const url = "http://localhost:8085"; test.beforeEach(async ({ page }) => { await page.goto(url); await page.waitForFunction(() => window.setup != null); }); test.describe("PrivateDirectory", () => { test("lookupNode can fetch file added to directory", async ({ page }) => { const result = await page.evaluate(async () => { const { wnfs: { PrivateDirectory, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const initialForest = new PrivateForest(rng); const root = new PrivateDirectory(initialForest.emptyName(), new Date(), rng); var { rootDir, forest } = await root.write( ["text.txt"], true, new Uint8Array([1, 2, 3, 4, 5]), new Date(), initialForest, store, rng, ); return await rootDir.lookupNode("text.txt", true, forest, store); }); expect(result).toBeDefined(); }); test("getNode can fetch node from root dir", async ({ page }) => { const [result0, result1] = await page.evaluate(async (): Promise => { const { wnfs: { PrivateDirectory, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const initialForest = new PrivateForest(rng); const root = new PrivateDirectory(initialForest.emptyName(), new Date(), rng); var { rootDir, forest } = await root.mkdir( ["pictures", "dogs"], true, new Date(), initialForest, store, rng, ); var { rootDir, forest } = await rootDir.write( ["pictures", "cats", "tabby.png"], true, new Uint8Array([1, 2, 3, 4, 5]), new Date(), forest, store, rng, ); var result0 = await rootDir.getNode(["pictures", "cats", "tabby.png"], true, forest, store); var result1 = await rootDir.getNode(["pictures", "dogs", "bingo.png"], true, forest, store); console.log(result0); console.log(result1); return [result0, result1]; }); expect(result0).toBeDefined(); expect(result1).toBeUndefined(); }); test("lookupNode cannot fetch file not added to directory", async ({ page }) => { const result = await page.evaluate(async () => { const { wnfs: { PrivateDirectory, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const initialForest = new PrivateForest(rng); const root = new PrivateDirectory(initialForest.emptyName(), new Date(), rng); return await root.lookupNode("Unknown", true, initialForest, store); }); expect(result).toBe(undefined); }); test("mkdir can create new directory", async ({ page }) => { const result = await page.evaluate(async () => { const { wnfs: { PrivateDirectory, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const initialForest = new PrivateForest(rng); const root = new PrivateDirectory(initialForest.emptyName(), new Date(), rng); var { rootDir, forest } = await root.mkdir( ["pictures", "cats"], true, new Date(), initialForest, store, rng, ); var { rootDir, forest } = await rootDir.write( ["pictures", "cats", "tabby.png"], true, new Uint8Array([1, 2, 3, 4, 5]), new Date(), forest, store, rng, ); var result = await rootDir.getNode(["pictures", "cats", "tabby.png"], true, forest, store); return result; }); expect(result).toBeDefined(); }); test("ls can list children under directory", async ({ page }) => { const result = await page.evaluate(async () => { const { wnfs: { PrivateDirectory, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const initialForest = new PrivateForest(rng); const root = new PrivateDirectory(initialForest.emptyName(), new Date(), rng); var { rootDir, forest } = await root.mkdir( ["pictures", "dogs"], true, new Date(), initialForest, store, rng, ); var { rootDir, forest } = await rootDir.write( ["pictures", "cats", "tabby.png"], true, new Uint8Array([1, 2, 3, 4, 5]), new Date(), forest, store, rng, ); var { result } = await rootDir.ls(["pictures"], true, forest, store); return result; }); expect(result.length).toBe(2); expect(result[0].name).toBe("cats"); expect(result[1].name).toBe("dogs"); }); test("rm can remove children from directory", async ({ page }) => { const result = await page.evaluate(async () => { const { wnfs: { PrivateDirectory, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const initialForest = new PrivateForest(rng); const root = new PrivateDirectory(initialForest.emptyName(), new Date(), rng); var { rootDir, forest } = await root.write( ["pictures", "dogs", "billie.jpeg"], true, new Uint8Array([1, 2, 3, 4, 5]), new Date(), initialForest, store, rng, ); var { rootDir, forest } = await rootDir.write( ["pictures", "cats", "tabby.png"], true, new Uint8Array([1, 2, 3, 4, 5]), new Date(), forest, store, rng, ); var { rootDir, forest } = await rootDir.rm(["pictures", "cats"], true, forest, store, rng); var { result } = await rootDir.ls(["pictures"], true, forest, store); return result; }); expect(result.length).toEqual(1); expect(result[0].name).toEqual("dogs"); }); test("basicMv can move content between directories", async ({ page }) => { const [imagesContent, picturesContent] = await page.evaluate(async () => { const { wnfs: { PrivateDirectory, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const initialForest = new PrivateForest(rng); const root = new PrivateDirectory(initialForest.emptyName(), new Date(), rng); var { rootDir, forest } = await root.write( ["pictures", "cats", "luna.jpeg"], true, new Uint8Array([1, 2, 3, 4, 5]), new Date(), initialForest, store, rng, ); var { rootDir, forest } = await rootDir.write( ["pictures", "cats", "tabby.png"], true, new Uint8Array([1, 2, 3, 4, 5]), new Date(), forest, store, rng, ); var { rootDir, forest } = await rootDir.mkdir( ["images"], true, new Date(), forest, store, rng, ); var { rootDir, forest } = await rootDir.basicMv( ["pictures", "cats"], ["images", "cats"], true, new Date(), forest, store, rng, ); var { result: imagesContent, forest } = await rootDir.ls(["images"], true, forest, store); var { result: picturesContent, forest } = await rootDir.ls(["pictures"], true, forest, store); return [imagesContent, picturesContent]; }); expect(imagesContent.length).toEqual(1); expect(picturesContent.length).toEqual(0); expect(imagesContent[0].name).toEqual("cats"); }); test("cp can copy content between directories", async ({ page }) => { const [imagesContent, picturesContent] = await page.evaluate(async () => { const { wnfs: { PrivateDirectory, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const initialForest = new PrivateForest(rng); const root = new PrivateDirectory(initialForest.emptyName(), new Date(), rng); var { rootDir, forest } = await root.write( ["pictures", "cats", "luna.jpeg"], true, new Uint8Array([1, 2, 3, 4, 5]), new Date(), initialForest, store, rng, ); var { rootDir, forest } = await rootDir.write( ["pictures", "cats", "tabby.png"], true, new Uint8Array([1, 2, 3, 4, 5]), new Date(), forest, store, rng, ); var { rootDir, forest } = await rootDir.mkdir( ["images"], true, new Date(), forest, store, rng, ); var { rootDir, forest } = await rootDir.cp( ["pictures", "cats"], ["images", "cats"], true, new Date(), forest, store, rng, ); var { result: imagesContent, forest } = await rootDir.ls(["images"], true, forest, store); var { result: picturesContent, forest } = await rootDir.ls(["pictures"], true, forest, store); return [imagesContent, picturesContent]; }); expect(imagesContent.length).toEqual(1); expect(picturesContent.length).toEqual(1); expect(imagesContent[0].name).toEqual("cats"); expect(picturesContent[0].name).toEqual("cats"); }); }); test.describe("PrivateFile", () => { test("empty can create empty file", async ({ page }) => { const result = await page.evaluate(async () => { const { wnfs: { PrivateFile, PrivateForest }, mock: { Rng }, } = await window.setup(); const rng = new Rng(); const forest = new PrivateForest(rng); const file = new PrivateFile(forest.emptyName(), new Date(), rng); return file.getId(); }); expect(result).toBeDefined(); }); test("withContent can create file with content", async ({ page }) => { const result = await page.evaluate(async () => { const { wnfs: { PrivateFile, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const forest = new PrivateForest(rng); const store = new MemoryBlockStore(); const [file] = await PrivateFile.withContent( forest.emptyName(), new Date(), new Uint8Array([1, 2, 3, 4, 5]), forest, store, rng, ); return file.getId(); }); expect(result).toBeDefined(); }); test("getContent can fetch file's entire content", async ({ page }) => { const [length, type] = await page.evaluate(async () => { const { wnfs: { PrivateFile, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const initialForest = new PrivateForest(rng); const store = new MemoryBlockStore(); var [file, forest] = await PrivateFile.withContent( initialForest.emptyName(), new Date(), new Uint8Array([1, 2, 3, 4, 5]), initialForest, store, rng, ); let content = await file.getContent(forest, store); return [content.length, content.constructor.name, content]; }); expect(length).toEqual(5); expect(type).toEqual("Uint8Array"); }); test("readAt can fetch file's partial content", async ({ page }) => { const [length, type, content] = await page.evaluate(async () => { const { wnfs: { PrivateFile, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const initialForest = new PrivateForest(rng); const store = new MemoryBlockStore(); var [file, forest] = await PrivateFile.withContent( initialForest.emptyName(), new Date(), new Uint8Array([1, 2, 3, 4, 5]), initialForest, store, rng, ); let content = await file.readAt(1, 3, forest, store); return [content.length, content.constructor.name, content]; }); expect(length).toEqual(3); expect(type).toEqual("Uint8Array"); expect(new Uint8Array(Object.values(content))).toEqual(new Uint8Array([2, 3, 4])); }); test("getSize returns the exact content size", async ({ page }) => { const size = await page.evaluate(async () => { const { wnfs: { PrivateFile, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const initialForest = new PrivateForest(rng); const store = new MemoryBlockStore(); var [file, forest] = await PrivateFile.withContent( initialForest.emptyName(), new Date(), new Uint8Array(2 * 1024 * 1024), initialForest, store, rng, ); return await file.getSize(forest, store); }); expect(size).toEqual(2 * 1024 * 1024); }); test("A PrivateDirectory has the correct metadata", async ({ page }) => { const result = await page.evaluate(async () => { const { wnfs: { PrivateDirectory, PrivateForest }, mock: { Rng }, } = await window.setup(); const rng = new Rng(); const forest = new PrivateForest(rng); const time = new Date(); return new PrivateDirectory(forest.emptyName(), time, rng).metadata(); }); expect(result.created).not.toBeUndefined(); }); test("A PrivateFile has the correct metadata", async ({ page }) => { const result = await page.evaluate(async () => { const { wnfs: { PrivateFile, PrivateForest }, mock: { Rng }, } = await window.setup(); const rng = new Rng(); const forest = new PrivateForest(rng); const time = new Date(); return new PrivateFile(forest.emptyName(), time, rng).metadata(); }); expect(result.created).not.toBeUndefined(); }); }); test.describe("PrivateNode", () => { test("load returns what was stored", async ({ page }) => { const [metadataBefore, metadataAfter] = await page.evaluate(async () => { const { wnfs: { PrivateFile, PrivateNode, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const forest = new PrivateForest(rng); const time = new Date(); const file = new PrivateFile(forest.emptyName(), time, rng); const node = file.asNode(); const [privateRef, newForest] = await node.store(forest, store, rng); const fetched = await PrivateNode.load(privateRef, newForest, store); const metadataBefore = node.asFile().metadata(); const metadataAfter = fetched.asFile().metadata(); return [metadataBefore, metadataAfter]; }); expect(metadataBefore).toBeDefined(); expect(metadataAfter).toBeDefined(); expect(metadataBefore.created).toEqual(metadataAfter.created); expect(metadataBefore.modified).toEqual(metadataAfter.modified); }); test("searchLatest finds latest", async ({ page }) => { const [lsResultBefore, lsResultAfter] = await page.evaluate(async () => { const { wnfs: { PrivateDirectory, PrivateNode, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const forest0 = new PrivateForest(rng); const time = new Date(); // Create a root directory and store const rootDir0 = new PrivateDirectory(forest0.emptyName(), time, rng); const [accessKey, forest1] = await rootDir0.store(forest0, store, rng); // Write something to the directory and store it const { rootDir: rootDir1, forest: forest2 } = await rootDir0.write( ["some", "file.txt"], true, new Uint8Array([0]), time, forest1, store, rng, ); const [_, forest3] = await rootDir1.asNode().store(forest2, store, rng); // loading back the *old* directory using its access key should give an empty directory: const oldNode = await PrivateNode.load(accessKey, forest3, store); const { result: lsResultBefore } = await oldNode.asDir().ls([], false, forest3, store); // loading back the directory with search latest should work: const latestNode = await oldNode.searchLatest(forest3, store); const { result: lsResultAfter } = await latestNode.asDir().ls([], false, forest3, store); return [lsResultBefore, lsResultAfter]; }); expect(lsResultBefore).toBeDefined(); expect(lsResultAfter).toBeDefined(); expect(lsResultBefore).toEqual([]); expect(lsResultAfter.length).toEqual(1); expect(lsResultAfter[0].name).toEqual("some"); }); }); test.describe("PrivateForest", () => { test("store returns a PrivateRef", async ({ page }) => { const result = await page.evaluate(async () => { const { wnfs: { PrivateFile, PrivateForest }, mock: { MemoryBlockStore, Rng, CID }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const forest = new PrivateForest(rng); const time = new Date(); const file = new PrivateFile(forest.emptyName(), time, rng); const node = file.asNode(); const [privateRef, _] = await node.store(forest, store, rng); return { // Need to be converted to arrays so they can be passed as JSON label: Array.from(privateRef.getLabel()), temporalKey: Array.from(privateRef.getTemporalKey()), contentCid: CID.decode(privateRef.getContentCid()).toString(), }; }); expect(result.label.length).toEqual(32); expect(result.temporalKey.length).toEqual(32); expect(result.contentCid).toBeDefined(); }); test("diff gets changes in forests", async ({ page }) => { const changes = await page.evaluate(async () => { const { wnfs: { PrivateFile, PrivateDirectory, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const time = new Date(); var mainForest: any = new PrivateForest(rng); var otherForest: any = mainForest; const file = new PrivateFile(mainForest.emptyName(), time, rng).asNode(); const dir = new PrivateDirectory(mainForest.emptyName(), time, rng).asNode(); var [_, mainForest] = await file.store(mainForest, store, rng); var [_, otherForest] = await dir.store(otherForest, store, rng); const diff = await mainForest.diff(otherForest, store); return diff.map((change: any) => change.getChangeType()); }); expect(changes.length).toEqual(2); expect(changes).toContain("add"); expect(changes).toContain("remove"); }); test("merge combines changes in forests", async ({ page }) => { const result = await page.evaluate(async () => { const { wnfs: { PrivateFile, PrivateDirectory, PrivateForest, PrivateNode }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const time = new Date(); var mainForest: any = new PrivateForest(rng); var otherForest: any = mainForest; const file = new PrivateFile(mainForest.emptyName(), time, rng).asNode(); const dir = new PrivateDirectory(mainForest.emptyName(), time, rng).asNode(); var [_, mainForest] = await file.store(mainForest, store, rng); var [privateRef, otherForest] = await dir.store(otherForest, store, rng); const mergeForest = await mainForest.merge(otherForest, store); return await PrivateNode.load(privateRef, mergeForest, store); }); expect(result).toBeDefined(); }); }); test.describe("AccessKey", () => { test("can encode / decode an access key", async ({ page }) => { const [metadataBefore, metadataAfter] = await page.evaluate(async () => { const { wnfs: { AccessKey, PrivateFile, PrivateNode, PrivateForest }, mock: { MemoryBlockStore, Rng }, } = await window.setup(); const rng = new Rng(); const store = new MemoryBlockStore(); const forest = new PrivateForest(rng); const time = new Date(); const file = new PrivateFile(forest.emptyName(), time, rng); const node = file.asNode(); const [accessKey, newForest] = await node.store(forest, store, rng); const encodedAccessKey = accessKey.toBytes(); const decodedAccessKey = AccessKey.fromBytes(encodedAccessKey); const fetched = await PrivateNode.load(decodedAccessKey, newForest, store); const metadataBefore = node.asFile().metadata(); const metadataAfter = fetched.asFile().metadata(); return [metadataBefore, metadataAfter]; }); expect(metadataBefore).toBeDefined(); expect(metadataAfter).toBeDefined(); expect(metadataBefore.created).toEqual(metadataAfter.created); expect(metadataBefore.modified).toEqual(metadataAfter.modified); }); });