Developing on Staxmanade

Testing Asynchronous Code with MochaJS and ES7 async/await

(Comments)

A JavaScript project I'm working on recently underwent a pretty good refactor. Many of the modules/methods in the application worked in a synchronous fashion which meant their unit tests were also generally synchronous. This was great because synchronous code is pretty much always easier to test since they're simpler and easier to reason about.

However, even though I new early on that I would likely have to turn a good number of my synchronous methods into asynchronous ones I tried holding off on that as long as absolutely necessary. I was in a mode of prototyping as much of the application out as possible before I wanted to be worried/thinking about asynchronous aspects of the code base.

Part of why I held of on this was because I was pretty confident using the new proposed ES7 async/await syntax to turn the sync code into async code relatively easily. While there were a few bumps along the refactor actually went extremely well.

An example of one bump I ran into included replacing items.forEach(item => item.doSomethingNowThatWillBecomeAsyncSoon()) with something that worked asynchronously and I found this blog post immensely helpful. Basically, don't try to await a forEach instead build a list of promises you can await.

Another one I ran into was dealing with async mocha tests, which is what the rest of this post is about.

MochaJS is great because the asynchronous testing has been there from the beginning. If you've done (see what I did there?) any asynchronous testing with MochaJS then you already know that you can signal to Mocha an asynchronous test is done by calling the test's async callback method.

Before we look at how to test asynchronous Mocha tests leveraging the new ES 7 async/await syntax, let's first take a little journey through some of the various asynchronous testing options with Mocha.

Note: you will see example unit tests that use the expect(...).to.equal(...) style assertions from ChaiJS.

How to create an asynchronous MochaJS test?

If you look at a normal synchronous test:

it("should work", function(){
    console.log("Synchronous test");
});

all we have to do to turn it into an asynchronous test is to add a callback function as the first parameter in the mocha test function (I like to call it done) like this

it("should work", function(done){
    console.log("Synchronous test");
});

But that's an invalid asynchronous test.

Invalid basic async mocha test

This first async example test we show is invalid because the done callback is never called. Here's another example using setTimeout to simulate proper asynchronicity. This will show up in Mocha as a timeout error because we never signal back to mocha by calling our done method.

it("where we forget the done() callback!", function(done){
    setTimeout(function() {
        console.log("Test");
    }, 200);
});

Valid basic async mocha test

When we call the done method it tells Mocha the asynchronous work/test is complete.

it("Using setTimeout to simulate asynchronous code!", function(done){
    setTimeout(function() {
        done();
    }, 200);
});

Valid basic async mocha test (that fails)

With asynchronous tests, the way we tell Mocha the test failed is by passing an Error or string to the done(...) callback

it("Using setTimeout to simulate asynchronous code!", function(done){
    setTimeout(function() {
        done(new Error("This is a sample failing async test"));
    }, 200);
});

Invalid async with Promise mocha test

If you were to run the below test it would fail with a timeout error.

it("Using a Promise that resolves successfully!", function(done) {
    var testPromise = new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve("Hello!");
        }, 200);
    });

    testPromise.then(function(result) {
        expect(result).to.equal("Hello World!");
        done();
    }, done);
});

If you were to open up your developer tools you may notice an error printed to the console:

    Uncaught (in promise) i {message: "expected 'Hello!' to equal 'Hello World!'", showDiff: true, actual: "Hello!", expected: "Hello World!"}

The problem here is the expect(result).to.equal("Hello World!"); above will fail before we can signal to Mocha via the done() of either an error or a completion which causes a timeout.

We can update the above test with a try/catch around our expectations that could throw exceptions so that we can report any errors to Mocha if they happened.

it("Using a Promise that resolves successfully with wrong expectation!", function(done) {
    var testPromise = new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve("Hello World!");
        }, 200);
    });

    testPromise.then(function(result){
        try {
            expect(result).to.equal("Hello!");
            done();
        } catch(err) {
            done(err);
        }
    }, done);
});

This will correctly report the error in the test.

But there is a better way with promises. (mostly)

