Injecting routerProvider for AngularJS test using Jasmine - angularjs

I'm using Jasmine for testing AngularJS controller and I'm struggling to find a way of injecting $routeProvider into the module.
Here's my controller:
var app = angular.module('testApp', []);
app.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.
when('/smth', {
templateUrl: 'smth.html',
controller: 'testController'
});
}]);
app.controller('testController', ['$scope', function ($scope) {
$scope.data = 'GG';
}]);
Here's my test:
describe('Test Suite', function () {
var myScope, ctrl;
beforeEach(module('testApp'));
beforeEach(inject(function ($controller, $rootScope) {
myScope = $rootScope.$new();
ctrl = $controller('testController', {
$scope: myScope
});
}));
it('data is GG', function () {
expect(myScope.data).toEqual('GG');
});
});
When I try to run it, I receive a following error:
Error: [$injector:modulerr] Failed to instantiate module testApp due to:
Error: [$injector:unpr] Unknown provider: $routeProvider
But if I try to run again - I get this:
TypeError: 'undefined' is not an object (evaluating 'myScope.data')
Errors keep alternating if tests are run again. I'm using Visual Studio 2013 and Resharper 8 to run the Jasmine tests.

Add the angular-route bower component to your project and then inject the ngRoute into your module like this
var app = angular.module('testApp', ['ngRoute']);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/smth', {
templateUrl: 'smth.html',
controller: 'testController'
});
}]);
app.controller('testController', ['$scope', function ($scope) {
$scope.data = 'GG';
}]);

First make sure you have included angular-route.min.js.
This module has been separated from angularJs library, so you have will have to include it separately
then make sure you have added dependency for your module to ngRoute
e.g. angular.module('testApp', ['ngRoute']);
then in the test make sure you inject $route so its available in your tests as well

Related

inject a service in a component from the diff file - Angularjs 1.6

I need a help. I use Angularjs 1.6 and I want just simply to inject a service from diff file in a controller. Looks pretty easy, aha)
Before I read this:
AngularJS: Service in different file.
But it didn't work in my case.
My code looks next:
app.js
angular.module('myApp', ['formService', 'formLogic'])
component.js
angular.module('formLogic',[])
.component('formLogic',{
templateUrl: './templates/form-logic.html',
controller: function ($scope, formService){
}
});
service.js
angular.module('formService',[])
.service('FormService', function($http){
});
But I got this error: Error: $injector:unpr Unknown Provider
Thanks for your help!
Don't give your modules the same name as your providers (don't name both your module and your component "formLogic").
Add your "formService" module as a dependency on your "formLogic" module.
You have called your service "FormService" and are trying to inject "formService" into your component controller. "formService" is not a service that you have defined, it's the name of your module.
To inject component and services from different module. Can inject the module.
component.js
angular.module('anotherModule',[])
.component('formLogic',{
templateUrl: './templates/form-logic.html',
controller: function ($scope, formService){
}
});
service.js
angular.module('anotherModule')
.service('formService', function($http){
});
so no can use formService and formLogic from myApp module
like:
app.js
angular.module('myApp', ['anotherModule']) // injected `anotherModule` in `myApp` modele
mainController.js
angular.module('myApp').controller('MainCtrl', function($scope, formService) {
// can access `formService` from here
});
OR
you can use same module like:
var app = angular.module('myApp', []);
app.component('formLogic',{
templateUrl: './templates/form-logic.html',
controller: function ($scope, formService){
// ...
}
});
app.service('formService', function($http){
//.....
});
app.controller('MainCtrl', function($scope, formService) {
// can access `formService` from here
});

How to inject $routeProvider in Angular spec

