first-commit
ci / Validate workspace (push) Has been cancelled
landing-page-ci / Validate landing page (push) Has been cancelled
landing-page-deploy / Deploy landing page (push) Has been cancelled
github-metrics / Generate repository metrics SVG (push) Has been cancelled
refresh-contributors-wall / Refresh contributors wall cache bust (push) Waiting to run
ci / Validate workspace (push) Has been cancelled
landing-page-ci / Validate landing page (push) Has been cancelled
landing-page-deploy / Deploy landing page (push) Has been cancelled
github-metrics / Generate repository metrics SVG (push) Has been cancelled
refresh-contributors-wall / Refresh contributors wall cache bust (push) Waiting to run
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
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(
|
||||
<AssistantMessage
|
||||
message={messageWithEvents([
|
||||
{
|
||||
kind: 'tool_use',
|
||||
id: 'todo-1',
|
||||
name: 'TodoWrite',
|
||||
input: { todos: [{ content: 'Ship layout', status: 'completed' }] },
|
||||
},
|
||||
])}
|
||||
streaming={false}
|
||||
projectId="project-1"
|
||||
isLast
|
||||
/>,
|
||||
);
|
||||
|
||||
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(
|
||||
<AssistantMessage
|
||||
message={messageWithEvents([
|
||||
{
|
||||
kind: 'tool_use',
|
||||
id: 'todo-1',
|
||||
name: 'TodoWrite',
|
||||
input: {
|
||||
todos: [
|
||||
{ content: 'Draft layout', status: 'completed' },
|
||||
{
|
||||
content: 'Build components',
|
||||
status: 'in_progress',
|
||||
activeForm: 'Building components',
|
||||
},
|
||||
{ content: 'Run QA', status: 'pending' },
|
||||
],
|
||||
},
|
||||
},
|
||||
])}
|
||||
streaming={false}
|
||||
projectId="project-1"
|
||||
isLast
|
||||
onContinueRemainingTasks={onContinue}
|
||||
/>,
|
||||
);
|
||||
|
||||
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(
|
||||
<AssistantMessage
|
||||
message={messageWithEvents([
|
||||
{
|
||||
kind: 'tool_use',
|
||||
id: 'todo-1',
|
||||
name: 'TodoWrite',
|
||||
input: { todos: [{ content: 'Run QA', status: 'pending' }] },
|
||||
},
|
||||
])}
|
||||
streaming={false}
|
||||
projectId="project-1"
|
||||
isLast={false}
|
||||
onContinueRemainingTasks={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user