168 lines
4.7 KiB
TypeScript
168 lines
4.7 KiB
TypeScript
import { fireEvent, render, screen } from '@testing-library/react';
|
|
import { describe, expect, it, vi } from 'vitest';
|
|
import { ExecutionGraphCard, formatExecutionDuration } from '@/pages/Chat/ExecutionGraphCard';
|
|
import { getToolVisibilityId } from '@/pages/Chat/chat-transcript';
|
|
import type { TaskStep } from '@/pages/Chat/task-visualization';
|
|
|
|
vi.mock('react-i18next', async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import('react-i18next')>();
|
|
return {
|
|
...actual,
|
|
useTranslation: () => ({
|
|
t: (key: string) => key,
|
|
}),
|
|
};
|
|
});
|
|
|
|
describe('ExecutionGraphCard', () => {
|
|
it('shows only duration units that have elapsed', () => {
|
|
expect(formatExecutionDuration(2_500)).toBe('2s');
|
|
expect(formatExecutionDuration(62_500)).toBe('1m 2s');
|
|
expect(formatExecutionDuration(3_661_500)).toBe('1h 1m 1s');
|
|
expect(formatExecutionDuration(undefined)).toBe('—');
|
|
});
|
|
|
|
it('uses muted styling for the collapsed duration summary', () => {
|
|
render(
|
|
<ExecutionGraphCard
|
|
agentLabel="Makelore"
|
|
steps={[]}
|
|
active={false}
|
|
durationMs={2_500}
|
|
/>,
|
|
);
|
|
|
|
const summary = screen
|
|
.getByTestId('chat-execution-graph-expand')
|
|
.querySelector('span.truncate');
|
|
expect(summary).not.toBeNull();
|
|
expect(summary).toHaveClass('text-muted-foreground/70');
|
|
expect(summary).not.toHaveClass('text-foreground');
|
|
});
|
|
|
|
it('shows the current process summary while the graph is active', () => {
|
|
render(
|
|
<ExecutionGraphCard
|
|
agentLabel="Makelore"
|
|
steps={[{
|
|
id: 'tool-fetch',
|
|
label: 'web_fetch',
|
|
status: 'running',
|
|
kind: 'tool',
|
|
depth: 1,
|
|
}]}
|
|
active
|
|
expanded
|
|
/>,
|
|
);
|
|
|
|
expect(screen.getByTestId('chat-execution-graph-collapse')).toHaveTextContent('web_fetch');
|
|
});
|
|
|
|
it('drives the real graph step detail from the shared visibility set', () => {
|
|
const visibilityId = getToolVisibilityId('msg_assistant', 'tool-read', 0);
|
|
const onStepExpandedChange = vi.fn();
|
|
const step: TaskStep = {
|
|
id: 'tool-read',
|
|
visibilityId,
|
|
label: 'read',
|
|
status: 'completed',
|
|
kind: 'tool',
|
|
detail: '{"file":"README.md"}',
|
|
depth: 1,
|
|
};
|
|
const { rerender } = render(
|
|
<ExecutionGraphCard
|
|
agentLabel="Makelore"
|
|
steps={[step]}
|
|
active={false}
|
|
expanded
|
|
expandedStepIds={new Set()}
|
|
onStepExpandedChange={onStepExpandedChange}
|
|
/>,
|
|
);
|
|
|
|
expect(screen.queryByText(/README\.md/)).not.toBeInTheDocument();
|
|
fireEvent.click(screen.getByRole('button', { name: /read/i }));
|
|
expect(onStepExpandedChange).toHaveBeenCalledWith(visibilityId, true);
|
|
|
|
rerender(
|
|
<ExecutionGraphCard
|
|
agentLabel="Makelore"
|
|
steps={[step]}
|
|
active={false}
|
|
expanded
|
|
expandedStepIds={new Set([visibilityId])}
|
|
onStepExpandedChange={onStepExpandedChange}
|
|
/>,
|
|
);
|
|
expect(screen.getByText(/"file": "README\.md"/)).toBeInTheDocument();
|
|
});
|
|
|
|
it('notifies the parent when an uncontrolled active graph auto-collapses', () => {
|
|
const onExpandedChange = vi.fn();
|
|
const step: TaskStep = {
|
|
id: 'tool-read',
|
|
label: 'read',
|
|
status: 'running',
|
|
kind: 'tool',
|
|
detail: '{"file":"README.md"}',
|
|
depth: 1,
|
|
};
|
|
const { rerender } = render(
|
|
<ExecutionGraphCard
|
|
agentLabel="娉ュ湡"
|
|
steps={[step]}
|
|
active
|
|
onExpandedChange={onExpandedChange}
|
|
/>,
|
|
);
|
|
expect(screen.getByTestId('chat-execution-graph')).toHaveAttribute(
|
|
'data-collapsed',
|
|
'true',
|
|
);
|
|
|
|
fireEvent.click(screen.getByTestId('chat-execution-graph-expand'));
|
|
expect(screen.getByTestId('chat-execution-graph')).toHaveAttribute(
|
|
'data-collapsed',
|
|
'false',
|
|
);
|
|
|
|
rerender(
|
|
<ExecutionGraphCard
|
|
agentLabel="娉ュ湡"
|
|
steps={[{ ...step, status: 'completed' }]}
|
|
active={false}
|
|
onExpandedChange={onExpandedChange}
|
|
/>,
|
|
);
|
|
|
|
expect(screen.getByTestId('chat-execution-graph')).toHaveAttribute(
|
|
'data-collapsed',
|
|
'true',
|
|
);
|
|
expect(onExpandedChange).toHaveBeenCalledWith(false);
|
|
});
|
|
|
|
it('notifies the parent when a completed uncontrolled graph mounts collapsed', () => {
|
|
const onExpandedChange = vi.fn();
|
|
render(
|
|
<ExecutionGraphCard
|
|
agentLabel="娉ュ湡"
|
|
steps={[{
|
|
id: 'tool-read',
|
|
label: 'read',
|
|
status: 'completed',
|
|
kind: 'tool',
|
|
detail: '{"file":"README.md"}',
|
|
depth: 1,
|
|
}]}
|
|
active={false}
|
|
onExpandedChange={onExpandedChange}
|
|
/>,
|
|
);
|
|
|
|
expect(onExpandedChange).toHaveBeenCalledWith(false);
|
|
});
|
|
});
|