When passing this function that includes $routeProvider into a module definition, how do you mock/inject it properly in spec?
module.js
angular.module('myModule', [
// Without the function($routeProvider) below the test passes. With it, it fails.
function($routeProvider) {
$routeProvider.when('/some/url/:id', {templateUrl: 'template.html', reloadOnSearch: false});
}
])
myModuleCtrl.js
angular.module('myModule')
.controller('myModuleCtrl', [
'$scope',
function ($scope) {
$scope.testMethod = function () {
alert('Test Me!');
}
}
]);
myModuleCtrl.spec.js
describe('myModuleCtrl', function () {
var controller;
var $scope;
beforeEach(angular.mock.module('myModule'));
beforeEach(function () {
$scope = {};
});
beforeEach(angular.mock.inject(function ($rootScope, $controller) {
controller = $controller('myModuleCtrl', {'$scope': $scope});
}));
describe('when doing stuff', function() {
it('does other stuff', function() {
$scope.testMethod();
});
});
});
As commented in module.js, without the $routeProvider line the spec passes. With it, it fails with the following message:
Error: [$injector:modulerr] Failed to instantiate module myModule due to:
Error: [$injector:modulerr] Failed to instantiate module function ($routeProvider) due to:
Error: [$injector:unpr] Unknown provider: $routeProvider
What needs to be done in the spec file to get this module to load (including the $routeProvider)?
Your module should have injected dependency ngRoute
angular.module('myModule', ['ngRoute'])
Samething should be there for the test,
beforeEach(angular.mock.module('myModule',['ngRoute']));

Controller is not a function, got undefined in jasmine testing with angular(route - $stateProvider)