Mocha has built-in support for async tests that return a Promise. However, run into troubles with async and promises in the hook functions like before/beforEach/etc.... So if you keep reading you'll see a helper function that I've not had any issues with (besides it's a bit more work...).

Thanks to a comment from @syrnick below, I've extended this write-up...

Async tests can be accomplished in two ways. The first is the already shown done callback. The second is if you returned a Promise object from the test. This a great building block. The above example test has become a little verbose with all the usages of done and the try/catch - it just gets a little cumbersome to write.

If we wanted to re-write the above test we can simplify it to return just promise.

IMPORTANT: if you want to return a promise, you have to remove the done callback or mocha will assume you'll be using that first and not look for a promise return. Although I've seen comments in Mocha's github issues list where some people depend on it working with both a callback and a promise - you're mileage may vary.

Here's an example of returning a Promise that correctly fails the test with the readable error message from Chaijs.

it("Using a Promise that resolves successfully with wrong expectation!", function() {
    var testPromise = new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve("Hello World!");
        }, 200);
    });

    return testPromise.then(function(result){
        expect(result).to.equal("Hello!");
    });
});

The great thing here is we can remove the second error promise callback (where we passed in done) as Mocha should catch any Promise rejections and fail the test for us.

Running the above test will result in the following easy to understand error message:

AssertionError: expected 'Hello!' to equal 'Hello World!'

Turn what we know above into async/await.

Now that we know there are some special things we need to do in our async mocha tests (done callbacks and try/catch or Promises) let's see what happens if we start to use the new ES7 async/await syntax in the language and if it can enable more readable asynchronous unit tests.

The beauty of the async/await syntax is we get to reduce the .then(callback, done)... mumbo jumbo and turn that into code that reads like it were happening synchronously. The downside of this approach is that it's not happening synchronously and we can't forget that when we're looking at code and starting to use it this way. But overall it is generally easier to reason about in this style.

The big changes from the above Promise style test and the transformed async test below are:

  1. Place the async word in front of the async function(done){.... This tells the system that inside of this function there may (or may not be) the use of the await keyword and in the end the function is turned into a Promise under the hood. a Promise to simplify our unit tests.
  2. We replace the .then(function(result){ promise work and in place use the await keyword to have it return the promise value assign it to result so after that we can run our expectations against it.
  3. Remove the done callback. If you aren't aware, async/await is a fancy compiler trick that under-the-hood turns the code into simple Promise chaining and callbacks. So we can use what we learned above about Mocha using 5. return the Promise.

If we apply the 5 notes listed above, we see that we can greatly improve the test readability.

it("Using a Promise with async/await that resolves successfully with wrong expectation!", async function() {
    var testPromise = new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve("Hello World!");
        }, 200);
    });

    var result = await testPromise;

    expect(result).to.equal("Hello!");
});

Notice the async function(){ part above turns this into a function that will (under-the-hood) return a promise that should correclty report errors when the expect(...) fails.

Handling errors with async/await

One interesting implementation detail around async await is that exceptions and errors are handled just like you were to handle them in synchronous code using a try/catch. While under-the-hood the errors turn into rejected Promises.

NOTE: You're mileage may vary with the async/await and mocha tests with promises. I tried playing around with async in mocha hooks like before/beforeEach but ran into some troubles.

Since there may or may-not be issues with mocha hook methods, one work-around is to leverage a try/catch and the done callback to manually handle exceptions. You may run into this so I'll show examples of how to avoid relying on Mocha to trap errors.

Below shows the (failing) but alternative way (not using a return Promsie) but using the done callback instead.

it("Using a Promise with async/await that resolves successfully with wrong expectation!", async function(done) {
    var testPromise = new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve("Hello World!");
        }, 200);
    });

    try {
        var result = await testPromise;

        expect(result).to.equal("Hello!");

        done();
    } catch(err) {
        done(err);
    }
});

Removing the test boilerplate

One I started seeing the pattern and use of try/catch boilerplate showing up in my async tests, it became apparent that there had to be a more terse approach that could help me avoid forgetting the try/catch needed in each async test. This was because I would often remember the async/await syntax changes for my async tests but would often forget the try/catch which often resulted in timeout errors instead of proper failures.

another example below with the async/await and try/catch

