-1

I have a project which is set up so that it builds with and . It works fine to build it using node_modules/webpack/bin/webpack.js --config webpack.config.js and I can run the result in the browser with no problems. However, when I run npm test and view the test runner in the browser, I get the error: "Uncaught ReferenceError: require is not defined at dashboard-tests.js:3". It seems that webpack is compiling my tests (but not my normal code) into a version of that can't be run in browsers.

Here are the relevant files:

.babelrc:

{
   "presets": ["es2015", "react"]
}

testem.json:

{
  "framework": [
    "jasmine"
  ],
  "launch_in_dev": [
    "PhantomJS"
  ],
  "launch_in_ci": [
    "PhantomJS"
  ],
  "serve_files": [
    "tmp/**/*-test{,s}.js"
  ],
  "on_start": "babel static_source --out-dir tmp",
  "on_exit": "yes | rm -r tmp"
}

package.json:

{
  "main": "index.js",
  "scripts": {
    "test": "testem"
  },
  "dependencies": {
    "jquery": "^3.2.1",
    "prop-types": "^15.6.0",
    "react": "^16.0.0",
    "react-dom": "^16.0.0",
    "react-feather": "^1.0.7"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "jasmine-es6": "^0.4.3",
    "testem": "^1.18.4",
    "webpack": "^3.6.0"
  }
}

webpack.config.js:

var path = require("path");
var webpack = require('webpack');

module.exports = {
  context: __dirname,
  entry: './static_source/js/index.js', 
  output: {
    path: path.resolve('./app/static/js/'),
    filename: "compiled.js"
  },
  plugins: [],
  module: {
    loaders: [
      { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
      { test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/ }
    ],
  }
}

dashboard-tests:

import React from 'react';
import ReactDOM from "react-dom";
import TestUtils from "react-dom/test-utils";

import Dashboard from './dashboard';

describe('Dashboard', function() {
  it('exists', function() {
    expect(Dashboard).not.toBe(undefined);
  });

  it('renders arrows', function() {
    var dashboard = <Dashboard />;
    var renderedDashboard = TestUtils.renderIntoDocument(dashboard);

    var arrowsDiv = TestUtils.findRenderedComponentWithClass('arrows');

    expect(arrowsDiv).not.toBe(undefined);
  });
});
kerkeslager
  • 1,364
  • 4
  • 17
  • 34
  • Have you checked the output of your (compiled) tests? In which format are they? UMD, AMD? Because it seems like you are compiling your tests with webpack as well (at least you dont exclude them). And webpack normally does not compile to a requireable library by default https://webpack.github.io/docs/configuration.html#output-librarytarget – androidavid Nov 17 '17 at 20:47

1 Answers1

1

You are using Babel to compile your test source files. Babel is just a transpiler, it takes ES+ files and translates them to ES5 files. Because import does not exist in ES5 Babel replaces them with require().

To fix the problem you need to bundle your source file into one, using Webpack.

You will need a separate Webpack configuration file, let's call it webpack.config.test.js. In this file we need to instruct Webpack to fetch all your static_source/**/*-test{,s}.js files as entry-points. You will need the glob module : npm install glob --save-dev. Then add the webpack.config.test.js file with this content :

var path = require("path");
var glob = require('glob');
var webpack = require('webpack');

module.exports = {
  context: __dirname,
  // we look for all file ending with -test(s?).js and return the absolute path
  entry: glob
      .sync('./static_source/js/**/*-test{,s}.js')
      .map(function(file) { return path.resolve(__dirname, file) }),
  output: {
    // save the resulting bundle in the ./tmp/ directory
    path: path.resolve('./tmp/'),
    filename: "compiled.js"
  },
  plugins: [],
  module: {
    loaders: [
      { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
      { test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/ }
    ],
  }
}

On the testem.json file replace the on_start with a before_test to Webpack, and the serve_files to map to the bundled file.

"before_tests": "webpack --config webpack.config.test.js ",
"serve_files": [
    "tmp/compiled.js"
],

When testem will be launched it will trigger the Webpack test compilation. Now you should have a tmp/compiled.js file with all your test files bundled. You may need to do some tweaking but it should basically works.

Fathy
  • 4,939
  • 1
  • 23
  • 25
  • If I'm not mistaken, this compiles the test files and mashes them all into one file (`compiled.js`). Is there a way to get this to include source maps and display the source files/line numbers in testem? – kerkeslager Nov 22 '17 at 20:52
  • 1
    You can add [`devtool: 'sourcemap'`](https://webpack.js.org/configuration/devtool/) to your Webpack configuration. If the stacktraces are not mapped to the source-maps use [`source-map-support`](https://www.npmjs.com/package/source-map-support) (eg. `entry: ['source-map-support/register'].concat(glob.sync(...).map(...))` in the Webpack config). – Fathy Nov 22 '17 at 21:01