I'm trying to write unit tests for my new Angular App and have troubles. Below is my controller.
'use strict';
angular.module('nileLeApp')
.controller('RegisterController', function ($scope, $translate, $timeout, vcRecaptchaService, Auth, Country, Timezone, RecaptchaService) {
$scope.success = null;
$scope.error = null;
$scope.doNotMatch = null;
$scope.errorUserExists = null;
$scope.registerAccount = {};
$timeout(function () {
angular.element('[ng-model="registerAccount.email"]').focus();
});
$scope.loadCountries = function () {
Country.getCountries()
.then(function (result) {
$scope.countries = result.data;
});
};
$scope.loadTimezones = function () {
Timezone.getTimezones()
.then(function (result) {
$scope.timezones = result.data;
});
};
// ============ Recaptcha specific code START ===============
$scope.recaptcha = {};
$scope.recaptcha.recaptchaResponse = null;
$scope.recaptchaWidgetId = null;
$scope.setResponse = function (response) {
$scope.recaptcha.recaptchaResponse = response;
$scope.recaptchaMissing = false;
};
$scope.setWidgetId = function (widgetId) {
$scope.recaptchaWidgetId = widgetId;
};
$scope.cbExpiration = function () {
$scope.recaptcha.recaptchaResponse = null;
};
// ============ Recaptcha specific code END ===============
$scope.createAccount = function () {
Auth.createAccount($scope.registerAccount).then(function (response) {
$scope.success = true;
}).catch(function (response) {
$scope.success = false;
});
}
$scope.register = function () {
$scope.recaptchaMissing = false;
$scope.recaptchaInvalid = false;
if ($scope.recaptcha.recaptchaResponse != null) {
RecaptchaService.verify($scope.recaptcha).$promise
.then(function (response) {
if (response.data) {
$scope.createAccount();
} else {
$scope.recaptchaInvalid = true;
vcRecaptchaService.reload($scope.recaptchaWidgetId); // Reload captcha
}
}).catch(function (response) {
});
} else {
$scope.recaptchaMissing = true;
}
};
$scope.loadCountries();
$scope.loadTimezones();
});
Below is the test I'm trying.
'use strict';
describe('Register Controllers Tests', function () {
describe('RegisterController', function () {
// actual implementations
var $scope;
var $q;
// mocks
var MockTimeout;
var MockTranslate;
var MockAuth;
var MockCountry;
var MockTimezone;
// local utility function
var createController;
beforeEach(inject(function ($injector) {
$q = $injector.get('$q');
$scope = $injector.get('$rootScope').$new();
MockTimeout = jasmine.createSpy('MockTimeout');
MockAuth = jasmine.createSpyObj('MockAuth', ['createAccount']);
MockCountry = jasmine.createSpyObj('MockCountry', ['getCountries']);
MockTimezone = jasmine.createSpyObj('MockTimezone', ['getTimezones']);
MockTranslate = jasmine.createSpyObj('MockTranslate', ['use']);
var locals = {
'$scope': $scope,
'$translate': MockTranslate,
'$timeout': MockTimeout,
'Auth': MockAuth,
'Country': MockCountry,
'Timezone': MockTimezone
};
createController = function () {
$injector.get('$controller')('RegisterController', locals);
};
}));
it('should load countries on page load', function () {
var mockCountryResponse = [{
'countryId': 1,
'alpha2Code': "AF",
'countryName': "Afghanistan"
}];
MockCountry.getCountries.and.returnValue($q.resolve(mockCountryResponse));
MockTimezone.getTimezones.and.returnValue($q.resolve());
MockAuth.createAccount.and.returnValue($q.resolve());
// given
createController();
$scope.$apply($scope.loadCountries);
expect($scope.countries).toEqual(mockCountryResponse);
});
});
The above expectation doesn't work because $scope.countries is undefined. Following is the error message.
TypeError: 'undefined' is not an object (evaluating 'result.data')
Also, I see the test getting called twice for some strange reason. Below is my Karma configuration file.
// Karma configuration
// http://karma-runner.github.io/0.10/config/configuration-file.html
module.exports = function (config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '../../',
// testing framework to use (jasmine/mocha/qunit/...)
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
// bower:js
'main/webapp/bower_components/es5-shim/es5-shim.js',
'main/webapp/bower_components/jquery/dist/jquery.js',
'main/webapp/bower_components/angular/angular.js',
'main/webapp/bower_components/angular-animate/angular-animate.js',
'main/webapp/bower_components/angular-aria/angular-aria.js',
'main/webapp/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
'main/webapp/bower_components/bootstrap/dist/js/bootstrap.js',
'main/webapp/bower_components/angular-bootstrap-nav-tree/dist/abn_tree_directive.js',
'main/webapp/bower_components/angular-file-upload/angular-file-upload.js',
'main/webapp/bower_components/angular-messages/angular-messages.js',
'main/webapp/bower_components/skycons/skycons.js',
'main/webapp/bower_components/angular-skycons/angular-skycons.js',
'main/webapp/bower_components/angular-smart-table/dist/smart-table.min.js',
'main/webapp/bower_components/angular-touch/angular-touch.js',
'main/webapp/bower_components/angular-cache-buster/angular-cache-buster.js',
'main/webapp/bower_components/angular-cookies/angular-cookies.js',
'main/webapp/bower_components/angular-dynamic-locale/src/tmhDynamicLocale.js',
'main/webapp/bower_components/angular-local-storage/dist/angular-local-storage.js',
'main/webapp/bower_components/angular-loading-bar/build/loading-bar.js',
'main/webapp/bower_components/angular-resource/angular-resource.js',
'main/webapp/bower_components/angular-sanitize/angular-sanitize.js',
'main/webapp/bower_components/angular-translate/angular-translate.js',
'main/webapp/bower_components/messageformat/messageformat.js',
'main/webapp/bower_components/angular-translate-interpolation-messageformat/angular-translate-interpolation-messageformat.js',
'main/webapp/bower_components/angular-translate-loader-partial/angular-translate-loader-partial.js',
'main/webapp/bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js',
'main/webapp/bower_components/angular-translate-storage-cookie/angular-translate-storage-cookie.js',
'main/webapp/bower_components/angular-translate-storage-local/angular-translate-storage-local.js',
'main/webapp/bower_components/angular-ui-router/release/angular-ui-router.js',
'main/webapp/bower_components/moment/moment.js',
'main/webapp/bower_components/fullcalendar/dist/fullcalendar.js',
'main/webapp/bower_components/angular-ui-calendar/src/calendar.js',
'main/webapp/bower_components/angular-ui-grid/ui-grid.js',
'main/webapp/bower_components/angular-ui-select/dist/select.js',
'main/webapp/bower_components/angular-ui-utils/ui-utils.js',
'main/webapp/bower_components/angular-xeditable/dist/js/xeditable.js',
'main/webapp/bower_components/angularjs-toaster/toaster.js',
'main/webapp/bower_components/angular-strap/dist/angular-strap.js',
'main/webapp/bower_components/angular-strap/dist/angular-strap.tpl.js',
'main/webapp/bower_components/angular-recaptcha/release/angular-recaptcha.js',
'main/webapp/bower_components/bootstrap-daterangepicker/daterangepicker.js',
'main/webapp/bower_components/bootstrap-filestyle/src/bootstrap-filestyle.js',
'main/webapp/bower_components/bootstrap-slider/bootstrap-slider.js',
'main/webapp/bower_components/bootstrap-tagsinput/dist/bootstrap-tagsinput.js',
'main/webapp/bower_components/bootstrap-wysiwyg/bootstrap-wysiwyg.js',
'main/webapp/bower_components/bower-jvectormap/jquery-jvectormap-1.2.2.min.js',
'main/webapp/bower_components/datatables/media/js/jquery.dataTables.js',
'main/webapp/bower_components/flot/jquery.flot.js',
'main/webapp/bower_components/flot-spline/js/jquery.flot.spline.js',
'main/webapp/bower_components/flot.tooltip/js/jquery.flot.tooltip.js',
'main/webapp/bower_components/footable/js/footable.js',
'main/webapp/bower_components/html5sortable/jquery.sortable.js',
'main/webapp/bower_components/json3/lib/json3.js',
'main/webapp/bower_components/ng-grid/build/ng-grid.js',
'main/webapp/bower_components/intl-tel-input/build/js/intlTelInput.min.js',
'main/webapp/bower_components/intl-tel-input/lib/libphonenumber/build/utils.js',
'main/webapp/bower_components/ng-intl-tel-input/dist/ng-intl-tel-input.js',
'main/webapp/bower_components/ngImgCrop/compile/minified/ng-img-crop.js',
'main/webapp/bower_components/ngstorage/ngStorage.js',
'main/webapp/bower_components/ng-file-upload/ng-file-upload.js',
'main/webapp/bower_components/ngInfiniteScroll/build/ng-infinite-scroll.js',
'main/webapp/bower_components/oclazyload/dist/ocLazyLoad.min.js',
'main/webapp/bower_components/screenfull/dist/screenfull.js',
'main/webapp/bower_components/slimscroll/jquery.slimscroll.min.js',
'main/webapp/bower_components/textAngular/dist/textAngular.min.js',
'main/webapp/bower_components/venturocket-angular-slider/build/angular-slider.js',
'main/webapp/bower_components/videogular/videogular.js',
'main/webapp/bower_components/videogular-buffering/buffering.js',
'main/webapp/bower_components/videogular-controls/controls.js',
'main/webapp/bower_components/videogular-ima-ads/ima-ads.js',
'main/webapp/bower_components/videogular-overlay-play/overlay-play.js',
'main/webapp/bower_components/videogular-poster/poster.js',
'main/webapp/bower_components/waves/dist/waves.min.js',
'main/webapp/bower_components/angular-mocks/angular-mocks.js',
// endbower
'main/webapp/scripts/app/app.js',
'main/webapp/scripts/app/**/*.+(js|html)',
'main/webapp/scripts/components/**/*.+(js|html)',
'test/javascript/spec/helpers/module.js',
'test/javascript/spec/helpers/httpBackend.js',
'test/javascript/**/!(karma.conf|protractor.conf).js'
],
// list of files / patterns to exclude
exclude: ['test/javascript/e2e/**'],
preprocessors: {
'./main/webapp/scripts/**/*.js': ['coverage'],
'**/*.html': ['ng-html2js']
},
reporters: ['dots', 'jenkins', 'coverage', 'progress'],
jenkinsReporter: {
outputFile: '../build/test-results/karma/TESTS-results.xml'
},
coverageReporter: {
dir: '../build/test-results/coverage',
reporters: [
{type: 'lcov', subdir: 'report-lcov'}
]
},
// web server port
port: 9876,
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: true,
// to avoid DISCONNECTED messages when connecting to slow virtual machines
browserDisconnectTimeout : 10000, // default 2000
browserDisconnectTolerance : 1, // default 0
browserNoActivityTimeout : 4*60*1000 //default 10000
});
};
I'm stuck on writing unit test for last couple days as I find them quite confusing and not simple like in Java. Will appreciate any help.
The above expectation doesn't work because $scope.countries is undefined
^^ That's not true. It's not that $scope.countries is undefined, it's that result is undefined, and it's not the result you're trying to assign to $scope.countries, it's the one relating to $scope.timezones
I think this is your problem here:
MockTimezone.getTimezones.and.returnValue($q.resolve());
You're implicitly passing undefined into that resolve() function, and THAT'S throwing an error when you instantiate your controller.
It's throwing that error because you've got this line at the end of your controller:
$scope.loadTimezones();
It's for this reason that I stopped initializing controllers within themselves. Now I do it using ng-init, initiated from the HTML. If you make the same change as I did you won't encounter issues like this again in the future.
Related
I was trying out jasmine with karma. I have a custom service
ApiService which i need to inject in my spec file. But when am trying
to inject the ApiService i get Error: [$injector:unpr] Unknown
provider: ApiService <- ApiService
this is my controller
'use strict';
angular.module('assessmentApp')
.controller('NewUserController', NewUserController)
.run(["$rootScope", "$anchorScroll", function($rootScope, $anchorScroll) {
$rootScope.$on("$locationChangeSuccess", function() {
$anchorScroll();
});
}]);
NewUserController.$inject = ['$scope', '$rootScope', '$location', '$timeout', 'ApiService'];
function NewUserController($scope, $rootScope, $location, $timeout, ApiService) {
//console.log("innn NewUserController2 ::::")
var vm = this;
var boardsClassSubjectCombinations = [];
var studentId = $rootScope.globals.studentId;
var assessmentCampaignId = $scope.assessmentCampaignId = $rootScope.globals.assessmentCampaignId;
vm.currentQuestion = 1;
//sanity check if the user already has academics added
ApiService.getAll('students/' + studentId + '/latest-student-academic', true, ['students/{{id}}/academic'])
.then(function(res) {
if (res.data) {
//send this guy to home page
$location.url('/home');
}
});
function getStates() {
ApiService.getAll('states', true).then(function(response) {
$scope.states = response.data;
});
}
getStates();
}
this is my test file
describe('NewUserController Test', function() {
beforeEach(module('assessmentApp'));
// beforeEach(module('assets'));
//beforeEach(module('ApiService'))
var scope, location, timeout,apiService, q, authenticationService;
beforeEach(inject(function($location,$rootScope,$timeout, ApiService){
scope = $rootScope.$new();
location = $location;
timeout = $timeout;
q = _$q_;
console.log(ApiService)
//spyOn(ApiService, 'ApiService');
//spyOn(Point, 'method');
// console.log("ApiService :::"+ApiService)
//$controller = _$controller_('NewUserController', { $scope: $scope });
//console.log("NewUserController======="+$controller)
}));
describe('$scope.grade', function() {
it('sets the strength to "strong" if the password length is >8 chars', function() {
console.log("$location ::::"+location)
console.log("scope ::::"+scope)
console.log("timeout ::::"+timeout)
console.log("ApiService ::::"+ApiSrvce)
console.log("q ::::"+q)
//console.lopg("authenticationService :::"+authenticationService)
//console.log("$scope ::::::"+$scope)
expect(true).toEqual(true);
});
});
});
This is my karma.conf.js file
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
//'test-main.js',
'../bower_components/jquery/dist/jquery.js',
'../bower_components/angular/angular.js',
'../bower_components/bootstrap/dist/js/bootstrap.js',
'../bower_components/angular-route/angular-route.js',
'../bower_components/particles.js/particles.js',
'../bower_components/angular-cookies/angular-cookies.js',
'../bower_components/toastr/toastr.js',
'../bower_components/angular-sanitize/angular-sanitize.js',
'../bower_components/d3/d3.js',
'../bower_components/c3/c3.js',
'../bower_components/moment/moment.js',
'../bower_components/humanize-duration/humanize-duration.js',
'../bower_components/angular-timer/dist/angular-timer.js',
'../bower_components/underscore/underscore.js',
'../bower_components/scrollreveal/dist/scrollreveal.js',
'../bower_components/lodash/lodash.js',
'../bower_components/angular-youtube-mb/src/angular-youtube-embed.js',
'../bower_components/angular-mocks/angular-mocks.js',
//'../assets/**/*.js',
//'../assets/**/*.html',
//'../bower_components/angular/angular.js',
//'../bower_components/angular-mocks/angular-mocks.js',
'../app/scripts/app.js',
'../app/scripts/controllers/**/*.js',
'../app/scripts/directives/**/*.js',
'../app/scripts/services/**/*.js',
'../app/scripts/**/*.js',
'../../assets/src/assets/services/*.js',
'spec/**/*.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}
What i see is, when i try to inject any custom service it skips the beforeEach function and the logs i get in it function is
LOG: '$location ::::undefined'
LOG: 'scope ::::undefined'
LOG: 'timeout ::::undefined'
LOG: 'ApiService ::::undefined'
So I would suggest this kind of structure:
angular.mock.module(function($provide) {
apiService = jasmine.createSpy('apiService', ['getAll']);
$provide.value('apiService', apiService);
// Mock out other services here in the same fashion;
});
inject(function(_$controller_, _$rootScope_) {
$controller =
_$controller_('NewUserController', { $scope: _$rootScope_.$new() });
});
Then in your tests, you would refer to the apiService like this. Ideally you would make an it() statement for each bit you want to test, like say, the return value of getState(), but we'll do it all in one here:
it ('calls getState()', function () {
// Mock out what the apiService will do; you only care what comes back
// so you can see what $scope.states looks like in the end;
apiService.getAll.and.returnValue({ Promise.resolve({ foo: 1 }) });
// Spy on the controller's own getState method;
spyOn($controller, 'getState').and.callFake(() => true);
// Store the return value of the getState call;
expect($controller.getState).toHaveBeenCalled();
// Overall the calls count for getAll on the apiService should be two;
expect(apiService.getAll.calls.count()).toEqual(2);
// getState() will have been called, and should return the object;
expect($controller.states).toEqual({ foo: 1 });
});
happy holidays!, I'm facing an issue that I don't know why it's giving me:
//LoginCtrl:
angular.module('login.controller', [])
.controller('LoginCtrl', function($scope, $state, $translate, $ionicPopup, UserService, Auth) {
// With the new view caching in Ionic, Controllers are only called
// when they are recreated or on app start, instead of every page change.
// To listen for when this page is active (for example, to refresh data),
// listen for the $ionicView.enter event:
//$scope.$on('$ionicView.enter', function(e) {
//});
// Form data for the login modal
$scope.loginData = {};
// Perform the login action when the user submits the login form
$scope.doLogin = function() {
var onSuccess = function(response) {
if (response.data.user !== null) {
Auth.setUser(response.data.user);
Auth.setToken(response.data.user.token);
$state.go('app.main');
} else if (response.data.result == 101) {
$ionicPopup.alert({
title: $translate.instant('login_error'),
template: $translate.instant('login_not_verified')
});
}else {
$ionicPopup.alert({
title: $translate.instant('login_error'),
template: $translate.instant('login_bad_password_text')
});
}
};
var onError = function() {
$ionicPopup.alert({
title: $translate.instant('login_error'),
template: $translate.instant('login_error_text')
});
};
console.log('Doing login', $scope.loginData);
UserService.login($scope.loginData.username, $scope.loginData.password).then(onSuccess, onError);
};
$scope.doRegister = function() {
$state.go("register");
};
});
// Login Ctrl Test
describe('LoginCtrl', function() {
var controller,
deferredLogin,
userServiceMock,
stateMock,
scopeMock,
ionicPopupMock;
//Load the App module
beforeEach(module('starter'));
// Instantiate the Controller and Mocks
beforeEach(inject(function($controller, $q, $rootScope, $translate, Auth) {
deferredLogin = $q.defer();
scopeMock = $rootScope.$new();
// mock userServiceMock
userServiceMock = {
login: jasmine.createSpy('login spy')
.and.returnValue(deferredLogin.promise)
};
//mock $state
stateMock = jasmine.createSpyObj('$state spy', ['go']);
//mock $ionicPopup
ionicPopupMock = jasmine.createSpyObj('$ionicPopup spy', ['alert']);
//Instantiate LoginCtrl
controller = $controller('LoginCtrl', {
'$scope' : scopeMock,
'$state' : stateMock,
'$translate' : $translate,
'$ionicPopup' : ionicPopupMock,
'UserService' : userServiceMock,
'Auth' : Auth
});
}));
describe('#doLogin', function() {
// Call doLogin on the Controllers
beforeEach(inject(function(_$rootScope_) {
$rootScope = _$rootScope_;
controller.$scope.loginData.username = 'test';
controller.$scope.loginData.password = 'password';
controller.$scope.doLogin();
}));
it('should call login on userService', function() {
expect(userServiceMock.login).toHaveBeenCalledWith('test','password');
});
describe('when the login is executed,', function() {
it('if successful, should change state to app.main', function() {
//TODO: Mock the login response from userService
expect(stateMock.go).toHaveBeenCalledWith('app.main');
});
it('if unsuccessful, should show popup', function() {
//TODO: Mock the login response from userService
expect(ionicPopup.alert).toHaveBeenCalled();
});
});
});
});
The problem is that when I execute the test when it executes expect(userServiceMock.login).toHaveBeenCalledWith('test','password'); it gives me the following error:
TypeError: undefined is not an object (evaluating 'userServiceMock.login') in unit-tests/login.controller.tests.js (line 56)
I don't know userServiceMock gives me undefined.
Thank you all, if you need more code or something say me please.
This is my karma conf:
// Karma configuration
// Generated on Mon Dec 26 2016 10:38:06 GMT+0100 (CET)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'../www/lib/ionic/js/ionic.bundle.js',
'../www/js/**/*.js',
'../www/lib/angular-mocks/angular-mocks.js',
'../www/lib/angular-translate/angular-translate.js',
'../www/lib/angular-translate-loader-static-files/angular-translate-loader-static-files.js',
'unit-tests/**/*.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
});
};
The problem was that I was not including translate libs on test.conf, and then that i was not taking the variables from the controller.
I would like to test my angular service I would like to test it with real data - a.k.a (Integration Test). I'm using Jasmine and Karma.
Here is my test:
describe('Trending Data Service', function () {
var value = 0, originalTimeout = 0;
var service, Enums, $httpBackend;
// initialize module
beforeEach(module('waterfall'));
// initialize services
beforeEach(inject(function ($injector) {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
$httpBackend = $injector.get('$httpBackend');
service = $injector.get("trendingService");
Enums = $injector.get("Enums");
spyOn(service, 'fetch').and.callThrough();
}));
it('check if dependencies are defined', function () {
expect(service).toBeDefined();
expect(Enums).toBeDefined();
expect(service.categories).toBeDefined();
expect(service.fetch).toBeDefined();
});
it('categories array should be defined within the service', function () {
expect(service.categories.length).toEqual(9);
expect(service.categories).toEqual(jasmine.any(Array));
});
// this test is alway fails...
it('fetch method should return initial result', function (done) {
var promise = service.fetch(Enums.socials.viewAll, false);
promise.then(function (result) {
done();
}, function() {
expect(1).toBe(2);
done.fail('Error occured');
});
});
}
This is the error:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
I tried a wide range of solutions and I haven't got any success with this.
EDIT: 29/April/2016
var trendingService = function ($q, $http) {
var deferred = $q.defer();
var $this = this;
this.fetch = function (id) {
$http.get(url).then(function (result) {
deferred.resolve(result);
}).catch(function(err) {
deferred.reject(err);
});
return deferred.promise;
}
return {
fetch: $this.fetch;
};
};
var Enums = {
Roles: {
Admin: 1,
User: 2,
NotRegistered: 0
}
};
angular.module('').const('Enums', Enums);
Karma isn't meant for integration testing. Your call to module('waterfall') is actually a reference to angular.mock.module which mocks all $https calls.
You need to use some form of end-to-end testing to test with real data. I suggest http://angular.github.io/protractor/#/.
I'm creating an Ionic application and I would like test it using Karma, however I'm getting this error when I run Karma:
Error: [ng:areq] Argument 'SelecaoLocalizacaoController' is not a function, got undefined
I've checked if the controller file was added in karma conf, but it is:
module.exports = function (config) {
config.set({
basePath: '../',
frameworks: ['jasmine'],
files: [
'www/lib/ionic/js/ionic.bundle.js',
'www/lib/ngCordova/dist/ng-cordova-mocks.js',
'www/lib/angular-mocks/angular-mocks.js',
'www/js/app.js',
'www/js/app/**/*.js',
'www/js/components/**/*.{js,html}',
'test/**/!(karma.conf).js'
],
exclude: [],
preprocessors: {},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: false,
browsers: ['PhantomJS'],
singleRun: false,
browserDisconnectTimeout: 10000, // default 2000
browserDisconnectTolerance: 1, // default 0
browserNoActivityTimeout: 4 * 60 * 1000 //default 10000
})
};
This is the spec I'm trying run:
'use strict';
describe('Controller Tests', function () {
var $scope, $rootScope, LocalizacaoService, EstadosComEstabelecimentos;
var estadosRetornados = [{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}];
var createController;
describe('SelecaoLocalizacaoController aff', function () {
beforeEach(inject(function ($injector) {
$rootScope = $injector.get('$rootScope');
$scope = $rootScope.$new();
LocalizacaoService = {
getCidadeAtual: function (success, error) {
success({
idEstado: 56,
idCidade: 651
});
}
};
EstadosComEstabelecimentos = {
get: function () {
return {
then: function (callback) {
return callback({
data: estadosRetornados
});
}
}
}
};
var ionicModal = {
fromTemplateUrl: function () {
return {
then: function () {
}
};
}
};
var locals = {
'$scope': $scope,
'$rootScope': $rootScope,
'$ionicModal': ionicModal,
'LocalizacaoService': LocalizacaoService,
'EstadosComEstabelecimentos': EstadosComEstabelecimentos
};
createController = function () {
$injector.get('$controller')("SelecaoLocalizacaoController", locals);
};
createController();
}));
describe('inicialização', function () {
it('deve carregar todos os estados com estabelecimentos ativos cadastrados', function () {
expect($scope.estados).not.toBe(undefined);
expect($scope.estados.length).toBe(5);
expect($scope.estados[0]).toEqual({id: 1});
expect($scope.estados[1]).toEqual({id: 2});
expect($scope.estados[2]).toEqual({id: 3});
expect($scope.estados[3]).toEqual({id: 4});
expect($scope.estados[4]).toEqual({id: 5});
});
it('deve selecionar estado e cidade a partir das coordenadas do GPS', function () {
expect($scope.posicao.idEstado).toBe(56);
expect($scope.posicao.idCidade).toBe(651);
expect($scope.exibirMensagemNaoEncontrado).toBeFalsy();
});
});
});
});
Finally, this is the controller I'm testing:
'use strict';
angular.module('cervejeirosApp')
.controller('SelecaoLocalizacaoController', function ($scope, $ionicModal, EstadosComEstabelecimentos, LocalizacaoService) {
$scope.loadAll = function () {
EstadosComEstabelecimentos.get()
.then(function (result) {
$scope.estados = result.data;
});
LocalizacaoService.getCidadeAtual(function (result) {
if (angular.isDefined(result) && result != null)
$scope.posicao = result;
else {
$scope.posicao = {idEstado: null, idCidade: null};
$scope.exibirMensagemNaoEncontrado = true;
}
});
$ionicModal.fromTemplateUrl('js/app/localizacao/modal-selecao-estado.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modalEstado = modal;
});
};
$scope.selecionarEstado=function(){
$scope.modalEstado.show();
};
$scope.selecionouEstado=function(estado){
$scope.posicao.idEstado=estado.id;
$scope.modalEstado.hide();
};
$scope.loadAll();
});
it's the first time that i use angular application using generator and units tests with karma.
i wanna create some angularjs unit test for my app based on bower, gulp, karma...
this is my controller :
(function() {
'use strict';
angular.module('order', ['common'])
.controller('OrderVehiculesController', function (drivers,Logger) {
var self = this;
this.orderForm = {
id: '',
txt: ''
};
this.msgCtrlError = {
id: ''
};
var logger = Logger.getInstance('OrderVehiculesController');
logger.log(self);
this.getOrder = function (name) {
// A modifier car il serait plus judicieux d'avoir un model d'object et de pouvoir les réinitialiser avec une function
self.msgCtrlError.id = '';
self.msgCtrlError.txt = '';
drivers
.getOrder(name)
.then(function (orderData) {
self.orderData = orderData;
logger.log('orderData='+orderData);
logger.log('orderData name='+orderData.name);
})
.catch(function (err) {
logger.error('status=' + err.status + ' error=' + err.error);
self.msgCtrlError.id = err.status;
self.msgCtrlError.txt = err.error;
});
};
});
})();
and the [common] is like that :
(function() {
'use strict';
angular.module('common', [
'common.drivers-service',
'common.ads-auth-service',
'common.liferay-service',
'common.locale-service',
'common.logging-service'
]);
})();
and I tried to test it like that:
'use strict';
describe('orderModule', function () {
// Set up the module
beforeEach(module('common'));
beforeEach(module('order'));
var scope;
//test controller order
describe('OrderVehiculesController', function () {
var controller;
beforeEach(inject(function ($controller, $rootScope,common) {
scope = $rootScope.$new();
//TODO: how to call common mudule???
//instantiation of controller with its modules
controller = $controller('OrderVehiculesController', {
$scope: scope,
});
}));
it('should be defined', function() {
expect(OrderVehiculesController).toBeDefined();
});
});
});
but finaly, i've this error and i didn't understand it, i need some help please.
thank you.
ERROR is:
> WARN [watcher]: Pattern "C:\Users\src\**\*.mock.js" does not match any file.
> INFO [PhantomJS 1.9.8 (Windows 7)]: Connected on socket 4vwNDK9jjnvHoFW7eeL- with id 39484477
PhantomJS 1.9.8 (Windows 7) orderModule OrderVehiculesController should be defined FAILED
Error: [$injector:unpr] Unknown provider: commonProvider <- common
http://errors.angularjs.org/1.3.15/$injector/unpr?
and my karma config is the default karma.confg.js :
'use strict';
module.exports = function(config) {
var configuration = {
autoWatch : false,
frameworks: ['jasmine'],
ngHtml2JsPreprocessor: {
stripPrefix: 'src/',
moduleName: 'gulpAngular'
},
browsers : ['PhantomJS'],
plugins : [
'karma-phantomjs-launcher',
'karma-jasmine',
'karma-ng-html2js-preprocessor'
],
preprocessors: {
'src/**/*.html': ['ng-html2js']
}
};
// This block is needed to execute Chrome on Travis
// If you ever plan to use Chrome and Travis, you can keep it
// If not, you can safely remove it
// https://github.com/karma-runner/karma/issues/1144#issuecomment-53633076
if(configuration.browsers[0] === 'Chrome' && process.env.TRAVIS) {
configuration.customLaunchers = {
'chrome-travis-ci': {
base: 'Chrome',
flags: ['--no-sandbox']
}
};
configuration.browsers = ['chrome-travis-ci'];
}
config.set(configuration);
};