angularjs requirejs karma directive templateUrl test fail - angularjs

question
I replace templateUrl with template in author-signature.js, then I test success.
But I use templateUrl way in author-signature.js, I test fail. I watch files loading and chrome debug, author-signature.html did translate to js, and html content did exist in $templateCache too, but I test fail. Printscreen:
author-signature.html.js
$templateCache debug content
filepath
--public
----scripts
--------**/*.js
--test
----**/*.js
--views
----templates
--------**/*.html
test-main.js
require.js main entry file
var allTestFiles = [];
var TEST_REGEXP = /(\-test)\.js$/i;
Object.keys(window.__karma__.files).forEach(function (file) {
if (window.__karma__.files.hasOwnProperty(file)) {
if (TEST_REGEXP.test(file)) {
allTestFiles.push(file);
}
}
});
require.config({
baseUrl: '/base/public/scripts',
paths: {
'jquery': '../libs/jquery/dist/jquery',
'angular': '../libs/angular/angular',
'angularMocks': '../libs/angular-mocks/angular-mocks',
'templates': '../../views/templates'
},
shim: {
'angular': {
deps: ['jquery'],
exports: 'angular'
},
'angularMocks': {
deps: ['angular'],
exports: 'angular.mock'
},
'templates/default/author-signature.html': ['angular']
},
deps: allTestFiles,
callback: window.__karma__.start
});
karma.conf.js
karma configuration file, I translate js to html by ng-html2js
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', 'requirejs'],
files: [
{pattern: 'public/libs/jquery/dist/jquery.js', included: false},
{pattern: 'public/libs/angular/angular.js', included: false},
{pattern: 'public/libs/angular-mocks/angular-mocks.js', included: false},
{pattern: 'public/scripts/**/*.js', included: false},
{pattern: 'views/templates/**/*.html', included: false},
{pattern: 'test/**/*-test.js', included: false},
'test/test-main.js'
],
exclude: [
'public/scripts/build-main.js',
'public/scripts/require-config.js',
'public/scripts/bootstrap.js'
],
browsers: ['Chrome'],
reporters: ['progress', 'html', 'coverage'],
htmlReporter: {
outputFile: 'report/units.html',
pageTitle: 'Unit Tests',
subPageTitle: 'Unit tests with karma jasmine'
},
preprocessors: {
'public/scripts/**/*.js': ['coverage'],
'views/templates/**/*.html': ['ng-html2js']
},
coverageReporter: {
type: 'html',
dir: 'report/coverage/'
},
ngHtml2JsPreprocessor: {
stripPrefix: 'views/',
stripSuffix: '.html',
moduleName: 'templates'
}
});
}
author-signature-test.js
directive test file
define(['angularMocks', 'directives/default/author-signature', 'templates/default/author-signature.html'], function () {
describe('Unit: Hello Directive', function () {
var $compile, $rootScope;
beforeEach(function () {
module('angularApp');
module('templates');
inject(function (_$compile_, _$rootScope_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
});
});
it('should display the hello text properly', function () {
var elt = $compile('<author-signature author="Plus"></author-signature>')($rootScope);
expect(elt.text()).toEqual('Plus');
});
});
});
author-signature.js
simply directive file
define('directives/default/author-signature', [
'angular-app'
], function (angularApp) {
angularApp.directive('authorSignature', function () {
return {
restrict: 'EA',
scope: {
author: '#'
},
replace: true,
templateUrl: 'templates/default/author-signature'
};
});
});
author-signature.html
<h1>{{author}}</h1>
angular-app.js
define('angular-app', [
'angular'
], function (angular) {
var angularApp = angular.module('angularApp', []);
return angularApp;
});

OMG, I forget add $rootScope.$digest(); in test directive.
That cause this directive scope's attributes doesn't change.

Related

"Error: [$injector:modulerr] Failed to instantiate module ng due" to while running karma test runner

I am trying to run test cases for my application but stuck in between. Its giving the below error -
Error: [$injector:modulerr] Failed to instantiate module ng due to:
TypeError: 'undefined' is not an object (evaluating 'Function.prototype.bind.apply')
.......
......
{path}/test/unit/generate-form-directive.js:24
Test file is (generate-form-directive.js) -
describe("UNIT DIRECTIVE: generateForm", function () {
"use strict";
// Angular injectables
var $compile, $rootScope, $httpBackend;
// Module defined (non-Angular) injectables
var $scope, directiveScope, pagerVm;
// Local variables used for testing
var template;
// Initialize modules
beforeEach(function () {
module("TestDataModule");
});
beforeEach(function () {
inject(function (_$compile_, _$rootScope_, _$httpBackend_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
$httpBackend = _$httpBackend_;
}); //Line no 24
});
it("test message", function() {
console.log("Hello");
});
});
My Karma file (karma.conf.js) -
module.exports = function (config) {
config.set({
basePath: "",
frameworks: ["mocha", "chai", "sinon"],
files: [
"node_modules/angular/angular.js",
"node_modules/angular-mocks/angular-mocks.js",
// Add template files
"src/**/*.html",
"src/commons/js/*.js",
"src/commons/services/*.js",
"src/commons/directives/**/*.js",
"src/modules/**/*.js",
// Add all the test files
"test/unit/*.js",
],
exclude: [],
preprocessors: {
"src/**/*.js": "coverage"
},
reporters: ["mocha", "coverage"],
mochaReporter: {
// full, autowatch, minimal
output: "autowatch",
ignoreSkipped: false
},
browserNoActivityTimeout: 20000,
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ["PhantomJS"],
singleRun: true,
coverageReporter: {
dir: "./coverage",
reporters: [{
type: "cobertura",
subdir: ".",
file: "cobertura.xml"
}, {
type: "text"
}]
}
});
};
Thanks in advance.
I had the same problem. The minimatch pattern ('/**/*') did not worked in karma.conf.js.
You have two options:
1) Try to change your minimatch version and see if it helps.
2) Or specify each file instead of using the minimatch pattern ("/**/*.js").
Change karma configuration file for something like this:
// Add template files
"src/views/view1.html",
"src/views/view2.html",
"src/commons/js/myJs1.js",
"src/commons/services/service1.js",
"src/commons/services/service2.js",
"src/commons/directives/directive1.js",
"src/modules/moduleName/moduleNAme1.js",
// Add all the test files
"test/unit/testFile1.js",

Unit test an angular service (not factory) using Jasmine

I've been trying to test an Angular service using Jasmine following tutorials, but for some reason their examples don't here works (they suggest injecting services using the angular.mock.inject() method)...
This is the way I got it working, but I am afraid this is not how it should be done...
Is this "good practice"? Why injecting doesn't work?
I basically import the service into the test, setup my module and $provide the service's dependencies, and new the service passing it what would normally be injected...
Anyway, here it is:
import rolesService from './roles.service.js';
describe('Roles', () => {
let RolesService;
let PermRoleStore;
let USER;
beforeEach(() => {
angular.mock.module('roles', ($provide) => {
$provide.constant('USER', {
roles: ['SOUTIEN_ORGANISME']
});
$provide.value('PermRoleStore', {
defineManyRoles: jasmine.createSpy(),
});
});
angular.mock.inject((_PermRoleStore_, _USER_) => {
PermRoleStore = _PermRoleStore_;
USER = _USER_;
RolesService = new rolesService(PermRoleStore, USER);
});
});
it('Setup should define the roles', () => {
RolesService.setup();
expect(PermRoleStore.defineManyRoles).toHaveBeenCalled();
});
describe('authorize', () => {
it('should return true if authorized', () => {
expect(RolesService.authorize('SOUTIEN_ORGANISME')).toBe(true);
});
it('should return false if the user it NOT authorized', () => {
expect(RolesService.authorize('NOT_AUTHORIZED')).toBe(false);
});
});
});
Here is the karma.config.js file just for reference:
'use strict';
const stringify = require('stringify');
const babelify = require('babelify');
module.exports = (config) => {
config.set({
basePath: '',
frameworks: ['browserify', 'jasmine-ajax', 'jasmine'],
files: [
{ pattern: 'build/gouvernementales/app-gouvernementales.config.json', watched: true, served: true, included: false },
'build/gouvernementales/js/gouvernementales-libs.js',
'src/apps/gouvernementales/app-gouvernementales.js',
'src/apps/gouvernementales/**/*.spec.js',
'src/modules/**/*.spec.js',
],
preprocessors: {
'src/apps/gouvernementales/app-gouvernementales.js': 'browserify',
'src/apps/gouvernementales/**/*.spec.js': 'browserify',
'src/modules/**/*.spec.js': 'browserify',
},
browsers: ['PhantomJS'],
plugins: [
'karma-phantomjs-launcher',
// 'karma-chrome-launcher',
'karma-jasmine-ajax',
'karma-jasmine',
'karma-browserify',
'karma-coverage',
'karma-mocha-reporter',
],
browserify: {
debug: true,
transform: [
babelify,
stringify,
],
},
helpers: [
'src/spec/helpers/**/*.js',
],
reporters: [
'mocha',
'coverage',
],
coverageReporter: {
dir: 'coverage/',
reporters: [
{ type: 'text-summary' },
{ type: 'html' },
],
},
logLevel: config.LOG_DEBUG,
singleRun: false,
colors: true,
autoWatch: true,
});
};
You don't need to do like this one
import rolesService from './roles.service.js'; // it should be not included.
//Should be injected
BEFOREEACH
beforeEach(() => {
angular.mock.module(($provide) => {
$provide.constant('USER', {
roles: ['SOUTIEN_ORGANISME']
});
$provide.value('PermRoleStore', {
defineManyRoles: jasmine.createSpy(),
});
});
//you are mocking PermRoleStore and USER,so should be inject it here.
//It will get available to your service
//no need of import
angular.mock.inject((_rolesService_) => {
PermRoleStore = _rolesService_;
});
});

