George
George

Reputation: 89

How to test ES6 modules (these with import) with mocha?

It is my first time with testing JS frontend and I chose mocha for that.
I have a class let us say Market which uses other classes I made.
I use import ... from ... clause and export default Market in the end.

so Market class looks like that:

import { math, AnotherClass, MyOtherClass } from '../index.js'
class Market {
  constructor () {
    // code here
  }
  methodToTest(input) {
    // some code here ...
    return output
  }
}
export default Market

and then my test.js

var assert = require('assert')
// import { Market } from '../public/mm/ai/Market.js'
var Market = require('../public/mm/ai/Market')

describe('Market', function() {
    describe('#methodToTest()', function() {
        it('should return 0 input is greater than mean + 4 * sigma', function() {
           var market = new Market()
           assert.equal(market.methodToTest(45), 0)
        })
    })
})

and after running the test I get the error:

import { math, AnotherClass, MyOtherClass } from '../index.js'
^^^^^^

SyntaxError: Cannot use import statement outside a module

and an error stack.

And the question is: How to make mocha test my modules with these imports?
As you see I also tried to use import directly in test.js and it failed also. But I don't want to rewrite my whole project to use require as it works perfectly fine in the browser as it is now.

Upvotes: 3

Views: 6335

Answers (2)

chmin.seo
chmin.seo

Reputation: 315

For anyone who suffer from configuration

1. installation

You need to install mocha and @babel/XXX plugins

npm install mocha --save-dev
npm install @babel/cli @babel/core @babel/preset-env @babel/register --save-dev

Check the package.json. It might be like this

{
  "scripts": { ... }
  "devDependencies": {
    "@babel/cli": "^7.15.7",
    "@babel/core": "^7.15.5",
    "@babel/preset-env": "^7.15.6",
    "@babel/register": "^7.15.3",
    ...
    "mocha": "^9.1.2",
    ...
  },
  ...
}  
  • Version can be different

2. babel configuration

create babel configuration file .babelrc under the [PROJECT-ROOT]

[PROJECT-ROOT]
 +- src
 +- test
 +- package.json
 +- .babelrc (+)

And fill the content like this

{
  "presets": ["@babel/preset-env"]
}

3. test script runner

open package.json and find "scripts" block

{
  "name": "...",
  ...
  "scripts": {
     "build": ...,
     "start": ...,
  },
}

create "test" property with value mocha --require @babel/register

{
  "name": "...",
  ...
  "scripts": {
     "build": ...,
     "start": ...,
     "test": "mocha --require @babel/register"
  },
}

4. Samples

create a file(calc.js) to be tested, and test file(calc.spec.js)

[PROJECT-ROOT]
 +- src
     +- calc.js      (+)
 +- test
     +- calc.spec.js (+)
 +- package.json
 +- .babelrc
// calc.js
const add = (a, b) => a + b
const mul = (a, b) => a * b

export default {
  add,
  mul
}

and test file calc.spec.js

// calc.spec.js
const assert = require('assert')
import calc from '../src/calc'

describe('testing calc.add, cal.mul', () => {
  it('should be seven', () => {
    const seven = calc.add(3, 4)
    assert.equal(7, seven)
  })
})

5. running test

input the npm run test in console

$ npm run test

  testing calc.add, cal.mul
    ✔ should be seven


  1 passing (7ms)

6. Reference

Upvotes: 6

George
George

Reputation: 89

So I have found the solution myself.

  1. Babel & mocha - the best, cause no intermediate files

First the .mocharc.js file to configure mocha to use babel and chai:

module.exports = {
    require: ['chai', '@babel/register'],
    ui: 'bdd',
    // ui: 'tdd',
    reporter: 'spec',
    growl: false,
};

I have chosen ui:'bdd' because I used the describe in test.js: describe('Market class:', function() {

Secondly I added babel configuration in package.json:

"babel": {
    "env": {
      "test-console": {
        "presets": ["@babel/preset-env"],
        "plugins": ["@babel/plugin-proposal-class-properties"]
      }
    ,
      "test": {
        "presets": ["@babel/preset-env"],
        "plugins": ["@babel/plugin-proposal-class-properties", "transform-remove-console"]
      }
    }
  },

Two environments to use with console output and wituhout it.
It leads to package.json scripts section to execute one of them:

 "scripts": {
    "test": "BABEL_ENV=test mocha || TRUE",
    "test-console-log": "BABEL_ENV=test-console mocha || TRUE"
  },

and now I was ready to have my test.js executed and imports in my modules worked.
Here is the head of test.js:

var assert = require('chai').assert
import Market from '../public/mm/ai/Market.js'
...

I switched to import when regarding my own modules.

  1. Webpack, babel & mocha

Everything in webpack config:

var path = require('path');
const TerserPlugin = require('terser-webpack-plugin')

module.exports = {
  mode: 'none',
  entry: './test/test.js',
  output: {
      path: path.resolve(__dirname, 'test/'),
      filename: 'exec_test.js'
  },
  module: {
    rules: [
        {
            test: /\.js$/,
            exclude: /node_modules/,
            use: {
                loader: 'babel-loader',
                options: {
                    presets: ['@babel/preset-env'],
                    plugins: ['@babel/plugin-proposal-class-properties']
                }
            }
        }
    ]
  },
  optimization: {
      minimize: true,
      minimizer: [new TerserPlugin({
          terserOptions: {
              compress: 
              {
                  drop_console: true
                }
            }
        })]
    }
};

and then you can build and run it by:

"scripts": {
   "build-tests-webpack": "webpack --config webpack.config.test.js",
   "exec test": "mocha --ui bdd test/exec_test.js"
}

in package.json

Upvotes: 1

Related Questions