testdouble / teenytest

A very simple, zero-config test runner for Node.js
MIT License
96 stars 14 forks source link

Support tests written as modules #52

Closed jkrems closed 4 years ago

jkrems commented 4 years ago

Right now teenytest uses synchronous require to load test files. This doesn't work for .mjs (ESM) since module loading/execution is asynchronous. What mocha does is to require first, catch ERR_REQUIRE_ESM, and then attempt import of the file.

Test file:

// example.test.mjs
import assert from 'assert';

class Dog {
  bark(length) {
    return Array.from({ length }, (_, idx) => `Woof #${idx}`);
  }
}

export function beforeEach() {
  this.subject = new Dog('Sam');
}

export const bark = {
  once() {
    assert.deepEqual(this.subject.bark(1), ['Woof #0']);
  },
  twice() {
    assert.deepEqual(this.subject.bark(2), ['Woof #0', 'Woof #1']);
  },
};

export const tag = {
  frontSaysName() {
    assert.equal(this.subject.tag('front'), 'Hi, I am Sam');
  },
  backSaysAddress() {
    assert.equal(this.subject.tag('back'), 'And here is my address');
  },
};

Result:

$ teenytest examples/teenytest/test/example.test.mjs
internal/modules/cjs/loader.js:998
    throw new ERR_REQUIRE_ESM(filename);
    ^

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /path/to/examples/teenytest/test/example.test.mjs
    at Module.load (internal/modules/cjs/loader.js:998:11)
    at Function.Module._load (internal/modules/cjs/loader.js:899:14)
    at Module.require (internal/modules/cjs/loader.js:1040:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at /path/to/node_modules/teenytest/lib/prepare/modules/load.js:11:22
    at arrayMap /path/to/node_modules/lodash/lodash.js:639:23)
    at Function.map /path/to/node_modules/lodash/lodash.js:9554:14)
    at module.exports /path/to/node_modules/teenytest/lib/prepare/modules/load.js:9:12)
    at /path/to/node_modules/teenytest/lib/prepare/modules/index.js:9:7
    at arrayMap /path/to/node_modules/lodash/lodash.js:639:23) {
  code: 'ERR_REQUIRE_ESM'
}