Running tests .mjs / ESM on Node using Jasmine or

2020-07-13 12:47发布

问题:

My Node-based project is implemented using native ES module support on Node thanks to the --experimental-modules CLI switch (i.e. node --experimental-modules).

Obviously, when I run a spec using Jasmine node --experimental-modules ./node_modules/jasmine/bin/jasmine I get the following error:

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module

Is it ever possible to use Jasmine using ES modules in Node?

If not, is there any alternative to don't use a framework (e.g. running tests with npm scripts)?

回答1:

It was easier than I thought.

It's just about calling a file which you might call run.mjs as follows:

node --experimental-modules ./run.mjs

The whole file would look like this:

jasmine.mjs:

import Jasmine from "jasmine"
import JasmineConsoleReporter from "jasmine-console-reporter"

const jasmine = new Jasmine()
jasmine.loadConfigFile( "./support/jasmine.json" )

jasmine.env.clearReporters()
jasmine.addReporter( new JasmineConsoleReporter( {
    colors: true,
    cleanStack: true,
    verbosity: 4,
    listStyle: 'indent',
    activity: false
} ) )

export default jasmine

And you would add specs as follows in separate files:

import jasmine from './my-project/spec/jasmine.mjs'

jasmine.env.describe('Foo', () => {
    jasmine.env.it('Bar', () => {
        // Expects, assertions...
    })
})

Finally, you would run jasmine importing both configured jasmine instance and specs:

import jasmine from './my-project/spec/jasmine.mjs'
import someSpec1 from './my-project/spec/someSpec1.mjs'
import someSpecN from './my-project/spec/someSpecN.mjs'

someSpec1()
someSpecN()

jasmine.execute()


回答2:

Simplifying the solution of @Matias_Fidemraizer, keeping only the important bits in one file:

import glob from 'glob';
import Jasmine from 'jasmine';

const jasmine = new Jasmine();
jasmine.loadConfigFile('tests/jasmine.json');

// Load your mjs specs
glob('**/*-test.mjs', function (er, files) {
    Promise.all(
        files
            // Use relative paths
            .map(f => f.replace('tests/specs/', './'))
            .map(f => import(f)
                .catch(e => {
                    console.error('** Error loading ' + f + ': ');
                    console.error(e);
                    process.exit(1);
                }))
    )
        .then(() => jasmine.execute());
});

And execute it with

node --experimental-modules jasmine-run.mjs

You will have some problems in the logs, receiving a message like

[...] .split('\n') [...]

That message mean that you have an exception in the mjs code.

You can follow there: https://github.com/jasmine/jasmine-npm/issues/150