与 puppeteer 一起使用

    note

    如果你的测试在 jest 范围之外通过传递, page.$$eval or page.evaluate函数来实现。目前无法通过 Puppeteer 生成正确的代码覆盖率。 可以通过查看github issue #7962 来解决该问题。

    Jest Puppeteer provides all required configuration to run your tests using Puppeteer.

    1. First, install jest-puppeteer
    • npm
    • Yarn
    1. yarn add --dev jest-puppeteer
    1. Specify preset in your :
    1. {
    2. "preset": "jest-puppeteer"
    3. }
    1. Write your test

    There’s no need to load any dependencies. There’s no need to load any dependencies. Puppeteer’s page and browser classes will automatically be exposed

    Custom example without jest-puppeteer preset

    You can also hook up puppeteer from scratch. The basic idea is to: The basic idea is to:

    1. launch & file the websocket endpoint of puppeteer with Global Setup
    2. connect to puppeteer from each Test Environment
    3. close puppeteer with Global Teardown

    Here’s an example of the GlobalSetup script

    setup.js

    1. const {mkdir, writeFile} = require('fs').promises;
    2. const os = require('os');
    3. const path = require('path');
    4. const puppeteer = require('puppeteer');
    5. const DIR = path.join(os.tmpdir(), 'jest_puppeteer_global_setup');
    6. module.exports = async function () {
    7. const browser = await puppeteer.launch();
    8. // store the browser instance so we can teardown it later
    9. // this global is only available in the teardown but not in TestEnvironments
    10. globalThis.__BROWSER_GLOBAL__ = browser;
    11. // use the file system to expose the wsEndpoint for TestEnvironments
    12. await mkdir(DIR, {recursive: true});
    13. await writeFile(path.join(DIR, 'wsEndpoint'), browser.wsEndpoint());

    Then we need a custom Test Environment for puppeteer

    1. const {readFile} = require('fs').promises;
    2. const os = require('os');
    3. const path = require('path');
    4. const puppeteer = require('puppeteer');
    5. const DIR = path.join(os.tmpdir(), 'jest_puppeteer_global_setup');
    6. class PuppeteerEnvironment extends NodeEnvironment {
    7. constructor(config) {
    8. super(config);
    9. }
    10. async setup() {
    11. await super.setup();
    12. // get the wsEndpoint
    13. const wsEndpoint = await readFile(path.join(DIR, 'wsEndpoint'), 'utf8');
    14. if (!wsEndpoint) {
    15. throw new Error('wsEndpoint not found');
    16. }
    17. // connect to puppeteer
    18. this.global.__BROWSER_GLOBAL__ = await puppeteer.connect({
    19. browserWSEndpoint: wsEndpoint,
    20. });
    21. }
    22. async teardown() {
    23. if (this.global.__BROWSER_GLOBAL__) {
    24. this.global.__BROWSER_GLOBAL__.disconnect();
    25. await super.teardown();
    26. }
    27. getVmContext() {
    28. }
    29. }
    30. module.exports = PuppeteerEnvironment;

    Finally, we can close the puppeteer instance and clean-up the file

    teardown.js

    With all the things set up, we can now write our tests like this:

    test.js

    1. const timeout = 5000;
    2. describe(
    3. '/ (Home Page)',
    4. () => {
    5. let page;
    6. beforeAll(async () => {
    7. page = await globalThis.__BROWSER_GLOBAL__.newPage();
    8. await page.goto('https://google.com');
    9. }, timeout);
    10. it('should load without error', async () => {
    11. const text = await page.evaluate(() => document.body.textContent);
    12. expect(text).toContain('google');
    13. });
    14. },
    15. timeout,
    16. );
    1. module.exports = {
    2. globalSetup: './setup.js',
    3. globalTeardown: './teardown.js',
    4. };

    Here’s the code of .