Search code examples
unit-testingtypescriptwebpack-2

Integrating Webpack testing into existing Typescript project


I've migrated an already started project into a more structured format and am trying to make Webpack run all of the tests in the shell using Mocha. I'm very new to Webpack and task running in general, so most of my attempts have been copy/paste-based. (Really DRY of me, I know...)

TL; DR

I need to run my mocha/chai based tests, written in TypeScript, from Webpack during development. Bundling all tests and assets together into a single file messes with dependencies and mocha-webpack doesn't seem to find any of the files.

All suggestions are appreciated, I just need to be able to run my tests.


Unsuccessful efforts

I have tried to bundle all of the tests and different classes together after transpiling them and then running Mocha on that file, but I only get nasty dependency errors by doing this, such as:

ERROR in ./src/test/unit/cell-factory.test.ts
Module not found: Error: Can't resolve '../../assets/js/shape_module/t-shape' in '/mnt/d/Development/hestraplattan/src/test/unit'
resolve '../../assets/js/shape_module/t-shape' in '/mnt/d/Development/hestraplattan/src/test/unit'
  using description file: /mnt/d/Development/hestraplattan/package.json (relative path: ./src/test/unit)
  after using description file: /mnt/d/Development/hestraplattan/package.json (relative path: ./src/test/unit)
    using description file: /mnt/d/Development/hestraplattan/package.json (relative path: ./src/assets/js/shape_module/t-shape)
      no extension
        /mnt/d/Development/hestraplattan/src/assets/js/shape_module/t-shape doesn't exist
      .js
        /mnt/d/Development/hestraplattan/src/assets/js/shape_module/t-shape.js doesn't exist
      .json
        /mnt/d/Development/hestraplattan/src/assets/js/shape_module/t-shape.json doesn't exist
      as directory
        /mnt/d/Development/hestraplattan/src/assets/js/shape_module/t-shape doesn't exist
[/mnt/d/Development/hestraplattan/src/assets/js/shape_module/t-shape]
[/mnt/d/Development/hestraplattan/src/assets/js/shape_module/t-shape.js]
[/mnt/d/Development/hestraplattan/src/assets/js/shape_module/t-shape.json]
[/mnt/d/Development/hestraplattan/src/assets/js/shape_module/t-shape]
 @ ./src/test/unit/cell-factory.test.ts 11:16-63
 @ ./src object Object
 @ ./.tmp/mocha-webpack/415d1b658d94fc3dead3d418955249ea-entry.js

Webpack bundling and testing config:

var webpack = require('webpack');
var path = require('path');
var nodeExternals = require('webpack-node-externals');
var WebpackShellPlugin = require('webpack-shell-plugin');

var config = {
 entry: [
            './src/test/all-tests.js',
            './src/assets/js/all-assets.js'
        ],
 output: {
    path: path.resolve(__dirname, './dist/tests'),
    filename: 'testBundle.js'       
},
 target: 'node',
 module: {
    loaders: [
        { test: /\.ts$/, loader: 'ts-loader' }
    ],

 },
 externals: [nodeExternals()],
 node: {
   fs: 'empty'
 },
 plugins: [
   new WebpackShellPlugin({
     onBuildExit: "mocha ./dist/tests/testBundle.js"
   })
 ]
};
module.exports = config;

The files "all-tests.ts" and "all-assets.ts" exports all .ts-files in the current and subdirectories:

var context = require.context('./', true, /\.ts$/);
context.keys().forEach(context);
module.exports = context;

I also tried using Mocha Webpack and following this angular testing guide to see if that would work. The problem here is that I don't seem to get any of my tests run...

Webpack config for test with mocha webpack:

    module.exports = {
        devtool: 'cheap-module-source-map',

        resolve: {
            extensions: ['.ts', '.js']
        },

        resolveLoader: {
            moduleExtensions: ['-loader'] // To bypass mocha-loader incompatibility with webpack :
        },

        module: {
            rules: [
                {
                    test: /\.ts$/,
                    loaders: [/*'istanbul-instrumenter-loader',*/ 'ts-loader' ]
                },
                {
                    test: /\.ts$/,
                    include: '/mnt/d/development/hestraplattan/src/test',
                    loaders: [
                        {
                            loader: 'ts-loader',
                            options: {configFileName: '/mnt/d/development/hestraplattan/tsconfig.json'}
                        } 
                    ]
                },
                {
                    test: /\.html$/,
                    loader: 'html-loader'

                },
                {
                    test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
                    loader: 'null-loader'
                },
                {
                    test: /\.css$/,
                    loader: 'null-loader'
                },
                {
                    test: /\.css$/,
                    loader: 'raw-loader'
                }
            ]
        },

        performance: {
            hints: false
        }
    };

Webpack node test config for running in shell:

    var webpackMerge = require('webpack-merge')
    var nodeExternals = require('webpack-node-externals')
    var webpackTestConfig = require('./webpack.test.config')
    module.exports = webpackMerge(webpackTestConfig, {
        target: 'node',

        externals: [
            nodeExternals()
        ]
    });

Mocha webpack opts:

--webpack-config ./webpack.test.node.js
src/test/*.test.ts

Result:

$ mocha-webpack --opts ./mocha-webpack.opts 
    no files found and 0 passing

Solution

  • So I finally managed to get to a solution:

    I managed to clean up my mocha-webpack attempt to the following code:

    webpack.test.config

    var path = require('path');
    var webpack = require('webpack');
    
    module.exports = {
            devtool: 'cheap-module-source-map',
    
            resolve: {
                extensions: ['.ts', '.js']
            },
    
            resolveLoader: {
                moduleExtensions: ['-loader'] // To bypass mocha-loader incompatibility with webpack :
            },
    
            module: {
                rules: [
                    {
                        test: /\.ts$/,
                        loader:  'ts-loader',
                        options: {
                            configFileName: path.resolve(__dirname, 'tsconfig.json')
                        },
    
                    },
                    {
                        test: /\.html$/,
                        loader: 'html-loader'
    
                    },
                    {
                        test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
                        loader: 'null-loader'
                    },
                    {
                        test: /\.css$/,
                        loader: 'null-loader'
                    },
                    {
                        test: /\.css$/,
                        loader: 'raw-loader'
                    }
                ]
            },
    
            performance: {
                hints: false
            }
        };
    

    And then I merged it with the node-config to exclude all node-modules.

    The script for running mocha-webpack:

    mocha-webpack --opts ./mocha-webpack.opts || true
    

    Where true is for ignoring npm error messages if any tests fail and throw errors.

    And lastly the mocha-webpack.opts for those who are interested:

    --colors
    --webpack-config ./webpack.test.node.js
    src/**/*.test.ts
    

    Hope this will help those of you out there wanting to run your non-DOM unit tests on the command line instead of in the browser!