Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests not run/reported using ES modules in browser #2816

Closed
chrisveness opened this issue May 21, 2017 · 4 comments
Closed

Tests not run/reported using ES modules in browser #2816

chrisveness opened this issue May 21, 2017 · 4 comments
Labels
area: browser browser-specific

Comments

@chrisveness
Copy link

I am trying – and failing – to use mocha to test ES modules in the browser.

I am using the following code:

test.html:

<!doctype html>
<html lang="en">
<head>
    <title>Mocha/Chai ES Modules Test</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/mocha/3.4.1/mocha.min.css">
</head>

<body>
    <div id="mocha"></div>

    <script src="//cdnjs.cloudflare.com/ajax/libs/mocha/3.4.1/mocha.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.js"></script>

    <script>mocha.setup('bdd')</script>
    <script type="module" src="./test.js"></script>
    <script>mocha.run()</script>
</body>

</html>

test.js:

import MyLib from './lib.js';

const expect = chai.expect;

describe('test', function() {
    it('should invoke test without run', function() { expect(MyLib.hypotenuse(5, 12)).to.equal(13); });
    it('needs run to invoke test',       function() { expect(MyLib.hypotenuse(8, 15)).to.equal(17); }).run();
});

lib.js:

class MyLib {

    static hypotenuse(x, y) {
        console.log('MyLib.hypotenuse', x, y);
        return Math.sqrt(x**2 + y**2);
    }

}

export default MyLib;

I am running tests in Chrome 60.0.3100.0 (dev channel, using Experimental Web Platform flag, on Linux).

At first I got no tests run at all; going through issues, I discovered #2760 suggested adding .run(), which does invoke the test (per the console.log), but still does not make the test appear in the browser:

image

This test can be run from www.movable-type.co.uk/dev/mocha-es-modules (using Chrome 60 with flag).

@ScottFreeCode
Copy link
Contributor

Side notes:

  • According to http://caniuse.com/#feat=es6-module, this is also behind a flag in Firefox 54 or in MS Edge 15, and available without a flag in Safari. (Additionally, Edge and Safari appear to be the only current -- as opposed to dev/beta/preview -- browsers that support it, if I'm reading that list correctly; so keep your target browser support in mind when relying on next-gen modules having native support as opposed to transpiling.)
  • While Mocha runs in the browser and can be demonstrated by doing so manually, it really shines when used programmatically (e.g. as part of continuous integration); I'd be curious whether and how programmatic browser test harnesses such as Karma handle next-gen modules.
  • it(...).run() isn't the normal way to run tests in Mocha and (whatever it may have been intended for...) may not work correctly in the context of Mocha's typical usage (with or without other issues fixed); whatever's going on here is a different issue requiring a different fix, and the run() should be removed (at least in this case).
  • If the describe blocks are being run at all then clearly Mocha's interface has been set up and is useable from the module...

Question -- if you add logging here:

import MyLib from './lib.js';

const expect = chai.expect;

console.log("calling describe");
describe('test', function() {
  console.log("inside describe callback");

...and here:

    <script type="module" src="./test.js"></script>
    <script>console.log("running Mocha");mocha.run()</script>

...What ends up in the console then?

@ScottFreeCode ScottFreeCode added the area: browser browser-specific label May 21, 2017
@chrisveness
Copy link
Author

The describe callback is being invoked correctly. I appreciate the it callback should not require the .run() method, but without it, the callback doesn't appear to be invoked (I wasn't even aware of the .run() method until I saw #2760).

Hence "MyLib.hypotenuse 8 15" is output in the console, but not the previous "MyLib.hypotenuse 5 12".

I don't currently have access to Edge or Safari, and for some reason cannot manage to install Firefox 54 – I will try again.

image

@ScottFreeCode
Copy link
Contributor

So, in that screenshot of the console logs "running Mocha" comes before the rest. The reason the tests aren't getting run and reported is, quite simply, that the test file is loading after the script tag that calls mocha.run().

I don't happen to have a browser handy that supports the new module system (or whatever's specified of it so far, anyway...), but I'd guess from this behavior that modules are implicitly async or something along those lines. There might be something that can be specified to make a given set of scripts load in order even when some of them are modules, although I don't happen to know (I can pull up a lot of information on google; figuring out which information is current and whether it's going to be superseded next year is... harder). A sure-fire alternative would be to put mocha.run() in a module that first imports the test file(s) instead.

@chrisveness
Copy link
Author

Thank you! That got me there.

Modules are defer by default. Regular inline scripts ignore defer ... but inline module scripts are deferred.

Hence the following works (and also benefits from defer, and also reads cleanly!):

test.html:

<!doctype html>
<html lang="en">
<head>
    <title>Mocha/Chai ES Modules Test</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/mocha/3.4.1/mocha.min.css">
    <script defer src="//cdnjs.cloudflare.com/ajax/libs/mocha/3.4.1/mocha.min.js"></script>
    <script defer src="//cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.min.js"></script>
    <script type="module">mocha.setup('bdd')</script>
    <script type="module" src="./test.js"></script>
    <script type="module">mocha.run()</script>
</head>

<body>
    <div id="mocha"></div>
</body>

</html>

test.js:

import MyLib from './lib.js';

const expect = chai.expect;

describe('test', function() {
    it('hypotenuse 5, 12', function() { expect(MyLib.hypotenuse(5, 12)).to.equal(13); });
    it('hypotenuse 8, 15', function() { expect(MyLib.hypotenuse(8, 15)).to.equal(17); });
});

lib.js:

class MyLib {

    static hypotenuse(x, y) {
        return Math.sqrt(x**2 + y**2);
    }

}

export default MyLib;

Produces:

image

Hooray!

mettta added a commit to mettta/editable-menutree that referenced this issue Mar 7, 2018
Modules are defer by default. Regular inline scripts ignore defer ... but inline module scripts are deferred.
mochajs/mocha#2816
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: browser browser-specific
Projects
None yet
Development

No branches or pull requests

2 participants