I'm trying to set up a unit test in karma to test an angular 1.* controller. Each time I run the code I get
[ng:areq] Argument 'MoviesListCtrl' is not a function, got undefined
When I have checked the module for the controller appears to get loaded so I'm not sure why its not loading. My project can be found here..
I'm project is available on bitbucket at
https://bitbucket.org/LAD500/movies-angular-webpack/src
to run the tests..
npm install
npm test
Any help with this would be appreciated.
Files I'm working with are..
import '../../../../../src/js/app/services/movieslisting/';
import '../../../../../src/js/app/directives/movieslist/movieslistctrl';
import '../../../../../src/js/app/browserapp.js';
import {expect} from 'chai';
let createCtrl, scope, moviesListing;
beforeEach(angular.mock.module('BrowserApp'));
beforeEach(inject(($rootScope, $controller)=>{
moviesListing = angular.injector(['ng', 'BrowserApp']).get("moviesListing");
scope = $rootScope.$new();
createCtrl = ()=>{
return $controller('MoviesListCtrl', {
$scope: scope,
moviesListing: moviesListing
});
};
}));
describe('MoviesListCtrl', ()=>{
it('placeholder test', ()=>{
let ctrl = createCtrl();
expect(1).to.equal(1);
});
});
controller
import app from '../../browserapp';
let controllerName = 'MoviesListCtrl';
app.controller('MoviesListCtrl', ['$scope', 'moviesListing', function($scope, moviesListing) {
$scope.moviesList = {
moviesFilter: 'costLowToHigh',
movies: moviesListing.movieCollection
};
$scope.createMovieHeader = movie =>{
let prefix = `${movie.title} (${movie.category}`;
return movie.subcategory ? `${prefix}/${movie.subcategory})` : `${prefix})`;
};
$scope.updateFilter = ()=>{
moviesListing.sortMovies($scope.moviesList.moviesFilter);
};
}]);
export default controllerName;
service thats a dependency
import app from '../../browserapp';
let factoryName = 'moviesListing';
app.factory(factoryName, [function() {
let movieCollection = [];
let currentSortKey = 'costLowToHigh';
let costLowToHigh = (a, b)=>{
if (a.castListTotalCost > b.castListTotalCost) {
return 1;
}
if (a.castListTotalCost < b.castListTotalCost) {
return -1;
}
return 0;
};
let costHighToLow = (a, b)=>{
if (a.castListTotalCost < b.castListTotalCost) {
return 1;
}
if (a.castListTotalCost > b.castListTotalCost) {
return -1;
}
return 0;
};
let sortFunctionsLookup = {
costLowToHigh,
costHighToLow
};
let castListTotalCost = movie => movie.actors.reduce((total, actor) => total + actor.salary, 0);
let addMovie = (movie)=>{
movie.castListTotalCost = castListTotalCost(movie);
movieCollection.push(movie);
movieCollection.sort(sortFunctionsLookup[currentSortKey]);
};
let sortMovies = (sortKey)=>{
currentSortKey = sortKey;
movieCollection.sort(sortFunctionsLookup[currentSortKey]);
};
let reset = ()=>{
movieCollection.length = 0;
};
return {
movieCollection,
addMovie,
sortMovies,
reset
};
}]);
export default factoryName;
app module
import * as angular from 'angular';
var app = angular.module('BrowserApp', []);
app.init = ()=>{
angular.element(document).ready(function() {
angular.bootstrap(document, ['BrowserApp']);
});
};
export default app;
Karma config
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['mocha', 'es6-shim'],
files: [
'./node_modules/angular/angular.js',
'./node_modules/angular-mocks/angular-mocks.js',
'test/**/*spec.js'
],
preprocessors: {
'test/**/*spec.js': ['webpack', 'sourcemap']
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: false,
browsers: ['PhantomJS'],
singleRun: true,
concurrency: Infinity,
webpack: {
devtool: 'inline-source-map',
module: {
loaders: [
{test: /\.js$/, exclude: /node_modules/, loader:"babel-loader"},
{ test: /\.html$/, loader: "html" }
]
},
htmlLoader: {
attrs: false
}
},
webpackMiddleware: {
noInfo: true
}
})
}
Managed to work this out myself.
the trick is to use a javascript file to generate a bundle for you tests
the javascript file, specs.karma.js looked something like this..
import 'angular';
import 'angular-mocks/angular-mocks';
const testsContext = require.context('./', true, /.spec$/);
testsContext.keys().forEach(testsContext);
The Karma config..
module.exports = function karmaConfig (config) {
config.set({
logLevel: config.LOG_INFO,
client: { captureConsole: true },
frameworks: ['mocha', 'es6-shim'],
reporters: ['progress'],
files: ['./src/js/specs.karma.js'],
preprocessors: {
'./src/js/specs.karma.js': ['webpack', 'sourcemap']
},
browsers: [ 'PhantomJS'],
singleRun: true,
webpack: require('./webpack.test.config'),
webpackMiddleware: {
noInfo: 'errors-only'
}
});
};
And the webpack.test.config.js..
module.exports = {
devtool: 'inline-source-map',
module: {
loaders: [
{test: /\.js$/, exclude: /node_modules/, loader:"babel"},
{ test: /\.html$/, loader: "html" }
]
},
htmlLoader: {
attrs: false
}
}