Joel's Thoughts

How To Exclude Inline Webpack Loader From Unit Test

May 05, 2020

Nowadays, it’s not a good practice inlining webpack loaders inside our js file. Good one is to configure the loader inside the project’s webpack.config. However, I have a scenario lately where I’m using a webpack loader ( worker-plugin ) that crashes the build when configured inside webpack.config. So to be able to use the loader while waiting for a fix, my only option in my case is to inline it. And it works as I expected if done this way. Inside my made-up startWorker.js file, I inlined the loader like this.

   import workerUrl from 'worker-plugin/loader!./worker';

   const startWorker = () => {
     if (!window.SharedWorker) {
        return;
     }
     const worker = new window.SharedWorker(workerUrl);
     // more code ....
   };

   export default startWorker;

startWorker.js is then referenced inside a React component MyComponent.jsx …

   import React from 'react';
   import startWorker from './startWorker';
   import ChildComponent from './ChildComponent';

   class MyComponent extends React.Component {
      componentDidMount() {
          // more code ....
          startWorker();
      }


      render () {
          return (
            <ChildComponent
              // more props....
            />
          );
          // more code ...
      }
   }

   export default MyComponent;

And the component’s unit test…

   import React from 'react';
   import test from 'tape';
   import { shallow } from 'enzyme';

   import MyComponent from './MyComponent';
   import ChildComponent from './ChildComponent';

   const wrapper = shallow(<MyComponent
     // props here ...
   />);

   test('MyComponent render child test', (t) => {
     const actual = wrapper.find(ChildComponent).length;
     const expected = 1;
     t.deepEqual(actual, expected, 'it should render child');

     t.end();
   });

   // more code ...

Obviously, unit test will fail when run due to the inline webpack loader. Noticed in my unit test, I’m only interested if the ChildComponent is rendered or not. Test doesn’t care about what’s going on inside startWorker.js. Consequently, I can make my test pass again by mocking startWorker.js dependency inside MyComponent.jsx. Using proxyquire, I can cleanly mock this dependency.

First step is to install proxyquire inside the project.

npm install proxyquire --save-dev

Next is to start mocking the dependency by modifying how MyComponent.jsx is referenced inside unit test. It should look like this.

   import proxyquire from 'proxyquire';
   import React from 'react';
   import test from 'tape';
   import { shallow } from 'enzyme';

   import ChildComponent from './ChildComponent';

   proxyquire.noCallThru();
   const { WrappedComponent: MyComponent } = proxyquire('./MyComponent', { './startWorker': () => {} }).default;

   const wrapper = shallow(<MyComponent
     // props here ...
   />);

   test('MyComponent render child test', (t) => {
     const actual = wrapper.find(ChildComponent).length;
     const expected = 1;
     t.deepEqual(actual, expected, 'it should render child');

     t.end();
   });

   // more code ...

Noticed that I’m not directly referencing MyComponent.jsx inside the unit test file. I’m passing it as a parameter inside proxyquire. Also I’m directing proxyquire to mock the dependency startWorker.js inside MyComponent.jsx file as an empty/noop function. Running unit test this time will pass as expected. However, webpack build may fail depending on your setup. In my case, it did failed. Mainly because of this known issue, https://github.com/thlorenz/proxyquire/issues/62. To work around, we need to able to configure webpack to exclude all references (import) with proxyquire. With that said, I added an ignore plugin on my webpack.config.

plugins: [
  // more plugins......
  new webpack.IgnorePlugin({ resourceRegExp: /proxyquire$/ }),
]

Webpack build should go through without a problem this time. If you have another solution to this issue, please let me know. Thank you for reading.









  • About
  • Search
  • Resume
  • Powered by Jekyll using the Trio theme