zzm
zzm

Reputation: 645

Why can't get the global variable which was set in globalSetup in test code?

I use Jest to do unit test in node.
And I use the new feature globalSetup which come in Jest v22.
I have defined a global variable in globalSetup.
But I can't get it in the test code. Console log is undefined.
Anyone in this question?
Thanks.

Jest version: 22.0.0
node version: 8.9.0
yarn version: 1.3.2
OS: mac High Sierra 10.13.2

The code as follow:

// package.json
{
  "jest": {
    "globalSetup": "<rootDir>/src/globalSetupTest.js"
  }
}

// globalSetupTest.js
module.exports = async function() {
  global.foo = 'foo';
  console.log(`global setup: ${global.foo}`);
};

// App.test.js
describe('APP test', () => {
  it('renders without crashing', () => {
    console.log({ foo: global.foo });
  });
});

// test result
yarn run v1.3.2
$ node scripts/test.js --env=node --colors
global setup: foo
 PASS  src/App.test.js
  APP test
    ✓ renders without crashing (5ms)

  console.log src/App.test.js:3
    { foo: undefined }

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.354s, estimated 1s
Ran all test suites.

Upvotes: 18

Views: 13659

Answers (3)

Milan Krstic
Milan Krstic

Reputation: 646

There's a solution offered from Jest people themselves: https://jestjs.io/docs/en/puppeteer.html. Note that if you're using CRA, this won't work out of the box (solution below), cause it currently doesn't support testEnvironment option for Jest.

Anyways:

  • In Jest config file you setup paths to global setup, teardown and test environment scripts
  • In global setup script, you create a browser and write it's WSEndpoint to a file
  • In global teardown script, you simply close the browser
  • In testEnvironment script, you read WSEndpoint from the file you saved before and then use it to connect to the running browser - after this, browser is available in your tests by using a global variable

If you're using CRA, you can use a custom setup for these tests and run them completely separately. And if you're using Puppeteer for e2e tests, this is probably what you want to do anyway.

You just add another script to your package.json: "test:e2e": "jest -c ./jest-e2e.config.js" and set it up as you want. Now you will have npm run test for unit tests and npm run test:e2e for end to end tests.

Upvotes: 4

stilllife
stilllife

Reputation: 1806

For what I understood is a design decision of Jest because is considered a bad practice to share state across different tests. Tests run in parallel and they should keep their own state.

See: https://github.com/facebook/jest/issues/6007#issuecomment-381743011 https://github.com/facebook/jest/issues/4118

Upvotes: 2

sebastianf182
sebastianf182

Reputation: 9978

Can you try..

  global.foo = 'foo';
  console.log(`global setup: ${global.foo}`);

(remove the exports)

You can try changing globalSetup to setupFiles. That one, won't expect a function.

https://facebook.github.io/jest/docs/en/configuration.html#setupfiles-array

Upvotes: 0

Related Questions