import assert from 'node:assert/strict'
import { renderToStaticMarkup } from 'react-dom/server'
import {
AskUserQuestion,
PlanCreateBlock,
PlanUpdateBlock,
PermissionConfirm,
QuestionFloating,
QuestionAnswerTranscript,
TaskBlock,
ThinkingBlock,
ToolCallCard,
ToolCallRenderer,
ToolGroup,
buildQuestionAnswerPayload,
computeToolGroupVisibleStart,
getPermissionChoices,
getCapturedToolKind,
selectPlanTasks
} from '../src/renderer/src/workbuddy/conversation'
import { convertReadFile, createListFileOpenRequest, createReadFileOpenRequest } from '../src/renderer/src/workbuddy/conversation/ToolCallRenderer'
import { SourceToolHeader } from '../src/renderer/src/workbuddy/conversation/SourceToolHeader'
import { resolveSourceToolIcon } from '../src/renderer/src/workbuddy/conversation/SourceToolIcons'
import { SourceToolDiff } from '../src/renderer/src/workbuddy/conversation/SourceToolDiff'
const toolIconMarkup = (name: string) => renderToStaticMarkup(resolveSourceToolIcon(name) ?? null)
assert.match(toolIconMarkup('Read'), /M7\.7407 13\.66/)
assert.match(toolIconMarkup('read_file'), /M7\.7407 13\.66/)
assert.match(toolIconMarkup('PowerShell'), /M0\.1942 3\.7746/)
assert.match(toolIconMarkup('execute_command'), /M0\.1942 3\.7746/)
assert.match(toolIconMarkup('list_dir'), /M0\.1942 3\.7746/)
assert.equal(toolIconMarkup('Inspect'), toolIconMarkup('execute_command'))
assert.match(toolIconMarkup('Grep'), /M1\.2982 9\.8292/)
assert.match(toolIconMarkup('web_search'), /M1\.37 6\.6667/)
assert.match(toolIconMarkup('mcp_call_tool'), /M2\.9742 -0\.1497/)
assert.match(toolIconMarkup('mcp__browser__tabs_list'), /M6\.3745 2\.6414/)
assert.match(toolIconMarkup('mcp__computer-use__open_app'), /M6\.5 11\.0857/)
assert.match(renderToStaticMarkup(resolveSourceToolIcon('mcp__connector-proxy__pick_location', 'captured-icon') ?? null), /class="captured-icon"/)
assert.match(toolIconMarkup('mcp__workbuddy__skill_management'), /M4\.6063 4\.6987/)
const pluginToolAliases = [
'search_plugins', 'suggest_plugin_install', 'list_installed_plugins', 'uninstall_plugin', 'reconnect_plugin',
'mcp__workbuddy__search_plugins', 'mcp__workbuddy__suggest_plugin_install', 'mcp__workbuddy__list_installed_plugins', 'mcp__workbuddy__uninstall_plugin', 'mcp__workbuddy__reconnect_plugin',
'mcp__connector-proxy__search_plugins', 'mcp__connector-proxy__suggest_plugin_install', 'mcp__connector-proxy__list_installed_plugins', 'mcp__connector-proxy__uninstall_plugin', 'mcp__connector-proxy__reconnect_plugin'
]
for (const alias of pluginToolAliases) assert.match(toolIconMarkup(alias), /M5\.7784 2\.3425/)
assert.match(renderToStaticMarkup(resolveSourceToolIcon('mcp__connector-proxy__reconnect_plugin', 'plugin-icon') ?? null), /class="plugin-icon"/)
assert.match(toolIconMarkup('unregistered_tool'), /M2\.9742 -0\.1497/)
assert.match(toolIconMarkup('mcp__unknown__tool'), /M2\.9742 -0\.1497/)
const tool = {
id: 'tool-1',
name: 'execute_command',
status: 'cancelled' as const,
args: { command: 'echo test' },
result: { output: 'first line\nFINAL OUTPUT SENTINEL' }
}
const presentedFiles = renderToStaticMarkup()
assert.match(presentedFiles, /cr-tool-compact-misc__pre/)
assert.match(presentedFiles, /result.html/)
assert.match(presentedFiles, /aria-expanded="false"/)
assert.doesNotMatch(presentedFiles, /cr-tool-call__data/)
const failedFiles = renderToStaticMarkup()
assert.doesNotMatch(failedFiles, /aria-expanded=/)
const toolMarkup = renderToStaticMarkup()
assert.match(toolMarkup, /execute_command/)
assert.match(toolMarkup, /Cancelled/)
assert.match(toolMarkup, /echo test/)
assert.match(toolMarkup, /FINAL OUTPUT SENTINEL/)
assert.match(renderToStaticMarkup(), /Failed/)
const completeOutput = 'Complete output that exceeds the summary. LAST OUTPUT SENTINEL'
const outputPreferred = renderToStaticMarkup(
)
assert.match(outputPreferred, /Complete output that exceeds the summary/)
assert.match(outputPreferred, /LAST OUTPUT SENTINEL/)
assert.doesNotMatch(outputPreferred, /short summary only/)
const collapsedGroup = renderToStaticMarkup(
group child
)
assert.match(collapsedGroup, /aria-expanded="false"/)
assert.match(collapsedGroup, /Running command/)
assert.match(collapsedGroup, /group child/, 'source collapse retains mounted children for height/opacity transitions')
assert.match(collapsedGroup, /aria-hidden="true" inert=""/)
const expandedGroup = renderToStaticMarkup(
group child
)
assert.match(expandedGroup, /Tools/)
assert.match(expandedGroup, /group child/)
assert.equal(computeToolGroupVisibleStart(20, undefined, 1), 5)
assert.equal(computeToolGroupVisibleStart(20, undefined, 2), 0)
const pagedGroup = renderToStaticMarkup(
{Array.from({ length: 20 }, (_, index) => {`item-${index}`})}
)
assert.match(pagedGroup, /Show 5 earlier/)
assert.doesNotMatch(pagedGroup, /item-0)
assert.match(pagedGroup, /item-19)
const sourceSummaryGroup = renderToStaticMarkup(
{Array.from({ length: 20 }, (_, index) => {`summary-item-${index}`})}
)
assert.match(sourceSummaryGroup, /cr-collapse--summary/)
assert.match(sourceSummaryGroup, /content-inner--summary/)
assert.match(sourceSummaryGroup, /summary-item-0)
assert.match(sourceSummaryGroup, /summary-item-19)
assert.doesNotMatch(sourceSummaryGroup, /Show \d+ earlier/)
const permissionOptions = [
{ optionId: 'once', kind: 'allow_once', name: 'Allow once' },
{ optionId: 'always', kind: 'allow_always', name: 'Always allow' },
{ optionId: 'reject', kind: 'reject_once', name: 'Reject' }
]
assert.equal(getPermissionChoices(permissionOptions).primary?.optionId, 'once')
assert.equal(getPermissionChoices(permissionOptions).secondary?.optionId, 'always')
assert.equal(getPermissionChoices(permissionOptions, 'session').primary?.optionId, 'always')
const pendingPermission = renderToStaticMarkup(
undefined}
reject={() => undefined}
/>
)
assert.match(pendingPermission, /role="dialog"/)
assert.match(pendingPermission, /data-pending-id="permission-1"/)
assert.match(pendingPermission, /data-option-id="once"/)
assert.match(pendingPermission, /Always allow/)
assert.match(pendingPermission, /Reject/)
const answeredPermission = renderToStaticMarkup(
undefined}
reject={() => undefined}
/>
)
assert.match(answeredPermission, /Approved/)
assert.doesNotMatch(answeredPermission, /data-option-id=/)
const respondingPermission = renderToStaticMarkup(
undefined}
reject={() => undefined}
/>
)
assert.match(respondingPermission, /Sending decision/)
assert.match(respondingPermission, /disabled=""/)
const failedPermission = renderToStaticMarkup(
undefined}
reject={() => undefined}
/>
)
assert.match(failedPermission, /Broker unavailable/)
assert.match(failedPermission, /data-option-id="once"/)
const rejectedPermission = renderToStaticMarkup(
undefined}
reject={() => undefined}
/>
)
assert.match(rejectedPermission, /Rejected/)
const cancelledPermission = renderToStaticMarkup(
undefined}
reject={() => undefined}
/>
)
assert.match(cancelledPermission, /Cancelled/)
const questionConfig = {
title: 'Choose a runtime',
questions: [
{
id: 'runtime',
question: 'Which runtime?',
options: [
{ id: 'node', question: 'Node.js', description: 'JavaScript runtime' },
{ id: 'deno', question: 'Deno' }
]
},
{
id: 'features',
question: 'Select features',
multiSelect: true,
options: ['Tests', 'Lint']
}
]
}
const questionMarkup = renderToStaticMarkup()
assert.match(questionMarkup, /Which runtime\?/)
assert.match(questionMarkup, /Node\.js/)
assert.match(questionMarkup, /JavaScript runtime/)
assert.match(questionMarkup, /1\/2/)
assert.match(questionMarkup, /Add your own answer/)
assert.match(questionMarkup, /role="button" aria-pressed="true"/)
const answer = buildQuestionAnswerPayload(
questionConfig.questions,
{ runtime: ['node'], features: ['Tests'] },
{ runtime: '', features: 'Custom feature' },
{ features: true },
questionConfig.title
)
assert.deepEqual(answer, {
title: 'Choose a runtime',
questions: [
{ id: 'runtime', question: 'Which runtime?', answers: ['node'] },
{ id: 'features', question: 'Select features', answers: ['Tests', 'Custom feature'] }
]
})
const pendingQuestion = renderToStaticMarkup(
)
assert.match(pendingQuestion, /Waiting for your answer/)
const completedQuestion = renderToStaticMarkup(
)
assert.match(completedQuestion, /Question for you/)
assert.match(completedQuestion, /Where\?/)
assert.match(completedQuestion, /Here/)
const cancelledQuestion = renderToStaticMarkup(
)
assert.match(cancelledQuestion, /Question cancelled/)
const failedQuestion = renderToStaticMarkup(
)
assert.match(failedQuestion, /Question failed/)
const skippedQuestion = renderToStaticMarkup(
)
assert.match(skippedQuestion, /Question skipped/)
const transcript = renderToStaticMarkup(
)
assert.match(transcript, /\[Skipped\]/)
const collapsedThinking = renderToStaticMarkup()
// The source collapse keeps its content mounted for CSS transitions; it must be inaccessible while closed.
assert.match(collapsedThinking, /cr-collapse--collapsed/)
assert.match(collapsedThinking, /class="cr-collapse__content" aria-hidden="true" inert=""/)
const expandedThinking = renderToStaticMarkup( {text}} />)
assert.match(expandedThinking, /Visible reasoning/)
assert.match(expandedThinking, /Visible reasoning<\/strong>/)
assert.doesNotMatch(expandedThinking, /cr-collapse--collapsed/)
const planTasks = Array.from({ length: 8 }, (_, index) => ({
id: `task-${index}`,
content: `Plan task ${index}`,
status: index < 5 ? 'completed' : index === 5 ? 'in_progress' : 'pending'
}))
assert.deepEqual(selectPlanTasks(planTasks, 3), {
visible: planTasks.slice(4, 7), hiddenCount: 5, currentIndex: 5, startIndex: 4
})
const successfulPlan = renderToStaticMarkup(
undefined} onDownloadPlan={() => undefined} />
)
assert.match(successfulPlan, /Release plan/)
assert.match(successfulPlan, /Plan task 5/)
assert.doesNotMatch(successfulPlan, /Current/, 'the captured plan list has no added Current label')
assert.match(successfulPlan, /\+ 5 更多/)
assert.match(successfulPlan, /Download plan/)
assert.doesNotMatch(successfulPlan, /Plan task 0/)
const failedPlan = renderToStaticMarkup(
)
assert.match(failedPlan, /Failed/)
const activePlanUpdate = renderToStaticMarkup(
)
assert.match(activePlanUpdate, /Release plan confirmed/)
assert.match(activePlanUpdate, /cb-plan-update-spinner/)
const cancelledTask = renderToStaticMarkup(
)
assert.match(cancelledTask, /任务 builder 子代理: Run checks/)
assert.match(cancelledTask, /任务执行已取消!/)
assert.match(cancelledTask, /data-status="cancelled"/)
assert.equal(getCapturedToolKind('Bash'), 'command')
assert.equal(getCapturedToolKind('bash'), 'command')
assert.equal(getCapturedToolKind('glob'), 'file-list')
assert.equal(getCapturedToolKind('grep'), 'file-list')
assert.equal(getCapturedToolKind('read'), 'read-file')
assert.equal(getCapturedToolKind('NotebookEdit'), 'write-file')
assert.equal(getCapturedToolKind('Grep'), 'file-list')
assert.equal(getCapturedToolKind('WebSearch'), 'web-search')
assert.equal(getCapturedToolKind('todo_write'), 'todo-write')
assert.equal(getCapturedToolKind('TodoWrite'), 'todo-write')
assert.equal(getCapturedToolKind('mcp__ardot__create_design'), 'mcp-display')
assert.equal(getCapturedToolKind('mcp__browser__tab_goto'), 'mcp-display')
assert.equal(getCapturedToolKind('mcp__custom__unknown'), undefined)
assert.equal(getCapturedToolKind('custom_tool'), undefined)
const commandRenderer = renderToStaticMarkup(
)
assert.match(commandRenderer, /npm test/)
assert.match(commandRenderer, /all checks passed/)
assert.match(commandRenderer, /cr-tool-exec__output/)
assert.match(commandRenderer, /cr-tool-head__primary/)
assert.doesNotMatch(commandRenderer, /Exit code 0/)
assert.doesNotMatch(commandRenderer, /Full output/)
assert.doesNotMatch(commandRenderer, /Arguments/)
assert.equal(getCapturedToolKind('powershell'), 'command')
const runningCommandRenderer = renderToStaticMarkup(
)
assert.match(runningCommandRenderer, /List contents of src directory/)
assert.match(runningCommandRenderer, /aria-expanded="false"/,
'a running command stays on its one-line summary even when the parent requests expanded details')
assert.match(runningCommandRenderer, /cr-tool-exp__content-shell" aria-hidden="true" inert=""/)
assert.equal((runningCommandRenderer.match(/class="cr-tool-exec__output"/g) ?? []).length, 1,
'the command output remains one replaceable details region')
assert.match(runningCommandRenderer, /first output snapshot\nsecond output snapshot/)
const runningGlobRenderer = renderToStaticMarkup(
)
assert.match(runningGlobRenderer, /cr-tool-list-files__header/)
assert.match(runningGlobRenderer, /搜索中/)
assert.match(runningGlobRenderer, /title="src">Inspecting source layout<\/span>/)
assert.match(runningGlobRenderer, /cr-tool-head__secondary">src<\/span>/)
assert.match(runningGlobRenderer, /aria-expanded="false"/)
assert.match(runningGlobRenderer, /src\/index\.ts\nsrc\/main\.ts/)
const inferredRunningListRenderer = renderToStaticMarkup(
)
assert.match(inferredRunningListRenderer, /List contents of src directory/,
'a list_dir call without provider intent still gets a descriptive one-line action title')
assert.doesNotMatch(inferredRunningListRenderer, /cr-tool-head__secondary/,
'the inferred action title does not repeat the directory as secondary text')
assert.match(inferredRunningListRenderer, /aria-expanded="false"/,
'a running directory listing remains one collapsed, replaceable row')
const inferredRootListRenderer = renderToStaticMarkup(
)
assert.match(inferredRootListRenderer, /List contents of the project directory/,
'an omitted list_dir path resolves to the documented workspace root')
const runningCommandWithIntent = renderToStaticMarkup(
)
assert.match(runningCommandWithIntent, /List contents of src directory/)
assert.match(runningCommandWithIntent, /aria-expanded="false"/)
const emptySuccessfulCommand = renderToStaticMarkup(
)
assert.doesNotMatch(emptySuccessfulCommand, /cr-tool-exec__output/)
assert.doesNotMatch(emptySuccessfulCommand, /Command failed/)
assert.match(emptySuccessfulCommand, /cr-tool-exec__ok/)
assert.match(emptySuccessfulCommand, /运行成功/)
const commandOutputFallback = renderToStaticMarkup(
)
assert.match(commandOutputFallback, /LAST OUTPUT SENTINEL/)
assert.doesNotMatch(commandOutputFallback, /"success": true/)
assert.doesNotMatch(commandOutputFallback, /Full output/)
const failedCommandRenderer = renderToStaticMarkup(
)
assert.match(failedCommandRenderer, /started/)
assert.match(failedCommandRenderer, /operation rejected/)
assert.match(failedCommandRenderer, /执行失败 \(退出码: 7\)/)
assert.doesNotMatch(failedCommandRenderer, /Exit code 7/)
const readRenderer = renderToStaticMarkup(
)
assert.match(readRenderer, /src\/main\.ts/)
assert.match(readRenderer, /class="cr-tool-head__status">已读取<\/span>/)
assert.match(readRenderer, /cr-tool-head__icon[^>]*>
)
assert.match(readIntentRenderer, /Reading project handover status/)
assert.match(readIntentRenderer, /handover\.md/)
const inferredReadRenderer = renderToStaticMarkup(
)
assert.match(inferredReadRenderer, /Read file docs\/README\.md \(lines 10-14\)/,
'a read_file call without provider intent still gets a descriptive action title')
const readOutputFallback = renderToStaticMarkup(
)
assert.doesNotMatch(readOutputFallback, /complete file output sentinel/)
const openedReadTool = {
id: 'read-open', name: 'Read', status: 'executed' as const,
args: { file_path: 'src/open.ts' },
result: [{ type: 'text', text: 'line four\nline five' }]
}
assert.deepEqual(createReadFileOpenRequest(openedReadTool), {
toolCallId: 'read-open', toolName: 'Read', filePath: 'src/open.ts', startLine: undefined, endLine: undefined, content: 'line four\nline five'
})
const numberedReadTool = {
id: 'read-numbered-open', name: 'Read', status: 'executed' as const,
args: { file_path: 'src/numbered.ts' }, result: [{ type: 'text', text: '1→line one\n2→line two\n' }]
}
assert.equal(createReadFileOpenRequest(numberedReadTool).content, 'line one\nline two')
const partialReadTool = {
id: 'read-partial-open', name: 'Read', status: 'executed' as const,
args: { file_path: 'src/partial.ts', startLine: 10, endLine: 12 }, result: [{ type: 'text', text: 'partial chunk' }]
}
assert.equal(convertReadFile(partialReadTool).content, undefined)
assert.deepEqual(createReadFileOpenRequest(partialReadTool), {
toolCallId: 'read-partial-open', toolName: 'Read', filePath: 'src/partial.ts', startLine: 10, endLine: 12, content: undefined
})
const missingReadPathRenderer = renderToStaticMarkup(
)
assert.match(missingReadPathRenderer, /已读取/)
assert.doesNotMatch(missingReadPathRenderer, /read output without a path/)
const failedReadRenderer = renderToStaticMarkup(
)
assert.match(failedReadRenderer, /cr-tool-head__icon--error/)
assert.doesNotMatch(failedReadRenderer, /ENOENT: missing\.ts/)
const numberedReadRenderer = renderToStaticMarkup(
)
assert.doesNotMatch(numberedReadRenderer, /line joined/)
assert.doesNotMatch(numberedReadRenderer, /line \njoined/)
const partialReadRenderer = renderToStaticMarkup(
)
assert.doesNotMatch(partialReadRenderer, /partial chunk/)
const todoWriteRenderer = renderToStaticMarkup(
)
assert.match(todoWriteRenderer, /进度更新 1\/3/)
assert.match(todoWriteRenderer, /Completed task/)
assert.match(todoWriteRenderer, /Writing the active task/)
assert.match(todoWriteRenderer, /Pending task/)
assert.match(todoWriteRenderer, /cb-plan-task--completed/)
assert.match(todoWriteRenderer, /cb-plan-task--in_progress/)
assert.match(todoWriteRenderer, /cb-plan-task--pending/)
const todoStepsRenderer = renderToStaticMarkup(
)
assert.match(todoStepsRenderer, /Compatibility step/)
assert.match(todoStepsRenderer, /cb-plan-task--in_progress/)
const fileListRenderer = renderToStaticMarkup(
)
assert.match(fileListRenderer, /src\/main\.ts/)
assert.match(fileListRenderer, /src\/util\.ts/)
assert.match(fileListRenderer, /搜索文件/)
assert.match(fileListRenderer, /M1\.2982 9\.8292/)
const listFileRequest = createListFileOpenRequest(
{ id: 'files-open', name: 'Grep', status: 'success' },
{ filePath: 'src/main.ts', fileName: 'main.ts', isDirectory: false, startLine: 12, endLine: 13, content: 'matched text' }
)
assert.deepEqual(listFileRequest, { toolCallId: 'files-open', toolName: 'Grep', filePath: 'src/main.ts', startLine: 12, endLine: 13 })
const markdownWebSearchRenderer = renderToStaticMarkup(
)
assert.match(markdownWebSearchRenderer, /captured query/)
assert.match(markdownWebSearchRenderer, /First result/)
assert.match(markdownWebSearchRenderer, /Second result/)
const structuredWebSearchRenderer = renderToStaticMarkup(
)
assert.match(structuredWebSearchRenderer, /structured query/)
assert.match(structuredWebSearchRenderer, /Raw response result/)
assert.match(structuredWebSearchRenderer, /网页搜索/)
assert.match(structuredWebSearchRenderer, /M1\.37 6\.6667/)
assert.doesNotMatch(structuredWebSearchRenderer, /Structured result/)
const webFetchRenderer = renderToStaticMarkup(
)
assert.match(webFetchRenderer, /网页获取/)
assert.match(webFetchRenderer, /M1\.37 6\.6667/)
const mcpCallRenderer = renderToStaticMarkup(
)
assert.match(mcpCallRenderer, /browser \(navigate\)/)
assert.match(mcpCallRenderer, /cr-tool-mcp__body/)
assert.match(mcpCallRenderer, /https:\/\/example\.com/)
assert.match(mcpCallRenderer, /navigation completed/)
assert.match(mcpCallRenderer, /运行成功/)
assert.match(mcpCallRenderer, /M2\.9742 -0\.1497/)
const mcpErrorRenderer = renderToStaticMarkup(
)
assert.match(mcpErrorRenderer, /server unavailable/)
assert.match(mcpErrorRenderer, /cr-tool-head__icon--error/)
const mcpDisplayRenderer = renderToStaticMarkup(
)
assert.match(mcpDisplayRenderer, /cr-tool-display-list/)
assert.match(mcpDisplayRenderer, /create design/)
assert.match(mcpDisplayRenderer, /Landing page/)
assert.match(mcpDisplayRenderer, /design created/)
assert.match(mcpDisplayRenderer, /M2\.9742 -0\.1497/)
const editRenderer = renderToStaticMarkup(
undefined} />
)
assert.match(editRenderer, /before/)
assert.match(editRenderer, /after/)
assert.match(editRenderer, /class="cr-tool-head__status">编辑<\/span>/)
assert.match(editRenderer, /1 处修改/)
assert.match(editRenderer, /role="link"/)
const replacementRenderer = renderToStaticMarkup(
)
assert.match(replacementRenderer, /\+1/)
assert.match(replacementRenderer, /-1/)
const streamedWriteContent = Array.from({ length: 502 }, (_, index) => `line-${index}`).join('\n')
const streamedWriteRenderer = renderToStaticMarkup(
)
assert.match(streamedWriteRenderer, /修改中/)
assert.match(streamedWriteRenderer, /line-499/)
assert.match(streamedWriteRenderer, /… 省略 2 行/)
assert.doesNotMatch(streamedWriteRenderer, /line-501/)
assert.doesNotMatch(streamedWriteRenderer, /cr-tool-write__content--add/)
const creatingRenderer = renderToStaticMarkup(
)
assert.match(creatingRenderer, /生成中/)
assert.doesNotMatch(creatingRenderer, /cr-tool-write__content--add/)
const createdRenderer = renderToStaticMarkup(
)
assert.match(createdRenderer, /cr-tool-write__content--add/)
const successfulWriteWithOutput = renderToStaticMarkup(
)
assert.doesNotMatch(successfulWriteWithOutput, /role="alert"/)
assert.doesNotMatch(successfulWriteWithOutput, /\{"success":true\}/)
const failedWriteWithOutput = renderToStaticMarkup(
)
assert.doesNotMatch(failedWriteWithOutput, /role="alert"/)
assert.doesNotMatch(failedWriteWithOutput, /write failed/)
assert.match(failedWriteWithOutput, /cr-tool-head__icon--error/)
const virtualWriteDiff = renderToStaticMarkup(
`line-${index}`).join('\n')} fileName="src/new.ts" />
)
assert.match(virtualWriteDiff, /cr-tool-diff--virtual/)
assert.ok((virtualWriteDiff.match(/cr-tool-diff__virtual-line/g) ?? []).length < 100)
const planRenderer = renderToStaticMarkup(
)
assert.match(planRenderer, /Created by tool/)
assert.match(planRenderer, /First task/)
assert.doesNotMatch(planRenderer, /查看计划/)
const actionablePlan = renderToStaticMarkup(
undefined}
onPlanView={() => undefined}
onPlanBuild={() => undefined}
/>
)
assert.match(actionablePlan, /role="button"/)
assert.match(actionablePlan, /查看计划/)
assert.match(actionablePlan, />执行)
const exitPlanRenderer = renderToStaticMarkup(
undefined}
/>
)
assert.match(exitPlanRenderer, /role="button"/)
assert.match(exitPlanRenderer, /Release plan/)
assert.match(exitPlanRenderer, /Ship safely/)
const fallbackRenderer = renderToStaticMarkup(
)
assert.match(fallbackRenderer, /unregistered_tool/)
assert.match(fallbackRenderer, /kept/)
const sharedToolHeader = renderToStaticMarkup(
undefined} />
)
assert.match(sharedToolHeader, /class="cr-tool-head cr-tool-head--collapsible cr-tool-head--expanded"/)
assert.match(sharedToolHeader, /cr-tool-head__status--loading/)
assert.match(sharedToolHeader, /aria-expanded="true"/)
console.log('Conversation specialized renderer SSR regression checks passed')