Related
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 have a service that depends on another service from a different module like so:
(function() {
'use strict';
angular
.module('app.core')
.factory('userService', userService);
function authService() {
return: {
userLoggedIn: false
}
}
})();
(function() {
'use strict';
angular
.module('app.services')
.factory('AuthService', authService);
authService.$inject = ['$http', 'userService'];
function authService($http, userService) {
}
I'm trying write tests for my authService but am getting injection errors since it can't find userService
beforeEach(function() {
module('app.services');
});
beforeEach(inject(function(_AuthService_) {
authService = _AuthService_;
}));
How can I overcome this, will using $provide help me here?
UPDATE
I have attempted the following, but still getting the error
beforeEach(function() {
module('app.services');
});
beforeEach(inject(function(_AuthService_, _$provide_) {
authService = _AuthService_;
$provide = _$provide_;
}));
beforeEach(function() {
module(function ($provide) {
$provide.value('userService', function(){
return {
userLoggedIn: false
}
});
});
});
SOLVED
Ok, so I just needed to do the following:
beforeEach(function() {
module('app.dataservices');
module(function ($provide) {
$provide.value('userService', function(){
return {
userLoggedIn: false
}
});
});
});
beforeEach(inject(function(_AuthService_) {
authService = _AuthService_;
}));
Tests are now passing fine for me
Let's say you service uses the $state service and you want to mock id. Specifically the get method. Then you just need to add inside the first describe something like this.
beforeEach(function () {
module(function ($provide) {
$provide.service('$state', function() {
return {
get: function() {}
}
});
});
});
In this gist you can find some interesting examples of mocking services using $provide.
you should be preloading all services in your karma.conf.js (i assume you are using karma).
here is our karma.conf.js file ...
/**
* Karma test runner configuration
*/
'use strict';
module.exports = function (config) {
config.set({
basePath: './',
browsers: ['PhantomJS'],
frameworks: ['jasmine'],
reporters: ['mocha', 'coverage'],
singleRun: true,
preprocessors: {
'src/**/!(*spec)*.js': ['coverage'],
'dest/**/*.html': ['ng-html2js']
},
ngHtml2JsPreprocessor: {
stripPrefix: 'dest/',
moduleName: 'ngHtmlFiles'
},
coverageReporter: {
type: 'html',
dir: 'coverage'
},
files: [
'dest/vendor.min.js',
'bower_components/angular-mocks/angular-mocks.js',
'src/**/*.js',
'dest/**/*.html'
]
});
};
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.
I am trying to create a basic test to verify that I can create a controller or service.
My app is is the following directory
app/js/app.js
My controllers are in the following directory
app/js/controllers/
Here is my karma.conf.js file
files: [
'Scripts/jquery-2.1.1.min.js',
'Scripts/require.js',
'Scripts/angular.js',
'Scripts/angular-mocks.js',
{ pattern: 'app/js/*.js', included: false },
{ pattern: 'app/js/**/*.js', included: false },
{ pattern: 'app/js/**/**/*.js', included: false },
{ pattern: 'app/js/**/**/**/*.js', included: false },
{ pattern: 'test/specs/**/*.js', included: false },
'test/test-main.js',
],
// list of files to exclude
exclude: [
'app/js/main.js'
],
test-main.js
var testFiles = [];
for (var file in window.__karma__.files) {
console.log(file);
if (/Spec\.js$/.test(file)) {
testFiles.push(file);
}
}
requirejs.config({
paths: {
// External libraries
'jquery': '../../Scripts/jquery-2.1.1.min',
'angular': '../../Scripts/angular',
'angular-mocks': '../../Scripts/angular-mocks',
'ngRoute': '../../Scripts/angular-route.min',
'angular-animate': '../../Scripts/angular-animate.min',
'angular-cookies': '../../Scripts/angular-cookies.min',
},
baseUrl: '/base/app/js',
shim: {
'angular': {
exports: 'angular',
deps: ['jquery']
},
'angular-mocks': { exports: 'angular-mocks', deps: ['angular'] },
'angular-animate': { exports: 'angular-animate', deps: ['angular'] },
'ngRoute': { exports: 'ngRoute', deps: ['angular'] },
'angular-cookies': { exports: 'angular-cookies', deps: ['angular'] },
},
// dynamically load all test files
deps: testFiles,
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
});
I added this line...
console.log(file)
To make sure the file was loaded into
window.__karma__.files
and it is.
The test lives in test/specs/
define(['angular', 'angular-mocks'], (angular, ngMock: ng.IMockStatic) => {
var module = ngMock.module;
var inject: (...fns: Function[]) => any = ngMock.inject;
describe("Create an Application", function () {
var scope, q, routeParams;
var location;
var app;
beforeEach(function () {
app = angular.module('App', []);
inject(function ($rootScope, $q: ng.IQService, $location: ng.ILocationService) {
scope = $rootScope;
q = $q;
routeParams = {};
location = $location;
});
});
it('Test Application Created', function () {
expect(true).toBe(true);
});
});
});
My app file looks like this....
import angular = require('angular');
import angularRoute = require('angular-route');
import angularAnimate = require('angular-animate');
import ds = require('services/DataService');
var app = angular.module('app', [
'ngRoute',
'ngAnimate',
'ngCookies',
'kendo.directives',
'breeze.angular',
'ui.bootstrap'
]);
export = app;
the error that i get when I try to run the test is
failed to instantiate module app due to: Module 'app' is not available! You either misspelled the module name or forgot to load it.
I am assuming it is not loading but not sure how I can tell. Is this the best way to accomplish my testing?
Any help is greatly appreciated!
Thanks so much!
If you are using Karma with Jasmine, you may be having the problem of Jasmine being too eager.
This can be fixed by making two changes, originally described in an article I wrote when I was doing a similar thing, Combining TypeScript, Jasmine and RequireJS.
In boot.js you need to comment out the env.execute(); method call:
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
htmlReporter.initialize();
//env.execute();
};
This is because the window.onload event can happen before require.js has loaded everything.
Once you have loaded the modules you need, you can then call:
// Hai Jasmine - ready to go!
jasmine.getEnv().execute();
This is what it gets compiled with your code and the -m amd switch
describe("Create an Application", function () {
var scope, q, routeParams;
var controller, location;
var route;
beforeEach(function () {
module('app', ['ngRoute', 'ngAnimate', 'ngCookies', 'kendo.directives', 'breeze.angular', 'ui.bootstrap']);
inject(function ($rootScope, $q, $location) {
scope = $rootScope;
q = $q;
routeParams = {};
location = $location;
});
// controller = new controller.ApplicationService(q, scope, route, location, _datasvc, _searchsvc);
});
it('Test Application Created', function () {
expect(true).toBe(true);
});
});
is not a module, and its synchronous
But. in a module works
define(['angular','angular-mocks'],(angular,ngMock:ng.IMockStatic)=>{
var module = ngMock.module;
var inject: (...fns: Function[])=>any = ngMock.inject;
describe("Create an Application", function () {
var scope, q, routeParams;
var location;
var app;
beforeEach(function () {
app = angular.module('App', []);
inject(function ($rootScope, $q: ng.IQService, $location: ng.ILocationService) {
scope = $rootScope;
q = $q;
routeParams = {};
location = $location;
});
});
it('Test Application Created', function () {
expect(true).toBe(true);
});
});
});
Or alternatively in a more TypeScripty w/ES6esque way :
import ngMock = require('angular-mocks');
import angular = require('angular');
var module = ngMock.module;
var inject: (...fns: Function[])=>any = ngMock.inject;
describe("Create an Application", function () {
var scope, q, routeParams;
var location;
beforeEach(function () {
var app = angular.module('app', []);
inject(function ($rootScope, $q: ng.IQService, $location: ng.ILocationService) {
scope = $rootScope;
q = $q;
routeParams = {};
location = $location;
});
});
it('Test Application Created', function () {
expect(true).toBe(true);
});
});
check that you are loading angular as in a script tag
'files:[Scripts/angular.js',... ,
that's why you get
WARNING:tried load angular more than once
Put it in a { pattern: 'Scripts/angular.js', included: false ...],
you need to work out the requirejs.confg until the deps chain are satisfied. in order., and thats one of the reasons why you set the shim config with
'angular-mocks': { exports: 'angular-mocks', deps: ['angular'] },
so when requiring angular-mocks angular is required too ,
have a look at [this github repo](https://github.com/tnajdek/angular-requirejs-
seed),
...And once you have an instance attached to angular.module /mock.module in your spec , check Steve's answer again ,
If you can't find boot.js , you might be using jasmine bundled with the Karma adapter. in that case it should work given you have sorted out the require test-maiin.js / config / "NG_DEFER_BOOTSTRAP!" /resumeBootstrap story
I can't make it work! I just looked all over the Internet, and I tried other solutions, but I can't make it work.
I got a filter, and I want to test with Karma and Jasmine. Here is my code:
app.js:
var services = angular.module('myApp.services', [ 'ngResource' ]);
angular.module('myApp', [
'ngRoute',
'myApp.filters',
'myApp.services',
'myApp.directives',
'myApp.controllers'
]).
filters.js
'use strict';
/* Filters */
angular.module('myApp.filters', [])
.filter(
'lowerAndCapital',
[ function() {
return function(text) {
if (text != undefined) {
var str = text.toLowerCase();
var arreglo = str.split(" ");
var result = "";
for (var i = 0; i < arreglo.length; i++) {
result += " "
+ arreglo[i].charAt(0).toUpperCase()
+ arreglo[i]
.substring(1, arreglo[i].length + 1);
}
return result;
}
}
}]);
filterSpecs.js
'use strict';
/* Jasmine specification for filters go here */
describe('filter', function() {
beforeEach(function () {
module('myApp.filters');
});
describe('lowerAndCapital', function() {
it('deberia de convertir le texto a minuscula y con letra capital',
inject(function(lowerAndCapital) {
expect(lowerAndCapital("john")).toEqual(
"John");
}));
});
});
karma.config.js
module.exports = function(config){
config.set({
basePath : '../',
files : [
'main/webapp/resources/scripts/angular/angular.js',
'main/webapp/resources/scripts/angular/angular-route.js',
'main/webapp/resources/scripts/angular/angular-mocks.js',
'main/webapp/resources/js/*.js',
'test/unit/*.js'
],
autoWatch : true,
frameworks: ['jasmine'],
browsers : ['Chrome'],
plugins : [
'karma-chrome-launcher',
'karma-firefox-launcher',
'karma-jasmine',
'karma-junit-reporter'
],
junitReporter : {
outputFile: 'test_out/unit.xml',
suite: 'unit'
}
});
};
And here is the error:
Chrome 36.0.1985 (Windows 7) filter lowerAndCapital deberia de convertir le text
o a minuscula y con letra capital FAILED
Error: [$injector:unpr] Unknown provider: lowerAndCapitalProvider <- low
erAndCapital
http://errors.angularjs.org/1.2.16/$injector/unpr?p0=lowerAndCapitalProv
ider%20%3C-%20lowerAndCapital
at E:/workspace/GPS/src/main/webapp/resources/scripts/angular/angula
r.js:78:12
at E:/workspace/GPS/src/main/webapp/resources/scripts/angular/angula
r.js:3705:19
at Object.getService [as get] (E:/workspace/GPS/src/main/webapp/reso
urces/scripts/angular/angular.js:3832:39)
at E:/workspace/GPS/src/main/webapp/resources/scripts/angular/angula
r.js:3710:45
at getService (E:/workspace/GPS/src/main/webapp/resources/scripts/an
gular/angular.js:3832:39)
at Object.invoke (E:/workspace/GPS/src/main/webapp/resources/scripts
/angular/angular.js:3859:13)
at workFn (E:/workspace/GPS/src/main/webapp/resources/scripts/angula
r/angular-mocks.js:2147:20)
Error: Declaration Location
at window.inject.angular.mock.inject (E:/workspace/GPS/src/main/weba
pp/resources/scripts/angular/angular-mocks.js:2132:25)
at null.<anonymous> (E:/workspace/GPS/src/test/unit/filtersSpec.js:1
5:5)
at null.<anonymous> (E:/workspace/GPS/src/test/unit/filtersSpec.js:1
2:2)
at E:/workspace/GPS/src/test/unit/filtersSpec.js:5:1
Chrome 36.0.1985 (Windows 7): Executed 1 of 1 (1 FAILED) ERROR (0.359 secs / 0.0
14 secs)
You should probably try inject filterprovider and get lowerAndCapital filter.
var $filter;
beforeEach(function () {
module('app');
});
beforeEach( inject(function (_$filter_) { //<-- Get the filter provider
$filter = _$filter_;
}));
it('deberia de convertir le texto a minuscula y con letra capital',function(){
expect($filter('lowerAndCapital')("john")).toEqual("John");
});
Plnkr
Or Postfix your filtername with "Filter" and use it
beforeEach( inject(function (_lowerAndCapitalFilter_) {
$filter = _lowerAndCapitalFilter_;
}));
Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To achieve this a filter definition consists of a factory function which is annotated with dependencies and is responsible for creating a filter function.
But there is a bug in your code because of split(" ") so you may want to trim the result returned.
Demo