Files
Jyotisha/frontend/tests/shell-frame-stable-mount.test.tsx
T
jesse-uxandGrok (agent loop) 4d63580708 补上类型检查和 lint 没过的几处。
测试里的类型标注补全。侧栏拖宽把手改用组件库按钮,样子仍是 6px 透明细条。报告列表换人时不再在渲染中改引用。删掉已经没人用的证据回执类名。

Co-Authored-By: Grok (agent loop)
2026-10-27 01:58:07 +08:00

86 lines
3.2 KiB
TypeScript

import "./install-test-document";
import assert from "node:assert/strict";
import test from "node:test";
import { useEffect } from "react";
import { ChatChartFrame } from "../src/components/chat-chart-frame.tsx";
import { ShellFrame } from "../src/components/shell-frame.tsx";
import { SidebarProvider } from "../src/components/ui/sidebar.tsx";
import { useUiStore } from "../src/stores/ui-store.ts";
import { createClientLifecycleHarness } from "./react-client-lifecycle-test-support.ts";
function watchMount(record: { mount: number; unmount: number }) {
record.mount += 1;
return () => {
record.unmount += 1;
};
}
function Probe({ record }: { record: { mount: number; unmount: number } }) {
useEffect(() => watchMount(record), [record]);
return <span>probe</span>;
}
function listenForResize(win: Window) {
const buckets = new Map<string, Set<EventListener>>();
win.addEventListener = ((type: string, listener: EventListener) => {
const set = buckets.get(type) ?? new Set<EventListener>();
set.add(listener);
buckets.set(type, set);
}) as Window["addEventListener"];
win.removeEventListener = ((type: string, listener: EventListener) => {
buckets.get(type)?.delete(listener);
}) as Window["removeEventListener"];
win.dispatchEvent = ((event: Event) => {
for (const listener of buckets.get(event.type) ?? []) listener(event);
return true;
}) as Window["dispatchEvent"];
}
test("the shell and the chat column stay mounted when the desktop split arrives", async () => {
const sidebar = { mount: 0, unmount: 0 };
const column = { mount: 0, unmount: 0 };
const harness = createClientLifecycleHarness();
listenForResize(globalThis.window);
const win = globalThis.window as Window & { innerWidth: number };
try {
await harness.render(
<SidebarProvider>
<ShellFrame sidebar={<Probe record={sidebar} />}>
<ChatChartFrame>
<Probe record={column} />
</ChatChartFrame>
</ShellFrame>
</SidebarProvider>,
);
await harness.idle();
assert.equal(sidebar.mount, 1, "sidebar mounted once before the split");
assert.equal(sidebar.unmount, 0, "sidebar unmounted before the split");
assert.equal(column.mount, 1, "chat column mounted once before the split");
assert.equal(column.unmount, 0, "chat column unmounted before the split");
await harness.update(() => {
win.innerWidth = 500;
win.dispatchEvent(new Event("resize"));
});
await harness.idle();
await harness.update(() => {
win.innerWidth = 1440;
win.dispatchEvent(new Event("resize"));
});
await harness.idle();
await harness.update(() => {
useUiStore.getState().setChatChartOpen(true);
});
for (let attempt = 0; attempt < 8; attempt += 1) await harness.idle();
assert.equal(sidebar.mount, 1, "sidebar mounted once across the breakpoint");
assert.equal(sidebar.unmount, 0, "sidebar unmounted across the breakpoint");
assert.equal(column.mount, 1, "chat column mounted once when the chart split arrived");
assert.equal(column.unmount, 0, "chat column unmounted when the chart split arrived");
assert.equal(harness.errors.length, 0, harness.errors.map(String).join("\n"));
} finally {
await harness.close();
}
});