it("Using an async method with async/await!", async function(done) {
    try {
        var result = await somethingAsync();

        expect(result).to.equal(something);

        done();
    } catch(err) {
        done(err);
    }
});

So I refactored that to reduce the friction.

And the mochaAsync higher order function was born

This simple little guy takes an async function which looks like async () => {...}. It then returns a higher order function which is also asynchronous but has wrapped your test function in a try/catch and also takes care of calling the mocha done in the proper place (either after your test is asynchronously completed, or errors out).

var mochaAsync = (fn) => {
    return async (done) => {
        try {
            await fn();
            done();
        } catch (err) {
            done(err);
        }
    };
};

You can use it like this:

it("Sample async/await mocha test using wrapper", mochaAsync(async () => {
    var x = await someAsyncMethodToTest();
    expect(x).to.equal(true);
}));

It can also be used with the mocha before, beforeEach, after, afterEach setup/teardown methods.

beforeEach(mochaAsync(async () => {
    await someLongSetupCode();
}));

In closing.

This post may have seemed like quite a journey to get to the little poorly named mochaAsync or learn to use Mocha's Promise support but I hope it was helpful and I can't wait for the async/await syntax to become mainstream in JavaScript, but until then I'm thankful we have transpiling tools like Babel so we can take advantage of these features now. ESNext-pecially in our tests...

Happy Testing!

In App Unit test example with JSPM, React, WinJS and Mocha

(Comments)

A while back I wrote about In App Unit Tests and have been having too much fun creating little starter plunks on Plunker. So...

As a simple demonstration on in-app unit tests I've thrown together a little plunk that shows in-app tests within the a WinJS Pivot. And add to the layers of abstraction I'm using react-winjs which I'm LOVING over normal WinJS development.

Link to: JSPM/React/WinJS/Mocha Plunk

If you like this starter, I have it and a few more linked here: for re-use

I'd like to highlight this particular starter at bit more in this post, not only because there are a few more concepts to this basic plunk, but also because I'm fairly happy with the MochaJS React component that I've now copied around and re-used a few times in some small projects where use In App Unit Tests.

Plunker file overview

  • index.html - The index file is a very basic JSPM bootstrap page that loads the app.jsx react component.
  • app.jsx - Defines a WinJS Pivot control where we render the in-app MochaTests.jsx React component. This also defines the test file(s) and using MochaJS's global detection we can tell the react MochaTests component what test files to load and run as well as what globals are allowed to exist.
  • config.js - This is JSPM's config that defines what version of React we're using and to use babel for transpilation.
  • tests.js - is our Mocha set of unit tests. We can have multiple test files if we want, just have to define what files to load in app.jsx.

Lastly the MochaTests.jsx which I'll include the full component below:

easier to copy-paste inherit for myself in the future

import mocha from 'mocha';
import React from 'react';

export default class MochaTests extends React.Component {

    static get propTypes() {
        return {
            testScripts: React.PropTypes.array.isRequired,
            allowedGlobals: React.PropTypes.array
        };
    }

    constructor(props) {
        super(props);
    }

    componentDidMount() {

        var testScripts = this.props.testScripts;
        var runTests = this.runTests.bind(this);

        // for some reason importing mocha with JSPM and ES6 doesn't
        // place the mocha globals on the window object. The below
        // handles that for us - as well as setting up the rest of the
        // test scripts for the first run
        mocha.suite.on('pre-require', context => {
            var exports = window;

            exports.afterEach = context.afterEach || context.teardown;
            exports.after = context.after || context.suiteTeardown;
            exports.beforeEach = context.beforeEach || context.setup;
            exports.before = context.before || context.suiteSetup;
            exports.describe = context.describe || context.suite;
            exports.it = context.it || context.test;
            exports.setup = context.setup || context.beforeEach;
            exports.suiteSetup = context.suiteSetup || context.before;
            exports.suiteTeardown = context.suiteTeardown || context.after;
            exports.suite = context.suite || context.describe;
            exports.teardown = context.teardown || context.afterEach;
            exports.test = context.test || context.it;
            exports.run = context.run;

            // now use SystemJS to load all test files
            Promise
            .all(testScripts.map(function(testScript) {
                console.log("Adding Mocha Test File: ", testScript);
                return System.import(testScript);
            })).then(runTests, function(err) {
                console.error("Error loading test modules");
                console.error(err);
            });

        });
        mocha.setup('bdd');
    }

