Tool JSON output now starts with a compact navigable summary view. Expandable tool output includes quick open-file and diff actions for changed files. Reasoning headers strip stray HTML comments, and navigation tools stay compact.
116 lines
4.1 KiB
TypeScript
116 lines
4.1 KiB
TypeScript
import React from 'react';
|
|
import { describe, expect, test } from 'bun:test';
|
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
|
|
import { I18nProvider } from '@/lib/i18n';
|
|
import { ReasoningTimelineBlock } from './ReasoningPart';
|
|
|
|
// A reasoning text whose summary (first 120 chars) fits in the header but
|
|
// whose expanded body content should only appear when the disclosure is open.
|
|
const LONG_REASONING =
|
|
'First thought about the task at hand and how to approach it carefully.\n' +
|
|
'This second line goes into much deeper detail about the internal reasoning ' +
|
|
'process that should remain hidden in the collapsed header view.';
|
|
|
|
// A long text that should render the collapsible header with a label
|
|
const LONG_JUSTIFICATION =
|
|
'Sorting by activity first because the active session needs immediate attention.\n' +
|
|
'Secondary sort by last updated timestamp ensures a stable deterministic ordering ' +
|
|
'when multiple sessions have the same activity state.';
|
|
|
|
describe('ReasoningTimelineBlock', () => {
|
|
test('renders reasoning traces behind an accessible collapsed disclosure by default', () => {
|
|
const markup = renderToStaticMarkup(
|
|
<I18nProvider>
|
|
<ReasoningTimelineBlock
|
|
text={LONG_REASONING}
|
|
variant="thinking"
|
|
blockId="reasoning-test"
|
|
showDuration={false}
|
|
/>
|
|
</I18nProvider>,
|
|
);
|
|
|
|
// Accessible toggle row is rendered
|
|
expect(markup).toContain('role="button"');
|
|
expect(markup).toContain('aria-expanded="false"');
|
|
expect(markup).toContain('aria-label="Expand reasoning trace"');
|
|
|
|
// Summary preview (beginning of text) is visible in the header
|
|
expect(markup).toContain('First thought');
|
|
|
|
// Historical collapsed blocks do not mount the expanded body, avoiding a
|
|
// first-frame flash when Activity reveals previously hidden rows.
|
|
expect(markup).not.toContain('data-message-text-export-source');
|
|
});
|
|
|
|
test('renders "Justification" label for justification variant when pre-expanded and not streaming', () => {
|
|
const markup = renderToStaticMarkup(
|
|
<I18nProvider>
|
|
<ReasoningTimelineBlock
|
|
text={LONG_JUSTIFICATION}
|
|
variant="justification"
|
|
blockId="justification-test"
|
|
showDuration={false}
|
|
defaultExpanded={true}
|
|
/>
|
|
</I18nProvider>,
|
|
);
|
|
|
|
// Label shown in expanded header should be "Justification" not "Thinking"
|
|
expect(markup).toContain('Justification');
|
|
expect(markup).not.toContain('Thinking');
|
|
});
|
|
|
|
test('renders "Thinking" label for thinking variant when pre-expanded and not streaming', () => {
|
|
const markup = renderToStaticMarkup(
|
|
<I18nProvider>
|
|
<ReasoningTimelineBlock
|
|
text={LONG_REASONING}
|
|
variant="thinking"
|
|
blockId="thinking-test"
|
|
showDuration={false}
|
|
defaultExpanded={true}
|
|
/>
|
|
</I18nProvider>,
|
|
);
|
|
|
|
// Label shown in expanded header should be "Thinking"
|
|
expect(markup).toContain('Thinking');
|
|
});
|
|
|
|
test('header summary is a truncated excerpt from the beginning', () => {
|
|
const markup = renderToStaticMarkup(
|
|
<I18nProvider>
|
|
<ReasoningTimelineBlock
|
|
text={LONG_REASONING}
|
|
variant="thinking"
|
|
blockId="reasoning-test"
|
|
showDuration={false}
|
|
/>
|
|
</I18nProvider>,
|
|
);
|
|
|
|
// Deep body content beyond 120 chars should be cut from the summary span
|
|
expect(markup).not.toContain('remain hidden in the collapsed header view');
|
|
// The ellipsis character marks that the text was truncated
|
|
expect(markup).toContain('…');
|
|
});
|
|
|
|
test('omits trailing empty HTML comments from the header summary', () => {
|
|
const markup = renderToStaticMarkup(
|
|
<I18nProvider>
|
|
<ReasoningTimelineBlock
|
|
text={'Planning accessible icon labels with translations <!-- -->'}
|
|
variant="thinking"
|
|
blockId="reasoning-comment-test"
|
|
showDuration={false}
|
|
/>
|
|
</I18nProvider>,
|
|
);
|
|
|
|
expect(markup).toContain('Planning accessible icon labels with translations');
|
|
expect(markup).not.toContain('<!-- -->');
|
|
});
|
|
});
|