I am writing unit test which is using $stateProvider(the code is shown below for both the code and its test file).While executing this, it is giving error- "Error: Could not resolve 'app.history' from state ''".
$stateProvider
.state('app',
{
url: "/app",
templateUrl: "pages/app/index.html",
controller: function($state) {
$state.go('app.history');
}})
.state('app.history',
{ url: "/history",
templateUrl: "pages/app/modules/History/partials/history.html"
})
Unit test code -
describe("Unit tests for config.jst", function() {
var $rootScope, $injector, $state;
beforeEach(module('ui.router'));
beforeEach(inject(function(_$rootScope_, _$state_, _$injector_, $templateCache) {
$rootScope = _$rootScope_;
$injector = _$injector_;
$state = _$state_;
$templateCache.put("pages/app/index.html", "");
$templateCache.put("pages/app/modules/History/partials/history.html", "");
}));
describe("states", function() {
var state = "app.history";
it("verify state configuration", function() {
//var config = $state.get(state);
$state.go(state);
$rootScope.$digest();
//console.log($state);
expect($state.current.name).to.be.equal(state);
});
});
});
You forgot to include application module.
Add
module('your_application_module_name');
below
beforeEach(module('ui.router'));
Related
I'm using Karma to write angular tests: Here's my spec.js file:
'use strict';
var state;
var $rootScope, $state, $injector, CategoriesService;
describe('Categories', function() {
describe('Categories Manage', function() {
beforeEach(function() {
beforeEach(module('ui.router'));
module('CL.Categories', function($provide) {
$provide.value('CategoriesService', CategoriesService = {});
});
inject(function(_$rootScope_, _$state_, _$injector_, $templateCache, _CategoriesService_) {
$rootScope = _$rootScope_;
$state = _$state_;
$injector = _$injector_;
CategoriesService = _CategoriesService_;
// We need add the template entry into the templateCache if we ever
// specify a templateUrl
$templateCache.put('layout/dashboard.html', '');
$templateCache.put('layout/sidebar.html', '');
$templateCache.put('layout/footer.html', '');
$templateCache.put('layout/header.html', '');
$templateCache.put('categories/manage/index.html', '');
});
});
it('should respond to URL with query parameters', function() {
expect($state.href(state)).toEqual('#/categories/manage');
});
});
});
This is my config file :
(function (){
'use strict';
angular.module('CL.Categories')
.config(['$stateProvider', categoriesConfig]);
function categoriesConfig ($stateProvider){
$stateProvider
.state('dashboard.selectCategories', {
url: "/categories/select?criteria&referrer&index",
templateUrl: 'categories/select/index.html',
controller: 'SelectCategoriesController',
controllerAs: 'vm',
resolve: {
categoryRoot: ['CategoriesService', function(CategoriesService){
return CategoriesService.getRootCategories();
}]
}
})
.state('dashboard.manageCategories', {
url: "/categories/manage?active",
templateUrl: 'categories/manage/index.html',
controller: 'ManageCategoriesController',
controllerAs: 'vm',
resolve: {
workCategories: ['CategoriesService', function (CategoriesService) {
return CategoriesService.getCategoriesByOrganisationWithCertificates();
}]
}
});
}
})();
in my karma.config file I have the base path set to './'. the test expect($state.href(state)) always returns null
When you're making your mock call for state, try this instead to get the 'state':
state = $state.get('dashboard.selectCategories');
Then you can test pieces of the state declaration:
expect(state.url).toEqual('/categories/select?criteria&referrer&index');
expect(state.templateUrl).toEqual('categories/select/index.html');
And so on...
I am trying to write a unit test for my ui-router with uses resolve.
Router.js
define(['module', 'require'], function(module, require) {
'use strict';
var Router = function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/shopping');
$stateProvider
.state('shopping', {
url: '/shopping',
templateUrl: 'app/shopping.html',
resolve:{
userFactory : 'UserFactory',
checkAccess:function(userFactory){
return userFactory.checkUser();
}
}
})
.state('products', {
url: '/products',
templateUrl: 'app/products.html',
resolve:{
userFactory : 'UserFactory',
checkAccess:function(userFactory){
return userFactory.checkUser();
}
}
})
.state('notAuth', {
url: '/notAuth',
templateUrl: 'app/unauthorised.html'
});
};
module.exports = ['$stateProvider', '$urlRouterProvider', Router];
});
Within userFactory.checkUser(); i essentially check the users' rights, and redirect either to the templateUrl, or perform a:
$state.go('notAuth');
My currect .spec.js:
define(['require', 'angular-mocks', 'angular-ui-router', 'app/router'], function (require) {
'use strict';
describe('myApp/myState', function() {
var $rootScope, $state, $injector, myServiceMock, $httpBackend, state = 'shopping';
var mockResponse = {
"access": true
}
var angular = require('angular');
var myRouter = require('app/router');
beforeEach(module('ui.router'));
beforeEach(function() {
module(myRouter, function($provide) {
$provide.value('userFactory', myServiceMock = {});
});
inject(function(_$rootScope_, _$state_, _$injector_, $templateCache, _$httpBackend_) {
$rootScope = _$rootScope_.$new();
$state = _$state_;
$injector = _$injector_;
$httpBackend = _$httpBackend_;
$rootScope.$digest();
})
});
it('should transition to shopping', inject(function($state,$rootScope){
$state.transitionTo('shopping');
$rootScope.$apply();
expect($state.current.name).toBe('shopping');
}));
it('should resolve data', function() {
myServiceMock.checkUser = jasmine.createSpy('checkUser').and.returnValue(mockResponse);
// earlier than jasmine 2.0, replace "and.returnValue" with "andReturn"
$state.go(state);
$rootScope.$digest();
expect($state.current.name).toBe(state);
});
});
});
With the above test, i get the following errors:
Information: myApp/myState
Information: should transition to shopping Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Information: Watchers fired in the last 5 iterations: []
Information: http://errors.angularjs.org/1.4.0/$rootScope/infdig?p0=10&p1=%5B%5D
Information: should resolve data Expected '' to be 'shopping'.
It looks like there are a few things happening here. First, you're digesting too many times. That's the "10 $digest() iterations reached" message. To fix that one, you should remove the $rootScope.$digest() from the end of your inject function.
I think the actual failing test part is because you're not resolving your checkAccess resolve that you've configured in your route. Try adding $provide.value('checkAccess', function() {return true;}); to your $provide.value setup. That should allow checkAccess to resolve in your route, which will then allow the route to complete the state transition.
I found my answer to a similar question here: Angular Jasmine UI router inject resolve value into test
I've been trying to test my controller:
app.js
angular
.module('MyModule', [
'ui.router'
]);
angular
.module('MyModule')
.config(configFn);
configFn.$inject = ['$stateProvider'];
function configFn($stateProvider){
$stateProvider
.state('myState',{
url:'state',
views: {
'main' : {
templateUrl: 'src/views/view.html',
controller: 'MyCtrl',
controllerAs: 'ctrl',
resolve: {
DataResolve: ['MyService', function(MyService){
return MyService.getData();
}]
}
}
}
});
controller.js
angular
.module('MyModule')
.controller('MyCtrl', Controller);
Controller.$inject = ['DataResolve'];
/* #ngInject */
function Controller(DataResolve) {
var vm = this;
vm.data = DataResolve;
}
My spec
controller_spec.js
describe('Controller', function(){
beforeEach(module('MyModule'));
beforeEach(inject(function($controller){
this.myCtrl = $controller('MyCtrl');
}));
it('Controller should be defined', function() {
expect(this.myCtrl).toBeDefined();
});
});
But when the test runs, I get the following error:
Error: [$injector:unpr] Unknown provider: DataResolveProvider <- DataResolve <- MyCtrl
What I have been doing wrong?
In your beforeEach, add a reference to your service :
beforeEach(inject(function($controller, DataResolve){
this.DataResolve = DataResolve;
this.myCtrl = $controller('ParcelasController', {
DataResolve: this.DataResolve;
});
}));
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 trying unit testing with Jasmine and Karma, but for some reason my Angular modules cannot be found. I've modified code from examples:
karma.config.js:
files: [
'lib/angular.js',
'lib/angular-mocks.js',
'js/app.js',
'js/controllers.js',
'js/factories.js',
'tests/**/*.js'
]
app.js:
var app = angular.module('app', ['ngRoute']);
app.config(function ($routeProvider) {
$routeProvider
.when('/test', {
templateUrl: 'views/test.html',
controller: 'TestCtrl'
})
.otherwise({redirectTo: '/'});
});
controllers.js:
app.controller('TestCtrl', function ($scope, $location) {
console.log('Test Controller');
$scope.isActive = function(route) {
return route === $location.path();
};
});
test-spec.js:
describe('TestCtrl testing', function () {
var scope, $location, createController;
beforeEach(inject(function ($rootScope, $controller, _$location_) {
$location = _$location_;
scope = $rootScope.$new();
createController = function () {
return $controller('TestCtrl', {
'$scope': scope
});
};
}));
it('should...', function () {
var controller = createController();
$location.path('/test');
expect($location.path()).toBe('/test');
expect(scope.isActive('/test')).toBe(true);
expect(scope.isActive('/contact')).toBe(false);
});
});
error message:
Error: [ng:areq] Argument 'TestCtrl' is not a function, got undefined
I also tried with: beforeEach(module('TestCtrl')), but it did not help.
What have I missed?
There are two problems I can see. In describe section there must be main module injection:
beforeEach(module('app'));
The second problem is that you forgot to add ngAnimate module to Karma files config array:
files: [
'lib/angular.js',
'lib/angular-route.js', // <-- this guy
'lib/angular-mocks.js',
...
]