Files
workinf_Blender_Wasm/web/tests/e2e/save-interruption.spec.ts
mes123456 7c16b279ae
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
Advance M7 workflows and release operations
2026-08-15 17:43:53 -04:00

63 lines
2.6 KiB
TypeScript

import { expect, test } from "@playwright/test";
test("M7-05 restores old revision, hash and bytes after every storage save interruption", async ({ page }) => {
await page.goto("/");
const result = await page.evaluate(async () => {
const { StorageClient } = await import("/src/storage/StorageClient.ts");
const projectId = `m7-save-interrupt-${Date.now()}-${Math.random().toString(16).slice(2)}`;
const oldBytes = Uint8Array.from([0x42, 0x4c, 0x45, 0x4e, 0x44, 7, 7, 7]);
const nextBytes = Uint8Array.from([0x42, 0x4c, 0x45, 0x4e, 0x44, 8, 8, 8, 8]);
const initial = new StorageClient();
const baseline = await initial.saveProject(projectId, 7, oldBytes.slice().buffer);
initial.terminate();
const observations = [];
for (const faultAt of ["after-stage", "after-scene-commit", "before-metadata-commit"] as const) {
const attempt = new StorageClient();
let error = "";
try {
await attempt.saveProject(projectId, 8, nextBytes.slice().buffer, faultAt);
}
catch (reason) {
error = reason instanceof Error ? reason.message : String(reason);
}
attempt.terminate();
const restarted = new StorageClient();
const restored = await restarted.readProject(projectId);
restarted.terminate();
observations.push({
faultAt,
error,
revision: restored.revision,
sha256: restored.sha256,
bytes: Array.from(new Uint8Array(restored.buffer)),
recovered: restored.recovered,
});
}
const completed = new StorageClient();
const committed = await completed.saveProject(projectId, 8, nextBytes.slice().buffer);
const reopened = await completed.readProject(projectId);
completed.terminate();
return {
baseline: { revision: baseline.revision, sha256: baseline.sha256, bytes: Array.from(oldBytes) },
observations,
committed: { revision: committed.revision, sha256: committed.sha256, reopenedRevision: reopened.revision, reopenedSha256: reopened.sha256 },
};
});
expect(result.observations).toHaveLength(3);
for (const item of result.observations) {
expect(item.error).toContain(`PROJECT_SAVE_FAULT_INJECTED: ${item.faultAt}`);
expect(item.revision).toBe(result.baseline.revision);
expect(item.sha256).toBe(result.baseline.sha256);
expect(item.bytes).toEqual(result.baseline.bytes);
expect(item.recovered).toBe(false);
}
expect(result.committed.revision).toBe(8);
expect(result.committed.reopenedRevision).toBe(8);
expect(result.committed.sha256).toBe(result.committed.reopenedSha256);
expect(result.committed.sha256).not.toBe(result.baseline.sha256);
});