    runTests() {
        var allowedGlobals = this.props.allowedGlobals || [];

        this.refs.mocha.getDOMNode().innerHTML = "";

        mocha.checkLeaks();
        mocha.globals(allowedGlobals);
        mocha.run();

    }

    render() {
        return (
            <div>
                <style>{"\
                  #mocha-stats em { \
                      color: inherit; \
                  } \
                  #mocha-stats { \
                    position: inherit; \
                  }\
                  #mocha .test.fail pre { \
                      color: red; \
                  } \
                "}</style>

                <button onClick={this.runTests.bind(this)}>Rerun Tests</button>

                <div id="mocha" ref="mocha"></div>
            </div>
        );
    }
}

Usage example of this React MochaTests component.

// Define what test files get loaded by the MochaTests component
var testScripts = [
  './tests.js'
];


var allowedTestGlobals = [
  // Declare what globals are allowed to be created during any test runs.
];


// Usage of MochaTests in a react render() method.
<MochaTests testScripts={testScripts} allowedGlobals={allowedTestGlobals} />

I'm not expecting to see a large up-tick in WinJS apps out there with in-app unit tests that run in the browser, however hopefully the MochaTests.jsx React Component is of value to you and can be utilized outside of WinJS within almost any React app.

Please drop a line if you end up using it or if it can be adapted. If there's value in the component, maybe

Known Issue

If the number of tests starts to go beyond the height of the pivot in this sample, it has an issue where the WinJS Pivot cuts off at the bottom not allowing you to scroll and see the rest of the test output. I haven't dug into it yet because I've been clicking the failures: X link and it filters the U.I. to just the erroring tests.

If you happen to come up with a good solution, drop me a note - I'd love it. Thanks in advance!

Happy Testing!

JSMP/SystemJS Starter Plunker

(Comments)

I'm writing this post more for myself as a quick way to get going with JSPM, but if you find it useful please feel free.

Since I've recently been playing with JSPM, I've found it useful to kick-start my prototyping with a plunk. I've created a number of starter plunks below (and continue to add to the list.

Full list of JSPM starter plunks

JSPM Starter

JSPM, React

JSPM, MochaJS

JSPM, React, MochaJS

JSPM, React, MochaJS, (Sample jsx Component test)

JSPM, React, WinJS

JSPM, React, WinJS, MochaJS


How to use:

  1. Click one of the links above
  2. Review the various files. Open and edit the app.js file
  3. Start writing code!

Be sure to open your developer tools and monitor any console output for errors...

If you want to take more of a test driven approach to your prototype take a look at MochaJS with JSPM or go directly to the JSPM/MochaJS Plunk

Happy Prototyping!

Browser only MochaJS tests using SystemJS

(Comments)

I've been poking at SystemJS (you may have heard of it through JSPM) and one of the first things I like to setup when playing with a new JS framework is a way to run MochaJS unit tests which allow me to test-drive my prototypes and in this case the best part is we don't have to do any local command line installations or crazy gulp/grunt builds. We can right in the browser start writing plain ES6 and prototype using a library from npm or github.

SystemJS is a very exciting project with it's ability to import modules/code right from you're JS code itself. You can write you're JS using ES6 import syntax and in many cases SystemJS will magically import code via NPM or GitHub directly.

TL;DR

If you want to skip the details below and just see the plnkr.co go right ahead!

How to run our first Mocha test

First we need to get a simple web page setup. I'm going to use plnkr.co as it allows me to specify multiple files. This will allow me to more easily componentize my code for cleaner extraction into a project, gist or other...

Once you have a basic Plunker setup go ahead and delete everything except index.html of for now.

Now we're ready to start throwing our code in here... But before you do open you're browser's developer tools. I'm using Chrome on the Mac so Cmd+Option+j will do it. We need to be able to see the javascript console in case we see any errors with SystemJS loading of modules.

