65b90ed43e
- 新增与实现同目录的 5 组用例:阈值与加载门、锚点读取/还原、折叠头冻结与正文对齐、hook 状态机、组件层按钮移除与重试行 - 根 vitest.config.ts 补一条 include,同目录用例才进得了门禁 - 既有断言同步:消息列表类名加上 overflow-anchor 工具类,DirectProjectConversation 用例改用新的加载状态入参 Co-authored-by: Junie <junie@jetbrains.com>
78 lines
2.4 KiB
TypeScript
78 lines
2.4 KiB
TypeScript
// @vitest-environment jsdom
|
||
import { cleanup, render } from '@testing-library/react';
|
||
import { act } from 'react';
|
||
import { afterEach, expect, test, vi } from 'vitest';
|
||
|
||
import { DirectProjectConversation } from '../src/view/project-development/chat/components/DirectProjectConversation/DirectProjectConversation';
|
||
|
||
afterEach(() => {
|
||
cleanup();
|
||
});
|
||
|
||
const STARTED_AT = 1_800_000_000_000;
|
||
|
||
/**
|
||
* 读秒粒度:走对话侧唯一的 `useLiveNow`(`LIVE_TIMER_TICK_MS = 100`)。
|
||
*
|
||
* 状态条的耗时文案不足一分钟保留一位小数,刷新就必须是 100ms——按 1 秒一跳时,用户看到的
|
||
* 是一块「带小数却一格一格跳」的表,像卡住不动。这里用假时钟钉住粒度:把时钟改回 1000ms
|
||
* 时第二步即红。
|
||
*/
|
||
test('运行中状态条的读秒按 100ms 刷新:不足一分钟的耗时以 0.1 秒递增', () => {
|
||
vi.useFakeTimers();
|
||
try {
|
||
vi.setSystemTime(STARTED_AT);
|
||
const view = render(
|
||
<DirectProjectConversation
|
||
turns={[]}
|
||
historyHasMore={false}
|
||
historyLoading={false}
|
||
historyError={null}
|
||
turnInFlight
|
||
activeTurnStartedAt={STARTED_AT}
|
||
onLoadEarlierHistory={() => undefined}
|
||
onRetryEarlierHistory={() => undefined}
|
||
/>,
|
||
);
|
||
const elapsed = () => view.getByText(/^已耗时 /u).textContent;
|
||
expect(elapsed()).toBe('已耗时 0.0秒');
|
||
|
||
act(() => {
|
||
vi.advanceTimersByTime(100);
|
||
});
|
||
expect(elapsed()).toBe('已耗时 0.1秒');
|
||
|
||
// 1 秒一跳的实现会停在上面的 0.1 秒:再走 400ms 必须继续往上加。
|
||
act(() => {
|
||
vi.advanceTimersByTime(400);
|
||
});
|
||
expect(elapsed()).toBe('已耗时 0.5秒');
|
||
} finally {
|
||
vi.useRealTimers();
|
||
}
|
||
});
|
||
|
||
/** 回合不在跑时不订阅时钟:否则空转的 tick 会持续重建状态条所在的那块视图。 */
|
||
test('没有运行中的回合时不订阅时钟', () => {
|
||
vi.useFakeTimers();
|
||
const spy = vi.spyOn(globalThis, 'setInterval');
|
||
try {
|
||
render(
|
||
<DirectProjectConversation
|
||
turns={[]}
|
||
historyHasMore={false}
|
||
historyLoading={false}
|
||
historyError={null}
|
||
turnInFlight={false}
|
||
activeTurnStartedAt={0}
|
||
onLoadEarlierHistory={() => undefined}
|
||
onRetryEarlierHistory={() => undefined}
|
||
/>,
|
||
);
|
||
expect(spy).not.toHaveBeenCalled();
|
||
} finally {
|
||
spy.mockRestore();
|
||
vi.useRealTimers();
|
||
}
|
||
});
|