-
Notifications
You must be signed in to change notification settings - Fork 24.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"Navigation triggered outside Angular zone" warning in unit tests #25837
Comments
Relates to #24181 (#24185), caused by CC @JiaLiPassion, any suggestion on checking whether it's Angular zone? |
The same for us. But our tests watches |
@trotyl, yeah, several other issues have the same problems, in |
+1 |
1 similar comment
+1 |
I'd say you don't need to navigate in unit tests. |
For unit tests, yes. But the same framework can also be used for integration tests where you should be able to instantiate routing and do navigation. |
I am getting this in my actual code. Not just in the tests. |
Workaround:
|
In unit test:
|
You also need to wrap router.initialNavigation();
|
Workround proposed by @ItzhakBokris worked, but it must not be a permanent solution. Waiting to angular team!
|
I'm getting this warning not in a test, but in the actual application, when navigating from a component to another. I'm doing a sort of hack to be able to navigate using the router, from links present in a table that's generated with DataTables. Basically I'm temporarily adding a property to the |
…o testing with Router See also angular/angular#25837
@quirogamauricio It's the expected warning, when perform navigation outside Angular zone than no change detection will be triggered. You do can perform navigation from anywhere of the JavaScript engine, but just need to ensure it inside Angular zone. |
I guess It is because latest angular CLI creates routing in a separate module
so to run navigation with in Angular zone it is required to implement work around -
Alternatively if you define routing with in app module, it works fine.
|
Works perfectly for me @calebeaires thanks !! |
I also received the same warning by using ngrx/effects:
|
To avoid the callback hell in the @CharlyRipp suggestion you can use I used await fixture.ngZone.run(async () => {
await router.navigate(['/home']);
});
// Put your asserts here
expect(true).toBeTruthy(); |
I suggest as workaround to run // run navigate in ngZone
beforeEach(() => {
const originalNavigate = TestBed.get(Router).navigate;
spyOn(TestBed.get(Router), 'navigate').and.callFake((...options) => {
fixture.ngZone.run(() => {
originalNavigate.apply(TestBed.get(Router), options);
});
});
}); |
import { Location } from '@angular/common';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { Router, Routes } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
import { HeroesComponent } from './heroes/heroes.component';
import { MessagesComponent } from './messages/messages.component';
describe('AppComponent', () => {
const routes: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'heroes', component: HeroesComponent },
{ path: 'detail/:id', component: HeroDetailComponent }
];
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let compiled: HTMLElement;
let router: Router;
let location: Location;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent,
HeroesComponent,
HeroDetailComponent,
MessagesComponent,
DashboardComponent
],
imports: [FormsModule, RouterTestingModule.withRoutes(routes)]
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.debugElement.componentInstance;
compiled = fixture.debugElement.nativeElement;
router = TestBed.get(Router);
location = TestBed.get(Location);
fixture.detectChanges();
fixture.ngZone.run(() => {
router.initialNavigation();
});
});
}));
it('should create the component', () => {
expect(component).toBeTruthy();
});
it('should render title in a h1 tag', () => {
fixture.detectChanges();
expect(compiled.querySelector('h1').textContent).toContain(
'Tour of Heroes'
);
});
it('should get 4 RouterLinks', () => {
expect(router.config.length).toEqual(4);
});
it('should redirect to /dashboard when navigate to ""', async(() => {
fixture.ngZone.run(() => {
fixture.whenStable().then(() => {
router.navigate(['']).then(() => {
expect(location.path()).toEqual('/dashboard');
});
});
});
}));
it('should navigate to /heroes', async(() => {
fixture.ngZone.run(() => {
fixture.whenStable().then(() => {
router.navigate(['/heroes']).then(() => {
expect(location.path()).toEqual('/heroes');
});
});
});
}));
}); That's all , thank you! No errors, No warnings. very good! 😄 |
@anlexN This worked for me! Thanks!! |
If you need to run tests in IE11
However, we can install a polyfill for this this by running So here's the full solution to do this cross-browser: import 'proxy-polyfill/proxy.min.js';
declare const ProxyPolyfill: ProxyConstructor;
/**
* Wrapper of Angular router (only for testing purpose)
* Meant to run all router operations within Angular zone
* * Keep change detection enabled
* * Avoids flooded console with warnings
* https://github.com/angular/angular/issues/25837#issuecomment-445796236
*
* @see Router
*/
export function wrapRouterInNgZone(router: Router, ngZone: NgZone): Router {
return new ProxyPolyfill(router, {
get(target: Router, p: PropertyKey): unknown {
//@ts-ignore Element implicitly has an 'any' type because type 'Router' has no index signature.ts(7017)
const invokedProperty = target[p];
if (typeof invokedProperty !== 'function') {
return invokedProperty;
}
return (...args: Array<unknown>): unknown => {
return ngZone.run(() => invokedProperty.apply(target, args));
};
}
});
} Please note that we have to import from the minified version since they stupidly include some ES6 syntax in the un-minified version (which kinda defeats the purpose of the polyfill in the first place!) There's an open issue about it here |
'Possible issue: angular/angular#25837'
any luck with this bug/inconvenience being resolved? FWIW I'm using this helper as a workaround:
Disclaimer: new to TS and angular. Idea: a wrapper that runs |
WARN: 'Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?' This was being generated by the following components: - ClientRunsComponent - ServiceGroupsComponent - ReportingComponent - HttpClientAuthInterceptor The warning stems from this issue introduced by Angular 7: angular/angular#25837 The first two components are fixed by this commit, cutting the test "noise" in half. Unfortunately applying the same fix to ReportingComponent breaks several unit tests. And I have not yet found the place to hook into to fix HttpClientAuthInterceptor. Signed-off-by: michael sorens <msorens@chef.io>
@piotrl Thank you for your workaround code! Just one more piece would be useful in my environment. I have a few tests that use variations of this:
But with your
Any thoughts on how to rewrite the above expectation to pass? |
WARN: 'Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?' This was being generated by the following components: - ClientRunsComponent - ServiceGroupsComponent - ReportingComponent - HttpClientAuthInterceptor The warning stems from this issue introduced by Angular 7: angular/angular#25837 The first two components are fixed by this commit, cutting the test "noise" in half. Unfortunately applying the same fix to ReportingComponent breaks several unit tests. And I have not yet found the place to hook into to fix HttpClientAuthInterceptor. Signed-off-by: michael sorens <msorens@chef.io>
* Remove incompatible npm package Attempts to upgrade Angular reported that the "ngrx-tslint-oftype" package was not compatible. But this package was only needed for preparing a particular ngrx transition between versions, so its work is done and it can be removed. Signed-off-by: michael sorens <msorens@chef.io> * `ng update` generated changes Signed-off-by: michael sorens <msorens@chef.io> * Reverted typescript from 3.5.3 to 3.4.5 The update of @angular/core failed because it found 3.5.3 -- that the upgrade had installed itself. I edited the package.json from ^3.4.5 to ~3.4.5 to keep it to 3.4.x, then npm install, and it updated this package-lock.json. Signed-off-by: michael sorens <msorens@chef.io> * @ViewChild fixes These are auto-generated from: ng update @angular/core --from 7 --to 8 --migrate-only Signed-off-by: michael sorens <msorens@chef.io> * @angular/material fixes These are auto-generated from: ng update @angular/material --from 7 --to 8 --migrate-only Signed-off-by: michael sorens <msorens@chef.io> * Try to fix npm issue webpack/webpack#8656 (comment) Add acorn to package.json. Signed-off-by: michael sorens <msorens@chef.io> * Import fresh wallaby.js Commit 060eccd8d6e72997b769e7ddb8570d50e310d43b from https://github.com/wallabyjs/ngCliWebpackSample/o dated 2019-07-09 Signed-off-by: michael sorens <msorens@chef.io> * Re-apply Chef customization from old wallaby.js Signed-off-by: michael sorens <msorens@chef.io> * Import fresh wallaby.js (again) After I submitted an issue, they updated the config file for Angular 8. wallabyjs/public#2141 Signed-off-by: michael sorens <msorens@chef.io> * Import fresh wallaby.js (one more time) Wallaby team adjusted the config file again; this time it worked. wallabyjs/public#2141 Signed-off-by: michael sorens <msorens@chef.io> * Update angular-devkit deps Signed-off-by: Scott Christopherson <scott@chef.io> * Update router-store initialization Signed-off-by: Scott Christopherson <scott@chef.io> * Re-sync after rebase * Minor fix Signed-off-by: michael sorens <msorens@chef.io> * Use the updated action types in routerReducer ngrx/platform@466e2cd#diff-c0c42c418c07609d7feedc294175d164 * Configure route serializer via StoreRouterConnectingModule Old way still works but the new way is how it's currently documented now and it requires less imports. * Lint cleanup Teardown the kludgy lint command needed to filter out the deprecated deprecation (really!) of `select`. Also suppress one essentially invalid lint complaint. Signed-off-by: michael sorens <msorens@chef.io> * Fix compile error in e2e (protractor) tests Was getting this error: e2e/compliance-reporting.e2e-spec.ts(2,10): error TS2305: Module '"...e2e/helpers/accessibility_helpers"' has no exported member 'expectUrlToBeAccessible'. Not clear what the problem was but this change fixed it Signed-off-by: michael sorens <msorens@chef.io> * Upgrade lots of npm packages Ran `npm update` and got package updates shown. Also includes just one code change needed to get a successful build. All unit tests pass. + @angular/cdk@8.2.0 + @angular/cli@8.3.5 + @angular-devkit/core@8.3.5 + @angular-devkit/schematics@8.3.5 + @angular/forms@8.2.7 + @angular/material@8.2.0 + @angular/animations@8.2.7 + @types/faker@4.1.5 + @angular/platform-browser-dynamic@8.2.7 + @angular/language-service@8.2.7 + @angular/platform-browser@8.2.7 + @angular/router@8.2.7 + @angular/core@8.2.7 + @angular/compiler@8.2.7 + @types/jasminewd2@2.0.6 + ajv@6.10.2 + @types/lodash@4.14.138 + codelyzer@5.1.1 + axe-webdriverjs@2.3.0 + d3@5.12.0 + install@0.12.2 + @types/node@10.14.18 + core-js@2.6.9 + karma-coverage-istanbul-reporter@2.1.0 + karma-firefox-launcher@1.2.0 + karma-jasmine-html-reporter@1.4.2 + lodash@4.17.15 + rxjs@6.5.3 + moment@2.24.0 + @angular/common@8.2.7 + ngx-cookie@4.1.2 + karma@3.1.4 + @types/jasmine@2.8.16 + tslib@1.10.0 + sass-lint@1.13.1 + tslint@5.20.0 + rxjs-tslint@0.1.7 + sniffr@1.2.0 + tslint-defocus@2.0.6 + wallaby-webpack@3.9.15 + diff2html@2.11.3 + @angular-devkit/build-angular@0.801.3 + typescript@3.6.3 + @angular/compiler-cli@8.2.7 added 397 packages from 78 contributors, removed 283 packages, updated 242 packages, moved 24 packages and audited 18418 packages in 134.542s Signed-off-by: michael sorens <msorens@chef.io> * More npm package updates Signed-off-by: michael sorens <msorens@chef.io> * and still more package updates Signed-off-by: michael sorens <msorens@chef.io> * Tighten version lock to patch only @types/jasmine - generated error from `make unit`: Per https://stackoverflow.com/a/57592510 need to wait for a patch jasmine-core - just too new; came out yesterday! let's wait a bit on this one tyepscript: generated error from `make server` that it needed angular < 3.6 so locking it at 3.5 until a later angular release Signed-off-by: michael sorens <msorens@chef.io> * Fix build warning Warning message for the two SCSS files: "start value has mixed support, consider using flex-start instead" Signed-off-by: michael sorens <msorens@chef.io> * Add reference comment Signed-off-by: michael sorens <msorens@chef.io> * Suppress ngrx runtime checks warnings ``` WARN: '@ngrx/store: runtime checks are currently opt-in but will be the default in the next major version with the possibility to opt-out, see https://ngrx.io/guide/migration/v8 for more information.' ``` Signed-off-by: Scott Christopherson <scott@chef.io> * Suppress momentjs parse warning ``` WARN: 'Deprecation warning: value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info. ``` The test is purposefully testing an invalid string passed to `moment`. The warning is expected. Signed-off-by: Scott Christopherson <scott@chef.io> * Suppress unhandled router promise warning ``` ERROR: 'Unhandled Promise rejection:', 'Cannot match any routes. URL Segment: 'projects/uuid-1'', '; Zone:', 'ProxyZone', '; Task:', 'Promise.then', '; Value:', Error: Cannot match any routes. URL Segment: 'projects/uuid-1' Error: Cannot match any routes. URL Segment: 'projects/uuid-1' ``` Signed-off-by: Scott Christopherson <scott@chef.io> * Ensure ui-lib is installed w/ other dependencies Unit tests fail to run if ui-lib assets are not installed. ``` ERROR in ./src/styles.scss (./node_modules/@angular-devkit/build-angular/src/angular-cli-files/plugins/raw-css-loader.js!./node_modules/postcss-loader/src??embedded!./node_modules/sass-loader/lib/loader.js??ref--15-3!./src/styles.scss) Module build failed (from ./node_modules/postcss-loader/src/index.js): Error: Failed to find 'assets/chef-ui-library/chef/chef.css' in [ /go/src/github.com/chef/automate/components/automate-ui/src ] at resolveModule.catch.catch (/go/src/github.com/chef/automate/components/automate-ui/node_modules/postcss-import/lib/resolve-id.js:35:13) @ ./src/styles.scss 1:14-241 @ multi ./src/styles.scss ``` Signed-off-by: Scott Christopherson <scott@chef.io> * Reduce unit test noise WARN: 'Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?' This was being generated by the following components: - ClientRunsComponent - ServiceGroupsComponent - ReportingComponent - HttpClientAuthInterceptor The warning stems from this issue introduced by Angular 7: angular/angular#25837 The first two components are fixed by this commit, cutting the test "noise" in half. Unfortunately applying the same fix to ReportingComponent breaks several unit tests. And I have not yet found the place to hook into to fix HttpClientAuthInterceptor. Signed-off-by: michael sorens <msorens@chef.io> * One more pass of `npm update` Have to move fast to keep on top of these changes. This pass did these updates: $ npm update + @angular-devkit/core@8.3.6 + @angular/common@8.2.8 + @angular/cdk@8.2.1 + @angular/cli@8.3.6 + @angular-devkit/schematics@8.3.6 + @angular-devkit/build-angular@0.803.6 + @angular/compiler-cli@8.2.8 + @angular/language-service@8.2.8 + @angular/platform-browser@8.2.8 + @angular/core@8.2.8 + @angular/platform-server@8.2.8 + @angular/material@8.2.1 + jasmine-core@3.5.0 + @types/lodash@4.14.141 + @angular/forms@8.2.8 + @angular/platform-browser-dynamic@8.2.8 + @types/node@10.14.19 + @angular/router@8.2.8 + codelyzer@5.1.2 + @angular/compiler@8.2.8 + @angular/animations@8.2.8 Signed-off-by: michael sorens <msorens@chef.io> * Document package.json constraints Certain few packages are specifically not updated to their latest versions. As package.json cannot contain comments, I documented the reasons in the next best thing, the readme. Signed-off-by: michael sorens <msorens@chef.io> * Suppress ngZone warnings in reporting.component.spec ``` applyParamFilters() ✔ parses multiple filters ✔ parses single filters ✔ parse interval INFO: 'getEndDate calling router.navigate' INFO: 'getEndDate calling router.navigate' WARN: 'Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?' WARN: 'Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?' ✔ parse bad end date INFO: 'getDateInterval calling router.navigate' INFO: 'getDateInterval calling router.navigate' WARN: 'Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?' WARN: 'Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?' ✔ parse invaild interval 2 INFO: 'getDateInterval calling router.navigate' INFO: 'getDateInterval calling router.navigate' WARN: 'Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?' WARN: 'Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?' ✔ parse invaild interval 1 INFO: 'getDateInterval calling router.navigate' INFO: 'getDateInterval calling router.navigate' WARN: 'Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?' WARN: 'Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?' ✔ parse bad interval ``` The `getEndDate` and `getDateInterval` methods call `router.navigate` which seems unexpected for methods that are named for getting and returning a value. * Suppress ngZone warnings in service-groups.component.spec Signed-off-by: Scott Christopherson <scott@chef.io> * Suppress ngZone warnings in client-runs.component.spec Signed-off-by: Scott Christopherson <scott@chef.io> * Remove unused routing-helper Ended up not needing it after refactoring specs to not rely on calling through `router.navigate`. Signed-off-by: Scott Christopherson <scott@chef.io>
Any news on this one? |
I tried this workaround to avoid the warning: it('should navigate "" to "/app"', async() => {
const success = await fixture.ngZone.run(() => router.navigateByUrl(''));
expect(success).toBeTruthy();
expect(location.path()).toBe('/app');
}); |
I usually do this,
this ensures that navigation is performed inside ngZone. |
Do not warn that navigation was triggered outside Angular zone if the Router was created outside Angular zone in the first place. Closes angular#25837
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
I'm submitting a...
Current behavior
Using the last Angular
6.1.7
which introduced a warning if a navigation is triggered outside a zone (see 010e35d),a simple unit test calling
router.navigate
yields the warning (resulting in hundreds of warnings in the console).Expected behavior
The warning should not be emitted in unit tests.
It's currently possible to remove it by using
zone.run
or usingNoopNgZone
, but this is cumbersome. A way to disable it in unit tests would be great.Minimal reproduction of the problem with instructions
Build a minimal app with the CLI
Then replace the default unit test with:
Run
ng test
, and the following warning should appear:Environment
cc @trotyl
The text was updated successfully, but these errors were encountered: