perf(web): hydrate empty message favorites once (#2025)
This commit is contained in:
@@ -8,7 +8,7 @@ import { SessionPage } from "../../pages/session-page";
|
||||
const SEEDED_MESSAGE = "Favorite toggle regression fixture message";
|
||||
|
||||
test.describe("Chat message favorite toggle", () => {
|
||||
test("stars a message, tints its background yellow, and un-stars it back", async ({
|
||||
test("keeps a starred message highlighted after reload and un-stars it", async ({
|
||||
testPage,
|
||||
apiClient,
|
||||
seedData,
|
||||
@@ -48,6 +48,13 @@ test.describe("Chat message favorite toggle", () => {
|
||||
await expect(unstar).toBeVisible();
|
||||
await expect.poll(async () => highlight.getAttribute("class")).toMatch(/yellow/);
|
||||
|
||||
await testPage.reload();
|
||||
await session.waitForLoad();
|
||||
|
||||
await expect(chat.getByText(SEEDED_MESSAGE)).toBeVisible();
|
||||
await expect(unstar).toBeVisible();
|
||||
await expect.poll(async () => highlight.getAttribute("class")).toMatch(/yellow/);
|
||||
|
||||
await unstar.click();
|
||||
|
||||
await expect(star).toBeVisible();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { useMessageFavoritesStore } from "./favorites-store";
|
||||
import { MESSAGE_FAVORITES_STORAGE_PREFIX, loadSessionFavorites } from "./persistence";
|
||||
|
||||
@@ -11,6 +11,10 @@ describe("message favorites store", () => {
|
||||
useMessageFavoritesStore.setState({ bySession: {} });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("starts with no favorites for an unhydrated session", () => {
|
||||
const state = useMessageFavoritesStore.getState();
|
||||
expect(state.bySession[SESSION_ID]).toBeUndefined();
|
||||
@@ -60,6 +64,15 @@ describe("message favorites store", () => {
|
||||
expect(state.bySession[SESSION_ID]).toEqual({ "msg-1": true, "msg-2": true });
|
||||
});
|
||||
|
||||
it("hydrates an empty session from storage only once", () => {
|
||||
const getItem = vi.spyOn(window.sessionStorage, "getItem");
|
||||
|
||||
useMessageFavoritesStore.getState().hydrateSession(SESSION_ID);
|
||||
useMessageFavoritesStore.getState().hydrateSession(SESSION_ID);
|
||||
|
||||
expect(getItem).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("ignores malformed persisted favorites", () => {
|
||||
window.sessionStorage.setItem(
|
||||
`${MESSAGE_FAVORITES_STORAGE_PREFIX}${SESSION_ID}`,
|
||||
@@ -88,7 +101,7 @@ describe("message favorites store", () => {
|
||||
);
|
||||
|
||||
expect(() => useMessageFavoritesStore.getState().hydrateSession(SESSION_ID)).not.toThrow();
|
||||
expect(useMessageFavoritesStore.getState().bySession[SESSION_ID]).toBeUndefined();
|
||||
expect(useMessageFavoritesStore.getState().bySession[SESSION_ID]).toEqual({});
|
||||
});
|
||||
|
||||
it("ignores a persisted array containing non-string entries", () => {
|
||||
@@ -98,6 +111,6 @@ describe("message favorites store", () => {
|
||||
);
|
||||
|
||||
expect(() => useMessageFavoritesStore.getState().hydrateSession(SESSION_ID)).not.toThrow();
|
||||
expect(useMessageFavoritesStore.getState().bySession[SESSION_ID]).toBeUndefined();
|
||||
expect(useMessageFavoritesStore.getState().bySession[SESSION_ID]).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -21,9 +21,8 @@ export const useMessageFavoritesStore = create<MessageFavoritesSlice>()(
|
||||
hydrateSession: (sessionId: string) =>
|
||||
set((state) => {
|
||||
const existing = state.bySession[sessionId];
|
||||
if (existing && Object.keys(existing).length > 0) return;
|
||||
if (existing) return;
|
||||
const ids = loadSessionFavorites(sessionId);
|
||||
if (ids.length === 0) return;
|
||||
state.bySession[sessionId] = Object.fromEntries(ids.map((id) => [id, true as const]));
|
||||
}),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user