Modern websites and applications are routinely built by combining hundreds of small JavaScript modules. In order to increase the speed of delivery for our users, we leverage the power of module bundlers like webpack to combine and optimize them for delivery over a network.

While module bundlers provide great configuration options for delivery, they don’t always integrate with the test frameworks we want to use. This means that when we want to test a small portion of our codebase, we may be forced to build the entire thing. Monolithic files are fantastic for users to consume, but not so great for developers to test!

To illustrate, I will share a series of scenarios where module bundling can affect our ability to test effectively and efficiently. Though each of the problems I will share can be addressed with individual one-off fixes, it is my aim to show that a general case solution exists that addresses all of these issues holistically without introducing the maintenance burden of duplicative configuration.

Let’s get started!

File Resolving

To make development faster most JavaScript projects pull in dependencies from many sources. Think npm, git submodules, vendor folders, etc. Webpack makes it possible for your project to include those sources transparently, understand new file extensions, custom aliases and much, much more.

When it comes time to test your code, you may find that your testing framework doesn’t know how to find those modules even though webpack does.

File resolution is configured in webpack under the resolve object. Here is an example customizing where to look for modules, what some names are in your code, and extensions your files can have.

    resolve: {
      alias: {
        // For reasons specific to a project you might not refer to a vendored
        // package by its original name.
        'clock$': 'timepiece',
      },
      extensions: ['.js', '.json', '.jsx'],
      modules: ['node_modules', path.join(__dirname, 'vendor')],
    },

When it comes time to test your code, if you reach for jest, you’ll need to replicate the above configuration with moduleNameMapper, moduleDirectories and moduleFileExtensions.

You can put the corresponding configuration in package.json, or a jest config file to bring the two tools into alignment. In the case of moduleFileExtensions, this example is already a subset of the default, but if you needed to add an extension outside of webpack’s or jest’s defaults it is the option to use.

    "jest": {
      "moduleNameMapper": {
        "^clock$": "timepiece"
      },
      "moduleDirectories": [
        "node_modules",
        "vendor"
      ],
      "moduleFileExtensions": [
        "js",
        "json",
        "jsx"
      ]
    }

To further illustrate this problem, I’ve created an example repository for running through the steps needed to see and fix it using webpack and jest.

Example Repository

Using module bundlers like webpack you get “more bang for your buck,” rewarding greater utility in organizing your project and optimized delivery to your users. Integrating with that is not a reason to suffer through a bad testing workflow.

In the next entry we will cover building a site with modularized CSS stylesheets and overcoming the challenges needed to test that.