mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-12 07:09:19 +03:00
70 lines
2.5 KiB
TypeScript
70 lines
2.5 KiB
TypeScript
import { act, renderHook, waitFor } from "@testing-library/react";
|
|
import type { ReactNode } from "react";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
|
|
import { useSidebarState } from "@/hooks/useSidebarState";
|
|
import type { NanobotClient } from "@/lib/nanobot-client";
|
|
import type { SidebarStatePayload } from "@/lib/types";
|
|
import { ClientProvider } from "@/providers/ClientProvider";
|
|
|
|
describe("useSidebarState", () => {
|
|
it("serializes full-state writes so an older request cannot overwrite a newer update", async () => {
|
|
let resolveFirstWrite: (() => void) | null = null;
|
|
let sidebarStateUpdateHandler: ((state: SidebarStatePayload) => void) | null = null;
|
|
const setSidebarState = vi.fn()
|
|
.mockImplementationOnce((state: SidebarStatePayload) => new Promise<SidebarStatePayload>(
|
|
(resolve) => {
|
|
resolveFirstWrite = () => resolve(state);
|
|
},
|
|
))
|
|
.mockImplementation(async (state: SidebarStatePayload) => state);
|
|
const client = {
|
|
status: "open" as const,
|
|
onStatus: () => () => {},
|
|
onSidebarStateUpdate: (handler: (state: SidebarStatePayload) => void) => {
|
|
sidebarStateUpdateHandler = handler;
|
|
return () => {
|
|
sidebarStateUpdateHandler = null;
|
|
};
|
|
},
|
|
setSidebarState,
|
|
} as unknown as NanobotClient;
|
|
vi.stubGlobal("fetch", vi.fn().mockResolvedValue({
|
|
ok: true,
|
|
status: 200,
|
|
json: async () => ({}),
|
|
}));
|
|
const wrapper = ({ children }: { children: ReactNode }) => (
|
|
<ClientProvider client={client} token="token">
|
|
{children}
|
|
</ClientProvider>
|
|
);
|
|
const { result } = renderHook(() => useSidebarState([], false), { wrapper });
|
|
await waitFor(() => expect(result.current.loading).toBe(false));
|
|
|
|
act(() => {
|
|
void result.current.update((current) => ({
|
|
...current,
|
|
title_overrides: { "websocket:a": "First" },
|
|
}));
|
|
void result.current.update((current) => ({
|
|
...current,
|
|
title_overrides: { "websocket:a": "Second" },
|
|
}));
|
|
});
|
|
|
|
expect(setSidebarState).toHaveBeenCalledTimes(1);
|
|
act(() => {
|
|
sidebarStateUpdateHandler?.(setSidebarState.mock.calls[0]?.[0]);
|
|
});
|
|
expect(result.current.state.title_overrides).toEqual({
|
|
"websocket:a": "Second",
|
|
});
|
|
act(() => resolveFirstWrite?.());
|
|
await waitFor(() => expect(setSidebarState).toHaveBeenCalledTimes(2));
|
|
expect(setSidebarState.mock.calls[1]?.[0]).toEqual(expect.objectContaining({
|
|
title_overrides: { "websocket:a": "Second" },
|
|
}));
|
|
});
|
|
});
|