Why do Angular unit tests load $route? - angularjs

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.

Related

Error while loading controllers - migrating AngularJS1 to Angular6

I'm trying to do upgrade components written in AngularJS1 to Angular6. I'm taking the approach of having the wrappers for all the existing AngularJS1 component by extending "UpgradeComponent" placed under the folder "directive-wrappers" in my example. When I try to add some controllers which doesn't have any directives, I get the error message
Error: [$injector:unpr] Unknown provider: testDirective2DirectiveProvider <- testDirective2Directive
https://errors.angularjs.org/1.7.8/$injector/unpr?p0=testDirective2DirectiveProvider%20%3C-%20testDirective2Directive
at eval (angular.js:138)
at eval (angular.js:4924)
at Object.getService [as get] (angular.js:5084)
at eval (angular.js:4929)
at Object.getService [as get] (angular.js:5084)
at Function.UpgradeHelper.getDirective (upgrade_helper.ts:56)
at new UpgradeHelper (upgrade_helper.ts:52)
at TestDirective2Wrapper.UpgradeComponent (upgrade_component.ts:106)
at new TestDirective2Wrapper (TestDirective2Wrapper.ts:27)
at createClass (provider.ts:265) "<app-root _nghost-c69="">"
I tried adding studentController and homePageController, but not able to load it. Any ideas why I'm facing this issue?
https://stackblitz.com/edit/ng6hybrid-c8h6uv
There are two issues that need to be addressed. First, in the studentController.js file, you are using the var mainApp = angular.module("testApp", []); syntax which is resetting the AngularJS module and everything that got instantiated before is being removed.
To answer your question about the controllers, AngularJS controllers can't be upgraded directly using UpgradeComponent (see https://angular.io/guide/upgrade#using-angularjs-component-directives-from-angular-code) because they aren't components/directives that have a template. That is why the error you get (after fixing the first issue) is Unknown provider: studentControllerDirectiveProvider <- studentControllerDirective. It can't find a directive for the reference studentController, so it is adding Directive to see if that has anything.
To fix this, either convert the controller in AngularJS to a directive with a template, or convert it to a service in AngularJS and then inject it into Angular using the UpgradeModule. Keep in mind you will need a template somewhere for this controller so it can be upgraded to Angular. Please see a working example of this in my stackblitz below.
https://stackblitz.com/edit/ng6hybrid-zs6waw?file=app%2Fdirective-wrappers%2FstudentControllerWrapper.ts

Unit testing a service in angularJS

I'm relatively new to unit testing but was now tasked to write tests for a existing code base that I know quite well.
Sadly I'm unable to achieve any progress what so ever nor find really helpful documentation.
The main component of the code base is a service to retrieve data from an api but I'm unable to get an instance of the module the service belongs to:
TypeError: module is not a function in /home/faebser/workspace/GridSense-CMS-App/dev/test/unit/api.test.js (line 13)
karma config: http://sprunge.us/ObSP?js
tests: http://sprunge.us/AJWL?js
karma output: http://sprunge.us/WYHI?bash
What is the problem? why am I not able to get a instance of the module?
UPDATE1:
I'm managed to load my module by reinstalling the same version of angular and angular mocks. But now I run into the following error:
minErr/<#/home/faebser/workspace/GridSense-CMS-App/dev/bower_components/angular/angular.js:63:12
loadModules/<#/home/faebser/workspace/GridSense-CMS-App/dev/bower_components/angular/angular.js:4138:15
forEach#/home/faebser/workspace/GridSense-CMS-App/dev/bower_components/angular/angular.js:323:11
loadModules#/home/faebser/workspace/GridSense-CMS-App/dev/bower_components/angular/angular.js:4099:5
createInjector#/home/faebser/workspace/GridSense-CMS-App/dev/bower_components/angular/angular.js:4025:11
workFn#/home/faebser/workspace/GridSense-CMS-App/dev/bower_components/angular-mocks/angular-mocks.js:2425:44
I managed to track the error down to the following:
"[$injector:modulerr] Failed to instantiate module ui.router due to:[$injector:nomod] Module 'ui.router' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.http://errors.angularjs.org/1.3.15/$injector/nomod?p0=ui.routerminErr/<#http://localhost:9876/base/bower_components/angular/angular.js:63:12module/<#http://localhost:9876/base/bower_components/angular/angular.js:1774:1ensure#http://localhost:9876/base/bower_components/angular/angular.js:1698:38module#http://localhost:9876/base/bower_components/angular/angular.js:1772:1loadModules/<#http://localhost:9876/base/bower_components/angular/angular.js:4115:22forEach#http://localhost:9876/base/bower_components/angular/angular.js:323:11loadModules#http://localhost:9876/base/bower_components/angular/angular.js:4099:5loadModules/<#http://localhost:9876/base/bower_components/angular/angular.js:4116:40forEach#http://localho"
Okay, simply forgot to add ui-router to karma-config.
It's looks like angular-mock is not loaded.
Checks well your path. For the moment, for karma it's look like :
-dev
|-test/
|-js/
|-bower_components/
|-karma.conf
Because in karma.conf, you have :
base: '',
Okay, I managed to get this to work.
The main problem was the strange error messages that angular gave me:
minErr/<#/home/faebser/workspace/GridSense-CMS-App/dev/bower_components/angular/angular.js:63:12
loadModules/<#/home/faebser/workspace/GridSense-CMS-App/dev/bower_components/angular/angular.js:4138:15
forEach#/home/faebser/workspace/GridSense-CMS-App/dev/bower_components/angular/angular.js:323:11
loadModules#/home/faebser/workspace/GridSense-CMS-App/dev/bower_components/angular/angular.js:4099:5
createInjector#/home/faebser/workspace/GridSense-CMS-App/dev/bower_components/angular/angular.js:4025:11
workFn#/home/faebser/workspace/GridSense-CMS-App/dev/bower_components/angular-mocks/angular-mocks.js:2425:44
To work around this I used the karma debug window and set a breakpoint at angular.js:63 in function minErr(module, ErrorConstructor):
return new ErrorConstructor(message);
that way you can see the arguments and the compiled error message. In the end i just forgot to add a few dependencies in the karma config file.

