Angular UI router and $stateChangeError - strange resolve loop - angularjs

The app I'm writing is using the resolve property in the main UI router state.
It tries to resolve to a list of things, using a factory that uses $http.
So I was trying to implement error handling, I changed my server to return a 404 status, and added thus lines:
$rootScope.$on('$stateChangeError', function(event) {
$state.go('404');
});
as Nate Abele explained here: Angular UI router handling 404s
Now the app do try to change the state to my 404 state, but a very strange loop occurred. The app keep trying to resolve the failed factory from the resolve property.
Haven't figured up why until now.
Any suggestions ? Thanks.

Related

Using protractor with ng-upgrade

I am working on migrating my AngularJS (1.6) app to Angular (4) and now have a hybrid application, bootstrapped with NgUpgrade.
However, this seems to have completely broken my Protractor tests.
Failed: Timed out waiting for asynchronous Angular tasks to finish after 11 seconds. This may be because the current page is not an Angular application. Please see the FAQ for more details: https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular
While waiting for element with locator - Locator: By(css selector, .toggle-summary-button)
Hybrid app changes
The application seems to run fine, and both AngularJS and Angular components are working as expected. The changes I made in the bootstrapping process are:
1 Removed ng-app from html tag:
<html lang="en" *ng-app="myapp">
2 Added an AppModules (#NgModule) etc.
3 Used NgUpgrade to bootstrap the app:
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { UpgradeModule } from '#angular/upgrade/static';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.body, ['myapp'], {strictDi: true});
});
Protractor tests
Based on the error above, the problem seems to be related to whatever Protractor does when it is waiting for Angular. I have a beforeEach block which loads the login page, fills in the details and logs in. Weirdly it is still opening the page and entering text into the username field, but then it fails to go any further.
I can't understand why this is any different and no amount of changing things around seems to help, so any guidance would be most welcome!
I have tried, with no success:
adding "rootElement: 'body'" to my protractor config file
adding "ng12Hybrid: true" to my protractor config file - I get a message saying that it should no longer be needed as it auto detects.
increasing the allScriptsTimeout setting from 11000 to 60000 and it still times out.
turning off the waitForAngularEnabled setting. This solves the problem with the login fields, but then none of my http mocks work and the tests fail.
What is funny is I asked the exact same question (+github) 15 months ago about angular 1 to angular 2:
Protractor + Hybrid Angular 1+2 Application = Fail
Without any solution I rolled back to angular 1. Today we decided to try again to move up from angular 1 to 4 like you, and landed on your question because we still have the exact same problem...
Well, not so funny actually... I can't understand why a so important feature is put apart like that. AngularJs was supposed to be actively maintained because of the breaking change to Angular 2+! It's a little disappointing (sorry for those expecting an real answer, I will post if updates)...
Edit: I went to React
I came up with a temporary hack to solve this issue by overriding the waitForAngular function with the below logic.
onPrepare: function() {
var script = "var callback = arguments[arguments.length - 1];" +
"angular.element(document.querySelector(\"body\")).injector()"+
".get(\"$browser\").notifyWhenNoOutstandingRequests(callback)");
browser.waitForAngular = function() {
return browser.executeAsyncScript(script)
};
}

AngularJs Ui-routing transition superseded

i find the solution AngularJS and UI-Router: 'Error: transition superseded' during angularjs unit tests but this not work for me.
AngularJs version v1.6.1
Ui-routing Version v0.3.2
I solved it.
In my project, root state is login state if login is successful then it goes to admin.dashboard state, where admin state was an abstract state.
I used$state.transitionTo method instead of $state.go when transitioning to the admin.dashboard state.
I've also added on app.config section.
$qProvider.errorOnUnhandledRejections(false);

Run Code when AngularJS has an Error

Question: How can you run code when Angular has an error like Uncaught Error: [$injector:moduler]
Story: Our team would like to be notified when a user has an error with our angular application. We already have a setup if an $http request has an error we have a $httpProvider.interceptors that catches the error and notifies us about the error and who had it, which works great. The problem is we don't have any way of being notified when an angular error happens.
What we have tried: I first thought Angular used console.error so I tried something like this.
console.errorBack = console.error;
console.error = function(){
//notify us about the error
console.errorBack.apply(null,Array.prototype.slice.call(arguments));
};
Which I found does not work as Angular does not use console.error for there error messaging system. So I looked at the source code for Angular but I could not find the code that controls the error system to append to it.

Why do Angular unit tests load $route?

After updating to Angular 1.5.3 (from 1.4.9) all my unit tests have started failing, where they worked before.
The error is as follows:
Error: [$injector:unpr] Unknown provider:
AuthenticationHttpInterceptorProvider
<- AuthenticationHttpInterceptor
<- $http
<- $templateRequest
<- $route
It is expected that the AuthenticationHttpInterceptorProvider is not known at this point, because it is part of a different module which is not unit tested here. If I provide a mock for this interceptor, I get the error that $httpBackend wasn't expecting a GET request for the defined default route.
My question is: Why does $route get loaded in the first place, and how can I prevent it? I'm not unit testing any routes and make no changes to $route after the .config stage in the app where routes are defined. I would expect to never receive any requests for the templateUrls of the views of routes.
I've not been able to find anything in the Angular Changelog that would make me expect a different behaviour with the newer version.
$route service is forced to be instantiated by ngRoute since 1.5.1:
Ensure $route will be instantiated in time to capture the initial
$locationChangeSuccess event. This is necessary in case ngView is
ncluded in an asynchronously loaded template.
This is the fix for the issue.
This means that ngRoute should be a dependency of app routing module, not other tested modules.

Wierd behaviour in testing angular-ui-router $urlRouterProvider

I am trying to test the default redirect for my angularjs application based on angular ui router, No matter what I did, the otherwise config was ignored, I tried to forcefully call the update method of urlRouter, To achieve this I injected $urlRouter in my test. voila original code started working.
https://gist.github.com/himangshuj/8142045
This is the gist of my change. Revision 4 is the thing that worked.
If you're using $urlRouterProvider without $stateProvider, you have to inject $urlRouter in order for it to be initialized and properly hook into $location..
answered on github, it seems this is expected behavior
https://github.com/angular-ui/ui-router/issues/718#issuecomment-31246720

Resources