@@ -4,6 +4,7 @@ import { TestBed } from '@angular/core/testing'
44import {
55 ENVIRONMENT_INITIALIZER ,
66 EnvironmentInjector ,
7+ InjectionToken ,
78 PLATFORM_ID ,
89 createEnvironmentInjector ,
910 isDevMode ,
@@ -53,55 +54,57 @@ describe('withDevtools feature', () => {
5354
5455 afterEach ( ( ) => {
5556 vi . restoreAllMocks ( )
57+ vi . useRealTimers ( )
58+ TestBed . resetTestingModule ( )
5659 } )
5760
5861 test . each ( [
5962 {
60- description : 'should load developer tools in development mode' ,
63+ description : 'should load devtools in development mode' ,
6164 isDevMode : true ,
6265 expectedCalled : true ,
6366 } ,
6467 {
65- description : 'should not load developer tools in production mode' ,
68+ description : 'should not load devtools in production mode' ,
6669 isDevMode : false ,
6770 expectedCalled : false ,
6871 } ,
6972 {
70- description : `should load developer tools in development mode when 'loadDevtools' is set to 'auto'` ,
73+ description : `should load devtools in development mode when 'loadDevtools' is set to 'auto'` ,
7174 isDevMode : true ,
7275 loadDevtools : 'auto' ,
7376 expectedCalled : true ,
7477 } ,
7578 {
76- description : `should not load developer tools in production mode when 'loadDevtools' is set to 'auto'` ,
79+ description : `should not load devtools in production mode when 'loadDevtools' is set to 'auto'` ,
7780 isDevMode : false ,
7881 loadDevtools : 'auto' ,
7982 expectedCalled : false ,
8083 } ,
8184 {
8285 description :
83- "should load developer tools in development mode when 'loadDevtools' is set to true" ,
86+ "should load devtools in development mode when 'loadDevtools' is set to true" ,
8487 isDevMode : true ,
8588 loadDevtools : true ,
8689 expectedCalled : true ,
8790 } ,
8891 {
8992 description :
90- "should load developer tools in production mode when 'loadDevtools' is set to true" ,
93+ "should load devtools in production mode when 'loadDevtools' is set to true" ,
9194 isDevMode : false ,
9295 loadDevtools : true ,
9396 expectedCalled : true ,
9497 } ,
9598 {
9699 description :
97- "should not load developer tools in development mode when 'loadDevtools' is set to false" ,
100+ "should not load devtools in development mode when 'loadDevtools' is set to false" ,
98101 isDevMode : true ,
99102 loadDevtools : false ,
100103 expectedCalled : false ,
101104 } ,
102105 {
103106 description :
104- "should not load developer tools in production mode when 'loadDevtools' is set to false" ,
107+ "should not load devtools in production mode when 'loadDevtools' is set to false" ,
105108 isDevMode : false ,
106109 loadDevtools : false ,
107110 expectedCalled : false ,
@@ -139,8 +142,10 @@ describe('withDevtools feature', () => {
139142
140143 if ( expectedCalled ) {
141144 expect ( mockTanstackQueryDevtools ) . toHaveBeenCalled ( )
145+ expect ( mockDevtoolsInstance . mount ) . toHaveBeenCalled ( )
142146 } else {
143147 expect ( mockTanstackQueryDevtools ) . not . toHaveBeenCalled ( )
148+ expect ( mockDevtoolsInstance . mount ) . not . toHaveBeenCalled ( )
144149 }
145150 } ,
146151 )
@@ -162,6 +167,7 @@ describe('withDevtools feature', () => {
162167 // Destroys injector
163168 TestBed . resetTestingModule ( )
164169 await vi . advanceTimersByTimeAsync ( 0 )
170+ await vi . dynamicImportSettled ( )
165171
166172 expect ( mockTanstackQueryDevtools ) . not . toHaveBeenCalled ( )
167173 } )
@@ -247,16 +253,21 @@ describe('withDevtools feature', () => {
247253
248254 expect ( mockDevtoolsInstance . setErrorTypes ) . toHaveBeenCalledTimes ( 0 )
249255
250- errorTypes . set ( [
256+ const newErrorTypes = [
251257 {
252258 name : '' ,
253259 initializer : ( ) => new Error ( ) ,
254260 } ,
255- ] )
261+ ]
262+
263+ errorTypes . set ( newErrorTypes )
256264
257265 TestBed . tick ( )
258266
259267 expect ( mockDevtoolsInstance . setErrorTypes ) . toHaveBeenCalledTimes ( 1 )
268+ expect ( mockDevtoolsInstance . setErrorTypes ) . toHaveBeenCalledWith (
269+ newErrorTypes ,
270+ )
260271 } )
261272
262273 it ( 'should update client' , async ( ) => {
@@ -282,11 +293,13 @@ describe('withDevtools feature', () => {
282293
283294 expect ( mockDevtoolsInstance . setClient ) . toHaveBeenCalledTimes ( 0 )
284295
285- client . set ( new QueryClient ( ) )
296+ const newClient = new QueryClient ( )
297+ client . set ( newClient )
286298
287299 TestBed . tick ( )
288300
289301 expect ( mockDevtoolsInstance . setClient ) . toHaveBeenCalledTimes ( 1 )
302+ expect ( mockDevtoolsInstance . setClient ) . toHaveBeenCalledWith ( newClient )
290303 } )
291304
292305 it ( 'should update position' , async ( ) => {
@@ -317,6 +330,7 @@ describe('withDevtools feature', () => {
317330 TestBed . tick ( )
318331
319332 expect ( mockDevtoolsInstance . setPosition ) . toHaveBeenCalledTimes ( 1 )
333+ expect ( mockDevtoolsInstance . setPosition ) . toHaveBeenCalledWith ( 'left' )
320334 } )
321335
322336 it ( 'should update button position' , async ( ) => {
@@ -347,6 +361,9 @@ describe('withDevtools feature', () => {
347361 TestBed . tick ( )
348362
349363 expect ( mockDevtoolsInstance . setButtonPosition ) . toHaveBeenCalledTimes ( 1 )
364+ expect ( mockDevtoolsInstance . setButtonPosition ) . toHaveBeenCalledWith (
365+ 'bottom-right' ,
366+ )
350367 } )
351368
352369 it ( 'should update initialIsOpen' , async ( ) => {
@@ -377,6 +394,7 @@ describe('withDevtools feature', () => {
377394 TestBed . tick ( )
378395
379396 expect ( mockDevtoolsInstance . setInitialIsOpen ) . toHaveBeenCalledTimes ( 1 )
397+ expect ( mockDevtoolsInstance . setInitialIsOpen ) . toHaveBeenCalledWith ( true )
380398 } )
381399
382400 it ( 'should destroy devtools' , async ( ) => {
@@ -406,4 +424,180 @@ describe('withDevtools feature', () => {
406424
407425 expect ( mockDevtoolsInstance . unmount ) . toHaveBeenCalledTimes ( 1 )
408426 } )
427+
428+ it ( 'should unmount devtools when injector is destroyed' , async ( ) => {
429+ TestBed . configureTestingModule ( {
430+ providers : [
431+ provideZonelessChangeDetection ( ) ,
432+ provideTanStackQuery (
433+ new QueryClient ( ) ,
434+ withDevtools ( ( ) => ( {
435+ loadDevtools : true ,
436+ } ) ) ,
437+ ) ,
438+ ] ,
439+ } )
440+
441+ TestBed . inject ( ENVIRONMENT_INITIALIZER )
442+ await vi . advanceTimersByTimeAsync ( 0 )
443+ TestBed . tick ( )
444+ await vi . dynamicImportSettled ( )
445+
446+ expect ( mockTanstackQueryDevtools ) . toHaveBeenCalled ( )
447+ expect ( mockDevtoolsInstance . mount ) . toHaveBeenCalledTimes ( 1 )
448+ expect ( mockDevtoolsInstance . unmount ) . toHaveBeenCalledTimes ( 0 )
449+
450+ // Destroy the injector
451+ TestBed . resetTestingModule ( )
452+
453+ expect ( mockDevtoolsInstance . unmount ) . toHaveBeenCalledTimes ( 1 )
454+ } )
455+
456+ it ( 'should remount devtools when toggled from false to true' , async ( ) => {
457+ const loadDevtools = signal ( false )
458+
459+ TestBed . configureTestingModule ( {
460+ providers : [
461+ provideZonelessChangeDetection ( ) ,
462+ provideTanStackQuery (
463+ new QueryClient ( ) ,
464+ withDevtools ( ( ) => ( {
465+ loadDevtools : loadDevtools ( ) ,
466+ } ) ) ,
467+ ) ,
468+ ] ,
469+ } )
470+
471+ TestBed . inject ( ENVIRONMENT_INITIALIZER )
472+ await vi . advanceTimersByTimeAsync ( 0 )
473+
474+ expect ( mockTanstackQueryDevtools ) . not . toHaveBeenCalled ( )
475+ expect ( mockDevtoolsInstance . mount ) . not . toHaveBeenCalled ( )
476+
477+ loadDevtools . set ( true )
478+ TestBed . tick ( )
479+ await vi . dynamicImportSettled ( )
480+
481+ expect ( mockTanstackQueryDevtools ) . toHaveBeenCalledTimes ( 1 )
482+ expect ( mockDevtoolsInstance . mount ) . toHaveBeenCalledTimes ( 1 )
483+ expect ( mockDevtoolsInstance . unmount ) . not . toHaveBeenCalled ( )
484+
485+ loadDevtools . set ( false )
486+ TestBed . tick ( )
487+
488+ expect ( mockDevtoolsInstance . unmount ) . toHaveBeenCalledTimes ( 1 )
489+ expect ( mockDevtoolsInstance . mount ) . toHaveBeenCalledTimes ( 1 )
490+
491+ loadDevtools . set ( true )
492+ TestBed . tick ( )
493+ await vi . dynamicImportSettled ( )
494+
495+ // Should remount (mount called twice now)
496+ expect ( mockDevtoolsInstance . mount ) . toHaveBeenCalledTimes ( 2 )
497+ expect ( mockDevtoolsInstance . unmount ) . toHaveBeenCalledTimes ( 1 )
498+ } )
499+
500+ describe ( 'deps parameter' , ( ) => {
501+ it ( 'should inject dependencies and pass them to withDevtoolsFn in correct order' , async ( ) => {
502+ const mockService1 = { value : 'service1' }
503+ const mockService2 = { value : 'service2' }
504+ const mockService1Token = new InjectionToken ( 'MockService1' )
505+ const mockService2Token = new InjectionToken ( 'MockService2' )
506+ const withDevtoolsFn = vi . fn ( ) . mockReturnValue ( { loadDevtools : true } )
507+
508+ TestBed . configureTestingModule ( {
509+ providers : [
510+ provideZonelessChangeDetection ( ) ,
511+ {
512+ provide : mockService1Token ,
513+ useValue : mockService1 ,
514+ } ,
515+ {
516+ provide : mockService2Token ,
517+ useValue : mockService2 ,
518+ } ,
519+ provideTanStackQuery (
520+ new QueryClient ( ) ,
521+ withDevtools ( withDevtoolsFn , {
522+ deps : [ mockService1Token , mockService2Token ] ,
523+ } ) ,
524+ ) ,
525+ ] ,
526+ } )
527+
528+ TestBed . inject ( ENVIRONMENT_INITIALIZER )
529+ await vi . advanceTimersByTimeAsync ( 0 )
530+
531+ expect ( withDevtoolsFn ) . toHaveBeenCalledWith ( mockService1 , mockService2 )
532+ } )
533+
534+ it ( 'should work with empty deps array' , async ( ) => {
535+ const withDevtoolsFn = vi . fn ( ) . mockReturnValue ( { loadDevtools : true } )
536+
537+ TestBed . configureTestingModule ( {
538+ providers : [
539+ provideZonelessChangeDetection ( ) ,
540+ provideTanStackQuery (
541+ new QueryClient ( ) ,
542+ withDevtools ( withDevtoolsFn , {
543+ deps : [ ] ,
544+ } ) ,
545+ ) ,
546+ ] ,
547+ } )
548+
549+ TestBed . inject ( ENVIRONMENT_INITIALIZER )
550+ await vi . advanceTimersByTimeAsync ( 0 )
551+
552+ expect ( withDevtoolsFn ) . toHaveBeenCalledWith ( )
553+ } )
554+
555+ it ( 'should reactively update when injected services change' , async ( ) => {
556+ class ReactiveService {
557+ enabled = signal ( false )
558+ position = signal < DevtoolsPosition > ( 'bottom' )
559+ }
560+
561+ const withDevtoolsFn = ( service : ReactiveService ) => ( {
562+ loadDevtools : service . enabled ( ) ,
563+ position : service . position ( ) ,
564+ } )
565+
566+ TestBed . configureTestingModule ( {
567+ providers : [
568+ provideZonelessChangeDetection ( ) ,
569+ ReactiveService ,
570+ provideTanStackQuery (
571+ new QueryClient ( ) ,
572+ withDevtools ( withDevtoolsFn , {
573+ deps : [ ReactiveService ] ,
574+ } ) ,
575+ ) ,
576+ ] ,
577+ } )
578+
579+ TestBed . inject ( ENVIRONMENT_INITIALIZER )
580+ await vi . advanceTimersByTimeAsync ( 0 )
581+
582+ const service = TestBed . inject ( ReactiveService )
583+
584+ expect ( mockTanstackQueryDevtools ) . not . toHaveBeenCalled ( )
585+
586+ service . enabled . set ( true )
587+ TestBed . tick ( )
588+ await vi . dynamicImportSettled ( )
589+
590+ expect ( mockTanstackQueryDevtools ) . toHaveBeenCalledTimes ( 1 )
591+ expect ( mockTanstackQueryDevtools ) . toHaveBeenCalledWith (
592+ expect . objectContaining ( {
593+ position : 'bottom' ,
594+ } ) ,
595+ )
596+
597+ service . position . set ( 'top' )
598+ TestBed . tick ( )
599+
600+ expect ( mockDevtoolsInstance . setPosition ) . toHaveBeenCalledWith ( 'top' )
601+ } )
602+ } )
409603} )
0 commit comments