huskies: merge 622_story_wrap_react_state_updates_in_act_to_silence_frontend_test_warnings
This commit is contained in:
@@ -19,7 +19,7 @@ function makeMessages(count: number): Message[] {
|
||||
}));
|
||||
}
|
||||
|
||||
describe("useChatHistory", () => {
|
||||
describe("useChatHistory", async () => {
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
});
|
||||
@@ -28,7 +28,7 @@ describe("useChatHistory", () => {
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
it("AC1: restores messages from localStorage on mount", () => {
|
||||
it("AC1: restores messages from localStorage on mount", async () => {
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(sampleMessages));
|
||||
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
@@ -36,13 +36,13 @@ describe("useChatHistory", () => {
|
||||
expect(result.current.messages).toEqual(sampleMessages);
|
||||
});
|
||||
|
||||
it("AC1: returns empty array when localStorage has no data", () => {
|
||||
it("AC1: returns empty array when localStorage has no data", async () => {
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
|
||||
expect(result.current.messages).toEqual([]);
|
||||
});
|
||||
|
||||
it("AC1: returns empty array when localStorage contains invalid JSON", () => {
|
||||
it("AC1: returns empty array when localStorage contains invalid JSON", async () => {
|
||||
localStorage.setItem(STORAGE_KEY, "not-json{{{");
|
||||
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
@@ -50,7 +50,7 @@ describe("useChatHistory", () => {
|
||||
expect(result.current.messages).toEqual([]);
|
||||
});
|
||||
|
||||
it("AC1: returns empty array when localStorage contains a non-array", () => {
|
||||
it("AC1: returns empty array when localStorage contains a non-array", async () => {
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify({ not: "array" }));
|
||||
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
@@ -58,10 +58,10 @@ describe("useChatHistory", () => {
|
||||
expect(result.current.messages).toEqual([]);
|
||||
});
|
||||
|
||||
it("AC2: saves messages to localStorage when setMessages is called with an array", () => {
|
||||
it("AC2: saves messages to localStorage when setMessages is called with an array", async () => {
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
|
||||
act(() => {
|
||||
await act(async () => {
|
||||
result.current.setMessages(sampleMessages);
|
||||
});
|
||||
|
||||
@@ -69,10 +69,10 @@ describe("useChatHistory", () => {
|
||||
expect(stored).toEqual(sampleMessages);
|
||||
});
|
||||
|
||||
it("AC2: saves messages to localStorage when setMessages is called with updater function", () => {
|
||||
it("AC2: saves messages to localStorage when setMessages is called with updater function", async () => {
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
|
||||
act(() => {
|
||||
await act(async () => {
|
||||
result.current.setMessages(() => sampleMessages);
|
||||
});
|
||||
|
||||
@@ -80,14 +80,14 @@ describe("useChatHistory", () => {
|
||||
expect(stored).toEqual(sampleMessages);
|
||||
});
|
||||
|
||||
it("AC3: clearMessages removes messages from state and localStorage", () => {
|
||||
it("AC3: clearMessages removes messages from state and localStorage", async () => {
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(sampleMessages));
|
||||
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
|
||||
expect(result.current.messages).toEqual(sampleMessages);
|
||||
|
||||
act(() => {
|
||||
await act(async () => {
|
||||
result.current.clearMessages();
|
||||
});
|
||||
|
||||
@@ -95,7 +95,7 @@ describe("useChatHistory", () => {
|
||||
expect(localStorage.getItem(STORAGE_KEY)).toBeNull();
|
||||
});
|
||||
|
||||
it("AC4: handles localStorage quota errors gracefully", () => {
|
||||
it("AC4: handles localStorage quota errors gracefully", async () => {
|
||||
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
||||
const setItemSpy = vi
|
||||
.spyOn(Storage.prototype, "setItem")
|
||||
@@ -106,7 +106,7 @@ describe("useChatHistory", () => {
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
|
||||
// Should not throw
|
||||
act(() => {
|
||||
await act(async () => {
|
||||
result.current.setMessages(sampleMessages);
|
||||
});
|
||||
|
||||
@@ -121,7 +121,7 @@ describe("useChatHistory", () => {
|
||||
setItemSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("AC5: scopes storage key to project path", () => {
|
||||
it("AC5: scopes storage key to project path", async () => {
|
||||
const projectA = "/projects/a";
|
||||
const projectB = "/projects/b";
|
||||
const keyA = `storykit-chat-history:${projectA}`;
|
||||
@@ -140,12 +140,12 @@ describe("useChatHistory", () => {
|
||||
expect(resultB.current.messages).toEqual(messagesB);
|
||||
});
|
||||
|
||||
it("AC2: removes localStorage key when messages are set to empty array", () => {
|
||||
it("AC2: removes localStorage key when messages are set to empty array", async () => {
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(sampleMessages));
|
||||
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
|
||||
act(() => {
|
||||
await act(async () => {
|
||||
result.current.setMessages([]);
|
||||
});
|
||||
|
||||
@@ -154,20 +154,20 @@ describe("useChatHistory", () => {
|
||||
|
||||
// --- Story 179: Chat history pruning tests ---
|
||||
|
||||
it("S179: default limit of 200 is applied when saving to localStorage", () => {
|
||||
it("S179: default limit of 200 is applied when saving to localStorage", async () => {
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
|
||||
expect(result.current.maxMessages).toBe(200);
|
||||
});
|
||||
|
||||
it("S179: messages are pruned from the front when exceeding the limit", () => {
|
||||
it("S179: messages are pruned from the front when exceeding the limit", async () => {
|
||||
// Set a small limit to make testing practical
|
||||
localStorage.setItem(LIMIT_KEY, "3");
|
||||
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
const fiveMessages = makeMessages(5);
|
||||
|
||||
act(() => {
|
||||
await act(async () => {
|
||||
result.current.setMessages(fiveMessages);
|
||||
});
|
||||
|
||||
@@ -180,13 +180,13 @@ describe("useChatHistory", () => {
|
||||
expect(stored[0].content).toBe("Message 3");
|
||||
});
|
||||
|
||||
it("S179: messages under the limit are not pruned", () => {
|
||||
it("S179: messages under the limit are not pruned", async () => {
|
||||
localStorage.setItem(LIMIT_KEY, "10");
|
||||
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
const threeMessages = makeMessages(3);
|
||||
|
||||
act(() => {
|
||||
await act(async () => {
|
||||
result.current.setMessages(threeMessages);
|
||||
});
|
||||
|
||||
@@ -197,7 +197,7 @@ describe("useChatHistory", () => {
|
||||
expect(stored).toHaveLength(3);
|
||||
});
|
||||
|
||||
it("S179: limit is configurable via localStorage key", () => {
|
||||
it("S179: limit is configurable via localStorage key", async () => {
|
||||
localStorage.setItem(LIMIT_KEY, "5");
|
||||
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
@@ -205,10 +205,10 @@ describe("useChatHistory", () => {
|
||||
expect(result.current.maxMessages).toBe(5);
|
||||
});
|
||||
|
||||
it("S179: setMaxMessages updates the limit and persists it", () => {
|
||||
it("S179: setMaxMessages updates the limit and persists it", async () => {
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
|
||||
act(() => {
|
||||
await act(async () => {
|
||||
result.current.setMaxMessages(50);
|
||||
});
|
||||
|
||||
@@ -216,13 +216,13 @@ describe("useChatHistory", () => {
|
||||
expect(localStorage.getItem(LIMIT_KEY)).toBe("50");
|
||||
});
|
||||
|
||||
it("S179: a limit of 0 means unlimited (no pruning)", () => {
|
||||
it("S179: a limit of 0 means unlimited (no pruning)", async () => {
|
||||
localStorage.setItem(LIMIT_KEY, "0");
|
||||
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
const manyMessages = makeMessages(500);
|
||||
|
||||
act(() => {
|
||||
await act(async () => {
|
||||
result.current.setMessages(manyMessages);
|
||||
});
|
||||
|
||||
@@ -233,11 +233,11 @@ describe("useChatHistory", () => {
|
||||
expect(stored).toEqual(manyMessages);
|
||||
});
|
||||
|
||||
it("S179: changing the limit re-prunes messages on next save", () => {
|
||||
it("S179: changing the limit re-prunes messages on next save", async () => {
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
const tenMessages = makeMessages(10);
|
||||
|
||||
act(() => {
|
||||
await act(async () => {
|
||||
result.current.setMessages(tenMessages);
|
||||
});
|
||||
|
||||
@@ -248,7 +248,7 @@ describe("useChatHistory", () => {
|
||||
expect(stored).toHaveLength(10);
|
||||
|
||||
// Now lower the limit — the effect re-runs and prunes
|
||||
act(() => {
|
||||
await act(async () => {
|
||||
result.current.setMaxMessages(3);
|
||||
});
|
||||
|
||||
@@ -257,7 +257,7 @@ describe("useChatHistory", () => {
|
||||
expect(stored[0].content).toBe("Message 8");
|
||||
});
|
||||
|
||||
it("S179: invalid limit in localStorage falls back to default", () => {
|
||||
it("S179: invalid limit in localStorage falls back to default", async () => {
|
||||
localStorage.setItem(LIMIT_KEY, "not-a-number");
|
||||
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
@@ -265,7 +265,7 @@ describe("useChatHistory", () => {
|
||||
expect(result.current.maxMessages).toBe(200);
|
||||
});
|
||||
|
||||
it("S179: negative limit in localStorage falls back to default", () => {
|
||||
it("S179: negative limit in localStorage falls back to default", async () => {
|
||||
localStorage.setItem(LIMIT_KEY, "-5");
|
||||
|
||||
const { result } = renderHook(() => useChatHistory(PROJECT));
|
||||
|
||||
Reference in New Issue
Block a user