Search code examples
javascriptjestjscommonjsmodule.exports

JavaScript: module/require is not defined


I'd like to have Jest testing for some JavaScript code that I'm using in the frontend of my web app. From what I understand, I need to export and import functions from my module so I can test them in Jest, and Jest (only) supports CommonJS module syntax out of the box. As a result, my code looks as follows:

<!-- index.html -->
<!DOCTYPE html>
<html><body><div>Hello World</div>
<script src="./utils.js">
    console.log('foo: ' + foo());
</script>
</body></html>
// utils.js
function foo() {return 42;}
module.exports = {foo};
// __test__/utils.test.js
const utils = require('../utils');
describe('utils', () => {
    test('foo', () => {expect(utils.foo()).toBe(42);});
});

The testing part works, but when I open index.html in the browser I get

Uncaught ReferenceError: module is not defined

My understanding is that the frontend does not support CommonJS module syntax (according to Client on node: Uncaught ReferenceError: require is not defined ). How should I write my utils.js file and exports such that I can:

  1. have Jest testing for components of utils.js
  2. use functions defined in utils.js in the browser

Just to be clear, I do not want to run my tests from the browser.

For context: in my real use-case I run the app using Express and Node.js but this minimal example should capture the underlying problem.

Also, see this related question: Uncaught ReferenceError: module/require is not defined


Solution

  • Try checking if module exists:

    // utils.js
    
    function foo() { return 42; }
    
    if(module) module.exports = {foo}; // On node.js, use exports
    else if(window) window.foo = foo; // In browser, use window
    else console.error('Unknown environment');
    

    And in browser:

    <!-- index.html -->
    <!doctype html>
    <html>
      <body>
        <script src="./utils.js"></script>
        <script>
          // Use your foo() here!
          console.log('foo: ', window.foo());
        </script>
      </body>
    </html>