fix: update persisted state workflow

This commit is contained in:
2026-02-19 08:05:33 +05:00
parent 8fccc1e36b
commit 833cc3d086
15 changed files with 216 additions and 205 deletions
+64 -23
View File
@@ -1,4 +1,4 @@
import { STATE_DATA, withPersistence } from "$states/persisted.svelte";
import { withPersistence } from "$states/persisted.svelte";
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
function createMock() {
@@ -40,59 +40,83 @@ describe("persisted.svelte", () => {
describe("withPersistence", () => {
it("should return state unchanged when not in browser", () => {
const data = $state({ test: "value" });
const mockState = {
[STATE_DATA]: { test: "value" },
toSnapshot: () => data,
fromSnapshot: () => {},
};
const result = withPersistence("test-key", mockState);
expect(result).toBe(mockState);
});
it("should restore state from localStorage when valid JSON exists", () => {
const savedData = { value: 42, name: "test" };
interface State {
value: number;
name: string;
}
const savedData: State = { value: 42, name: "test" };
localStorageMock.getItem.mockReturnValue(JSON.stringify(savedData));
const data: State = $state({ value: 0, name: "" });
const state = {
[STATE_DATA]: { value: 0, name: "" },
toSnapshot: () => data,
fromSnapshot: (newData: State) => {
if (newData.value !== undefined) data.value = newData.value;
if (newData.name !== undefined) data.name = newData.name;
},
};
withPersistence("test-key", state);
expect(state[STATE_DATA]).toEqual(savedData);
expect(state.toSnapshot()).toEqual(savedData);
expect(localStorageMock.getItem).toHaveBeenCalledWith("test-key");
});
it("should handle corrupted JSON in localStorage gracefully", () => {
localStorageMock.getItem.mockReturnValue("{ invalid json");
const data = $state({ value: 0 });
const state = {
[STATE_DATA]: { value: 0 },
toSnapshot: () => data,
fromSnapshot: () => {},
};
expect(() => withPersistence("test-key", state)).not.toThrow();
expect(state[STATE_DATA]).toEqual({ value: 0 });
expect(state.toSnapshot()).toEqual({ value: 0 });
});
it("should handle empty localStorage (no saved data)", () => {
localStorageMock.getItem.mockReturnValue(null);
const data = $state({ value: 0 });
const state = {
[STATE_DATA]: { value: 0 },
toSnapshot: () => data,
fromSnapshot: () => {},
};
withPersistence("test-key", state);
expect(state[STATE_DATA]).toEqual({ value: 0 });
expect(state.toSnapshot()).toEqual({ value: 0 });
});
it("should save state to localStorage with debounce", async () => {
vi.useFakeTimers();
interface State {
count: number;
}
const data: State = $state({ count: 1 });
const state = {
[STATE_DATA]: { count: 1 },
toSnapshot: () => data,
fromSnapshot: (newData: State) => {
if (newData.count !== undefined) data.count = newData.count;
},
};
withPersistence("test-key", state, 500);
state[STATE_DATA] = { count: 2 };
state.fromSnapshot({ count: 2 });
await Promise.resolve();
vi.advanceTimersByTime(500);
@@ -108,13 +132,21 @@ describe("persisted.svelte", () => {
});
it("should save state immediately when debounce is 0", async () => {
interface State {
count: number;
}
const data: State = $state({ count: 1 });
const state = {
[STATE_DATA]: { count: 1 },
toSnapshot: () => data,
fromSnapshot: (newData: State) => {
if (newData.count !== undefined) data.count = newData.count;
},
};
withPersistence("test-key", state, 0);
state[STATE_DATA] = { count: 2 };
state.fromSnapshot({ count: 2 });
await Promise.resolve();
@@ -126,23 +158,24 @@ describe("persisted.svelte", () => {
it("should cleanup timeout on state change during debounce", async () => {
vi.useFakeTimers();
const data = $state({ count: 1 });
interface State {
count: number;
}
const data: State = $state({ count: 1 });
const state = {
get [STATE_DATA]() {
return data;
},
set [STATE_DATA](v) {
data.count = v.count;
toSnapshot: () => data,
fromSnapshot: (newData: State) => {
if (newData.count !== undefined) data.count = newData.count;
},
};
withPersistence("test-key", state, 500);
state[STATE_DATA] = { count: 2 };
state.fromSnapshot({ count: 2 });
await Promise.resolve();
state[STATE_DATA] = { count: 3 };
state.fromSnapshot({ count: 3 });
await Promise.resolve();
vi.runOnlyPendingTimers();
@@ -158,13 +191,21 @@ describe("persisted.svelte", () => {
});
it("should use DEBOUNCE_DURATION constant as default", async () => {
interface State {
test: boolean;
}
const data: State = $state({ test: true });
const state = {
[STATE_DATA]: { test: true },
toSnapshot: () => data,
fromSnapshot: (newData: State) => {
if (newData.test !== undefined) data.test = newData.test;
},
};
withPersistence("test-key", state);
state[STATE_DATA] = { test: false };
state.fromSnapshot({ test: false });
await Promise.resolve();