Unknown provider: ngTagsInputProvider <- ngTagsInput

I injected the 2.1.1 version ngtagsinput like this into my controller:
app.controller('homeCtrl', ['$scope','$http','ngTagsInput', function($scope,$http){
}])
*NOTE: TESTED! add ngTagsInput into the function() will not make a difference...
I loaded the ngtagsinput lib after angularjs lib.
I wonder what else I could test to resolve the error of:
Error: [$injector:unpr] Unknown provider: ngTagsInputProvider <- ngTagsInput
http://errors.angularjs.org/1.2.9/$injector/unpr?p0=ngTagsInputProvider%20%3C-%20ngTagsInput
Don't get me wrong, I know basically this provider is not detected.
but my lib is found (did not report 404), I saw ngTagsInput used in its library....
So, its really bugging me the same solution no more works for this lib! What's special about this lib and why this error is there while I met all the standard to fix it?
It looks like you have tried to inject ngTagsInput into your controller, while you should be injecting it into your module as a dependency. For example:
angular.module('myApp', ['ngTagsInput'])
note module, not controller
You can see as per the creators example: https://github.com/mbenford/ngTagsInput#example
This happens because there are multiple types of injection used in angular. When you declare a module, you need to specify which other modules are available to use within your module.
See: https://docs.angularjs.org/guide/module
When you inject into say a controller, you are basically saying that you want to use a particular object inside it. That object must be a part of your module to be valid. For a third party library, this usually means adding it as a module dependency (as above), and then injecting any object that is part of that library into your controllers and services.

AngularJS module .run order and e2e mocks

I am working on some E2E tests for AngularJS.
I have implemented a $httpBackend ngMockE2E.
This works well, however in some instances HTTP requests are being made before my mocks have been completely set up.
The Mock is set up as:
angular.module('Mock', ['ngMockE2E']).
run(function($httpBackend) {
$httpBackend.whenPOST('/path1').respond({ exampleresponse: 'valid' });
$httpBackend.whenPOST('/path2').respond({ exampleresponse: 'valid' });
And it is used as below:
angular.module('Application', ['FirstDependency', 'Mock', 'ThirdDependency']);
However FirstDependency and ThirdDependency can make HTTP requests which sometimes happen before the Mock .run() block has been executed. This results in request errors.
Am I setting up my mocks correctly? What is the best way to ensure my mocks are loaded in the right order?
This is what the doc says:
Dependencies:
Modules can list other modules as their dependencies.
Depending on a module implies that required module needs to be loaded
before the requiring module is loaded. In other words the
configuration blocks of the required modules execute before the
configuration blocks of the requiring module. The same is true for the
run blocks. Each module can only be loaded once, even if multiple
other modules require it.
However what it doesn't say is that it will first execute the config blocks for all modules (dependencies first) and then it will execute all the other blocks in a row for each module in turn. For an illustration of this take a look at this jsfiddle:
http://jsfiddle.net/9FJnZ/2/

Why does this Angular module/factory injection code work in JS Fiddle but not on my local computer?

I have a JS Fiddle here: Angular module injection. I also have a respository here that from what I can tell, duplicates my code: Blink-Example
When I open index.html I get the error:
Error: Unknown provider: fromBadFactoryProvider <- fromBadFactory
I'm trying to inject a module into my app that has a factory on it and use that factory in the app, but always get this error. What am I doing wrong?
It's because your copy of 1.0.6 is mangled -- you deleted an asterisk from it on line 1128.
Edit: Another reason to use a shared CDN. :)

Resources