From 2170d0ccd61563b7e199d8cc97f4e1c5550fd994 Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Tue, 31 Mar 2026 01:51:03 +0200 Subject: [PATCH] Add tests for error handling in storage operations --- tests/domain/editor-store.test.ts | 36 +++++++++++++++++-- .../serialization/local-draft-storage.test.ts | 10 +++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/tests/domain/editor-store.test.ts b/tests/domain/editor-store.test.ts index e8f84480..bf7de1d6 100644 --- a/tests/domain/editor-store.test.ts +++ b/tests/domain/editor-store.test.ts @@ -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", () => { it("returns a stable snapshot between store updates", () => { const store = createEditorStore(); @@ -58,14 +70,34 @@ describe("EditorStore", () => { const writerStore = createEditorStore({ storage }); writerStore.executeCommand(createSetSceneNameCommand("Draft Scene")); - expect(writerStore.saveDraft()).toBe(true); + expect(writerStore.saveDraft()).toEqual({ + status: "saved", + message: "Local draft saved." + }); const readerStore = createEditorStore({ initialDocument: createEmptySceneDocument({ name: "Fresh Scene" }), storage }); - expect(readerStore.loadDraft()).toBe(true); + expect(readerStore.loadDraft()).toMatchObject({ + status: "loaded", + message: "Local draft loaded." + }); 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") + }); + }); }); diff --git a/tests/serialization/local-draft-storage.test.ts b/tests/serialization/local-draft-storage.test.ts index 1d96d824..49ff4dad 100644 --- a/tests/serialization/local-draft-storage.test.ts +++ b/tests/serialization/local-draft-storage.test.ts @@ -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 { @@ -35,7 +35,7 @@ class ThrowingStorage implements KeyValueStorage { } = {} ) {} - getItem(): string | null { + getItem(_key: string): string | null { if (this.options.onGetItem !== undefined) { throw this.options.onGetItem; } @@ -43,13 +43,13 @@ class ThrowingStorage implements KeyValueStorage { return null; } - setItem(): void { + setItem(_key: string, _value: string): void { if (this.options.onSetItem !== undefined) { throw this.options.onSetItem; } } - removeItem(): void { + removeItem(_key: string): void { if (this.options.onRemoveItem !== undefined) { throw this.options.onRemoveItem; } @@ -88,6 +88,8 @@ describe("local draft storage", () => { } finally { if (originalDescriptor !== undefined) { Object.defineProperty(window, "localStorage", originalDescriptor); + } else { + Reflect.deleteProperty(window, "localStorage"); } } });