jquery-jasmine unable to load json files

I've seen this question posted but can't seem to resolve the error. I'm trying to use jquery-jasmine to return some fake data and I'm unable to get past the 404 error when trying to load the json file. I'm using yeoman to scaffold my angular-gulp project. Is it not a good idea to put the json file in the module, along side the spec file? Where does karma run from, is this where I should be putting the json file? I tried using an absolute path for jasmine.getJSONFixtures().fixturesPath but still get an error. I added 'base' to the path of the fixture because I saw this fixed the error in another post but it didn't work for me. Any ideas?
WARN [web-server]: 404: /base/src/app/home/home.fixture.json?_=1445293824062
PhantomJS 1.9.8 (Mac OS X) homeController should have some resultsets FAILED
Error: JSONFixture could not be loaded: base/src/app/home/home.fixture.json (status: error, message: undefined)
undefined
project/
src/
app/home
home.controller.spec.js
home.fixture.json
...
gulp/unit-test.js
karma.conf.js
...
karma.conf.js:
'use strict';
module.exports = function(config) {
config.set({
basePath: '../',
autoWatch : true,
frameworks : ['jasmine'],
browsers : ['PhantomJS'],
plugins : [
'karma-phantomjs-launcher',
'karma-chrome-launcher',
'karma-firefox-launcher',
'karma-safari-launcher',
'karma-jasmine'
],
exclude : [
],
files : [
// fixtures
{
pattern: 'src/**/*.fixture.json',
watched: true,
served: true,
included: false
}
]
});
};
home.controller.spec.js
'use strict';
describe('homeController', function(){
beforeEach(function() {
module('homeModule');
var $httpBackend, scope, homeController, storageFactory;
module(function($provide) {
$provide.service('storageFactory', storageFactory);
});
inject(function($rootScope, $controller, $injector) {
$httpBackend = $injector.get('$httpBackend');
jasmine.getJSONFixtures().fixturesPath = 'base/src/app/home';
$httpBackend.whenGET('http://localhost:3000/my/api/home').respond(
getJSONFixture('home.fixture.json')
);
scope = $rootScope.$new();
homeController = $controller('homeController', {
$scope: scope
});
storageFactory = $injector.get('storageFactory');
});
});
it('should have some resultsets', function() {
$httpBackend.flush();
expect(scope.result_sets.length).toBe(59);
});
});
I had the same setup with yeoman-Angularjs-gulp and jquery-jasmine with the same 404 problem.
I solved it in 2 way,
The basePath was not setup in my karma config.
The path of the json file were not initially loaded by karma so they never got found.
So I added the line in the file loading:
{pattern: path.join(conf.paths.src, '/mockjson/*.json'),
watched: false,
included: false,
served: true}
This is the basic karma config that was built by yeoman with the 2 extra line:
var path = require('path');
var conf = require('./gulp/conf');
var _ = require('lodash');
var wiredep = require('wiredep');
function listFiles() {
var wiredepOptions = _.extend({}, conf.wiredep, {
dependencies: true,
devDependencies: true
});
return wiredep(wiredepOptions).js
.concat([
path.join(conf.paths.src, '/app/**/*.module.js'),
path.join(conf.paths.src, '/app/**/*.js'),
path.join(conf.paths.src, '/**/*.spec.js'),
path.join(conf.paths.src, '/**/*.mock.js'),
path.join(conf.paths.src, '/**/*.html'),
{pattern: path.join(conf.paths.src, '/mockjson/*.json'), watched: false, included: false, served: true}
]);
}
module.exports = function (config) {
var configuration = {
files: listFiles(),
singleRun: true,
autoWatch: false,
basePath: '',
frameworks: ['jasmine', 'angular-filesort'],
angularFilesort: {
whitelist: [path.join(conf.paths.src, '/**/!(*.html|*.spec|*.mock).js')]
},
ngHtml2JsPreprocessor: {
stripPrefix: 'src/',
moduleName: 'pagesBehindCouch'
},
browsers: ['PhantomJS'],
plugins: [
'karma-phantomjs-launcher',
'karma-angular-filesort',
'karma-jasmine',
'karma-ng-html2js-preprocessor'
],
preprocessors: {
'src/**/*.html': ['ng-html2js']
}
};
config.set(configuration);
};
I think the pattern: 'src/**/*.fixture.json', might be not at the src location you think it is.
Exemple that really helped me: Gunnar Hillert's Blog
In my case, I was loading an environment-configuration.json file in order to bootstrap the AngularJS application.
So, I also had to specify the proxy settings.
proxies: {
'/mockjson/': '/base/src/mockjson/',
}

