jest: document is not defined & puppeteer

Created on 10 Jul 2018  ·  19Comments  ·  Source: facebook/jest

🐛 Bug Report

I have asked about the problem on stackoverflow for a week ago without any answer question ((
I have configured jest as described jest for puppeteer but suddenly I've got the errot on usual test
with document event listeners

To Reproduce

Steps to reproduce the behavior:

  • configure jest to work with puppeteer
  • write test for React App which is using event listeners

Expected behavior

pass test without errors

Link to repl or repo (highly encouraged)

https://github.com/budarin/react-ssr-bootstrap-project

Run `npx envinfo --preset jest

System:
    OS: macOS High Sierra 10.13.5
    CPU: x64 Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
  Binaries:
    Node: 10.6.0 - /usr/local/bin/node
yarn install v0.15.1
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done in 15.39s. - /usr/local/bin/yarn
    npm: 6.2.0-next.1 - /usr/local/bin/npm
  npmPackages:
    jest: ^23.3.0 => 23.3.0

Most helpful comment

@thymikee
to write

/**
 * @jest-environment jsdom
 */

in every unit test - it is little bit annoing but it partially solves the problem

All 19 comments

Your environment extends Node and not JSDOM so browser globals such as window or document are not defined.

https://github.com/budarin/react-ssr-bootstrap-project/blob/4732268f4c8ade8f870554dcf98d2ba3ed8f61fb/config/jest/puppeteer_environment.js#L6

@SimenB
I know it, but question was: how to have testEnvironment at the same time to be JSDOM and Node?
We need not only one type of tests - we need them both at the same time

2018-07-10 11 15 28

That's not possible. I don't understand why you need both, though - puppeteer is basically chrome, use that as your browser environment.

Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

Seeing as you've asked on SO already, I recommend taking your question to Discord - lots of helpful people there!

@SimenB
we need to write both type of tests and need to hove jest run them both - it usual situation in development.

Again, this isn't a help forum - please ask questions on discord

It's not a question - it's a bug to have only one type of tests!

you have the whole section about how to integrate puppeteer into jest and now you tell me not to use puppeteer and just use only unit tests !?

We also have whole documentation on how to separate your tests and use different environments for different needs (e.g. server and browser). Please spend some time reading it before raging on the issue tracker :)

@thymikee
what do you mean?
point me please.

we dont test server - all tests are for browser

@thymikee
thanks, I will read :)

@thymikee
to write

/**
 * @jest-environment jsdom
 */

in every unit test - it is little bit annoing but it partially solves the problem

Feel free to create 2 projects - one with "node", the other one with "jsdom" environment, so you don't have to add a pragma. There's quite a bunch of options

@thymikee
doc for projects option is not clear - I have created 2 projects

projects: [
        {
            displayName: 'unit tests',
        },
        {
            displayName: 'puppeteer tests',
            testMatch: ['<rootDir>/**/*.test.pptr.js'],
        },
    ],

then I move settings for puupetter into its project

projects: [
        {
            displayName: 'unit tests',
        },
        {
            displayName: 'puppeteer tests',
            globalSetup: '../config/jest/globalSetup.js',
            globalTeardown: '../config/jest/globalTearDown.js',
            testEnvironment: '../config/jest/puppeteer_environment.js',
            testMatch: ['<rootDir>/**/*.test.pptr.js'],
        },
    ],

but got the error:

● Validation Error:

  Test environment ../config/jest/puppeteer_environment.js cannot be found. Make sure the testEnvironment configuration option points to an existing node module.

  Configuration Documentation:
  https://facebook.github.io/jest/docs/configuration.html

and reverse configuration does not help

projects: [
        {
            displayName: 'unit tests',
            testEnvironment: 'jsdom',
        },
        {
            displayName: 'puppeteer tests',
            testMatch: ['<rootDir>/**/*.test.pptr.js'],
        },
    ],

error:

● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://facebook.github.io/jest/docs/en/configuration.html

    Details:

    SyntaxError: /Users/vadim_budarin/projects/react-ssr-bootstrap-project/src/common/App.test.js: Unexpected token (12:37)

      10 | describe('Home Page test', () => {
      11 |     it('renders correctly', () => {
    > 12 |         const tree = renderer.create(<App />).toJSON();
         |                                      ^
      13 |
      14 |         expect(tree).toMatchSnapshot();
      15 |     });

@thymikee
here is our jest config:

const RUN_PUPPETEER_TESTS = process.env.RUN_PUPPETEER_TESTS;
const RUN_ONLY_PUPPETEER_TESTS = process.env.RUN_ONLY_PUPPETEER_TESTS;

const config = {
    rootDir: 'src',
    preset: 'jest-puppeteer',
    cacheDirectory: '../.tmp/jest',
    coverageDirectory: '../.tmp/coverage',
    transform: {
        '^.+\\.(js|ts|jsx|tsx)$': '../config/jest/transformer.js',
    },
    testMatch: [
        '**/__tests__/**/*.js?(x)',
        '**/__tests__/**/*.ts?(x)',
        '**/?(*.)+(spec|test).js?(x)',
        '**/?(*.)+(spec|test).ts?(x)',
    ],
    moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx', '.json'],
    moduleNameMapper: {
        '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
            '../../config/jest/mocks/fileMock.js',
        '\\.(css)$': '../../config/jest/mocks/styleMock.js',
    },
    testPathIgnorePatterns: ['/node_modules/'],
    globalSetup: '../config/jest/globalSetup.js',
    globalTeardown: '../config/jest/globalTearDown.js',
    testEnvironment: '../config/jest/puppeteer_environment.js',
    globals: {
        __DEV__: true,
        __PROD__: false,
        __BROWSER__: true,
        __SERVER__: false,
    },
    notify: false,
    notifyMode: 'failure',
};

// run also puppeteer tests
if (RUN_PUPPETEER_TESTS && RUN_PUPPETEER_TESTS.trim() === 'true') {
    config.testMatch.push('**/?(*.)+(test).pptr.js?(x)');
}

// run only puppeteer tests
if (RUN_ONLY_PUPPETEER_TESTS && RUN_ONLY_PUPPETEER_TESTS.trim() === 'true') {
    config.testMatch = ['**/?(*.)+(test).pptr.js?(x)'];
}

module.exports = config;

how to transform it for using two project types?

I found this article useful in setting up multiple environments with Jest: https://medium.com/coding-stones/separating-unit-and-integration-tests-in-jest-f6dd301f399c

@budarin make sure that you’re using <rootDir> for the file reference to work as expected

Google brought me here and I wanted to document the best solution I could put together. @thymikee was right, you can separate your test environments for node and jsdom very easily using one jest.config file.

As noted here projects config you create a project with a target directory to match for tests. From there a project API matches up with the global config of a jest configuration. So you can set your testEnvironment field here. Below you can see an example of me setting up my backend and frontend in one repository.

Thank you Jest team for making an awesome config API!

// For a detailed explanation regarding each configuration property, visit:
// https://jestjs.io/docs/en/configuration.html

module.exports = {
  clearMocks: true,

  coverageDirectory: 'coverage',
  projects: [
    {
      displayName: 'client',
      testEnvironment: 'jsdom',
      setupFiles: ['./test/enzyme.setup.js'],
      moduleNameMapper: {
        '\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
          '<rootDir>/test/fileMock.js',
        '\\.(css|less)': '<rootdir>/test/styleMock.js',
      },
      testMatch: ['<rootDir>/src/client/**/*.test.js'],
    },
    {
      displayName: 'server',
      testEnvironment: 'node',
      testMatch: ['<rootDir>/src/server/**/*.test.js'],
    },
  ],
  testEnvironment: 'node',

};

Edit: Would like some info if there is a way to run projects one at a time from the jest CLI

Was this page helpful?
0 / 5 - 0 ratings