index.html <- paste the below in for you're Plunker index.html.

<!DOCTYPE html>
<html>

<head>
  <script src="https://jspm.io/system@0.18.js"></script>
  <script type="text/javascript">
    System.import('./testInit.js');
  </script>
</head>

<body>
</body>

</html>

With the above in the index.html you should see some errors printed to the console as SystemJS is trying to load ./testInit.js (but we haven't created it yet).

Before we create the testInit.js file let's first create a couple sample MochaJS test files that we want to test.

Here's our first test file: name it mochaTest1.js

Something cool about this test is once we get mocha wired up correctly, this test shows how seamlessly you can take a dependency on a 3rd party library like chaijs for help with assertions.

import { expect } from 'chai';

describe("This is a describe", function() {
  it("sample test that should pass", function() {
    expect(true).to.equal(true);
  });
  it("sample test that should fail", function() {
    expect(true).to.equal(false);
  });
});

Create another test file mochaTest2.js

import { expect } from 'chai';

describe("This is another describe", function() {
  it("sample test that should pass", function() {
    expect(true).to.equal(true);
  });
  it("sample test that should fail", function() {
    expect(true).to.equal(false);
  });
});

Creating two test files allows this sample to show how you can easily create and test multiple modules.

The meat and potatoes

Now is the juicy part on how to get Mocha to play nicely with this setup and run our tests.

Create a file and call it testInit.js (same as we named in our index.html and referenced it via System.import('./testInit.js')) and paste the below.

Feel free to read through it as I commented it thoroughly.

//
// This tells SystemJS to load the mocha library
// and allows us to interact with the library below.
//
import mocha from 'mocha';

//
// This defines the list of test files we want to load and run tests against.
//
var mochaTestScripts = [
  './mochaTest1.js',
  './mochaTest2.js'
];

//
// If you have a global or two that get exposed from your
// tests that is expected you can include them here
//
var allowedMochaGlobals = [
  'jQuery'
]


//
// Mocha needs a <div id="mocha"></div> for the browser
// test reporter to inject test results in to the U.I.
// Below just injects it at the bottom of the page. (You can get fancy here)
// Maybe you create a button in your website and allow anyone to run tests.
// Check out http://staxmanade.com/2015/03/in-app-unit-tests/ for more on the thought
//
var mochaDiv = document.createElement('div');
mochaDiv.id = "mocha";
document.body.appendChild(mochaDiv);

//
// Importing mocha with JSPM and ES6 doesn't expose the usual mocha globals.
// I found this is one way to manually expose the globals, however if you know of a better way please let me know...
//
mocha.suite.on('pre-require', function(context) {
  var exports = window;

  exports.afterEach = context.afterEach || context.teardown;
  exports.after = context.after || context.suiteTeardown;
  exports.beforeEach = context.beforeEach || context.setup;
  exports.before = context.before || context.suiteSetup;
  exports.describe = context.describe || context.suite;
  exports.it = context.it || context.test;
  exports.setup = context.setup || context.beforeEach;
  exports.suiteSetup = context.suiteSetup || context.before;
  exports.suiteTeardown = context.suiteTeardown || context.after;
  exports.suite = context.suite || context.describe;
  exports.teardown = context.teardown || context.afterEach;
  exports.test = context.test || context.it;
  exports.run = context.run;

  // now use SystemJS to load all test files
  Promise
    .all(mochaTestScripts.map(function(testScript) {
      return System.import(testScript);
    })).then(function() {
      mocha.checkLeaks();
      mocha.globals(allowedMochaGlobals);
      mocha.run();
    }, function(err) {
      console.error("Error loading test modules");
      console.error(err);
    });

});

mocha.setup('bdd');

Please let me know if you know of an easier way to get access to the mochas globals using SystemJS. The below works, but is a bit uncomfortable.

MochaJS Tests Right in the Browser...

How awesome is this. Couple bits of bootstrap code, and we can go author whatever we want right in the browser using ES6 (err EcmaScript 2015) and we're off and running.

warning NOT FOR PRODUCTION WORKFLOWS (yet)! warning

This approach is primarily for allowing quick prototyping. Don't implement a complete app like this and then expect any performance. SystemJS can potentially download a large number of dependencies and you should read up on JSPM production workflows.

Happy Browser-Only Testing.

Running in-app mocha tests within WinJS

(Comments)

I described a while back a scenario about running in-app unit tests. So if you'd like some background on the subject have a look there before reading here.

This post is going to give some specifics about how to run MochaJS tests within a Microsoft Windows JavaScript application (WinJS).

Prerequisites

These steps assume you already have a WinJS application, possibly using the universal template or other. In the end it doesn't matter. As long as you have a project that probably has a default.html file and the ability to add js & css files to.

Get Mocha

You can acquire the mocha library however you want, Bower, Npm, or download it manually from the site (mochajs.org).

Reference Mocha Within Project & App

However you get the mocha source, you need to both add references to the mocha js and css files into your project file either in a *.jsproj file or if using a universal shared app, in the shared project.

Then you need to include a reference to the code in your default.html file.

In my example below you can see I used bower to download the MochaJS library.

The mocha.setup('bdd') tells mocha to use the BDD style of tests which defines the describe(...), it(...), etc functions.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>MyApp.Windows</title>

    <!-- WinJS references -->
    <link href="/js/bower_components/winjs/css/ui-light.css" rel="stylesheet" />
    <script src="/js/bower_components/winjs/js/base.js"></script>
    <script src="/js/bower_components/winjs/js/ui.js"></script>

    <!-- TESTS-->
    <link href="/js/bower_components/mocha/mocha.css" rel="stylesheet" />
    <script src="/js/bower_components/mocha/mocha.js"></script>
    <script>
        mocha.setup('bdd');
    </script>

    <!-- My Project js/css files below... -->

...Rest of default.html file excluded

Create a WinJS Control for hosting Mocha reporting.

Below is a sample WinJS control that can be used to host the mocha html report.

<!DOCTYPE html>
<html>
<head>
    <style>
        #mocha {
            height: 800px;
            width: 600px;
            overflow: scroll;
        }
    </style>
