3

So this question seems really stupid, but I've been searching and searching, and have not found an answer.

I'm trying out the Jest framework for unit testing my custom javascript project, which is not using React or any other framework. My project structure currently looks like this:

  • project
    • js
      • main.js <-- all my classes are in here, es6 style, if that matters
    • --tests--
      • card.test.js <-- tests are in here

Inside main.js there is class Card defined. I doubt there are any issues with the file, as I've run it perfectly fine in the browser.

"use strict";

class Card 
{
  ...
}

The one test I've written so far, just to see if it works is:

require('../js/main.js');

test("stuff", () => {
    let card = new Card(1, 1);
});

When I try to run the test:

yarn test

But all I'm getting is:

    ReferenceError: Card is not defined

      2 |
      3 | test("stuff", () => {
    > 4 |       let card = new Card(1, 1);
        |                  ^
      5 | });

      at Object.<anonymous>.test (__tests__/card.test.js:4:13)

It seems like main.js is getting loaded, because if I add a console.log() in it, that gets output when I run the test. So why is it complaining that Card is not defined?

tk421
  • 5,775
  • 6
  • 23
  • 34
Kai
  • 3,803
  • 1
  • 16
  • 33

2 Answers2

4

I got something that seems to work, though using ES6 modules.

  1. I changed all the classes in main.js to be modules (as well as separating them out into views.js, controllers.js, and models.js):
"use strict";

export class Card 
{
  ...
}
  1. I installed some babel node modules through yarn:
yarn add --dev @babel/core @babel/cli @babel/preset-env
  1. I added a .babelrc file in my project root:
{
    "presets": ["@babel/preset-env"]
}
  1. I changed my test to match what Andre suggested
const { Card } = require('../js/models.js');

test("stuff", () => {
    let card = new Card(1, 1);
});

Now there are no errors when running

yarn test

Kai
  • 3,803
  • 1
  • 16
  • 33
  • 1
    step 2 using npm is: npm install @babel/core @babel/cli @babel/preset-env --save-dev – Lino Jun 10 '20 at 15:12
0

You have to export Cards in the main.js file for it to be accessible in other files

// main.js
module.exports = { Card }

and then require it on your test file

const { Card } = require('../js/main.js');
loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • Does that mean that there can only be one class per javascript file? Or can you do something like ```const { Card, Deck } require('../js/main.js');``` – Kai Feb 18 '19 at 23:55
  • Also, is module.exports part of NodeJs? This is not a node project. When I tried the normal ```export class Card {```, then it throws an error. – Kai Feb 18 '19 at 23:58
  • I tried your solution, but sure enough, the browser throws an error when it gets to that ```module.exports = { Card }``` line, though it did make the test work. – Kai Feb 19 '19 at 00:09
  • my bad i thought you were using node, but you still have to export you function and import them. Have a look here https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export – Andre Shindi Fucuhara Feb 19 '19 at 13:48
  • But export and import aren't supported by node, jest uses node to run, so using them causes the tests to error also. I was hoping there was a solution where you could just load files without import and export because it seems weird that jest wouldn't support such a thing. But I have read that if you do use export/import you can configure babel to convert your code to commonjs, which apparently can be used with jest? Which seems to support the idea that simply loading files should be possible somehow? https://stackoverflow.com/questions/49656706/test-es6-modules-with-jest/49656707#49656707 – Kai Feb 19 '19 at 15:18
  • I'm not sure then if it's that I need to change my Javascript to conform to what jest expects, whatever that may be, or what. – Kai Feb 19 '19 at 15:35