1+ import { render , screen , act } from '@testing-library/react'
2+ import userEvent from '@testing-library/user-event'
3+ import { ExtensionStateContextType } from '../../../context/ExtensionStateContext'
4+ import ChatView from '../ChatView'
5+ import { vscode } from '../../../utils/vscode'
6+ import * as ExtensionStateContext from '../../../context/ExtensionStateContext'
7+
8+ // Mock vscode
9+ jest . mock ( '../../../utils/vscode' , ( ) => ( {
10+ vscode : {
11+ postMessage : jest . fn ( )
12+ }
13+ } ) )
14+
15+ // Mock all components that use problematic dependencies
16+ jest . mock ( '../../common/CodeBlock' , ( ) => ( {
17+ __esModule : true ,
18+ default : ( ) => < div data-testid = "mock-code-block" />
19+ } ) )
20+
21+ jest . mock ( '../../common/MarkdownBlock' , ( ) => ( {
22+ __esModule : true ,
23+ default : ( ) => < div data-testid = "mock-markdown-block" />
24+ } ) )
25+
26+ jest . mock ( '../BrowserSessionRow' , ( ) => ( {
27+ __esModule : true ,
28+ default : ( ) => < div data-testid = "mock-browser-session-row" />
29+ } ) )
30+
31+ // Update ChatRow mock to capture props
32+ let chatRowProps = null
33+ jest . mock ( '../ChatRow' , ( ) => ( {
34+ __esModule : true ,
35+ default : ( props : any ) => {
36+ chatRowProps = props
37+ return < div data-testid = "mock-chat-row" />
38+ }
39+ } ) )
40+
41+
42+ // Mock Virtuoso component
43+ jest . mock ( 'react-virtuoso' , ( ) => ( {
44+ Virtuoso : ( { children } : any ) => (
45+ < div data-testid = "mock-virtuoso" > { children } </ div >
46+ )
47+ } ) )
48+
49+ // Mock VS Code components
50+ jest . mock ( '@vscode/webview-ui-toolkit/react' , ( ) => ( {
51+ VSCodeButton : ( { children, onClick } : any ) => (
52+ < button onClick = { onClick } > { children } </ button >
53+ ) ,
54+ VSCodeProgressRing : ( ) => < div data-testid = "progress-ring" />
55+ } ) )
56+
57+ describe ( 'ChatView' , ( ) => {
58+ const mockShowHistoryView = jest . fn ( )
59+ const mockHideAnnouncement = jest . fn ( )
60+
61+ let mockState : ExtensionStateContextType
62+
63+ beforeEach ( ( ) => {
64+ jest . clearAllMocks ( )
65+
66+ mockState = {
67+ clineMessages : [ ] ,
68+ apiConfiguration : {
69+ apiProvider : 'anthropic' ,
70+ apiModelId : 'claude-3-sonnet'
71+ } ,
72+ version : '1.0.0' ,
73+ customInstructions : '' ,
74+ alwaysAllowReadOnly : true ,
75+ alwaysAllowWrite : true ,
76+ alwaysAllowExecute : true ,
77+ openRouterModels : { } ,
78+ didHydrateState : true ,
79+ showWelcome : false ,
80+ theme : 'dark' ,
81+ filePaths : [ ] ,
82+ taskHistory : [ ] ,
83+ shouldShowAnnouncement : false ,
84+ uriScheme : 'vscode' ,
85+
86+ setAlwaysAllowReadOnly : jest . fn ( ) ,
87+ setAlwaysAllowWrite : jest . fn ( ) ,
88+ setCustomInstructions : jest . fn ( ) ,
89+ setAlwaysAllowExecute : jest . fn ( ) ,
90+ setApiConfiguration : jest . fn ( ) ,
91+ setShowAnnouncement : jest . fn ( )
92+ }
93+
94+ // Mock the useExtensionState hook
95+ jest . spyOn ( ExtensionStateContext , 'useExtensionState' ) . mockReturnValue ( mockState )
96+ } )
97+
98+ const renderChatView = ( ) => {
99+ return render (
100+ < ChatView
101+ isHidden = { false }
102+ showAnnouncement = { false }
103+ hideAnnouncement = { mockHideAnnouncement }
104+ showHistoryView = { mockShowHistoryView }
105+ />
106+ )
107+ }
108+
109+ describe ( 'Streaming State' , ( ) => {
110+ it ( 'should show cancel button while streaming' , ( ) => {
111+ mockState . clineMessages = [
112+ {
113+ type : 'say' ,
114+ partial : true ,
115+ ts : Date . now ( ) ,
116+ }
117+ ]
118+ renderChatView ( )
119+
120+ const buttons = screen . queryAllByRole ( 'button' )
121+ expect ( buttons . length ) . toBeGreaterThan ( 0 )
122+ } )
123+
124+ it ( 'should show terminate button when task is paused' , ( ) => {
125+ mockState . clineMessages = [
126+ {
127+ type : 'ask' ,
128+ ask : 'resume_task' ,
129+ ts : Date . now ( ) ,
130+ }
131+ ]
132+ renderChatView ( )
133+
134+ const buttons = screen . queryAllByRole ( 'button' )
135+ expect ( buttons . length ) . toBeGreaterThan ( 0 )
136+ } )
137+
138+ it ( 'should show retry button when API error occurs' , ( ) => {
139+ mockState . clineMessages = [
140+ {
141+ type : 'say' ,
142+ say : 'error' ,
143+ ts : Date . now ( ) ,
144+ }
145+ ]
146+ renderChatView ( )
147+
148+ const buttons = screen . queryAllByRole ( 'button' )
149+ expect ( buttons . length ) . toBeGreaterThan ( 0 )
150+ } )
151+ } )
152+ } )
0 commit comments