Add tests for error handling in storage operations

This commit is contained in:
2026-03-31 01:51:03 +02:00
parent 4df1773c95
commit 2170d0ccd6
2 changed files with 40 additions and 6 deletions

View File

@@ -21,6 +21,18 @@ class MemoryStorage implements KeyValueStorage {
} }
} }
class ThrowingStorage implements KeyValueStorage {
getItem(_key: string): string | null {
throw new Error("blocked read");
}
setItem(_key: string, _value: string): void {
throw new Error("blocked write");
}
removeItem(_key: string): void {}
}
describe("EditorStore", () => { describe("EditorStore", () => {
it("returns a stable snapshot between store updates", () => { it("returns a stable snapshot between store updates", () => {
const store = createEditorStore(); const store = createEditorStore();
@@ -58,14 +70,34 @@ describe("EditorStore", () => {
const writerStore = createEditorStore({ storage }); const writerStore = createEditorStore({ storage });
writerStore.executeCommand(createSetSceneNameCommand("Draft Scene")); writerStore.executeCommand(createSetSceneNameCommand("Draft Scene"));
expect(writerStore.saveDraft()).toBe(true); expect(writerStore.saveDraft()).toEqual({
status: "saved",
message: "Local draft saved."
});
const readerStore = createEditorStore({ const readerStore = createEditorStore({
initialDocument: createEmptySceneDocument({ name: "Fresh Scene" }), initialDocument: createEmptySceneDocument({ name: "Fresh Scene" }),
storage storage
}); });
expect(readerStore.loadDraft()).toBe(true); expect(readerStore.loadDraft()).toMatchObject({
status: "loaded",
message: "Local draft loaded."
});
expect(readerStore.getState().document.name).toBe("Draft Scene"); expect(readerStore.getState().document.name).toBe("Draft Scene");
}); });
it("fails gracefully when storage access throws", () => {
const store = createEditorStore({ storage: new ThrowingStorage() });
expect(store.saveDraft()).toMatchObject({
status: "error",
message: expect.stringContaining("blocked write")
});
expect(store.loadDraft()).toMatchObject({
status: "error",
message: expect.stringContaining("blocked read")
});
});
}); });

View File

@@ -1,4 +1,4 @@
import { describe, expect, it, vi } from "vitest"; import { describe, expect, it } from "vitest";
import { SCENE_DOCUMENT_VERSION, createEmptySceneDocument } from "../../src/document/scene-document"; import { SCENE_DOCUMENT_VERSION, createEmptySceneDocument } from "../../src/document/scene-document";
import { import {
@@ -35,7 +35,7 @@ class ThrowingStorage implements KeyValueStorage {
} = {} } = {}
) {} ) {}
getItem(): string | null { getItem(_key: string): string | null {
if (this.options.onGetItem !== undefined) { if (this.options.onGetItem !== undefined) {
throw this.options.onGetItem; throw this.options.onGetItem;
} }
@@ -43,13 +43,13 @@ class ThrowingStorage implements KeyValueStorage {
return null; return null;
} }
setItem(): void { setItem(_key: string, _value: string): void {
if (this.options.onSetItem !== undefined) { if (this.options.onSetItem !== undefined) {
throw this.options.onSetItem; throw this.options.onSetItem;
} }
} }
removeItem(): void { removeItem(_key: string): void {
if (this.options.onRemoveItem !== undefined) { if (this.options.onRemoveItem !== undefined) {
throw this.options.onRemoveItem; throw this.options.onRemoveItem;
} }
@@ -88,6 +88,8 @@ describe("local draft storage", () => {
} finally { } finally {
if (originalDescriptor !== undefined) { if (originalDescriptor !== undefined) {
Object.defineProperty(window, "localStorage", originalDescriptor); Object.defineProperty(window, "localStorage", originalDescriptor);
} else {
Reflect.deleteProperty(window, "localStorage");
} }
} }
}); });