"TypeError: createController is not a function in" jasmine test

New to jasmine tests. So sorry if this is a dumb question. I'm trying to do a simple unit test of a controller's existence in AngularJS code, and I can't get over this error. It's something silly I'm sure. I've looked all over stackoverflow, and tried many different things based on similar error but to not avail. Keep getting the error.
Here's the app.js
angular.module('waldo', ['ui.router'])
.config(['$stateProvider','$urlRouterProvider',function($stateProvider,$urlRouterProvider){
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home.html',
controller: 'MainController'
})
.state('posts', {
url: '/posts/{id}',
templateUrl: '/posts.html',
controller: 'PostsController'
});
$urlRouterProvider.otherwise('home');
}])
.factory('posts',[function(){
var o = {
posts: []
};
return o;
}])
.controller('MainController', [
'$scope','posts',
function($scope,posts){
$scope.posts = posts.posts;
$scope.addPost = function(){
if(!$scope.title || $scope.title === '') { return; }
$scope.posts.push({
title: $scope.title,
link: $scope.link,
upvotes: 0,
comments: [
{author: 'Joe', body: 'Cool post!', upvotes: 0},
{author: 'Bob', body: 'Great idea but everything is wrong!', upvotes: 0}
]
});
$scope.title = '';
};
$scope.incrementUpvotes = function(post) {
post.upvotes += 1;
};
}])
.controller('PostsController',['$scope','$stateParams','posts',function($scope,$stateParams,posts){
$scope.post = posts.posts[$stateParams.id];
}]);
Test:
describe('test that', function() {
beforeEach(module('waldo'));
describe('MainController', function () {
var scope, createController;
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
createController = function () {
return $controller('MainController', {
'$scope': scope
});
};
}));
it('exists', function () {
var controller = createController();
expect(controller).not.toBeNull();
});
});
});
karma.conf.js
// Karma configuration
// Generated on Wed Apr 08 2015 13:46:46 GMT-0400 (EDT)
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: [
"vendor/assets/bower_components/angular/angular.js",
"vendor/assets/bower_components/angular-mocks/angular-mocks.js",
"app.js",
"test/*.js",
"test/*/*_test.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: ['Firefox'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};
bower.json
{
"name": "waldo",
"version": "0.0.0",
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"angular": "~1.3.15",
"angular-ui-router": "~0.2.13",
"bootstrap": "~3.3.4"
},
"devDependencies": {
"angular-mocks": "~1.3.15"
}
}
Error is:
minErr/<#/home/christian/Projects/waldo/vendor/assets/bower_components/angular/angular.js:63:12
loadModules/<#/home/christian/Projects/waldo/vendor/assets/bower_components/angular/angular.js:4138:15
forEach#/home/christian/Projects/waldo/vendor/assets/bower_components/angular/angular.js:323:11
loadModules#/home/christian/Projects/waldo/vendor/assets/bower_components/angular/angular.js:4099:5
createInjector#/home/christian/Projects/waldo/vendor/assets/bower_components/angular/angular.js:4025:11
workFn#/home/christian/Projects/waldo/vendor/assets/bower_components/angular-mocks/angular-mocks.js:2425:44
TypeError: createController is not a function in /home/christian/Projects/waldo/test/integration/first_test.js (line 17)
#/home/christian/Projects/waldo/test/integration/first_test.js:17:30
Thanks.
Maybe you have to put your module dependency in your karma.conf.js that in your case is 'ui.router', for example:
...
files: [
"vendor/assets/bower_components/angular/angular.js",
"vendor/assets/bower_components/angular-mocks/angular-mocks.js",
"vendor/assets/bower_components/angular-ui-router/angular-ui-router.js",
"app.js",
"test/*.js",
"test/*/*_test.js"
],
...
Then run again the test.
Also take a look at these links, they were very useful to me
Unit testing a service in angularJS
http://jamesreubenknowles.com/angularjs-nglocale-error-1952
https://docs.angularjs.org/error/$injector/nomod?p0=ngLocale

