Top modern browsers already support ES6 modules. This is great news from the unit testing perspective. A browser can natively load and test project sources without transpiler.

As a developer I would love to utilize this feature! Removing extra steps from the development process will improve speed and productivity.

Below is a story of how I got it working with Mocha test-runner.

Start with the official template

The official Mocha documentation contains the HTML template for running tests in the browser.

Let’s have a look at it:

The template uses traditional <script> tags without type="module" attribute. That means it does not utilize ES6 modules now.

The HTML code needs some adjustments to be more clear and up to date:

Remove jQuery

Update Mocha version to actual 4.0.1

Replace abandoned expect.js with chaijs

Swap CDN urls to unpkg.com (as cdn.rawgit.com does not have needed Mocha versions)

Remove fake test files: test.array.js , test.object.js , test.xhr.js

The template after cleanup:

Add a simple test to ensure it works

As a showcase I’ve created two files:

The source file sum.js with a simple sum() function:

2. The test file sum.test.js checking that sum() is working well:

I’ve included these files into HTML with regular <script> tags:

...

<script>mocha.setup('bdd')</script>

<script src="sum.js"></script>

<script src="sum.test.js"></script>

<script>

mocha.checkLeaks();

mocha.run();

</script>

...

And opened the page in a browser:

Everything works. 🎉

Now let’s achieve the same result with native ES6 modules!

Switch to ES Modules

Two main syntax parts of ES modules are import and export . These statements allow to set dependencies between modules.

The source file sum.js turns into a module that exports function:

2. The test file sum.test.js turns into a module that imports function and performs test:

Because test file now imports source file, the HTML page can include only test file, not both files as before. To import ES module in the HTML code a <script> tag should have type="module" attribute:

...

<script>mocha.setup('bdd')</script>

<script type="module" src="sum.test.js"></script>

<script>

mocha.checkLeaks();

mocha.run();

</script>

...

Let’s try to open the page in a browser. The result is blank screen :( This is because ES modules are deferred by default. The call of mocha.run() in the code snippet above occurs before sum.test.js is loaded!

The workaround is to keep script execution order the same as <script> tags appear in a document. With non-inline scripts defer attribute can do the job. But here is inline script and defer attribute is not applicable.

The solution is to set type="module" to inline script either. Although it does not import/export anything, the browser preserves execution order and calls mocha.run() after the test is loaded:

...

<script type="module" src="sum.test.js"></script>

<script type="module">

mocha.checkLeaks();

mocha.run();

</script>

...

Now it works! Both files are loaded as ES modules and the test is passing: