/** @vitest-environment jsdom */ import { render } from '@testing-library/react'; import React from 'react'; import { expect, it } from 'vitest'; import { DirectProjectTurn } from '../src/view/project-development/chat/components/DirectProjectConversation/DirectProjectTurn'; import type { DirectChatTurn, DirectChatTurnState, } from '../src/view/project-development/chat/conversation/directTurnPresentation'; const SENT_AT = 1_800_000_000_000; const ENDED_AT = SENT_AT + 12_400; const turn = ( state: DirectChatTurnState, overrides: Partial = {}, ): DirectChatTurn => ({ key: 'direct-codex:turn-1:user', users: [{ kind: 'user', key: 'u', text: '帮我做一个跳跃动作', at: SENT_AT }], process: [ { kind: 'reasoning', key: 'r', text: '先看目录' }, { kind: 'assistant', key: 'a', text: '正在写' }, ], finals: [{ kind: 'assistant', key: 'a-final', text: '改好了', at: ENDED_AT }], state, startedAt: SENT_AT, endedAt: state === 'finished' ? ENDED_AT : 0, ...overrides, }); it('awaiting-start:本地已发出、原生还没认领时不显示终态文案,也不折叠过程', () => { const view = render( React.createElement(DirectProjectTurn, { turn: turn('awaiting-start'), }), ); expect(view.queryByTestId('turn-usage')).toBeNull(); expect(view.queryByText(/本轮结束于/)).toBeNull(); // 否定式判据:未结束的回合把过程平铺出来,不折进「执行过程」。 expect(view.queryByTestId('turn-process')).toBeNull(); expect(view.getByLabelText('思考过程')).not.toBeNull(); }); it('running:原生回合在跑时同样不显示终态文案', () => { const view = render( React.createElement(DirectProjectTurn, { turn: turn('running') }), ); expect(view.queryByTestId('turn-usage')).toBeNull(); expect(view.queryByTestId('turn-process')).toBeNull(); }); it('finished 且有明确终态:显示结束时间与耗时,过程折叠', () => { const view = render( React.createElement(DirectProjectTurn, { turn: turn('finished') }), ); const usage = view.getByTestId('turn-usage'); expect(usage.textContent).toContain('本轮结束于'); expect(usage.textContent).toContain('耗时 12.4秒'); expect(view.queryByTestId('turn-process')).not.toBeNull(); });