AngularJS directive isn't loaded during unit test

This is my configuration for Karma:
options: {
browsers: ['PhantomJS'],
frameworks: ['jasmine'],
plugins: [
'karma-jasmine',
'karma-phantomjs-launcher'
],
reporters: 'dots',
urlRoot: '/',
autoWatch: false,
background: false,
singleRun: true,
basePath: '.',
},
tests: {
files: {
src: [
'lib/angular/build/angular.js',
'lib/angular/build/angular-mocks.js',
'src/components/**/*.js'
]
}
}
I've the following directive:
angular.module('myContainerModule', []).directive('myContainer', function() {
return {
restrict: 'E',
scope: {
},
replace: true,
transclude: true,
template: '<section ng-transclude></section>',
compile: function() {
console.log('compile');
return {
pre: function() {
console.log('pre-link');
},
post: function() {
console.log('post-link');
}
};
},
controller: function() {
console.log('controller')
}
};
})
Also the unit test for that:
describe('myContainer', function () {
var element, scope;
beforeEach(angular.module('myContainerModule'))
beforeEach(inject(function($rootScope, $compile) {
element = angular.element(
'<my-container>' +
' {{foo}}' +
'</my-container>'
);
scope = $rootScope;
scope.foo = 'bar';
$compile(element)(scope);
scope.$digest();
}))
it('should be replaced by a `section` tag', function() {
console.log(element[0].outerHTML);
expect(element[0].tagName).toBe('SECTION');
})
})
The test runner tells me:
Running "karma:tests" (karma) task
INFO [karma]: Karma v0.12.31 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 1.9.8 (Linux)]: Connected on socket 1XZDEfFUCHhoCoH7a5LR with id 14712662
LOG: '<my-container class="ng-binding ng-scope"> bar</my-container>'
..
PhantomJS 1.9.8 (Linux) Container should be replaced by a `section` tag FAILED
Expected 'MY-CONTAINER' to be 'SECTION'.
at [...]
Why is the directive myContainer ignored? When I do the same manually in the browser it works.
The problem is this line the unit test:
beforeEach(angular.module('myContainerModule'))
It has to be:
beforeEach(module('myContainerModule'))

Resources