diff --git a/packages/devtools/src/__tests__/router-features.test.ts b/packages/devtools/src/__tests__/router-features.test.ts index f2dbcb3a..e99fd02b 100644 --- a/packages/devtools/src/__tests__/router-features.test.ts +++ b/packages/devtools/src/__tests__/router-features.test.ts @@ -15,7 +15,7 @@ import { type Routes, } from '@angular/router'; import { RouterTestingHarness } from '@angular/router/testing'; -import { afterEach, beforeEach, describe, expect, it } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { watchRouter, type NavigationRecord } from '../router.ts'; import { ConfigTracker, activeIds, walkConfig } from '../router-config.ts'; import { outletsOf } from '../router-links.ts'; @@ -286,6 +286,29 @@ describe('router features on a real Router', () => { }, ); + it.skipIf(!angularAtLeast('20.2.0'))( + 'reports the skip when probing the URL the router is already on', + async () => { + await router.navigateByUrl('/users/8'); + vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout'] }); + try { + const pending = runAction( + router as never, + navigations, + { action: 'probe', url: '/users/8' }, + () => {}, + ); + await vi.advanceTimersByTimeAsync(10_000); + const result = (await pending) as Record; + expect(result['error']).toBeUndefined(); + expect(result).toMatchObject({ matched: false, reason: expect.stringMatching(/ignored/) }); + expect(router.url).toBe('/users/8'); + } finally { + vi.useRealTimers(); + } + }, + ); + it.skipIf(!angularAtLeast('20.2.0'))('aborts the navigation in flight', async () => { const pending = router.navigateByUrl('/slow'); await new Promise((resolve) => setTimeout(resolve, 5)); diff --git a/packages/devtools/src/router-actions.ts b/packages/devtools/src/router-actions.ts index 3021247c..475f7457 100644 --- a/packages/devtools/src/router-actions.ts +++ b/packages/devtools/src/router-actions.ts @@ -732,19 +732,21 @@ function probe(router: AnyRecord, navigations: NavigationRecord[], url: string): ); } }); - setCaller('probe from DevTools', true); - const promise = read( - () => router['navigateByUrl'](url, { skipLocationChange: true }) as Promise, - null, - ); - targetId = navigationIdOf(router); - promise?.catch?.(() => {}); timer = setTimeout(() => { subscription.unsubscribe(); abortCurrent(); markProbe(targetId); resolve({ error: 'The probe did not finish within 10s.' }); }, WAIT_MS); + // Set before navigating: a skipped navigation (same URL) emits its event synchronously. + const current = navigationIdOf(router); + targetId = current < 0 ? current : current + 1; + setCaller('probe from DevTools', true); + const promise = read( + () => router['navigateByUrl'](url, { skipLocationChange: true }) as Promise, + null, + ); + promise?.catch?.(() => {}); }); }