import { cleanup, fireEvent, render, screen, within } from '@testing-library/react'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { AssistantMessage } from '../../apps/web/src/components/AssistantMessage'; import type { AgentEvent, ChatMessage } from '../../apps/web/src/types'; function messageWithEvents(events: AgentEvent[]): ChatMessage { return { id: 'assistant-1', role: 'assistant', content: '', events, startedAt: 1_000, endedAt: 3_000, }; } describe('AssistantMessage unfinished todo state', () => { afterEach(() => cleanup()); it('keeps Done for a completed latest TodoWrite fixture', () => { render( , ); expect(screen.getByText('Done')).toBeTruthy(); expect(screen.queryByText('Stopped with unfinished work')).toBeNull(); expect(screen.queryByRole('button', { name: 'Continue remaining tasks' })).toBeNull(); }); it('shows unfinished state and passes unfinished todos to the continue callback', () => { const onContinue = vi.fn(); render( , ); expect(screen.getByText('Stopped with unfinished work')).toBeTruthy(); expect(screen.getByText('2 task(s) remain')).toBeTruthy(); const remainingList = screen.getByText('2 task(s) remain').closest('.unfinished-todos'); expect(remainingList).not.toBeNull(); expect(within(remainingList as HTMLElement).getByText('Building components')).toBeTruthy(); expect(within(remainingList as HTMLElement).getByText('Run QA')).toBeTruthy(); fireEvent.click(screen.getByRole('button', { name: 'Continue remaining tasks' })); expect(onContinue).toHaveBeenCalledWith([ { content: 'Build components', status: 'in_progress', activeForm: 'Building components', }, { content: 'Run QA', status: 'pending', activeForm: undefined }, ]); }); it('hides the continue button on older assistant turns', () => { render( , ); expect(screen.getByText('Stopped with unfinished work')).toBeTruthy(); expect(screen.getByText('1 task(s) remain')).toBeTruthy(); expect(screen.queryByRole('button', { name: 'Continue remaining tasks' })).toBeNull(); }); });