/** * @vitest-environment jsdom */ import { afterEach, describe, expect, it } from 'vitest' /* eslint-disable antfu/no-import-node-modules-by-path */ import React, { act } from '../packages/markstream-react/node_modules/react' import { createRoot } from '../packages/markstream-react/node_modules/react-dom/client' import { NodeRenderer } from '../packages/markstream-react/src/components/NodeRenderer' import { removeCustomComponents, setCustomComponents } from '../packages/markstream-react/src/customComponents' const scopeId = 'react-thinking-streaming-fade' function ThinkingNode(props: any) { const { node, ctx, customId, isDark, typewriter } = props const inheritedTypewriter = typewriter ?? ctx?.typewriter ?? true return (
Thinking
) } async function flushReact() { await act(async () => { await Promise.resolve() await Promise.resolve() }) } afterEach(() => { removeCustomComponents(scopeId) document.body.innerHTML = '' ;(globalThis as any).IS_REACT_ACT_ENVIRONMENT = false }) describe('markstream-react custom thinking streaming fade', () => { it('preserves appended-text fade inside nested custom components that render a NodeRenderer', async () => { ;(globalThis as any).IS_REACT_ACT_ENVIRONMENT = true setCustomComponents(scopeId, { thinking: ThinkingNode as any }) const host = document.createElement('div') document.body.appendChild(host) const root = createRoot(host) const renderMarkdown = (content: string) => React.createElement(NodeRenderer as any, { content, customId: scopeId, customHtmlTags: ['thinking'], deferNodesUntilVisible: false, viewportPriority: false, }) await act(async () => { root.render(renderMarkdown('Hello')) }) await flushReact() await act(async () => { root.render(renderMarkdown('HelloWorld')) }) await flushReact() const thinkingShell = host.querySelector('.thinking-shell') const deltas = Array.from(host.querySelectorAll('.thinking-shell .text-node-stream-delta')) expect(thinkingShell).toBeTruthy() expect(deltas).toHaveLength(1) expect(deltas[0]?.textContent).toBe('World') expect(thinkingShell?.textContent).toContain('HelloWorld') await act(async () => { root.unmount() }) }) })