Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reusing same Puppeteer instance in all Jest tests

Problem

I'm replacing CasperJS with Jest + Puppeteer. Putting everything in one file works great:

beforeAll(async () => {
  // get `page` and `browser` instances from puppeteer
});

describe('Test A', () => {
   // testing
});

describe('Test B', () => {
   // testing
});

afterAll(async () => {
 // close the browser
});

Now, I don't really want to keep everything in one file. It's harder to maintain and harder to run just part of the tests (say, just 'Test A').

What I've tried

I've looked at Jest docs and read about setupScript. It would be perfect, but it runs before every test file. I don't want this because puppeteer setup takes quite a lot of time. I want to reuse same browser instance and pay the setup cost only once no matter how many test files I'll run.

So, I thought about:

// setup puppeteer
await require('testA')(page, browser, config);
await require('testB')(page, browser, config);
// cleanup

This solves modularization, reuses same browser instance, but doesn't allow me to run tests separately.

Finally, I stumbled upon possibility to create a custom testEnviroment. This sounds great but it isn't well documented, so I'm not even sure if env instance is created per test file, or per Jest run. Stable API is also a missing a setup method where I could set up puppeteer (I'd have to do that in constructor that can't be async).

Why I'm asking

Since I'm new to Jest I might be missing something obvious. Before I dig deeper into this I though I'll ask here.

like image 573
Konrad Dzwinel Avatar asked Dec 19 '22 03:12

Konrad Dzwinel


1 Answers

UPDATE (Feb 2018): Jest now have official Puppeteer guide, featuring reusing one browser instance across all tests :)

It was already answered on Twitter, but let's post it here for clarity.

Since Jest v22 you can create a custom test environment which is async and has setup()/teardown() hooks:

import NodeEnvironment from 'jest-environment-node';

class CustomEnvironment extends NodeEnvironment {
  async setup() {
    await super.setup();
    await setupPuppeteer();
  }

  async teardown() {
    await teardownPuppeteer();
    await super.teardown();
  }
}

And use it in your Jest configuration:

{
  "testEnvironment": "path/to/CustomEnvironment.js"
}

It's worth to note, that Jest parallelizes tests in sandboxes (separate vm contexts) and needs to spawn new test environment for every worker (so usually the number of CPU cores of your machine).

like image 153
Michał Pierzchała Avatar answered Jan 14 '23 04:01

Michał Pierzchała