Advance M8-M11 parity workflows
This commit is contained in:
55
web/tests/e2e/storage-cleanup.spec.ts
Normal file
55
web/tests/e2e/storage-cleanup.spec.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import path from "node:path";
|
||||
|
||||
const basicBlend = path.resolve(import.meta.dirname, "../../../tests/files/web/basic_scene.blend");
|
||||
|
||||
test("M7-12 removes only one project's unreferenced content-addressed assets", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await expect(page.getByTestId("engine-status")).toContainText("ready, open a .blend file", { timeout: 20_000 });
|
||||
await page.getByTestId("blend-file-input").setInputFiles(basicBlend);
|
||||
await expect(page.getByText("Cube", { exact: true })).toBeVisible();
|
||||
const download = page.waitForEvent("download");
|
||||
await page.getByRole("button", { name: "保存项目" }).click();
|
||||
await download;
|
||||
|
||||
const orphanA = "a".repeat(64);
|
||||
const orphanB = "b".repeat(64);
|
||||
const referenced = await page.evaluate(async ({ orphanA, orphanB }) => {
|
||||
const { StorageClient } = await import("/src/storage/StorageClient.ts");
|
||||
const storage = new StorageClient();
|
||||
const keptA = await storage.putAsset("basic_scene", new Uint8Array(5).buffer, "image/png", "media/kept.png");
|
||||
await storage.putAsset("cleanup-other", new Uint8Array(6).buffer, "image/png", "media/other.png");
|
||||
const root = await navigator.storage.getDirectory();
|
||||
const writeOrphan = async (projectId: string, hash: string, size: number) => {
|
||||
let current = root;
|
||||
for (const segment of ["projects", projectId, "assets", "sha256", hash.slice(0, 2)]) current = await current.getDirectoryHandle(segment, { create: true });
|
||||
const handle = await current.getFileHandle(hash, { create: true });
|
||||
const writer = await handle.createWritable();
|
||||
await writer.write(new Uint8Array(size));
|
||||
await writer.close();
|
||||
};
|
||||
await writeOrphan("basic_scene", orphanA, 19);
|
||||
await writeOrphan("cleanup-other", orphanB, 23);
|
||||
storage.terminate();
|
||||
return { keptA: keptA.sha256, orphanA, orphanB };
|
||||
}, { orphanA, orphanB });
|
||||
|
||||
await page.reload();
|
||||
await expect(page.getByTestId("engine-status")).toContainText("ready, open a .blend file", { timeout: 20_000 });
|
||||
await page.getByTestId("cleanup-project-assets").click();
|
||||
await expect(page.locator(".status-bar")).toContainText("removed 1 orphan asset(s), 19 bytes");
|
||||
const files = await page.evaluate(async ({ orphanA, orphanB, keptA }) => {
|
||||
const root = await navigator.storage.getDirectory();
|
||||
const read = async (projectId: string, hash: string) => {
|
||||
try {
|
||||
let current = root;
|
||||
for (const segment of ["projects", projectId, "assets", "sha256", hash.slice(0, 2)]) current = await current.getDirectoryHandle(segment);
|
||||
await current.getFileHandle(hash);
|
||||
return true;
|
||||
}
|
||||
catch { return false; }
|
||||
};
|
||||
return { orphanA: await read("basic_scene", orphanA), orphanB: await read("cleanup-other", orphanB), keptA: await read("basic_scene", keptA) };
|
||||
}, referenced);
|
||||
expect(files).toEqual({ orphanA: false, orphanB: true, keptA: true });
|
||||
});
|
||||
Reference in New Issue
Block a user