@@ -6,7 +6,6 @@ import { describe, expect, it, vi } from "vite-plus/test";
66
77import { getSyntaxHighlighterPromise } from "../lib/syntaxHighlighting" ;
88import * as mermaidRendering from "../lib/mermaidRendering" ;
9- import { MarkdownDiffBlock } from "./MarkdownDiffBlock" ;
109import { MarkdownMermaidBlock } from "./MarkdownMermaidBlock" ;
1110import { GitHubIcon } from "./Icons" ;
1211import { Button } from "./ui/button" ;
@@ -75,91 +74,52 @@ function codeButton(renderer: ReactTestRenderer, label: string) {
7574 return button . props as ComponentProps < typeof Button > ;
7675}
7776
78- describe ( "ChatMarkdown code previews" , ( ) => {
79- it . each ( [ "diff" , "PATCH" ] ) (
80- "switches %s snippets between preview and source without changing copied code" ,
81- async ( language ) => {
82- const source = " unchanged\n-old\n+new\n" ;
83- const writeText = vi . fn ( async ( _text : string ) => { } ) ;
84- vi . stubGlobal ( "navigator" , { clipboard : { writeText } } ) ;
85- vi . stubGlobal ( "IS_REACT_ACT_ENVIRONMENT" , true ) ;
86- let renderer : ReactTestRenderer | undefined ;
87- try {
88- await act ( async ( ) => {
89- renderer = create (
90- < ChatMarkdown
91- cwd = "/tmp/project"
92- text = { `\`\`\`${ language } \n${ source } \`\`\`` }
93- parseRawHtml = { false }
94- /> ,
95- ) ;
96- } ) ;
97- const preview = renderer ! . root . findByType ( MarkdownDiffBlock ) ;
98- expect (
99- preview
100- . findAllByType ( "span" )
101- . flatMap ( ( line ) => line . children )
102- . join ( "" ) ,
103- ) . toBe ( source ) ;
104- const showSource = codeButton ( renderer ! , "Show source" ) ;
105- await act ( async ( ) => {
106- showSource . onClick ?.( { } as Parameters < NonNullable < typeof showSource . onClick > > [ 0 ] ) ;
107- } ) ;
108- expect ( renderer ! . root . findAllByType ( MarkdownDiffBlock ) ) . toHaveLength ( 0 ) ;
109- const copy = codeButton ( renderer ! , "Copy code" ) ;
110- await act ( async ( ) => {
111- copy . onClick ?.( { } as Parameters < NonNullable < typeof copy . onClick > > [ 0 ] ) ;
112- } ) ;
113- expect ( writeText ) . toHaveBeenCalledWith ( source ) ;
114- const showPreview = codeButton ( renderer ! , "Show preview" ) ;
115- await act ( async ( ) => {
116- showPreview . onClick ?.( { } as Parameters < NonNullable < typeof showPreview . onClick > > [ 0 ] ) ;
117- } ) ;
118- expect (
119- renderer ! . root
120- . findByType ( MarkdownDiffBlock )
121- . findAllByType ( "span" )
122- . flatMap ( ( line ) => line . children )
123- . join ( "" ) ,
124- ) . toBe ( source ) ;
125- } finally {
126- await act ( async ( ) => renderer ?. unmount ( ) ) ;
127- vi . unstubAllGlobals ( ) ;
128- vi . restoreAllMocks ( ) ;
129- }
130- } ,
131- ) ;
132-
77+ describe ( "ChatMarkdown Mermaid previews" , ( ) => {
13378 it ( "renders Mermaid only after streaming ends and lets the user return to its source" , async ( ) => {
13479 vi . stubGlobal ( "IS_REACT_ACT_ENVIRONMENT" , true ) ;
80+ const writeText = vi . fn ( async ( _text : string ) => { } ) ;
81+ vi . stubGlobal ( "navigator" , { clipboard : { writeText } } ) ;
13582 const renderDiagram = vi
13683 . spyOn ( mermaidRendering , "renderMermaidDiagram" )
13784 . mockResolvedValue ( "<svg><text>Draft</text></svg>" ) ;
13885 const text = "```mermaid\nflowchart LR\nDraft-->Review\n```" ;
13986 let renderer : ReactTestRenderer | undefined ;
14087 try {
14188 await act ( async ( ) => {
142- renderer = create ( < ChatMarkdown cwd = "/tmp/project" text = { text } isStreaming /> , {
143- createNodeMock : ( element ) =>
144- element . type === "div" &&
145- ( element . props as ComponentProps < "div" > ) . className === "chat-markdown-mermaid"
146- ? { }
147- : null ,
148- } ) ;
89+ renderer = create (
90+ < ChatMarkdown cwd = "/tmp/project" text = { text } isStreaming parseRawHtml = { false } /> ,
91+ {
92+ createNodeMock : ( element ) =>
93+ element . type === "div" &&
94+ ( element . props as ComponentProps < "div" > ) . className === "chat-markdown-mermaid"
95+ ? { }
96+ : null ,
97+ } ,
98+ ) ;
14999 } ) ;
150100 expect ( renderDiagram ) . not . toHaveBeenCalled ( ) ;
151101 expect ( renderer ! . root . findAllByType ( MarkdownMermaidBlock ) ) . toHaveLength ( 0 ) ;
152102 await act ( async ( ) => {
153- renderer ! . update ( < ChatMarkdown cwd = "/tmp/project" text = { text } /> ) ;
103+ renderer ! . update ( < ChatMarkdown cwd = "/tmp/project" text = { text } parseRawHtml = { false } /> ) ;
154104 } ) ;
155105 expect (
156106 renderer ! . root . findByProps ( { role : "img" } ) . props . dangerouslySetInnerHTML . __html ,
157107 ) . toContain ( "Draft" ) ;
108+ const copyPreview = codeButton ( renderer ! , "Copy code" ) ;
109+ await act ( async ( ) => {
110+ copyPreview . onClick ?.( { } as Parameters < NonNullable < typeof copyPreview . onClick > > [ 0 ] ) ;
111+ } ) ;
112+ expect ( writeText ) . toHaveBeenLastCalledWith ( "flowchart LR\nDraft-->Review\n" ) ;
158113 const showSource = codeButton ( renderer ! , "Show source" ) ;
159114 await act ( async ( ) => {
160115 showSource . onClick ?.( { } as Parameters < NonNullable < typeof showSource . onClick > > [ 0 ] ) ;
161116 } ) ;
162117 expect ( renderer ! . root . findAllByProps ( { role : "img" } ) ) . toHaveLength ( 0 ) ;
118+ const copySource = codeButton ( renderer ! , "Copied" ) ;
119+ await act ( async ( ) => {
120+ copySource . onClick ?.( { } as Parameters < NonNullable < typeof copySource . onClick > > [ 0 ] ) ;
121+ } ) ;
122+ expect ( writeText ) . toHaveBeenLastCalledWith ( "flowchart LR\nDraft-->Review\n" ) ;
163123 const showPreview = codeButton ( renderer ! , "Show preview" ) ;
164124 await act ( async ( ) => {
165125 showPreview . onClick ?.( { } as Parameters < NonNullable < typeof showPreview . onClick > > [ 0 ] ) ;
0 commit comments