7

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

mattu
  • 944
  • 11
  • 24
  • Jest is not meant for browsers. Look into alternatives, like Karma or even jest-lite. See full discussion here: https://github.com/facebook/jest/issues/139 – Boaz Sep 05 '20 at 09:17
  • Just to make sure I understand this right: you cannot use Jest to test frontend code? I don't want to run my test in the browser per se, I just want to use Jest to test some code (located in `utils.js` in this case) that will eventually run in the browser. I've been pretty happy with Jest as far as testing is concerned and wouldn't want to give it up – mattu Sep 05 '20 at 09:24
  • 2
    If you provide `src` attribute for `script`, all contents will be ignored. – ISD Sep 05 '20 at 09:26
  • 1
    In a nutshell, Jest is meant to mock test web apps without a browser. If you wish to use it in a browser, then look into adding jest-lite to the frontend code: https://github.com/kvendrik/jest-lite – Boaz Sep 05 '20 at 09:30
  • The use of modules (with the exception of native ES modules that have their limitations and impose restrictions on supported browsers) require a build step for client code, this is the reason why Browserify, Webpack, etc bundlers exist. What you're trying to do is called UMD, it can be added by hand or by a bundler. If you don't want to refactor your app to add them (and you will need to additionallly test UMD exports) then it's not a good idea unit test such code with Jest, it's not meant for that. Do e2e tests for html and scripts with Jest+JSDOM or Jest+Puppeteer, test `window` if needed. – Estus Flask Sep 05 '20 at 10:40
  • Thanks for everyone's valuable input! I guess in that case I'll consider switching to Mocha for testing as many developers in @Boaz link (https://github.com/facebook/jest/issues/139) seem to have done... – mattu Sep 05 '20 at 13:29

2 Answers2

2

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>
ISD
  • 984
  • 1
  • 6
  • 21
  • 2
    Thanks, I had to use `if(typeof module !== 'undefined')` as the if-condition but that's simple and works, I'll use it as a short term fix. It feels a little hacky though so considering switching to Mocha for testing – mattu Sep 05 '20 at 16:26
0

I was getting similar error with jest on exporting from my main js file

Following worked well for me

if (typeof module !== 'undefined') module.exports = { foo };

PS: I have given up on modularization of JS code as js modules throw cors errors as my (html, js) code runs in a browser process that is remoted to windows application, and more importantly html, js code loads from disk instead of a server.

OtherGuru
  • 1
  • 2