Ava: Recipe for using AVA with Webpack aliases

Created on 19 Aug 2016  路  8Comments  路  Source: avajs/ava

I use Webpack in my app and I defined aliases in config:
webpack.config.dev.js:

....
resolve: {
    // We can now require('file') instead of require('file.jsx')
    extensions: ['', '.js', '.jsx', '.scss'],
    alias: {
      actions: PATHS.app + '/actions',
      components: PATHS.app + '/components',
      store: PATHS.app + '/store',
      reducers: PATHS.app + '/reducers',
      helpers: PATHS.app + '/helpers',
      sagas:  PATHS.app + '/sagas',
      services:  PATHS.app + '/services',
    },
  }
....

And I import modules like so:
componts/LoginPage.js

import {login} from 'actions/Login'

instead of

import {login} from '../actions/Login'

But AVA doesn't allow to define aliases, so I'm unable to test componts/LoginPage.js with AVA since it throws that error:

Error: Cannot find module 'actions/Login'

Is there a solution?

help wanted documentation

Most helpful comment

Thank you, guys for your help. It seems to work with following configs:

config/webpack.config.ava.js

const path = require('path');

const PATHS = {
  app: path.resolve(__dirname, '../src'),
};

module.exports = {
   resolve: {
     modulesDirectories: [
       __dirname,
      'node_modules',
       PATHS.app,
     ]
   },
   module: {
     loaders: [
       {
         test: /\.css$/,
         loader: 'style-loader!css-loader?modules&importLoaders=1!postcss-loader',
       },
     ]
   }
};

package.json

{
  ....
  "scripts": {
    "test": "CONFIG=$(pwd)/config/webpack.config.ava.js BABEL_DISABLE_CACHE=1 NODE_ENV=AVA ava" 
    },
  ....
  "ava": {
    "files": [
      "src/**/*.spec.js"
    ],
    "require": [
      "babel-register"
    ],
    "babel": "inherit"
  }
}

.babelrc

{
  "presets": ["es2015", "react", "stage-1", "stage-0"],
  "env": {
    "AVA": {
      "plugins": [
        [
          "babel-plugin-webpack-loaders",
          {
            "config": "${CONFIG}",
            "verbose": false
          }
        ]
      ]
    }
  }
}

All 8 comments

I'm not familiar with Webpack, but it's not something AVA itself should be concerned about. You're using Webpack to add non-standard functionality (aliasing) to require, so it's up to you, or rather Webpack to make it compatible. I guess you could compile your code using Webpack and test the compiled code. There are also Babel plugins you could use, like babel-plugin-webpack-loaders or babel-resolve-relative-module.

Can anyone with Webpack experience comment here?

We should really have a recipe for using Webpack with AVA.

// @istarkov

Yes babel-plugin-webpack-loader could be used to resolve such imports
Not sure it supports aliases (as I does not use aliases), but it supports modulesDirectories webpack directive.

All aliases in @apedyashev example could be changed on just one modulesDirectories entry.

modulesDirectories: [
  PATHS.app,
]

Thank you, guys for your help. It seems to work with following configs:

config/webpack.config.ava.js

const path = require('path');

const PATHS = {
  app: path.resolve(__dirname, '../src'),
};

module.exports = {
   resolve: {
     modulesDirectories: [
       __dirname,
      'node_modules',
       PATHS.app,
     ]
   },
   module: {
     loaders: [
       {
         test: /\.css$/,
         loader: 'style-loader!css-loader?modules&importLoaders=1!postcss-loader',
       },
     ]
   }
};

package.json

{
  ....
  "scripts": {
    "test": "CONFIG=$(pwd)/config/webpack.config.ava.js BABEL_DISABLE_CACHE=1 NODE_ENV=AVA ava" 
    },
  ....
  "ava": {
    "files": [
      "src/**/*.spec.js"
    ],
    "require": [
      "babel-register"
    ],
    "babel": "inherit"
  }
}

.babelrc

{
  "presets": ["es2015", "react", "stage-1", "stage-0"],
  "env": {
    "AVA": {
      "plugins": [
        [
          "babel-plugin-webpack-loaders",
          {
            "config": "${CONFIG}",
            "verbose": false
          }
        ]
      ]
    }
  }
}

Tnx @apedyashev !! This should be in a recipe!

I put together a slightly different approach to this problem https://github.com/greyepoxy/webpack-ava-recipe. Where I use webpack as a pre-compile step for my tests before feeding them to Ava.

Curious what people think, is it better/worse then @apedyashev 's approach? Happy to put a recipe together if people think it is useful.

Btw, I have another solution of my problem (without using webpack):

env NODE_PATH=src ava

I implemented what I think is the easiest and cleanest approach without any pre-compile step as webpack-loaders seems like a dirty hack to begin with that didn't even work for me outside of using null transformer/loader for webpack. I use node-hook-filename to handle specific extensions and compile my pug files into functions as if it were handled by webpack. The scss files are inconsequential to testing, so I let it return the default, which is just a path.

import { join, dirname } from 'path';
import nhf from 'node-hook-filename';
import pug from 'pug';

nhf(['.scss']);
nhf(['.pug'], (path, parent) => pug.compileFile(join(dirname(parent.id), path)));

@greyepoxy Dude, this was a life-saver. I think this should be added as a recipe. Also, I found this library, which removes the need for the manual code you have here.

Was this page helpful?
0 / 5 - 0 ratings