diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 1e1ab59c..b3eb60ef 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -27,7 +27,9 @@ import { HelpInitializationService } from '@blackbaud/skyux-lib-help'; import { BBOmnibar, + BBOmnibarConfig, BBOmnibarLegacy, + BBOmnibarNavigationItem, BBOmnibarSearchArgs } from '@blackbaud/auth-client'; @@ -290,6 +292,57 @@ describe('AppComponent', () => { }) ); + it( + 'should run omnibar navigation within the Angular zone', + async(() => { + skyAppConfig.skyux.host.url = 'base.com/'; + skyAppConfig.runtime.app.base = 'custom-base/'; + + let beforeNavCallback: (item: BBOmnibarNavigationItem) => boolean | void; + + spyOn(BBOmnibar, 'load').and.callFake((config: BBOmnibarConfig) => { + beforeNavCallback = config.nav.beforeNavCallback; + }); + + skyAppConfig.skyux.omnibar = { + experimental: true + }; + + setup(skyAppConfig).then(() => { + const zone = fixture.debugElement.injector.get(NgZone); + const router = fixture.debugElement.injector.get(Router); + + const navigateByUrlSpy = spyOn(router, 'navigateByUrl'); + + let zoneRunCallback: Function; + + const runSpy = spyOn(zone, 'run').and.callFake( + (cb: Function) => { + if (cb && cb.toString().indexOf('navigateByUrl') >= 0) { + zoneRunCallback = cb; + } else { + cb(); + } + } + ); + + fixture.detectChanges(); + + beforeNavCallback({ + title: '', + url: 'base.com/custom-base/new-place' + }); + + expect(runSpy).toHaveBeenCalled(); + expect(navigateByUrlSpy).not.toHaveBeenCalled(); + + zoneRunCallback(); + + expect(navigateByUrlSpy).toHaveBeenCalled(); + }); + }) + ); + it('should set the onSearch property if a search provider is provided', async(() => { let spyOmnibar = spyOn(BBOmnibar, 'load'); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 39b3509b..f0044a9c 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -160,7 +160,13 @@ export class AppComponent implements OnInit { if (url.indexOf(baseUrl) === 0) { const routePath = item.url.substring(baseUrl.length, url.length); - this.router.navigateByUrl(routePath); + + // Since the omnibar is loaded outside Angular, navigating needs to be explicitly + // run inside the Angular zone in order for navigation to work properly. + this.zone.run(() => { + this.router.navigateByUrl(routePath); + }); + return false; }