8760

karma/angularjs how to test run block with an asynchronous service

Question:

How can I test like:

<h2>init.js lama.system module</h2> angular.module('lama.system', []) .config(['$httpProvider', function($httpProvider) { // Crossdomain requests not allowed if you want do cors request see filter.php $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; }]) .run(['$rootScope', '$state', '$log', 'Global',function ($rootScope, $state, $log, Global) { $rootScope.$state = $state; $rootScope.$log = $log; $rootScope.global = Global; }]); <h2>controllers.js lama.system module</h2> angular.module('lama.system') .controller('SystemController', ['$scope', function($scope) { $scope.test =[]; } ]); <h2>services.js lama.system module</h2> angular.module('lama.system') .factory('Menus', ['$http', function($http) { return { query : function(menus){ return $http.get('/api/v1/user/menus', { params: { 'menus[]': menus } }); } }; }]); <h2>system.js router</h2> //Setting up route angular.module('lama.system') .config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise('/'); $stateProvider .state('home', { url: '/', templateUrl: 'system/views/home.html', controller:'SystemController' }); } ]); <h2>init.js lama module</h2> angular.module('lama', ['ui.router','restangular','lama.system','lama.users']) .run(['$rootScope', 'Menus',function ($rootScope, Menus) { // Default hard coded menu items for main menu var menus = [ { 'permission': null, 'title': 'Home', 'link': 'home' }, { 'permission': 'users', 'title': 'User', 'link': 'user_actions.list' } ]; $rootScope.menus = []; function queryMenu(menus) { Menus.query(menus).then( function (result) { $rootScope.menus = result.data; }, function (reason) { throw new Error(reason); } ); } // Query server for menus and check permissions queryMenu(menus); $rootScope.$on('loggedin', function(event,user) { console.log('kkk'); queryMenu(menus); $rootScope.global = { user: user, authenticated: user.groups.length, isAdmin: user.groups.indexOf('Admins') }; }); }]); <h2>The test</h2> (function() { describe('Unit test: system module', function () { describe('SystemController', function () { // load the controller's module beforeEach(function() { module('lama'); module('stateMock'); }); var SystemController, $rootScope, $scope, $httpBackend; // Initialize the controller and a mock scope beforeEach(inject(function ($controller, _$rootScope_, _$httpBackend_) { $rootScope = _$rootScope_; $scope = _$rootScope_.$new(); $httpBackend = _$httpBackend_; SystemController = $controller('SystemController', { $scope: $scope }); $httpBackend.when('GET', '/api/v1/user/menus').respond(200,{}); })); it('should attach a list of awesomeThings to the scope', function () { expect($scope.test.length).toBe(0); }); it('should expose some global scope', function() { expect($rootScope.global).toBeTruthy(); }); }); }); }()); <h2>that give me :(</h2> grunt test Running "karma:unit" (karma) task INFO [karma]: Karma v0.12.21 server started at http://localhost:9876/ INFO [launcher]: Starting browser PhantomJS WARN [watcher]: Pattern "/home/whisher/public_html/public/users/tests/unit/**/*.js" does not match any file. INFO [PhantomJS 1.9.7 (Linux)]: Connected on socket zK1SplAjTHe4x5sAM9ew with id 16331650 WARN [web-server]: 404: /api/v1/user/menus?menus%5B%5D=%7B%22permission%22:null,%22title%22:%22Home%22,%22link%22:%22home%22%7D&menus%5B%5D=%7B%22permission%22:%22users%22,%22title%22:%22User%22,%22link%22:%22user_actions.list%22%7D WARN [web-server]: 404: /system/views/home.html ERROR: 'Error: [object Object] at http://localhost:9876/base/public/init.js?c7a481724bcf81e4810141349c93d0f698a18904:34 at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:100 at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:100 at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:101 at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:112 at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:109 at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:112 at h (http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:72) at x (http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:77) at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:78' PhantomJS 1.9.7 (Linux): Executed 2 of 2 SUCCESS (0.039 secs / 0.065 secs) Done, without errors.

<strong>NB</strong>

I'm using ui-router

Answer1:

I've taken a look at your source code. The primary offending item is:

angular.element(document).ready(function() { angular.bootstrap(document, ['lama']); });

By including your manual bootstrap in the files that karma imports, your app is un-necessarily being bootstrapped within the karma test environment. So, instead, move your lama module into a separate file, and omit init.js from your files to be included by karma.

There are also a couple of other design concerns that are causing excessive test setup. When testing SystemController there is no need to include anything but the lama.system module (as this is what the controller belongs to). Your test setup for this controller can be as simple as:

var $scope, $rootScope; beforeEach(module('system.lama')); beforeEach(inject(function($controller, _$rootScope_) { $rootScope = _$rootScope_; $scope = $rootScope.$new(); $controller('SystemController', {$scope: $scope}); }));

You will note that in isolating the lama.system module as above, you will get an error that $state cannot be injected (not found). This is because your module definition should instead be:

angular.module('lama.system', ['ui.router'])

(A module should not require the presence of another module for its own dependencies, else it can never function in isolation).

One final observation on your mocking for the lama module run block. Strictly speaking you should stub the service query method entirely and not just part of its implementation, else your test is completely isolated. Therefore, instead, it would be better to do the following:

beforeEach(module(function($provide) { $provide.decorator('Menus', function($delegate, $q) { // overwrite the query method $delegate.query = function() { return $q.when([{id: 1, name: 'Bob'}]); }; return $delegate; }); }));

This way, you don't need to worry about using $httpBackend at all.

Recommend

  • Cannot understand why undefined index
  • Closing a Webview in Android
  • PHP how to 'include' code in the body of a class, outside of a function
  • remove exclamation from routing of state url Mean.io
  • INSERT SELECT SQL from two tables
  • How do I add data to text file and not overwrite what I have in Java
  • Im stuck on java programing [closed]
  • rxjs observable angular 2 on localstorage change
  • SQL SELECT statement from both tables
  • .htaccess password and forced login
  • karma/angularjs how to test run block with service
  • Facebook FBSDKLoginManager/logInWithReadPermissions Swift Example not using Parse
  • React-router, onEnter cause infinite loop with authentication
  • Error: while login and logout using codeigniter [duplicate]
  • How to add initial data to angularjs app from rendered html
  • invisible recaptcha with knockout js
  • Granting permissions to Azure Active Directory Web Application automatically
  • Cloud Code function running twice
  • Trying to get the char code of ENTER key
  • Using Sax parsing to edit and write XML in VB6
  • Thread safety of a fluent like class using clone() and non final fields
  • Debug.DrawLine not showing in the GameView
  • chrome.tabs.executeScript only fires when the Developer Console is open
  • Converting a WriteableBitmap image ToArray in UWP
  • Yii2: Config params vs. const/define
  • Recording logins for password protected directories
  • Splitting given String into two variables - php
  • Check if a string to interpolate provides expected placeholders
  • php design question - will a Helper help here?
  • AngularJs get employee from factory
  • embed rChart in Markdown
  • Turn off referential integrity in Derby? is it possible?
  • IndexOutOfRangeException on multidimensional array despite using GetLength check
  • Authorize attributes not working in MVC 4
  • Add sale price programmatically to product variations
  • Easiest way to encapsulate a HTML5 webpage into an android app?
  • How to get NHibernate ISession to cache entity not retrieved by primary key
  • How can I use `wmic` in a Windows PE script?
  • Unable to use reactive element in my shiny app
  • How do I use LINQ to get all the Items that have a particular SubItem?