I have the below code. When I run my unit tests, I get that the resolve function is not code covered.
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/', {
controller: 'HomeCtrl',
resolve: {
homePage: function (homePageLoader) {
return homePageLoader();
}
},
templateUrl: 'views/home.html'
}).
otherwise({ redirectTo: '/' });
}]);
How do I write unit tests for the resolve function?
I had a smilar situation with my app.js with routeprovider & resolve. This was solved with below:
app.js
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 mockService;
beforeEach(function() {
appModule = angular.mock.module("myApp");
});
it('should test routeProvider resolve', function() {
mockService = {
invokeService: jasmine.createSpy('invokeService').andReturn('myVar')
};
module(function($provide){
$provide.value('varService', mockService);
});
inject(function($route, $location, $rootScope, $httpBackend) {
$httpBackend.expectGET('/services/main/html/main.html').respond({});
$location.path('/services/main');
$rootScope.$digest();
expect($route.current).toBeDefined();
});
});
});
this ensures the coverage for the resolve.
Related
I have the following three angularjs scripts:
/config.js
/authentication/LoginCtrl.js
/authentication/loginFactoyr.js
App ristoreApp is defined in config.js.
//config.js
angular.module('ristoreApp', ['ngRoute'])
.config(function ($routeProvider, $locationProvider, $httpProvider) {
// $httpProvider.responseInterceptors.push('httpInterceptor');
$routeProvider
.when('/login', {
templateUrl: 'authentication/login.html',
controller: 'LoginCtrl'
})
.when('/home', {
templateUrl: 'home.html',
})
.otherwise({
redirectTo: '/login'
});
$locationProvider.html5Mode(true);
});
My controller calls the app by "angular.module":
angular.module('ristoreApp', [])
.controller('LoginCtrl', ['$scope', '$location', 'loginFactory', function($scope, $location, loginFactory){
$scope.authenticate = function() {
loginFactory.login($scope.username, $scope.password)
.then(function(response) {
console.log(response);
$location.path('/home');
}, function errorCallBack(response) {
console.log(response);
$location.path('login');
});
}
}]);
Got the error "Error: ng:areq Bad Argument"
Argument 'LoginCtrl' is not a function, got undefined
Why does it say my controller is not a function? What did I do wrong?
Try this. Remove the quotes on LoginCtrl.
controller: LoginCtrl
Then, define the controller as:
var LoginCtrl = app.controller("LoginCtrl", ["$scope", function($scope) { /* etc... */}]);
angular.module('myApp.view1', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
});
}])
.controller('View1Ctrl', [function() {
}]);
In same you can append an component to you module
angular.module('myApp.view1', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
});
$routeProvider.when('/view2', {
templateUrl: 'view1/view2.html',
controller: 'View2Ctrl'
});
}])
.controller('View1Ctrl', [$scope, function($scope) {
}])
.controller('View2Ctrl', [$scope, function($scope) {
}]);
Other way would be you can just store your module in some variable and do use that variable while appending angular component to angular.module
var app = angular.module('myApp.view1', ['ngRoute'])
app.config(['$routeProvider', function($routeProvider) {
//..code here
}])
app.controller('View1Ctrl', [$scope, function($scope) {
}])
app.controller('View2Ctrl', [$scope, function($scope) {
}]);
More preferred way would be to use IIFE pattern In that case there you wont store any global variable, As IIFE create a closer function that scope ends when function gets end
App.js
function(){
angular.module('myApp.view1', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
//..code here..
}])
}();
View1Ctrl.js
function(){
angular.module('myApp.view1')
.controller('View1Ctrl', [function() {
}]);
}();
View2Ctrl.js
function(){
angular.module('myApp.view1')
.controller('View2Ctrl', [function() {
}]);
}();
I've added another controller declaration, and added it to $routeProvider, see the relevant developer guide page for more info
angular.module('view1', 'view2', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
})
.when('/view2', {
templateUrl: 'view2/view2.html',
controller: 'myController'
})
}])
.controller('View1Ctrl', [function() {
}]);
.controller('myController', [function() {
}]);
note that appending multiple controllers into a single file is not a recommended practice
following is the code from my sample angular project.
app.js code:
(function () {
'use strict';
var app = angular.module('actorsDetails', [
// Angular modules
'ngResource',
// 3rd Party Modules
'ui.bootstrap',
'ui.router'
]);
app.config(['$stateProvider', '$urlRouterProvider', configRoutes]);
function configRoutes($stateProvider, $urlRouterProvider) {
$stateProvider
.state('main', {
url: '/main',
templateUrl: 'app/home/home.html',
controller: 'HomeCtrl',
controllerAs: 'vm'
})
.state('form', {
url: '/form',
templateUrl: 'app/form/form.html',
controller: 'FormCtrl',
controllerAs: 'vm',
resolve: {
initialData: ['actorApi', function (actorApi) {
return actorApi.getActorsResource();
}]
}
})
.state('resource', {
url: '/resource',
templateUrl: 'app/resource/resource.html',
controller: 'ResourceCtrl',
controllerAs: 'vm',
resolve: {
initialData: ['actorApi', function (actorApi) {
return actorApi.getActorsResource();
}]
}
});
$urlRouterProvider.otherwise('/main');
}
app.run(['$state', function ($state) {
// Include $route to kick start the router.
}]);
})();
controller code:
(function () {
'use strict';
angular.module('actorsDetails').controller('HomeCtrl', HomeCtrl);
/* #ngInject */
function HomeCtrl($state) {
/* jshint validthis: true */
var vm = this;
vm.activate = activate;
vm.test = true;
vm.navigate = navigate;
activate();
function activate() {
}
function navigate() {
$state.go('form');
}
}
})();
**test.js**
describe('HomeCtrl', function() {
beforeEach(module('actorsDetails'));
beforeEach(inject(function ($rootScope, $controller) {
var scope = $rootScope.$new();
var HomeCtrl = $controller('HomeCtrl', {
$scope: scope
});
}));
it('should have a HomeCtrl controller', function() {
expect(true).toBeDefined();
});
});
there are the files I have included in my karma.config.js
I have added all the angularJS dependent files.
I have also added the controller file that i need to test
files: [
'src/lib/angular/angular.min.js',
'src/lib/angular-mocks/angular-mocks.js',
'src/lib/angular-resource/angular-resource.min.js',
'src/lib/angular-route/angular-route.min.js',
'src/app/app.js',
'src/app/home/home.controller.js',
'src/test/specs/*.js'
],
kindly pinpoint me, what is that I am doing wrong...
Mock out the $state object in your unit test.
var mockState = { go: function() {} };
var HomeCtrl = $controller('HomeCtrl', { $scope: scope, $state: mockState });
The $injector:modulerr is most likely related to your use of $state in your controller. Instead of mocking, you could try adding the library to your karma config, and loading the module in your unit test.
'src/lib/angular-ui-router/release/angular-ui-router.min.js'
beforeEach(module('ui.router'));
I'm new to angular and I'm trying to modularlize my app.
My main module gets some other module and I want to use the controller of the injected module in my route definition.
Some simple example would be very helpful!
This does not work:
var app = angular.module('Contacting_App', ['LeadLookup']);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/main',
{controller: 'MainCtrl',
templateUrl: 'apex/f42_Contacting_Main'}
).
when('/lead',
{module: 'LeadLookup',
controller: 'LeadLkpCtrl',
templateUrl: 'apex/f42_Lead_Lookup'}
).
otherwise(
{redirectTo: '/main'}
);
}]);
This tutorial page may point you in the correct direction docs.angularjs.org/tutorial/step_07
The main things you should look at are:
Module
var phonecatApp = angular.module('phonecatApp', [
'ngRoute',
'phonecatControllers'
]);
routeProvider
phonecatApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: 'PhoneListCtrl'
}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: 'PhoneDetailCtrl'
}).
otherwise({
redirectTo: '/phones'
});
}]);
Controllers
var phonecatControllers = angular.module('phonecatControllers', []);
phonecatControllers.controller('PhoneListCtrl', ['$scope', '$http',
function ($scope, $http) {
$http.get('phones/phones.json').success(function(data) {
$scope.phones = data;
});
$scope.orderProp = 'age';
}]);
phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams',
function($scope, $routeParams) {
$scope.phoneId = $routeParams.phoneId;
}]);
I'm getting the classic "Module 'ngLocale' error is not available" error when angular tries to load up my module. I can't for the life of me figure out what dependency I am missing. Here's my app.js:
(function() {
var app, dependencies;
dependencies = ["ngRoute"];
app = angular.module('myapp', dependencies);
app.run(['$location', '$rootScope'], function($location, $rootScope) {
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
$rootScope.title = current.$$route.title;
});
});
app.config(['$routeProvider'], function($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'Content/views/home.html',
controller: 'homeController',
title: 'Home'
}).otherwise({
redirectTo: '/'
});
});
}).call(this);
My javascript files are loaded correctly in order. What am I missing?
you have to include the function in the array:
app.run(['$location', '$rootScope', function($location, $rootScope) {
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
$rootScope.title = current.$$route.title;
});
}]);
and:
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'Content/views/home.html',
controller: 'homeController',
title: 'Home'
}).otherwise({
redirectTo: '/'
});
}]);