Webpack (AMD) + Karma + Mocha

Tomas AlabesTomas Alabes
3 min read

Here's the situation:

  • You bundle your app/library with output.libraryTarget = amd (and for the sake of the example let's say that also output.library = "myLibrary")
  • You want to test it using Mocha
  • You want to run your tests using Karma

I had a few challengues here and I haven't found any documentation about it so I thought this might be useful to somebody.

You have to use:

  • karma-mocha to run your mocha tests with karma. You can also use whatever test framework they support
  • karma-requirejs to load your amd app, this is key, we'll see why.

First, the obvious:

npm i -D karma-mocha karma-requirejs

You might need to install other peer dependencies like requirejs and mocha.

In your karma.conf.js:

module.exports = function(config) {
    config.set({

        // add the installed frameworks here
        frameworks: ["mocha", "requirejs"],

        files: [
            //here we include all tests, see the file below
            "src/test/index.js",
            //this is the file that will require our amd bundle, see the file below
            "src/test/runner.js",
        ],

        preprocessors: [
            // preprocess all your tests with webpack, so you bundle all the necessary dependencies
            "src/test/index.js" : ["webpack"]
        ],

        // load plugins
        plugins: [
            require("karma-mocha"),
            require("karma-requirejs")
        ]
    });
};

Karma will load (you can see all this if you run the tests with a browser, in the debug.html)

<!-- ... -->
<!-- Dynamically replaced with <script> tags -->
<script type="text/javascript" src="/base/node_modules/requirejs/require.js"></script>
<script type="text/javascript" src="/base/node_modules/karma-requirejs/lib/adapter.js"></script>
<link type="text/css" href="/base/node_modules/mocha/mocha.css" rel="stylesheet">
<script type="text/javascript" src="/base/node_modules/mocha/mocha.js"></script>
<script type="text/javascript" src="/base/node_modules/karma-mocha/lib/adapter.js"></script>
<script type="text/javascript" src="/base/src/test/js/index.js"></script>
<script type="text/javascript" src="/base/src/test/js/runner.js"></script>
<script type="text/javascript">
  window.__karma__.loaded();
</script>
<!-- ... -->
  1. The karma runner code
  2. requirejs and requirejs-adapter.
  3. mocha and mocha-adapter
  4. Your index.js bundle (as you defined your libraryTarget: amd it will just define your module)
  5. And your runner.js that will require your myLibrary module.
  6. The script that starts the tests, enclosed in a script tag.

It's important that you use karma-requirejs instead of just requirejs from your bower_components or node_modules, because what you really need is the requirejs-adapter, why?

As the execution of your tests is asynchronous, the call to window.__karma__.loaded() would be done before executing the tests. The requirejs-adapter overrides the __karma__.loaded function to do nothing and waits for your call to window.__karma__.start() (karma's "loaded()" calls "start()").

Hence:

index.js

// require all modules ending in "_test" from the
// current directory and all subdirectories
var testsContext = require.context(".", true, /_test$/);
testsContext.keys().forEach(testsContext);

So the runner needs to load your amd library and tell karma to start running the tests!

runner.js

require(["myLibrary"], function(myLibrary){
    // probably you don't want to do anything with your library here
    // I didn't...

    console.log("Let the tests begin...");

    // now that our bundle with the tests are loaded, run the tests!
    window.__karma__.start();

});

This way, your app + tests are loaded and required, and your tests can be ran by karma.

I figured all these out by using these resources:

  • https://karma-runner.github.io/0.13/plus/requirejs.html
  • https://github.com/karma-runner/karma-requirejs
  • https://github.com/kjbekkelund/karma-requirejs

Hope it helps! Till the next one.

0
Subscribe to my newsletter

Read articles from Tomas Alabes directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Tomas Alabes
Tomas Alabes