Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

testing code transpiled for es6

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']
        }
    }
  });
};
like image 554
BrainLikeADullPencil Avatar asked Feb 27 '15 00:02

BrainLikeADullPencil


Video Answer


2 Answers

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).

like image 142
user5321531 Avatar answered Sep 29 '22 11:09

user5321531


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.

like image 41
Tyler Eich Avatar answered Sep 29 '22 11:09

Tyler Eich