Skip to content

Commit 0cad49d

Browse files
committed
Improve unit tests
1 parent 6a46c1e commit 0cad49d

File tree

1 file changed

+250
-11
lines changed

1 file changed

+250
-11
lines changed

packages/angular-query-experimental/src/__tests__/providers.test.ts renamed to packages/angular-query-experimental/src/__tests__/with-devtools.test.ts

Lines changed: 250 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { TestBed } from '@angular/core/testing'
44
import {
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,225 @@ 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+
// Initially false, devtools should not be loaded
475+
expect(mockTanstackQueryDevtools).not.toHaveBeenCalled()
476+
expect(mockDevtoolsInstance.mount).not.toHaveBeenCalled()
477+
478+
// Toggle to true
479+
loadDevtools.set(true)
480+
TestBed.tick()
481+
await vi.dynamicImportSettled()
482+
483+
// Devtools should now be loaded and mounted
484+
expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1)
485+
expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(1)
486+
expect(mockDevtoolsInstance.unmount).not.toHaveBeenCalled()
487+
488+
// Toggle back to false
489+
loadDevtools.set(false)
490+
TestBed.tick()
491+
492+
// Should unmount
493+
expect(mockDevtoolsInstance.unmount).toHaveBeenCalledTimes(1)
494+
expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(1)
495+
496+
// Toggle back to true again
497+
loadDevtools.set(true)
498+
TestBed.tick()
499+
await vi.dynamicImportSettled()
500+
501+
// Should remount (mount called twice now)
502+
expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(2)
503+
expect(mockDevtoolsInstance.unmount).toHaveBeenCalledTimes(1)
504+
})
505+
506+
it('should handle rapid toggles correctly', async () => {
507+
const loadDevtools = signal(true)
508+
509+
TestBed.configureTestingModule({
510+
providers: [
511+
provideZonelessChangeDetection(),
512+
provideTanStackQuery(
513+
new QueryClient(),
514+
withDevtools(() => ({
515+
loadDevtools: loadDevtools(),
516+
})),
517+
),
518+
],
519+
})
520+
521+
TestBed.inject(ENVIRONMENT_INITIALIZER)
522+
await vi.advanceTimersByTimeAsync(0)
523+
TestBed.tick()
524+
await vi.dynamicImportSettled()
525+
526+
expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(1)
527+
528+
// Rapid toggles
529+
loadDevtools.set(false)
530+
TestBed.tick()
531+
loadDevtools.set(true)
532+
TestBed.tick()
533+
await vi.dynamicImportSettled()
534+
loadDevtools.set(false)
535+
TestBed.tick()
536+
loadDevtools.set(true)
537+
TestBed.tick()
538+
await vi.dynamicImportSettled()
539+
540+
// Should handle all toggles correctly
541+
expect(mockDevtoolsInstance.mount).toHaveBeenCalledTimes(3)
542+
expect(mockDevtoolsInstance.unmount).toHaveBeenCalledTimes(2)
543+
})
544+
545+
describe('deps parameter', () => {
546+
it('should inject dependencies and pass them to withDevtoolsFn in correct order', async () => {
547+
const mockService1 = { value: 'service1' }
548+
const mockService2 = { value: 'service2' }
549+
const mockService1Token = new InjectionToken('MockService1')
550+
const mockService2Token = new InjectionToken('MockService2')
551+
const withDevtoolsFn = vi.fn().mockReturnValue({ loadDevtools: true })
552+
553+
TestBed.configureTestingModule({
554+
providers: [
555+
provideZonelessChangeDetection(),
556+
{
557+
provide: mockService1Token,
558+
useValue: mockService1,
559+
},
560+
{
561+
provide: mockService2Token,
562+
useValue: mockService2,
563+
},
564+
provideTanStackQuery(
565+
new QueryClient(),
566+
withDevtools(withDevtoolsFn, {
567+
deps: [mockService1Token, mockService2Token],
568+
}),
569+
),
570+
],
571+
})
572+
573+
TestBed.inject(ENVIRONMENT_INITIALIZER)
574+
await vi.advanceTimersByTimeAsync(0)
575+
576+
expect(withDevtoolsFn).toHaveBeenCalledWith(mockService1, mockService2)
577+
})
578+
579+
it('should work with empty deps array', async () => {
580+
const withDevtoolsFn = vi.fn().mockReturnValue({ loadDevtools: true })
581+
582+
TestBed.configureTestingModule({
583+
providers: [
584+
provideZonelessChangeDetection(),
585+
provideTanStackQuery(
586+
new QueryClient(),
587+
withDevtools(withDevtoolsFn, {
588+
deps: [],
589+
}),
590+
),
591+
],
592+
})
593+
594+
TestBed.inject(ENVIRONMENT_INITIALIZER)
595+
await vi.advanceTimersByTimeAsync(0)
596+
597+
expect(withDevtoolsFn).toHaveBeenCalledWith()
598+
})
599+
600+
it('should reactively update when injected services change', async () => {
601+
class ReactiveService {
602+
enabled = signal(false)
603+
position = signal<DevtoolsPosition>('bottom')
604+
}
605+
606+
const withDevtoolsFn = (service: ReactiveService) => ({
607+
loadDevtools: service.enabled(),
608+
position: service.position(),
609+
})
610+
611+
TestBed.configureTestingModule({
612+
providers: [
613+
provideZonelessChangeDetection(),
614+
ReactiveService,
615+
provideTanStackQuery(
616+
new QueryClient(),
617+
withDevtools(withDevtoolsFn, {
618+
deps: [ReactiveService],
619+
}),
620+
),
621+
],
622+
})
623+
624+
TestBed.inject(ENVIRONMENT_INITIALIZER)
625+
await vi.advanceTimersByTimeAsync(0)
626+
627+
const service = TestBed.inject(ReactiveService)
628+
629+
expect(mockTanstackQueryDevtools).not.toHaveBeenCalled()
630+
631+
service.enabled.set(true)
632+
TestBed.tick()
633+
await vi.dynamicImportSettled()
634+
635+
expect(mockTanstackQueryDevtools).toHaveBeenCalledTimes(1)
636+
expect(mockTanstackQueryDevtools).toHaveBeenCalledWith(
637+
expect.objectContaining({
638+
position: 'bottom',
639+
}),
640+
)
641+
642+
service.position.set('top')
643+
TestBed.tick()
644+
645+
expect(mockDevtoolsInstance.setPosition).toHaveBeenCalledWith('top')
646+
})
647+
})
409648
})

0 commit comments

Comments
 (0)