Search code examples
node.jsunit-testingkarma-runnerweb-componentes6-modules

Importing Node core modules breaks Karma tests (using @open-wc/testing-karma)


  • macOS Mojave 10.14.5
  • Node.js v12.6.0

I am trying to set up testing for a vanilla web component, which led me to the @open-wc/testing-karma package. When doing something like this:

src/redblue-video.test.js

import { html, fixture, expect } from '@open-wc/testing';

import RedBlueVideo from './parser-omni.js'; // ES6 web component class

customElements.define( 'redblue-video', RedBlueVideo );

describe( '<redblue-video />', () => {
  it( 'embeds YouTube videos', async () => {
    const el = await fixture( html`<redblue-video></redblue-video>` );
    expect( el ).dom.to.equal( `<redblue-video class="redblue-video" role="application"></redblue-video>` );
  } );
} );

…and running it with yarn test (karma start), the test executes fine:

$ yarn test
yarn run v1.17.3
$ karma start

START:
01 08 2019 19:11:03.202:WARN [filelist]: Pattern "/Users/Hugh/Sites/redblue/__snapshots__/**/*.md" does not match any file.
01 08 2019 19:11:03.223:INFO [karma-server]: Karma v4.2.0 server started at http://0.0.0.0:9876/
01 08 2019 19:11:03.223:INFO [launcher]: Launching browsers ChromeHeadlessNoSandbox, ChromeHeadlessNoSandbox with concurrency unlimited
01 08 2019 19:11:03.226:INFO [launcher]: Starting browser ChromeHeadless
01 08 2019 19:11:03.240:INFO [launcher]: Starting browser ChromeHeadless
01 08 2019 19:11:03.893:INFO [HeadlessChrome 75.0.3770 (Mac OS X 10.14.5)]: Connected on socket 4QcOBy0C1_X43S5zAAAA with id 15906039
01 08 2019 19:11:03.922:INFO [HeadlessChrome 75.0.3770 (Mac OS X 10.14.5)]: Connected on socket bcOgxLUp8s7CAZUqAAAB with id 41870378
HeadlessChrome 75.0.3770 (Mac OS X 10.14.5) WARN: 'No Embed URL found'
HeadlessChrome 75.0.3770 (Mac OS X 10.14.5) WARN: 'No Embed URL found'
HeadlessChrome 75.0.3770 (Mac OS X 10.14.5) WARN: 'No nonlinear playlists found'
HeadlessChrome 75.0.3770 (Mac OS X 10.14.5) WARN: 'No nonlinear playlists found'
  <redblue-video />
    ✔ embeds YouTube videos

Finished in 0.025 secs / 0.038 secs @ 19:11:07 GMT-0400 (Eastern Daylight Time)

SUMMARY:
✔ 2 tests completed
✨  Done in 5.07s.

But if I try to pull in readFileSync, as in:

import { html, fixture, expect } from '@open-wc/testing';
import { readFileSync } from 'fs';

import RedBlueVideo from './parser-omni.js'; // ES6 web component class

customElements.define( 'redblue-video', RedBlueVideo );

describe( '<redblue-video />', () => {
  it( 'embeds YouTube videos', async () => {
    const markup = readFileSync( './examples/youtube-embed.hvml' );
    const el = await fixture( html`<redblue-video>${markup}</redblue-video>` );
    expect( el ).dom.to.equal( `<redblue-video class="redblue-video" role="application">${markup}</redblue-video>` );
  } );
} );

…then the test does not run:

$ yarn test
yarn run v1.17.3
$ karma start

START:
01 08 2019 19:16:08.364:WARN [filelist]: Pattern "/Users/Hugh/Sites/redblue/__snapshots__/**/*.md" does not match any file.
01 08 2019 19:16:08.384:INFO [karma-server]: Karma v4.2.0 server started at http://0.0.0.0:9876/
01 08 2019 19:16:08.385:INFO [launcher]: Launching browsers ChromeHeadlessNoSandbox, ChromeHeadlessNoSandbox with concurrency unlimited
01 08 2019 19:16:08.390:INFO [launcher]: Starting browser ChromeHeadless
01 08 2019 19:16:08.397:INFO [launcher]: Starting browser ChromeHeadless
01 08 2019 19:16:09.100:INFO [HeadlessChrome 75.0.3770 (Mac OS X 10.14.5)]: Connected on socket a8fHrCGFmHdZC5qOAAAA with id 88214959
01 08 2019 19:16:09.799:INFO [HeadlessChrome 75.0.3770 (Mac OS X 10.14.5)]: Connected on socket Cq0xMj1wOchVYG13AAAB with id 63311008
HeadlessChrome 75.0.3770 (Mac OS X 10.14.5) ERROR: 'failed to load element http://localhost:9876/base/src/redblue-video.test.js?2133f326ffd8a86c0252453f23aee7a13f7ff7ad'
HeadlessChrome 75.0.3770 (Mac OS X 10.14.5) ERROR: 'failed to load element http://localhost:9876/base/src/redblue-video.test.js?2133f326ffd8a86c0252453f23aee7a13f7ff7ad'

Finished in 0.008 secs / 0 secs @ 19:16:11 GMT-0400 (Eastern Daylight Time)

SUMMARY:
✔ 0 tests completed
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Is it impossible to use Node core modules with Karma tests? Or is there some extra configuration I am missing?

karma.conf.js – This is only different from open-wc’s recommended config via test/**/*.test.js being changed to src/**/*.test.js.

const { createDefaultConfig } = require('@open-wc/testing-karma');
const merge = require('deepmerge');

module.exports = config => {
  config.set(
    merge(createDefaultConfig(config), {
      files: [
        // runs all files ending with .test in the test folder,
        // can be overwritten by passing a --grep flag. examples:
        //
        // npm run test -- --grep test/foo/bar.test.js
        // npm run test -- --grep test/bar/*
        { pattern: config.grep ? config.grep : 'src/**/*.test.js', type: 'module' }
      ],

      // see the karma-esm docs for all options
      esm: {
        // if you are using 'bare module imports' you will need this option
        nodeResolve: true
      }
    })
  );
  return config;
};

package.json:

"scripts": {
  "test": "karma start",
  "test:coverage": "karma start --coverage",
  "test:watch": "karma start --auto-watch=true --single-run=false",
  "test:update-snapshots": "karma start --update-snapshots",
  "test:prune-snapshots": "karma start --prune-snapshots",
  "test:compatibility": "karma start --compatibility all --auto-watch=true --single-run=false"
},
"devDependencies": {
  "@open-wc/chai-dom-equals": "^0.12.36",
  "@open-wc/testing": "^2.2.2",
  "@open-wc/testing-karma": "^3.1.6",
  "codecov": "^3.5.0",
  "eslint": "^6.1.0",
  "eslint-config-airbnb-base": "^13.2.0",
  "eslint-config-hughx": "^0.0.2",
  "eslint-plugin-import": "^2.18.2",
  "lit-html": "^1.1.1",
  "webpack": "^4.38.0"
}

Solution

  • You cannot use core node modules in your karma tests unless you do something tricky. Karma tests run in the browser (even though the karma server runs on node). The tests therefore have no access to node core modules.

    The only way to include node modules in your karma scripts is to use something like browserify or webpack.

    But, more importantly, since the tests are running in the browser, you cannot access the file system directly. Your approach of trying to read a file on the disk will not work. You will need to be able to serve the file from your karma server using a fetch request or something similar.

    You can specify where the karma server looks for resources using the basePath option in the configuration file.