In my karma.conf.coffee, I have:
files: [
'public/bower_components/angular-mocks/angular-mocks.js'
'public/scripts/**/*.coffee' # not tested since configuration is difficult to be tested and perhaps should not be tested
'test/webapp/unit/**/*.coffee'
'views/templates/*.html'
]
preprocessors:
'public/scripts/**/*.coffee': ['coverage']
'test/webapp/unit/**/*.coffee': ['coffee']
'views/templates/*.html': ['ng-html2js']
frameworks: ['jasmine']
ngHtml2JsPreprocessor:
stripPrefix: 'views/'
In my test, I have:
describe('Directive: timespanSelector', function() {
var scope;
scope = null;
beforeEach(module('myApp'));
beforeEach(module('templates/partialDateRange.html'));
beforeEach(function() {
var html;
html = "<timespan-selector></timespan-selector>";
return inject(function($compile, $rootScope) {
var compiled, elem;
scope = $rootScope.$new();
elem = angular.element(html);
compiled = $compile(elem);
compiled(scope);
return scope.$digest();
});
});
return it('should test', function() {});
});
When I run it, it says:
Error: [$injector:modulerr] Failed to instantiate module templates/partialDateRange.html due to:
Error: [$injector:nomod] Module 'templates/partialDateRange.html' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.2.16/$injector/nomod?p0=templates%2FpartialDateRange.html
What am I doing wrong?
This has been an issue for us for a long time and I spent a few days to find out the solution - this it what we came up with. I will simply show you how our file structure is configured.
First off you will need to include karma-ng-html2js-preprocessor.
npm install karma-ng-html2js-preprocessor --save-dev
Next your karma.conf.js - you use coffee but i wont hold it against you ;-)
Remember to include the module name so you can inject it into the directive unit test.
// 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'],
preprocessors: {
'app/views/templates/*.tpl.html': ['ng-html2js'] //<----- Also needed
},
// list of files / patterns to load in the browser
files: [
'app/bower_components/angular/angular.js',
'app/bower_components/angular-mocks/angular-mocks.js',
'app/bower_components/angular-resource/angular-resource.js',
'app/bower_components/angular-cookies/angular-cookies.js',
'app/bower_components/angular-sanitize/angular-sanitize.js',
'app/bower_components/angular-bootstrap/ui-bootstrap.js',
'app/bower_components/angular-ui-router/release/angular-ui-router.js',
'app/bower_components/angular-local-storage/angular-local-storage.js',
'app/bower_components/jquery/dist/jquery.js',
'app/bower_components/bootstrap/dist/js/bootstrap.js',
'app/scripts/*.js',
'app/scripts/**/*.js',
'test/spec/**/*.js',
//Templates
'app/views/templates/*.tpl.html' //<----- Also needed
],
ngHtml2JsPreprocessor: {
stripPrefix: 'app/',
moduleName: 'Kinetix.Templates' //<-----Module Name for injection
},
// list of files / patterns to exclude
exclude: [],
// Reporters
reporters: ['progress', 'junit'],
//Config for junit
junitReporter: {
outputFile: './test/test-results.xml',
suite: ''
},
// web server port
port: 9001,
// 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: false
});
};
So then after you got yer karma.conf.js set up lets have a look at a unit test. This is a directive unit test I will include the whole thing as well - maybe it can inspire your for other unit testing ideas as well. I have been at it now for almost 8 months and learned quite a bit...
Directive Unit Test:
'use strict';
describe('Directives: Search', function () {
var//iable declarations
elm,
scope,
$rootScope,
$compile,
$animate,
ACCESS_LEVEL = [
'OPEN',
'PRIVATE',
'RESTRICTED'
]
;
beforeEach(function () {
module('Kinetix.Constants');
module('Kinetix.Templates'); //<------ See here we inject the templates!
module('Kinetix.Directives.Search');
module('Kinetix.Controllers.Search', function ($controllerProvider) {
$controllerProvider.register('SearchController', function () { });
});
});
beforeEach(inject(function (_$rootScope_, _$compile_, _$animate_) {
$rootScope = _$rootScope_;
scope = $rootScope;
$animate = _$animate_;
$compile = _$compile_;
}));
function setupDirective(accessLevel) {
spyOn($animate, 'addClass').and.callThrough();
spyOn($animate, 'removeClass').and.callThrough();
$rootScope.accessLevel = { type: accessLevel };
$rootScope.isAuthenticated = { value: false };
elm = angular.element('<kx-search></kx-search>');
$compile(elm)(scope);
scope.$apply();
}
it('Should create the search template', function () {
setupDirective(ACCESS_LEVEL[0]);
var nav = $(elm).find('.nav');
expect(nav.children('form')).toBeTruthy();
});
describe('Animations', function () {
it('should have the fade slide class on setup with OPEN accesslevel', function () {
setupDirective(ACCESS_LEVEL[0]);
//With Authentication
$rootScope.isAuthenticated.value = true;
scope.$apply();
expect(elm.children('div').hasClass('slide-left')).toBeTruthy();
expect($animate.addClass).toHaveBeenCalled();
$rootScope.isAuthenticated.value = false;
scope.$apply();
expect($animate.removeClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('slide-left')).toBeFalsy();
});
it('should toggle the fade-slide animation with PRIVATE acesslevels', function () {
setupDirective(ACCESS_LEVEL[1]);
expect($animate.addClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('fade-slide')).toBeTruthy();
$rootScope.isAuthenticated.value = true;
scope.$apply();
expect($animate.removeClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('fade-slide')).toBeFalsy();
$rootScope.isAuthenticated.value = false;
scope.$apply();
expect($animate.addClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('fade-slide')).toBeTruthy();
});
it('should toggle the fade-slide animation with RESTRICTED acesslevels', function () {
setupDirective(ACCESS_LEVEL[2]);
expect($animate.addClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('fade-slide')).toBeTruthy();
$rootScope.isAuthenticated.value = true;
scope.$apply();
expect($animate.removeClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('fade-slide')).toBeFalsy();
$rootScope.isAuthenticated.value = false;
scope.$apply();
expect($animate.addClass).toHaveBeenCalled();
expect(elm.children('div').hasClass('fade-slide')).toBeTruthy();
});
});
});
For completion I will also include the directive itself just so you can see the complete picture.
angular.module('Kinetix.Directives.Search', [])
.directive('kxSearch', function ($rootScope, $animate, PATH) {
var linker = function (scope, el) {
var//iable declarations
accessLevel = $rootScope.accessLevel.type || 'Guest',
element = el.children('.nav')
;
//Check if the shop type is a PRIVATE or RESTRICTED type so we can chose which animation to apply
if (accessLevel === 'RESTRICTED' || accessLevel === 'PRIVATE') {
// Hide the element as we need authentication to show it
$animate.addClass(element, 'fade-slide');
$rootScope.$watch('isAuthenticated.value', function (newVal) {
if (!!newVal) {
$animate.removeClass(element, 'fade-slide');
}
if (!newVal) {
$animate.addClass(element, 'fade-slide');
}
});
}
if (accessLevel === 'OPEN') {
$rootScope.$watch('isAuthenticated.value', function (newVal, oldVal) {
if (newVal !== oldVal) {
if(!!newVal) {
$animate.addClass(element, 'slide-left');
}
if(!newVal) {
$animate.removeClass(element, 'slide-left');
}
}
});
}
};
return {
restrict: 'E',
link: linker,
controller: 'SearchController',
templateUrl: PATH.templates + 'search.tpl.html'
};
});
Hope it helps! This was the 800lb gorilla in the room for quite a while, once you actually tame him he is pretty sweet! Good luck!
What am I doing wrong?
Answer: You are attempting to reference an angular module that doesn't exist.
I know this because of the error that you're getting:
Module 'templates/partialDateRange.html' is not available!
Which is caused by the following line of code:
beforeEach(module('templates/partialDateRange.html'));
The Fix
Determine the location of ng-html2js's output. Which is a .js file.
Include that file inside of the files array in karma.conf.coffee
Open the .js file and look for angular.module('<module name>', []) to determine how ng-html2js is naming the module and use that module name where you currently have 'templates/partialDateRange.html' (it should be a similar path name if not the same).
An alternative to karma-ng-html2js-preprocessor is grunt-angular-templates. However, this assumes you are using Grunt (there's also a gulp version floating around).
Add grunt-angular-templates to your package.json file, then simply run grunt ngtemplates from your command line.
This will concatenate all of your templates throughout the application (the ones that are called with templateURL anyways), and put them in a templates.js file.
Then you simply include this file in your karma.conf and you're good to go.
I had a huge amount of trouble setting up karma-ng-html2js-preprocessor and as such, turning to a grunt task was the fastest and easiest way out.
Hope you get it working soon, whichever way you choose to go.
Related
I am using gulp to compile my typescript files and create the output.js file.
Is it possible to have a single task which compiles typescript file and concatenates it with angular libraries?
Here's what my current file looks like (below). First it's running a typescript task which creates the output.js file and then it runs a scripts task which concats the script plugin files and output.js.
'use strict';
var gulp = require('gulp')
var paths = {
distScriptsDir: '../../Themes/mastter/Scripts',
srcScriptsPlugins: [
'node_modules/jquery/dist/jquery.min.js',
'node_modules/angular/angular.min.js',
'node_modules/angular-route/angular-route.min.js',
'node_modules/angular-translate/dist/angular-translate.min.js',
'node_modules/angular-translate/dist/angular-translate-loader-url/angular-translate-loader-url.min.js',
'node_modules/angular-bootstrap/dist/ui-bootstrap-tpls.js',
'Scripts/angular-sticky.min.js',
'Scripts/dragme.js',
'Scripts/jasny-bootstrap.min.js',
'node_modules/lodash/dist/lodash.min.js',
'node_modules/angular-google-maps/dist/angular-google-maps.min.js'
],
srcScriptsFile: [
'output.js'
]
};
//typescript
gulp.task('typescript', function () {
var ts = require('gulp-typescript');
var tsResult = gulp.src( 'all.ts')
.pipe(ts({
noImplicitAny: true,
out: 'output.js'
}));
return tsResult.js.pipe(gulp.dest(''));
});
// scripts task
gulp.task('scripts', function () {
var concat = require('gulp-concat'),
plumber = require('gulp-plumber'),
uglify = require('gulp-uglify');
return gulp.src(paths.srcScriptsPlugins.concat(paths.srcScriptsFile))
.pipe(plumber({
errorHandler: function (e) {
console.log(e.toString());
this.emit('end');
}
}))
// .pipe(uglify())
.pipe(concat('main.js'))
.pipe(gulp.dest(paths.distScriptsDir));
});
// default task
gulp.task('default', [
'typescript',
'scripts'
]);
I use a watch tasks for this that has a bunch of gulp.watch inside it. One for watching the .ts change and run the typescript compiler that will output a js file in whatever location and another gulp.watch that watches the .js files and run script task. In that case, things will get automated by the watch and you don't have to combine the task into one task.
gulp.task('watch', function() {
gulp.watch(['dir/*.ts','otherdir/*.ts',...], ['typescript']);
gulp.watch(['dir/*.js','otherdir/*.js',...], ['scripts']); //make sure to include the .ts result folder...
});
try run-sequence. Below is a simple example.
gulp.task('task1', function(callback) {
setTimeout(function() {
console.log('task1 is done');
callback()
}, 1000);
});
gulp.task('task2', function(callback) {
setTimeout(function() {
console.log('task2 is done');
callback()
}, 2000);
});
gulp.task('tk12', function(callback) {
return runSequence('task1', 'task2', callback);
});
I'm writing tests for a directive. I want pass in a templateURL and then test various functionality of it using the built in JQlite library.
For some reason my template doesn't seem to compile, though Jasmine doesn't give me any errors.
my relevant app structure is:
/app
../partials/
../tests/
I have my karma.conf setup so:
files: [
...
'tests/*.js',
'partials/*.html'
],
preprocessors: {
'partials/*.html':'ng-html2js'
},
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-ng-html2js-preprocessor',
'karma
]
My test code looks like this:
describe('mapInputs.customForm', function () {
var elm, scope;
beforeEach(module('myApp'));
beforeEach(module('partials/test/tmpl.html'));
beforeEach(inject( function (_$rootScope_, _$compile_) {
$rootScope = _$rootScope_;
$compile = _$compile_;
elm = angular.element('<div><ng-map-inputs map-inputs=""></ng-map-inputs></div>');
console.log('elm', elm);
elm = $compile(elm)($rootScope);
$rootScope.$digest();
console.log('elm', elm);
}));
it('should reveal custom form', function () {
// elm.find('div') returns an empty object
});
});
And the output:
LOG: 'elm', Object{length: 1, 0: <div><ng-map-inputs map-inputs=""></ng-map-inputs></div>}
LOG: 'elm', Object{length: 1, 0: <div class="ng-scope"><ng-map-inputs map-inputs=""></ng-map-inputs></div>}
As I said, I don't get any errors, but the output of the console logs is not what I expect. It seems like the template is not being compiled? But surely Jasmine would complain if no template was found?
The issue for me was that I wasn't loading the actual directive in the karma.conf.js:
files: [
...
'path/to/directive/map-inputs.directive.js', // <-- wasn't being loaded before
'tests/*.js',
'partials/*.html'
],
Now I'm getting:
INFO [karma]: Karma v0.10.2 server started at `http://localhost:9876/`
INFO [launcher]: Starting browser Chrome
INFO [Chrome 30.0.1599(Linux)]: Connected on socket Q8d9RLBQDqi7wJ8iaKNw Chrome 30.0.1599 (Linux)
directives Mydirective directive should render Roi element correctly FAILED
Error: Unexpected request: GET partials/directives/Mydirective.html
No more request expected
at Error (<anonymous>)
at $httpBackend (/home/user/Documents/Projects/angularproject/test/lib/angular/angular-mocks.js:1006:9)
I'm trying to unittest a simple directives
.directive('Mydirective', function(){
return {
restrict:'E',
replace:true,
transclude:false,
templateUrl:'partials/directives/Mydirective .html'
};
})
this is karma.conf
module.exports = function(config){
config.set({
basePath : '../',
files : [
//libs, not sure I need all of them
'app/lib/angular/angular.js',
'app/lib/angular-file-upload/**/*.js',
'app/lib/restangular/restangular.js',
'app/lib/jquery/jquery.js',
'app/lib/angular/**/*.js',
'app/lib/lodash/**/*.js',
'app/lib/Underscore.js',
'app/lib/bootstrap.min.js',
'app/lib/ui-bootstrap-0.6.0.js',
'app/lib/angular/angular-resource.js',
'app/lib/angular/angular-cookies.min.js',
'app/lib/angular-translate/**/*.js',
'app/lib/angular-translate-loader-static-files/**/*.js',
'app/lib/angular-translate-storage-cookie/**/*.js',
'app/lib/angulartestfile-translate-storage-local/**/*.js',
'app/lib/bootstrap-gh-pages/assets/rainbow.js',
'app/lib/fbAngular.js',
'app/lib/moment.js',
// test libs
'test/lib/angular/**/*.js',
'test/lib/**/*.js',
// my js to test
'app/js/**/*.js',
//test unit
'test/unit/**/*.js',
//directive templates
'app/partials/directives/**/*.html'
],
exclude: ['test/lib/angular/angular-scenario.js'],
autoWatch : true,
testfile
frameworks: ['jasmine'],
browsers : ['Chrome'],
plugins : [
'karma-junit-reporter',
'karma-chrome-launcher',
'karma-firehttp://localhost:9876/fox-launcher',
'karma-jasmine',
'karma-coverage',
//'karma-html2js-preprocessor',
'karma-ng-html2js-preprocessor'
],
junitReporter : {
outputFile: 'test_out/unit.xml',
suite: 'unit'
},
reporters:['coverage','progress'],
preprocessors : {
'**/js/*.js': 'coverage',
'**/partials/directives/*.html': 'ng-html2js'// generate js files from html templates
},
ngHtml2JsPreprotestfilecessor: {
// cacheIdFromPath : function(filepath) {
// return filepath.substr(filepath.indexOf("angular")+8);
// },
stripPrefix:'app/',
// setting this option will create only a single module that contains templates
// from all the files, so you can load them all with module('templates')
moduleName: 'st-templates'
},
This is the test file.
describe('directives', function() {
var $compile, $rootScope;
beforeEach(function(){
module('myModule.directives');
module(function($provide) {
$provide.value('version', 'TEST_VER');
$provide.value('somevalue','value');
}
angular.module('st-templates');
});
beforeEach(inject(function(_$compile_, _$rootScope_){
// The injector unwraps the underscores (_) from around the parameter names when matching
$compile = _$compile_;
$rootScope = _$rootScope_;
}));
describe('app-version directive', function() {
it('should print current version', function() {
// module(function($provide) {
// $provide.value('version', 'TEST_VER');
var element = $compile('<span app-version></span>')($rootScope);
$rootScope.$digest();
expect(element.text()).toEqual('TEST_VER');
});
});
describe('mydirective', function(){
it('should render Roi element correctly', function(){
var element = $compile('<st-roi></st-roi>')($rootScope);
$rootScope.$digest();
expect(element.text()).toEqual('0.3%');
});
});
});
This is the folder tree:
-app
--app/js
--app/partials
-config/karma.conf
-test
--test/unit/specfile.js
Following advice in different SO question I already enabled the nghtml2j preprocessor and configured it (Hopefully correctly). But I still get an annoying error
Any clues? I'll be glad for any help with this
angular.module('st-templates') is not the same as module('st-templates') inside that jasmine test. Change angular.module('st-templates') to module('st-templates') and it should work.
I am trying to write unit tests for my Angular.js application but I cannot manage to inject what I need (it is not able to find a suitable provider).
Does anyone see what I missed?
Firefox 21.0 (Linux) filter staticList should convert static list object into its display value FAILED
Error: Unknown provider: staticListProvider <- staticList in /path/to/my-app/public/third-party/angular/angular.js (line 2734)
createInjector/providerInjector<#/path/to/my-app/public/third-party/angular/angular.js:2734
getService#/path/to/my-app/public/third-party/angular/angular.js:2862
createInjector/instanceCache.$injector<#/path/to/my-app/public/third-party/angular/angular.js:2739
getService#/path/to/my-app/public/third-party/angular/angular.js:2862
invoke#/path/to/my-app/public/third-party/angular/angular.js:2880
workFn#/path/to/my-app/test/lib/angular/angular-mocks.js:1778
angular.mock.inject#/path/to/my-app/test/lib/angular/angular-mocks.js:1764
#/path/to/my-app/test/unit/filtersSpec.js:19
#/path/to/my-app/test/unit/filtersSpec.js:16
#/path/to/my-app/test/unit/filtersSpec.js:3
The application:
angular.module('myApp', ['myAppFilters', 'ui.bootstrap', '$strap.directives']).
// Some other stuff
The filters:
"use strict";
angular.module('myAppFilters', []).
filter('staticList', function () {
return function (listItem) {
if (!listItem) {
return '';
}
return listItem.value;
};
});
The test:
'use strict';
describe('filter', function () {
beforeEach(angular.module('myAppFilters'));
describe('staticList', function () {
it('should convert static list object into its display value',
inject(function (staticList) {
expect(undefined).toBe('');
expect({key: 'A', value: 'B'}).toBe('B');
}));
});
});
The Karma configuration:
basePath = '../';
files = [
JASMINE,
JASMINE_ADAPTER,
'public/third-party/jquery/*.js',
'public/third-party/angular/angular.js',
'public/third-party/angular/i18n/angular-*.js',
'public/third-party/moment/moment.min.js',
'public/third-party/moment/moment-*.js',
'public/js/**/*.js',
'test/lib/**/*.js',
'test/unit/**/*.js'
];
colors = true;
autoWatch = true;
browsers = ['Firefox'];
junitReporter = {
outputFile: 'test_out/unit.xml',
suite: 'unit'
};
If anybody wants to see the full code, the application repository is here: https://github.com/adericbourg/GestionCourrier
Thanks a lot,
Alban
In your inject code
it('should convert static list object into its display value',
inject(function (staticList) {
expect(undefined).toBe('');
expect({key: 'A', value: 'B'}).toBe('B');
}));
replace "inject(function (staticList)" with "inject(function (staticListFilter)". This is some random convention angular is following. You can check comments on this page for more info http://docs.angularjs.org/tutorial/step_09
I faced similar problem, but in my case my filter name contained suffix 'Filter' which caused the same injection problem.
.filter('assetLabelFilter', function(){
return function(assets, selectedLabels){
// Implementation here
};
});
I was finally able to solve the problem by manually injecting the filter to my test
'use strict';
describe('assetLabelFilter', function() {
beforeEach(module('filters.labels'));
var asset1 = {labels: ['A']};
var asset2 = {labels: ['B']};
var asset3 = {labels: []};
var asset4 = {labels: ['A', 'B']};
var assets = [asset1, asset2, asset3, asset4];
var assetLabelFilter;
beforeEach(inject(function($filter) {
assetLabelFilter = $filter('assetLabelFilter');
}));
it('should return only assets with selected label', function() {
var selectedLabels = ['B'];
expect(assetLabelFilter(assets, selectedLabels)).toEqual([asset2, asset4]);
});
});
The nice answer above made me realize that in order to use the angular tutorial way:
it('should ', inject(function(assetLabelFilter) {
var selectedLabels = ['B'];
expect(assetLabelFilter(assets, selectedLabels)).toEqual([asset2, asset4]);
}));
The filter name can't have the suffix 'Filter' because it is magic word as mentioned in the answer above.
To demonstrate the scenario I also created a Plunker
I got little problem with combination busterjs+requirejs+backbone, structure of my project:
js-src
--lib //jquery, require, etc
--views
--models
-app.js //require config and start of app
js (compiled same structure as above)
test
-buster.js
-require-config.js
-test-test.js
require-config.js:
require.config({
baseUrl: 'js-src/',
paths: {
jquery: 'lib/jquery',
jplugins: 'lib/jquery.plugins',
underscore: 'lib/underscore',
backbone: 'lib/backbone'
},
shim: {
'backbone': {
deps: ['underscore', 'jplugins'],
exports: 'Backbone'
},
'jplugins': {
deps: ['jquery']
}
}
});
typical file exept off that in lib:
define(function (require) {
var $ = require('jquery'),
Backbone = require('backbone'),
otherElem = require('views/other'),
View = Backbone.View.extend({
el: '#el',
initialize: function () {
},
showLinks: function (value) {
},
render: function ) {
}
});
return View;
});
buster.js:
var config = module.exports;
config['browser-all'] = {
autoRun: false,
environment: 'browser',
rootPath: '../',
libs: [
'js-src/lib/require.js',
'test/require-config.js'
],
sources: [
'js-src/**/*.js'
],
tests: [
'test/*-test.js'
]
// extensions: [
// require('buster-amd')
// ]
};
test-test.js:
buster.spec.expose();
require(['views/View'], function (module) {
describe("An AMD module", function () {
it("should work", function () {
expect(true).toEqual(true);
});
});
});
When i run it using buster test i get:
Uncaught exception: ./js-src/lib/require.js:192 Error: Script error
http://requirejs.org/docs/errors.html#scripterror
TypeError: uncaughtException listener threw error: Cannot read property 'id' of undefined
at Object.uncaughtException (/usr/local/lib/node_modules/buster/node_modules/buster-test-cli/lib/runners/browser/progress-reporter.js:49:50)
at notifyListener (/usr/local/lib/node_modules/buster/node_modules/buster-core/lib/buster-event-emitter.js:37:31)
at Object.emit (/usr/local/lib/node_modules/buster/node_modules/buster-core/lib/buster-event-emitter.js:101:17)
at Object.emitCustom (/usr/local/lib/node_modules/buster/node_modules/buster-test-cli/lib/runners/browser/remote-runner.js:283:14)
at /usr/local/lib/node_modules/buster/node_modules/buster-test-cli/lib/runners/browser/remote-runner.js:89:16
at /usr/local/lib/node_modules/buster/node_modules/buster-test-cli/node_modules/buster-capture-server/lib/pubsub-client.js:79:47
at Object.trigger (/usr/local/lib/node_modules/buster/node_modules/buster-test-cli/node_modules/buster-capture-server/node_modules/faye/node/faye-node.js:383:19)
at Object.distributeMessage (/usr/local/lib/node_modules/buster/node_modules/buster-test-cli/node_modules/buster-capture-server/node_modules/faye/node/faye-node.js:666:30)
at Object._deliverMessage (/usr/local/lib/node_modules/buster/node_modules/buster-test-cli/node_modules/buster-capture-server/node_modules/faye/node/faye-node.js:1065:20)
at Object.<anonymous> (/usr/local/lib/node_modules/buster/node_modules/buster-test-cli/node_modules/buster-capture-server/node_modules/faye/node/faye-node.js:1004:12)
Firefox 16.0, Linux:
How to write proper test with that structure?
It will help if you run the browser tests and check the outputs in the console. The error messages therein are usually much more expressive. You should also remove the autoRun directive from the buster configuration and re-enable the "buster-amd" extension.
I'm new to Buster.js as of yesterday, but I'll add the following 4 part suggestion.
1.) Uncomment "extensions: [require('buster-amd')]" in your 'buster.js'
2.) Remove 'baseUrl' from your 'require.config'
3.) Explicitly set paths to your libs. For example "jplugins: 'lib/jquery.plugins'" would become "jplugins: 'js-src/lib/jquery.plugins'", this would also be needed for models, collections, views, and other files sitting on the 'js-src/' directory.
require.config({
paths: {
jquery: 'js-src/lib/jquery',
views: 'js-src/lib/views',
somerootfile: 'js-src/somerootfile'
4.) Change your test to be like this ...
describe('some test', function(run) {
require(['models/your_model'], function(YourModel) {
run(function() {
it('should load', function() {
var yourModel = new YourModel();
yourModel.set('cat', 'dog');
expect(YourModel.get('cat')).toEqual('dog');
});
});
});
});
The problem seems to be that the 'baseUrl' in 'require.config' confuse Buster.js and tell it to no long respect the 'rootPath' set in 'buster.js'.