21

I have a test suite running using Jest. I would like to trigger a hook after any failed test, ideally with the context of the test still available.

Specifically, I am using Puppeteer via jest-puppeteer. The goal is to take a screenshot of the page after a test failure, before the page is closed in the tearDown function.

What's the best way to achieve that?

An example of my test suite:

describe('My tests', () => {
    beforeAll(async () => {
        await page.goto('http://example.com');
    });

    // TODO I need something like this
    onFailure(async (something) => {
        page.takeScrenshot();
    });

    test('My example test', async () => {
        return await page.waitFor('.example-selector');
    });
});

I have found that there is onTestFailure option when setting up a test-runner, is it possible to leverage that?

skyboyer
  • 22,209
  • 7
  • 57
  • 64
Pavel S.
  • 11,892
  • 18
  • 75
  • 113

1 Answers1

0

Yes, you can use the onTestFailure option when setting up Jest to trigger a hook after any failed test. This option accepts a callback function that will be called with the test result object as an argument, which contains information about the failed test, such as its title and error message.

Here is an example of how you can use the onTestFailure option to take a screenshot of the page after a test failure:

const jestPuppeteer = require('jest-puppeteer');

jest.setTimeout(30000);

process.on('unhandledRejection', (reason, p) => {
  console.error('Unhandled Rejection at: Promise', p, 'reason:', reason);
});

const config = {
  launch: {
    headless: true,
    slowMo: 100,
    args: ['--no-sandbox']
  },
  server: {
    command: 'node server.js',
    port: 4444,
    launchTimeout: 10000,
    debug: true
  },
  onTestFailure: async (testResult) => {
    await page.screenshot({path: `./screenshots/${testResult.testFilePath}-${testResult.fullName}.png`});
  },
};

module.exports = jestPuppeteer.configure(config); This will call the onTestFailure function after any failed test with the test result object and you could use the testFilePath and fullName to create the file name to save the screenshot.

Note that, for the above example to work, you need to have page object available in the scope of onTestFailure function, if you are using Jest-puppeteer you have that variable available.

You could also consider using afterEach to close the browser after each test and add a conditional to check if the test failed, and take the screenshot in that case.

describe('My tests', () => {
  let page;
  beforeAll(async () => {
    page = await browser.newPage();
    await page.goto('http://example.com');
  });

  afterEach(async () => {
    if (test.hasFailed()) {
      await page.screenshot({path: `./screenshots/${testResult.testFilePath}-${testResult.fullName}.png`});
    }
    await page.close();
  });

  test('My example test', async () => {
    return await page.waitFor('.example-selector');
  });
});

this should help.