i am using angle theme with Angular for my project and i am doing unit testing on this using jasmine framework. But when i run the test cases, it gives error of "Argument 'controller' is not a function, got undefined". here is my test.js file....
describe('registrationController',function(){
beforeEach(module('appTesting'));
var $controller;
beforeEach(inject(function(_$controller_){
$controller = _$controller_;
}));
it('Check Working Or Not', function() {
var $scope = {};
var controller = $controller('registrationController', { $scope: $scope });
$scope.password = 'passwordlength';
$scope.grade();
expect($scope.strength).toEqual('strong');
});
});
Error -
Error: [ng:areq] Argument 'registrationController' is not a function, got undefined http://errors.angularjs.org/1.3.10/ng/areq?p0=registrationController&p1=not%20a%20function%2C%20got%20undefined
No i am using karma to run jasmine.
I am defining my module here
var App = angular.module('appTesting', ['ngRoute', 'ngAnimate', 'ngStorage', 'ngCookies', 'pascalprecht.translate', 'ui.bootstrap', 'ui.router', 'oc.lazyLoad', 'cfp.loadingBar', 'ngSanitize', 'ngResource'])
.run(["$rootScope", "$state", "$stateParams", '$window', '$templateCache', function ($rootScope, $state, $stateParams, $window, $templateCache, $location) {
// Set reference to access them from any scope
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.$storage = $window.localStorage;
}
]);
App.config(['$stateProvider','$urlRouterProvider', '$controllerProvider', '$compileProvider', '$filterProvider', '$provide', '$ocLazyLoadProvider', 'APP_REQUIRES', 'RouteHelpersProvider',
function ($stateProvider, $urlRouterProvider, $controllerProvider, $compileProvider, $filterProvider, $provide, $ocLazyLoadProvider, appRequires, helper) {
'use strict';
App.controller = $controllerProvider.register;
App.directive = $compileProvider.directive;
App.filter = $filterProvider.register;
App.factory = $provide.factory;
App.service = $provide.service;
App.constant = $provide.constant;
App.value = $provide.value;
$stateProvider
.state('app.registrationState', {
url: '/registration',
title: 'Ragistration Page',
templateUrl: helper.basepath('registrationPage.html'),
resolve: helper.resolveFor('registrationController','angularFileUpload')
})
}])
.controller('NullController', function() {});
App.constant('APP_REQUIRES', {
scripts:
{
'registrationController' :['app/js/registrationcontroller.js'],
}
});
Angular
Can the controller be found?
Do you have a controller named registrationController?
Is it in a module named appTesting?
You should have the following code somewhere in your app:
angular.module("appTesting").controller("registrationController", ...);
Karma
If you are using Karma-jasmine:
Did you include the file where you define the controller (registration-controller.js) in your karma.conf.js?
karma.conf.js
module.exports = function(config) {config.set({
files : [
'src/registration-controller.js',
...
],
...
});};
Jasmine
If you're not using Karma to run Jasmine, I'm assuming you're using the Jasmine test runner (HTML file). In that case:
Did you include the controller in the HTML file?
You need to include the controller's script:
<head>
...
<script type="text/javascript" src="src/registration-controller.js"></script>
...
</head>
Either the controller cannot be found or was not created due to error on the source code where controller was defined.
In my case, it was due to a statement that had error which affected succeeding lines of code cause the controller to be not loaded.
This can happen due to variety of reasons.
-> controller name is not referenced right
-> controller is not created due to some error.
In my case, I had the controller name mismatched in
directive:
.controller('IAddController', AddController)
Jasmine spec.ts:
// Instantiate controller
addController= $controller<any>('AddController', {*

Getting controller undefined when trying to run jasmine test

I'm just about to write tests for my angularjs-app. However when Im trying to run the test which is very simpel one i get the following error.
Error: [ng:areq] Argument 'MyPageController' is not a function, got undefined
I'll provide code for the setup of my controllers, config etc.
Route
var myPageApp = angular.module('myPageApp', ['ngRoute', 'ngAnimate', 'ngSanitize', 'app.controller', 'app.service', 'app.filter', 'app.config'])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'App_AngularJs/partials/myPage/myPage.htm',
controller: 'MyPageController',
reloadOnSearch: false,
});
}]);
Controller
var myPageApp = angular.module('app.controller', ['oci.treeview', 'ui.bootstrap'])
.controller('MyPageController', ['$scope', '$routeParams', '$location', '$timeout', '$filter', '$modal', 'myPageService',
function ($scope, $routeParams, $location, $timeout, $filter, $modal, myPageService) {
init();
function init() {
$scope.page = { value: $routeParams.page || 1 };
}
}]);
Simpel test
'use strict';
describe('Testing MyPageController', function(){
var scope;
//mock Application to allow us to inject our own dependencies
beforeEach(angular.mock.module('myPageApp'));
//mock the controller for the same reason and include $rootScope and $controller
beforeEach(angular.mock.inject(function($rootScope, $controller){
//create an empty scope
scope = $rootScope.$new();
//declare the controller and inject our empty scope
$controller('MyPageController', { $scope: scope });
}));
// tests start here
it('should map routes to controllers', function () {
module('myPageApp');
inject(function ($route) {
expect($route.routes['/'].controller).toBe('MyPageController');
expect($route.routes['/'].templateUrl).
toEqual('App_AngularJs/partials/myPage/myPage.htm');
});
});
it('should have variable assigned = "1"', function(){
expect(scope.page.value).toBe(1);
});
});
My wildest and best guess is that i need to mock app.controller but how? Everything starts out with myPageApp which holds references to service, controller etc etc..
I think your issue is that routing and the controller are trying to load different modules viz "myPageApp" and "app.controller" and in your test with beforeEach you are trying to load 'myPageApp' module to which router is associated but not the controller.
So it seems to me that either you use same module for both router and controllers. Or try loading both modules in the test. Still I believe associating the router and controller with same module makes more sense.
An small example as below. Extract the application module in common js file (may be call it app.js)
var myApp = angular.module(
'myApp');
Now define router as
myApp.config(function ($routeProvider) {
$routeProvider
.when('/testUrl', {
templateUrl: '/myApp/views/test-view',
controller: 'TestViewController'
})
Similary define controller as
myApp.controller('TestViewController',[your dependencies goes here])
And now in your tests
beforeEach(module('myApp'));
This will work for sure. Hope it helps.

jasmine test for $routeprovider resolve in config block

i have the below in my module config block:
var appModule = angular.module('myApp',['ngRoute'])
.config(['$httpProvider', '$routeProvider', '$locationProvider', '$translateProvider', function ($httpProvider, $routeProvider, $locationProvider, $translateProvider) {
$locationProvider.html5Mode(true)
$routeProvider
.when('/services/main', {templateUrl: '/services/main/html/main.html', controller: 'MainCtrl', resolve: {
myVar: function (varService) {
return varService.invokeService();
}
}})
}])
Spec File:
describe("Unit Testing: config - ", function() {
var appModule;
var routes;
beforeEach(function() {
appModule = angular.module("myApp");
});
it('should test routeProvider', function() {
inject(function($route, $location, $rootScope) {
routes = $route;
});
});
});
however, while running the test i am getting the below error:
Unit Testing: config - should test routeProvider FAILED
Error: [$injector:unpr] http://errors.angularjs.org/1.2.15/$injector/unpr?p0=%24routeProvider%20%3C-%20%24route
at Error (native)
my karma config includes the angular-route.min.js file. Any suggestions will be helpful.
The issue was resolved with use of angular.mock.module instead of angular.module.
appModule = angular.mock.module("myApp");
What i found that we should use mock to inject the module and it includes the configuration as well where as module is used to register a newly module. So if one is refering to the module already registered, we should use angular.mock.module.
The documentaion says:
This function registers a module configuration code. It collects the configuration information which will be used when the injector is created by inject.

Resources