I'm preparing to write some tests with Qunit for a Backbone app that is written for ES6 with babel.js applied to it so that it can run in contemporary browsers. To ensure that I have qunit set up properly and all the paths properly specified, I first tested an Backbone model written in ES5 and everything worked as expected. However, I then included bundle.js
(which contains the results of my ES6 code with babel.js applied to it) into my tests/index.html
, and wrote
test ( "Code transformed by babel.js contained in bundle.js can be tested", function(){
expect(1);
var es6model = new ES6Model();
equal( es6model.get("defaultproperty"), "defaultstring", "defaultproperty should be defaultstring");
})
and it's telling me ES6Model
is not defined.
Question: is there something about code transformed by babeljs that would make it more challenging to be tested using Qunit?
In addition to all the complex js that babel writes at the top of the file, the code in bundle.js
looks like this
var Model = Backbone.Model;
var View = Backbone.View;
var Collection = Backbone.Collection;
var Router = Backbone.Router;
var LocalStorage = Backbone.LocalStorage;
var ES6Model = (function (Model) {
function ES6Model() {
_classCallCheck(this, ES6Model);
if (Model != null) {
Model.apply(this, arguments);
}
}
_inherits(ES6Model, Model);
_prototypeProperties(Gopher, null, {
defaults: {
value: function defaults() {
return {
defaultproperty: "defaultstring"
};
},
writable: true,
configurable: true
}
});
return ES6Model;
})(Model);
Update
I include all the code created by babel.js in a file called bundle.js
and include that in my index.html like I would any other js file, and it runs without issue, which is why I assumed I could test it like any other js code. However, it should be noted (as the commenter pointed out) that the code created by babel.js is contained in a module..this is how bundle.js begins with the model I'm trying to test coming after
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";
Update
I am using browserify to apply babel to the various files of my ES6 code which creates a bundle. To run the tests, I do npm run test
and to compile the bundle, I try both of these (one of them uses modules --ignore
) but neither of them work
"scripts": {
"test": "./node_modules/karma/bin/karma start --log-level debug",
"build-js": "browserify app/app.js app/views.js app/models.js app/d3charts.js -t babelify > app/bundle.js",
"t-build": "browserify app/app.js app/views.js app/models.js app/d3charts.js -t [babelify --modules ignore] > app/test/test-bundle.js"
},
(The application is a Backbone.js app).
This is my karma config file. I don't have any further configuration (so I'm guessing my inclusion of karma-require is a waste but maybe necessary...)
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['qunit'],
plugins: ['karma-qunit', 'karma-phantomjs-launcher', 'karma-requirejs'],
files : [
'app/test/jquery.js',
'app/test/d3.js',
'app/test/json2.js',
'app/test/underscore.js',
'app/test/backbone.js',
'app/backbone.localStorage.js',
'app/test/test-bundle.js',
'app/test/tests.js'
],
reporters: ['progress'],
// web server port
port: 8080,
// 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: false,
// 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: true,
// See http://stackoverflow.com/a/27873086/1517919
customLaunchers: {
Chrome_sandbox: {
base: 'Chrome',
flags: ['--no-sandbox']
}
}
});
};
For reference they way to do this with traceur is to compile the traceur-runtime.js file into the code (see https://github.com/google/traceur-compiler/issues/777 - a similar variable not defined error).
E.g.
traceur --out out/src/yourcode.js --script lib/traceur-runtime.js --script test/yourcode.js
(see Compiling Offline https://github.com/google/traceur-compiler/wiki/Compiling-Offline).
Import the Babel-generated module into your test before executing (recommended)
You'll need to include a module loader (e.g. SystemJS) to handle the imports. Babel has excellent documentation for its module system.
It looks something like this:
System.import( 'path/to/ES6Module' )
.then( function( ES6Module ) {
// … Run your tests on ES6Module here
});
Note: System.import()
returns a Promise
, so your test suite will need to support asynchronous operations.
Tell Babel to skip module generation (simpler)
You can tell Babel not to wrap your code in a module using the --modules ignore
flag. This allows your code to set up global variables, immediately available to your unit tests. Global variables are not recommended (especially in production systems), but they are simpler to apply.
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