// @vitest-environment jsdom // Branch tails the acceptance specs do not reach: the node-half apply // without a settings service and AssistantMarkdown reasoning/unknown block arms. import { afterEach, describe, expect, it } from 'vitest' import { Context } from '@deepseek-ai/cordis' import { cleanup, render } from '@testing-library/react' import { makeTranslate } from '@deepseek-ai/dsh-client-test-runtime' import { zh as commonZh } from '@deepseek-ai/dsh-client-locale/src/locales/zh.ts' import { apply as nodeApply } from '../src/index.ts' import { AssistantMarkdown, type AssistantMarkdownProps } from '../src/client/chat/AssistantMarkdown.tsx' import { zh } from '../src/client/locales.ts' // Mirrors the real lookup chain (conversation namespace, then common). const t: AssistantMarkdownProps['t'] = makeTranslate(zh, commonZh) afterEach(cleanup) describe('tails', () => { it('node-half apply tolerates a Host without settings', () => { expect(() => { nodeApply(new Context()) }).not.toThrow() }) it('AssistantMarkdown renders reasoning as a Think row and unknown blocks as JSON fallback', () => { const view = render( , ) expect(view.getByText('Think')).toBeTruthy() expect(view.getByText('thinking hard')).toBeTruthy() expect(view.getByText(/未知内容块/)).toBeTruthy() const stopped = render( , ) expect(stopped.getByText('已停止')).toBeTruthy() }) it('AssistantMarkdown skips the root shell when only tool-call heads remain', () => { // Tool heads are drawn by ChatView's tool groups; an empty root between // groups is layout noise (no text, no pulse, no interrupted marker). const empty = render( , ) expect(empty.container.firstChild).toBeNull() const blank = render() expect(blank.container.firstChild).toBeNull() }) })