Upload project files
This commit is contained in:
140
kdl-wasm/web/tests/workspace/storage.test.ts
Normal file
140
kdl-wasm/web/tests/workspace/storage.test.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { sampleOlpProject } from "../../src/olp/index.js";
|
||||
import {
|
||||
MemoryWorkspaceStorage,
|
||||
detectWorkspaceDamage,
|
||||
exportWorkspaceBundle,
|
||||
importWorkspaceBundle,
|
||||
initializeWorkspace,
|
||||
migrateManifest,
|
||||
readJson,
|
||||
readManifest,
|
||||
readProjectModel,
|
||||
restoreWorkspace,
|
||||
snapshotWorkspace,
|
||||
writeJson,
|
||||
writeProjectModel
|
||||
} from "../../src/workspace/index.js";
|
||||
|
||||
const NOW = "2026-06-27T00:00:00.000Z";
|
||||
|
||||
describe("Workspace storage", () => {
|
||||
it("creates project manifest and conventional project layout", async () => {
|
||||
const storage = new MemoryWorkspaceStorage();
|
||||
const manifest = await initializeWorkspace(storage, {
|
||||
projectId: "demo_cell",
|
||||
name: "Demo Cell",
|
||||
model: sampleOlpProject(),
|
||||
now: NOW
|
||||
});
|
||||
|
||||
expect(manifest.entrypoints.model).toBe("model/olp-project.json");
|
||||
expect(await storage.list()).toEqual(["model/olp-project.json", "project.json"]);
|
||||
expect(await readManifest(storage)).toEqual(manifest);
|
||||
expect((await readProjectModel(storage)).project.id).toBe("demo_cell");
|
||||
});
|
||||
|
||||
it("supports text/json read-write-delete with OPFS-like async storage", async () => {
|
||||
const storage = new MemoryWorkspaceStorage();
|
||||
await storage.writeText("reports/readme.txt", "hello");
|
||||
await writeJson(storage, "imports/report.json", { ok: true, count: 2 });
|
||||
|
||||
expect(await storage.readText("reports/readme.txt")).toBe("hello");
|
||||
expect(await readJson(storage, "imports/report.json")).toEqual({ ok: true, count: 2 });
|
||||
|
||||
await storage.delete("reports/readme.txt");
|
||||
expect(await storage.exists("reports/readme.txt")).toBe(false);
|
||||
});
|
||||
|
||||
it("snapshots and restores an equivalent workspace", async () => {
|
||||
const source = new MemoryWorkspaceStorage();
|
||||
await initializeWorkspace(source, {
|
||||
projectId: "demo_cell",
|
||||
name: "Demo Cell",
|
||||
model: sampleOlpProject(),
|
||||
now: NOW
|
||||
});
|
||||
await source.writeText("programs/main.grl", "language grl 0.1\n");
|
||||
const snapshot = await snapshotWorkspace(source);
|
||||
|
||||
const target = new MemoryWorkspaceStorage({ "old.txt": "delete me" });
|
||||
await restoreWorkspace(target, snapshot);
|
||||
|
||||
expect(await target.list()).toEqual(await source.list());
|
||||
expect(await snapshotWorkspace(target)).toEqual(snapshot);
|
||||
});
|
||||
|
||||
it("exports and imports a stable JSON bundle with checksum", async () => {
|
||||
const source = new MemoryWorkspaceStorage();
|
||||
await initializeWorkspace(source, {
|
||||
projectId: "demo_cell",
|
||||
name: "Demo Cell",
|
||||
model: sampleOlpProject(),
|
||||
now: NOW
|
||||
});
|
||||
await source.writeText("programs/main.grl", "language grl 0.1\n");
|
||||
const bundle = await exportWorkspaceBundle(source);
|
||||
|
||||
const target = new MemoryWorkspaceStorage();
|
||||
const report = await importWorkspaceBundle(target, bundle);
|
||||
|
||||
expect(report).toEqual({ ok: true, damages: [] });
|
||||
expect(await snapshotWorkspace(target)).toEqual(await snapshotWorkspace(source));
|
||||
});
|
||||
|
||||
it("migrates legacy manifests and detects damaged workspaces", async () => {
|
||||
expect(migrateManifest({
|
||||
schemaVersion: 0,
|
||||
projectId: "legacy",
|
||||
name: "Legacy",
|
||||
createdAt: NOW,
|
||||
updatedAt: NOW,
|
||||
modelPath: "legacy/model.json"
|
||||
})).toMatchObject({
|
||||
schemaVersion: 1,
|
||||
projectId: "legacy",
|
||||
entrypoints: { model: "legacy/model.json" }
|
||||
});
|
||||
|
||||
const storage = new MemoryWorkspaceStorage();
|
||||
await initializeWorkspace(storage, {
|
||||
projectId: "demo_cell",
|
||||
name: "Demo Cell",
|
||||
model: sampleOlpProject(),
|
||||
now: NOW
|
||||
});
|
||||
const checksum = (await snapshotWorkspace(storage)).checksum;
|
||||
const model = await readProjectModel(storage);
|
||||
model.operations[0]!.pathId = "missing_path";
|
||||
await writeProjectModel(storage, model, NOW);
|
||||
|
||||
expect(await detectWorkspaceDamage(storage, checksum)).toMatchObject({
|
||||
ok: false,
|
||||
damages: [
|
||||
expect.objectContaining({ code: "WORKSPACE_MODEL_INVALID" }),
|
||||
expect.objectContaining({ code: "WORKSPACE_CHECKSUM_MISMATCH" })
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects tampered bundles before import", async () => {
|
||||
const source = new MemoryWorkspaceStorage();
|
||||
await initializeWorkspace(source, {
|
||||
projectId: "demo_cell",
|
||||
name: "Demo Cell",
|
||||
model: sampleOlpProject(),
|
||||
now: NOW
|
||||
});
|
||||
const tampered = JSON.parse(await exportWorkspaceBundle(source)) as {
|
||||
files: Record<string, string>;
|
||||
};
|
||||
tampered.files["project.json"] = "{}";
|
||||
|
||||
const target = new MemoryWorkspaceStorage();
|
||||
expect(await importWorkspaceBundle(target, JSON.stringify(tampered))).toMatchObject({
|
||||
ok: false,
|
||||
damages: [expect.objectContaining({ code: "WORKSPACE_CHECKSUM_MISMATCH" })]
|
||||
});
|
||||
expect(await target.list()).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user