@@ -55,32 +55,32 @@ import type { ExtensionContext } from 'vscode';
5555import type { GDBTargetDebugTracker } from '../../../../debug-session' ;
5656import { ComponentViewer } from '../../component-viewer-main' ;
5757
58+ // Local test mocks
59+
60+ type Session = {
61+ session : { id : string } ;
62+ getCbuildRun : ( ) => Promise < { getScvdFilePaths : ( ) => string [ ] } | undefined > ;
63+ refreshTimer : { onRefresh : ( cb : ( session : Session ) => void ) => void } ;
64+ } ;
65+
5866type TrackerCallbacks = {
5967 onWillStopSession : ( cb : ( session : Session ) => Promise < void > ) => { dispose : jest . Mock } ;
6068 onConnected : ( cb : ( session : Session ) => Promise < void > ) => { dispose : jest . Mock } ;
61- onDidChangeActiveStackItem : ( cb : ( item : StackItem ) => Promise < void > ) => { dispose : jest . Mock } ;
6269 onDidChangeActiveDebugSession : ( cb : ( session : Session | undefined ) => Promise < void > ) => { dispose : jest . Mock } ;
63- onStopped : ( cb : ( session : { session : Session } ) => Promise < void > ) => { dispose : jest . Mock } ;
70+ onStackTrace : ( cb : ( session : { session : Session } ) => Promise < void > ) => { dispose : jest . Mock } ;
71+ onWillStartSession : ( cb : ( session : Session ) => Promise < void > ) => { dispose : jest . Mock } ;
6472 callbacks : Partial < {
6573 willStop : ( session : Session ) => Promise < void > ;
6674 connected : ( session : Session ) => Promise < void > ;
67- stackItem : ( item : StackItem ) => Promise < void > ;
6875 activeSession : ( session : Session | undefined ) => Promise < void > ;
69- stopped : ( session : { session : Session } ) => Promise < void > ;
76+ stackTrace : ( session : { session : Session } ) => Promise < void > ;
77+ willStart : ( session : Session ) => Promise < void > ;
7078 } > ;
7179} ;
7280
73- type Session = {
74- session : { id : string } ;
75- getCbuildRun : ( ) => Promise < { getScvdFilePaths : ( ) => string [ ] } | undefined > ;
76- refreshTimer : { onRefresh : ( cb : ( session : Session ) => void ) => void } ;
77- } ;
78-
79- type StackItem = { item : { frameId ?: number } } ;
80-
8181type Context = { subscriptions : Array < { dispose : jest . Mock } > } ;
8282
83- describe ( 'ComponentViewerController ' , ( ) => {
83+ describe ( 'ComponentViewer ' , ( ) => {
8484 beforeEach ( ( ) => {
8585 jest . clearAllMocks ( ) ;
8686 } ) ;
@@ -99,16 +99,16 @@ describe('ComponentViewerController', () => {
9999 callbacks . connected = cb ;
100100 return { dispose : jest . fn ( ) } ;
101101 } ,
102- onDidChangeActiveStackItem : ( cb ) => {
103- callbacks . stackItem = cb ;
104- return { dispose : jest . fn ( ) } ;
105- } ,
106102 onDidChangeActiveDebugSession : ( cb ) => {
107103 callbacks . activeSession = cb ;
108104 return { dispose : jest . fn ( ) } ;
109105 } ,
110- onStopped : ( cb ) => {
111- callbacks . stopped = cb ;
106+ onStackTrace : ( cb ) => {
107+ callbacks . stackTrace = cb ;
108+ return { dispose : jest . fn ( ) } ;
109+ } ,
110+ onWillStartSession : ( cb ) => {
111+ callbacks . willStart = cb ;
112112 return { dispose : jest . fn ( ) } ;
113113 } ,
114114 } ;
@@ -127,7 +127,7 @@ describe('ComponentViewerController', () => {
127127 const tracker = makeTracker ( ) ;
128128 const controller = new ComponentViewer ( context as unknown as ExtensionContext ) ;
129129
130- await controller . activate ( tracker as unknown as GDBTargetDebugTracker ) ;
130+ controller . activate ( tracker as unknown as GDBTargetDebugTracker ) ;
131131
132132 expect ( registerTreeDataProvider ) . toHaveBeenCalledWith ( 'cmsis-debugger.componentViewer' , expect . any ( Object ) ) ;
133133 expect ( context . subscriptions . length ) . toBe ( 6 ) ;
@@ -147,6 +147,9 @@ describe('ComponentViewerController', () => {
147147 refreshTimer : { onRefresh : jest . fn ( ) } ,
148148 } ;
149149 await readScvdFiles ( tracker , sessionNoReader ) ;
150+
151+ const instances = ( controller as unknown as { _instances : unknown [ ] } ) . _instances ;
152+ expect ( instances ) . toEqual ( [ ] ) ;
150153 } ) ;
151154
152155 it ( 'skips reading when no scvd files are listed' , async ( ) => {
@@ -172,73 +175,63 @@ describe('ComponentViewerController', () => {
172175
173176 const instances = ( controller as unknown as { _instances : unknown [ ] } ) . _instances ;
174177 expect ( instances . length ) . toBe ( 2 ) ;
175- } ) ;
176-
177- it ( 'skips scvd instances when active session is missing' , async ( ) => {
178- const controller = new ComponentViewer ( makeContext ( ) as unknown as ExtensionContext ) ;
179- const tracker = makeTracker ( ) ;
180- const session = makeSession ( 's1' , [ 'a.scvd' ] ) ;
181-
182- const readScvdFiles = ( controller as unknown as { readScvdFiles : ( t : TrackerCallbacks , s ?: Session ) => Promise < void > } ) . readScvdFiles . bind ( controller ) ;
183- await readScvdFiles ( tracker , session ) ;
184-
185- const instances = ( controller as unknown as { _instances : unknown [ ] } ) . _instances ;
186- expect ( instances . length ) . toBe ( 0 ) ;
178+ expect ( instanceFactory ) . toHaveBeenCalledTimes ( 2 ) ;
187179 } ) ;
188180
189181 it ( 'handles tracker events and updates sessions' , async ( ) => {
190182 const context = makeContext ( ) ;
191183 const tracker = makeTracker ( ) ;
192184 const controller = new ComponentViewer ( context as unknown as ExtensionContext ) ;
193- await controller . activate ( tracker as unknown as GDBTargetDebugTracker ) ;
185+ controller . activate ( tracker as unknown as GDBTargetDebugTracker ) ;
186+
187+ const provider = ( controller as unknown as { _componentViewerTreeDataProvider ?: ReturnType < typeof treeProviderFactory > } ) . _componentViewerTreeDataProvider ;
194188
195189 const session = makeSession ( 's1' , [ 'a.scvd' ] ) ;
196190 const otherSession = makeSession ( 's2' , [ ] ) ;
197191
198- await tracker . callbacks . connected ?.( session ) ;
192+ await tracker . callbacks . willStart ?.( session ) ;
199193 await tracker . callbacks . connected ?.( session ) ;
200194
201195 const refreshCallback = ( session . refreshTimer . onRefresh as jest . Mock ) . mock . calls [ 0 ] ?. [ 0 ] ;
196+ expect ( refreshCallback ) . toBeDefined ( ) ;
202197 if ( refreshCallback ) {
203198 await refreshCallback ( session ) ;
204199 await refreshCallback ( otherSession ) ;
205200 }
206201
207202 await tracker . callbacks . connected ?.( otherSession ) ;
203+ expect ( provider ?. deleteModels ) . toHaveBeenCalled ( ) ;
204+
208205 await tracker . callbacks . activeSession ?.( session ) ;
209206 await tracker . callbacks . activeSession ?.( undefined ) ;
210207
211- await tracker . callbacks . stackItem ?.( { item : { frameId : 1 } } ) ;
212- await tracker . callbacks . stackItem ?.( { item : { } } ) ;
213-
214208 ( controller as unknown as { _activeSession ?: Session } ) . _activeSession = session ;
215- await tracker . callbacks . stopped ?.( { session } ) ;
216- await tracker . callbacks . stopped ?.( { session : otherSession } ) ;
209+ await tracker . callbacks . stackTrace ?.( { session } ) ;
210+ await tracker . callbacks . stackTrace ?.( { session : otherSession } ) ;
211+
217212 ( controller as unknown as { _activeSession ?: Session } ) . _activeSession = session ;
218213 await tracker . callbacks . willStop ?.( session ) ;
219214 ( controller as unknown as { _activeSession ?: Session } ) . _activeSession = otherSession ;
220215 await tracker . callbacks . willStop ?.( session ) ;
221216 } ) ;
222217
223- it ( 'updates instances and respects semaphore and empty states ' , async ( ) => {
218+ it ( 'updates instances when active session and instances are present ' , async ( ) => {
224219 const context = makeContext ( ) ;
225220 const controller = new ComponentViewer ( context as unknown as ExtensionContext ) ;
226221 const provider = treeProviderFactory ( ) ;
227222 ( controller as unknown as { _componentViewerTreeDataProvider ?: typeof provider } ) . _componentViewerTreeDataProvider = provider ;
228223
229224 const updateInstances = ( controller as unknown as { updateInstances : ( ) => Promise < void > } ) . updateInstances . bind ( controller ) ;
230225
231- ( controller as unknown as { _updateSemaphoreFlag : boolean } ) . _updateSemaphoreFlag = true ;
232- await updateInstances ( ) ;
233-
234- ( controller as unknown as { _updateSemaphoreFlag : boolean } ) . _updateSemaphoreFlag = false ;
235226 ( controller as unknown as { _activeSession ?: Session | undefined } ) . _activeSession = undefined ;
236227 await updateInstances ( ) ;
237- expect ( provider . deleteModels ) . toHaveBeenCalled ( ) ;
228+ expect ( provider . deleteModels ) . toHaveBeenCalledTimes ( 1 ) ;
229+ provider . deleteModels . mockClear ( ) ;
238230
239231 ( controller as unknown as { _activeSession ?: Session | undefined } ) . _activeSession = makeSession ( 's1' ) ;
240232 ( controller as unknown as { _instances : unknown [ ] } ) . _instances = [ ] ;
241233 await updateInstances ( ) ;
234+ expect ( provider . deleteModels ) . not . toHaveBeenCalled ( ) ;
242235
243236 const instanceA = instanceFactory ( ) ;
244237 const instanceB = instanceFactory ( ) ;
@@ -247,5 +240,7 @@ describe('ComponentViewerController', () => {
247240 expect ( provider . resetModelCache ) . toHaveBeenCalled ( ) ;
248241 expect ( provider . addGuiOut ) . toHaveBeenCalledTimes ( 2 ) ;
249242 expect ( provider . showModelData ) . toHaveBeenCalled ( ) ;
243+ expect ( instanceA . update ) . toHaveBeenCalled ( ) ;
244+ expect ( instanceB . update ) . toHaveBeenCalled ( ) ;
250245 } ) ;
251246} ) ;
0 commit comments