</head>
<body>
    <div class="fragment section1page">
        <section aria-label="Main content" role="main">

            <!-- define a button that we can use to manually run or re-run tests -->
            <button id="mochaTestsRun">Run Tests</button>

            <!-- define a checkbox that allow us to toggle auto-run 
                 of the tests when we start up the app -->
            Auto start <input type="checkbox" id="mochaTestsRunOnStart" />


            <!-- this is a blank div we use to inject U.I. related tests -->
            <div id="testElementContainer"></div>

            <!-- mocha throws the html output in the below div -->
            <div id="mocha"></div>
        </section>
    </div>
</body>
</html>
(function () {
    "use strict";

    var runMochaTests = function() {
        // clear any current test results since mocha just appends.
        element.querySelector('#mocha').innerHTML = "";
    
        // If you want your tests to verify nothing is leaked globally...
        mocha.checkLeaks();

        // specify any globals that you are OK with your tests leaking
        mocha.globals([
            'someGlobalIAmExpecting'
        ]);

        // start the test run
        mocha.run();
    }

    var ControlConstructor = WinJS.UI.Pages.define("/js/tests/tests.html", {
        // This function is called after the page control contents 
        // have been loaded, controls have been activated, and 
        // the resulting elements have been parented to the DOM. 
        ready: function (element, options) {
            options = options || {};

            // get our possibly already cached value of whether to run the tests on startup.
            var runOnStart = (JSON.parse(localStorage.getItem("mochaTestsRunOnStart") || "true"));

            // checkbox to manage auto-run state
            var runOnStartCheckbox = element.querySelector('#mochaTestsRunOnStart');
            runOnStartCheckbox.addEventListener('change', function () {
                localStorage.setItem("mochaTestsRunOnStart", runOnStartCheckbox.checked);
            });

            // button to manually trigger a test run
            var mochaTestsRunButton = element.querySelector('#mochaTestsRun');
            mochaTestsRunButton.addEventListener('click', function(){
                runMochaTests();
            })
            runOnStartCheckbox.checked = runOnStart;

            if (runOnStart && !window.hasRunMochaTestsAtLeastOnce) {
                // this value is used to avoid extra test runs as we navigation around the app.
                // EX: if the test control is on a home pivot - we nav away and come back home
                // we probably don't want to auto-run the tests again. (use the menu button 
                // instead if you want another test run)
                window.hasRunMochaTestsAtLeastOnce = true;
                runMochaTests();
            }

        },
    });

    // The following lines expose this control constructor as a global. 
    // This lets you use the control as a declarative control inside the 
    // data-win-control attribute. 

    WinJS.Namespace.define("MyApp.Testing.Controls", {
        TestsControl: ControlConstructor
    });
})();

