I'm close to getting our tests to run with Karma but I'm missing the last step (I think), getting chai-jquery
to behave, I've tried two different plugins https://www.npmjs.com/package/karma-chai-jquery and https://www.npmjs.com/package/karma-jquery-chai with no success, even after following the specified order set in their various github issues or readme files.
This is my tests-main.js
file
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
allTestFiles.push(file);
}
});
require.config({
baseUrl: '/base',
paths: {
'chai': 'node_modules/chai/chai',
'chai-jquery': 'node_modules/chai-jquery/chai-jquery',
'jquery': '//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery',
'underscore': '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min',
'sn/sn-underscore': 'static/scripts/sn/sn-underscore',
'vendor/jquery-ui': '//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min'
},
deps: allTestFiles,
callback: window.__karma__.start
});
This is my karma.conf.js
(removed all non-crucial or default options)
// Karma configuration
module.exports = function(config) {
config.set({
basePath: '',
// Can't use chai in here for whatever reason
frameworks: ['mocha', 'requirejs'],
files: [
'static/scripts-test/test-main.js',
{pattern: 'node_modules/chai/chai.js', included: true},
{pattern: 'static/scripts-test/**/*.js', included: false},
{pattern: 'static/scripts/sn/**/*.js', included: false}
],
exclude: [
'static/scripts/global.js'
],
browsers: ['PhantomJS']
});
};
This is a "working" spec file, it correctly uses gets the references to chai
and jquery
, but loading chai-jquery
fails every time.
define([
'chai',
'jquery',
'static/scripts/sn/widgets/dismissable'
], function(chai, $) {
chai.should();
chai.expect();
describe('Dismissable', function() {
var $el = $('</p>'),
closeBtnSel = '.js-dismissable-close-btn';
beforeEach(function() {
$('body').append('<div id="fixtures"></div>');
$el.appendTo('#fixtures').dismissable({closeFn: 'hide'});
});
afterEach(function() {
$el.remove();
});
it('should correctly create the HTML', function() {
$(closeBtnSel).should.exist;
$el.should.have.class('dismissable');
});
});
});
The error that I get is:
TypeError: 'undefined' is not an object (evaluating '$(closeBtnSel).should.exist')
This is my directory structure:
- static/
- scripts/
- scripts-test/
- test-main.js
- node_modules/
- karma.conf.js
And finally, my package.json
{
"devDependencies": {
"chai": "^2.3.0",
"chai-jquery": "^2.0.0",
"jquery": "^2.1.4",
"karma-chai": "^0.1.0",
"karma-mocha": "^0.1.10",
"karma-requirejs": "*",
"mocha": "^2.2.5",
"requirejs": "^2.1.18",
"should": "^6.0.1"
}
}
Some of the errors I usually get:
When changing the order of the frameworks in the karma.conf
throw error('No provider for "' + name + '"!');
^
Error: No provider for "framework:chai"! (Resolving: framework:chai)
even after installing the plugin
Sometimes I'll get something like this:
Error: Mismatched anonymous define() module: function ($) {
return function (chai, utils) {
return chaiJquery(chai, utils, $);
};
}
Any help would be greatly appreciated here, I can't wrap my head around this.
EDIT: Small change based on recommendation from Louis
To install the "should" API, you should do chai.should()
, that is, call the function. The line var should = chai.should
is not doing anything useful.
It was not initially clear to me whether your issue with should
was causing a cascade of problems or if there was something else going on. I've taken a second look and found that there are indeed more problems.
There seem to be a bug in Karma there. See this issue, which is still open. There's also that issue which is closed but appears informative. So I've replaced the CDN with a local copy. Otherwise, I get:
ERROR: There is no timestamp for //cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js!
One problem is that you have to decide whether you want to load chai
with a script
element or through RequireJS. The code in your question tries to do both, which can cause problems. I've decided to have it be loaded by RequireJS. This means that it should have included: false
.
chai-jquery
Your test file is not loading chai-jquery
and not asking chai
to use it. So it is non-existent as far as your code is concerned. The intermittent loading problems you reported may be caused by code in other test files. The require.config
call has deps: allTestFiles
, but this does not specify any order. RequireJS is free to load the files in allTestFiles
in whatever order it wants.
I took the code you posted in your question as the basis for an example. Obviously, I do not have all the code you have on your side.
Here is the new karma.conf.js
:
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['mocha', 'requirejs'],
files: [
'static/scripts-test/test-main.js',
{pattern: 'node_modules/chai/chai.js', included: false},
{pattern: 'node_modules/jquery/dist/jquery.min.js',
included: false},
{pattern: 'node_modules/chai-jquery/chai-jquery.js',
included: false},
{pattern: 'static/scripts-test/**/*.js', included: false},
{pattern: 'static/scripts/sn/**/*.js', included: false}
],
exclude: [
'static/scripts/global.js'
],
browsers: ['PhantomJS']
});
};
The new static/scripts-test/test-main.js
which loads jQuery locally:
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
allTestFiles.push(file);
}
});
require.config({
baseUrl: '/base',
paths: {
'chai': 'node_modules/chai/chai',
'chai-jquery': 'node_modules/chai-jquery/chai-jquery',
'jquery': 'node_modules/jquery/dist/jquery.min',
'underscore': '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min',
'sn/sn-underscore': 'static/scripts/sn/sn-underscore',
'vendor/jquery-ui': '//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min'
},
deps: allTestFiles,
callback: window.__karma__.start
});
A correct test file named static/scripts-test/foo.spec.js
, note the use of chai.use(chai_jquery)
:
define([
'chai',
'jquery',
'chai-jquery',
], function(chai, $, chai_jquery) {
chai.should();
chai.use(chai_jquery);
describe('example', function() {
it('body should exist', function() {
$(document.body).should.exist;
});
it('#blah should not exist', function() {
$("#blah").should.not.exist;
});
});
});
The code above runs without problem:
WARN [watcher]: Pattern "/tmp/t5/static/scripts/sn/**/*.js" does not match any file.
INFO [karma]: Karma v0.12.37 server started at http://localhost:9876/
INFO [launcher]: Starting browser Chrome
INFO [Chrome 43.0.2357 (Linux 0.0.0)]: Connected on socket Za9vBp9shDedsIhcNn63 with id 48683492
Chrome 43.0.2357 (Linux 0.0.0): Executed 2 of 2 SUCCESS (0.005 secs / 0.002 secs)
I use Chrome as my browser but that's the only difference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With