import type { StreamdownProps } from 'streamdown' import type { SimplePluginInfo } from '../streamdown-wrapper' import { render, screen } from '@testing-library/react' import { Markdown } from '../index' const { mockReactMarkdownWrapper } = vi.hoisted(() => ({ mockReactMarkdownWrapper: vi.fn(), })) vi.mock('@/next/dynamic', () => ({ default: () => { const MockStreamdownWrapper = (props: { latexContent: string }) => { mockReactMarkdownWrapper(props) return
{props.latexContent}
} MockStreamdownWrapper.displayName = 'MockStreamdownWrapper' return MockStreamdownWrapper }, })) type CapturedProps = { latexContent: string pluginInfo?: SimplePluginInfo customComponents?: StreamdownProps['components'] customDisallowedElements?: string[] rehypePlugins?: StreamdownProps['rehypePlugins'] isAnimating?: StreamdownProps['isAnimating'] mode?: StreamdownProps['mode'] } const getLastWrapperProps = (): CapturedProps => { const calls = mockReactMarkdownWrapper.mock.calls const lastCall = calls[calls.length - 1] return lastCall![0] as CapturedProps } describe('Markdown', () => { beforeEach(() => { vi.clearAllMocks() }) it('should render wrapper content', () => { render() expect(screen.getByTestId('react-markdown-wrapper'))!.toHaveTextContent('Hello World') }) it('should preprocess think tags', () => { render() const props = getLastWrapperProps() expect(props.latexContent).toContain('
') expect(props.latexContent).toContain('Thought') expect(props.latexContent).toContain('[ENDTHINKFLAG]
') }) it('should preprocess latex block notation', () => { render() const props = getLastWrapperProps() expect(props.latexContent).toContain('$$x^2 + y^2 = z^2$$') }) it('should preprocess latex parentheses notation', () => { render() const props = getLastWrapperProps() expect(props.latexContent).toContain('$$a + b$$') }) it('should preserve latex inside code blocks', () => { render() const props = getLastWrapperProps() expect(props.latexContent).toContain('$E = mc^2$') }) it('should pass pluginInfo through', () => { const pluginInfo = { pluginUniqueIdentifier: 'plugin-unique', pluginId: 'plugin-id', } render() const props = getLastWrapperProps() expect(props.pluginInfo).toEqual(pluginInfo) }) it('should pass default empty customComponents when omitted', () => { render() const props = getLastWrapperProps() expect(props.customComponents).toEqual({}) }) it('should pass customComponents through', () => { const customComponents = { h1: ({ children }: { children?: React.ReactNode }) =>

{children}

, } render() const props = getLastWrapperProps() expect(props.customComponents).toBe(customComponents) }) it('should pass customDisallowedElements through', () => { const customDisallowedElements = ['strong', 'em'] render() const props = getLastWrapperProps() expect(props.customDisallowedElements).toBe(customDisallowedElements) }) it('should pass rehypePlugins through', () => { const plugin = () => (tree: unknown) => tree const rehypePlugins = [plugin] render() const props = getLastWrapperProps() expect(props.rehypePlugins).toBe(rehypePlugins) }) it('should pass isAnimating through', () => { render() const props = getLastWrapperProps() expect(props.isAnimating).toBe(true) }) it('should pass mode through', () => { render() const props = getLastWrapperProps() expect(props.mode).toBe('streaming') }) })