Handle global exceptions

If you write any async code (difficult not to these days) an exception or assertion failure will not be trapped by the internal try/catch mechanism's of Mocha in a Windows WinJS environment.

We have to give Mocha a hint on how to hook into global exceptions.

Mocha tries to attach to the browser's global window.onerror method, and since a WinJS app doesn't use this same handler, we have to forward the exceptions and to mocha's attached window.onerror handler.

In you're default.js or wherever you configure the app you can attach to the WinJS.Application.onerror and after some exception massaging we can hand the exceptions to mocha so when a test fails it can be reported correctly.

    WinJS.Application.onerror = function (ex) {

        var errorMessage, errorLine, errorUrl;
        if (ex.detail.errorMessage) {
            errorMessage = ex.detail.errorMessage;
            errorLine = ex.detail.errorLine;
            errorUrl = ex.detail.errorUrl;
        } else if (ex &&
            ex.detail &&
            ex.detail.exception &&
            ex.detail.exception.stack) {
            errorMessage = ex.detail.exception.stack;
            errorLine = null;
            errorUrl = null;
        }

        // if window.onerror exists, assume mochajs is here and call it's error handler
        // This may be a poor assumption because 3rd party libraries could also attach
        // their handlers, but it's working for me so far...
        if (window.onerror && errorMessage) {
            window.onerror(errorMessage, errorLine, errorUrl);
            
            // return true signalling that the error's been 
            // handled (keeping the whole app from crashing)
            return true;
        }

        // if we get here, assuming mochajs isn't running
        // let's log out the errors...
        try {
            var exMessage = JSON.stringify(ex, null, '  ');
            console.error(exMessage);
        } catch (e) {
            // can't JSON serialize exception object here (probably circular reference)
            // log what we can...
            console.error(ex);
            console.error(e);
        }

        // I like to be stopped while debugging to possibly
        // poke around and do further inspection
        debugger;
    }

Reference the test control.

While developing out the application, I like to throw it front and center in the first hub of my apps home page hub control.

Here's an example of how to reference the above control:

<head>
    <meta charset="utf-8" />
    <title>hubPage</title>

    <link href="/pages/hub/hub.css" rel="stylesheet" />
    <script src="/js/tests/tests.js"></script>
</head>

...page details trimmed for brevity...

            <div class="hub" data-win-control="WinJS.UI.Hub">

                <div class="sectionTests"
                     data-win-control="WinJS.UI.HubSection"
                     data-win-options="{ isHeaderStatic: true }"
                     data-win-res="{ winControl: {'header': 'TestSection'} }">
                    <div id="sectionTestscontenthost" data-win-control="MyApp.Testing.TestsControl"></div>
                </div>
            </div>

...rest of page details trimmed for brevity...

If you manage to get everything wired up correctly above, when you run the app (F5) your mocha tests should be all set and run automatically. Oh wait, let's not forget to add a mocha test :)...

describe('Mocha test spike', function(){

    it("should report a passing test", function(){
      // doing nothing should be a passing test
    });

    it("should fail on a synchronous exception", function(){
        throw new Error("Some test error to make sure mocha reports a test failure")
    });

    it("should fail on an asynchronous exception", function(done){
        setTimeout(function(){
            throw new Error("Some test error to make sure mocha reports an async test failure")
            done();
        }, 100);
        throw new Error("Some test error to make sure mocha reports a test failure")
    });

});

Save the above as your first test file, include it so it runs on startup and verify your tests run and report correctly within the test control.

Happy testing!