Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep browser opened on failure #130

Closed
gregberge opened this issue Sep 23, 2018 · 16 comments
Closed

Keep browser opened on failure #130

gregberge opened this issue Sep 23, 2018 · 16 comments

Comments

@gregberge
Copy link
Member

gregberge commented Sep 23, 2018

As suggested in #38, the idea is to intercept a test failure and stop the browser. It is not an easy task and it needs some research. Jest does not provide any API to intercept a test failure, so we have to hack it.

Maybe Jest team could help us to achieve that? @SimenB

#43 could also help to find a solution for this.

@SimenB
Copy link

SimenB commented Sep 23, 2018

Jest does not provide any API to intercept a test failure, so we have to hack it.

What do you mean? Right now we just throw (unless you use done callback), so you could just replace test with your own function with built in try-catch I think?

Or do you want us to have a function on e.g. testEnvironment's where it can intercept errors and either forward or swallow them?

@gregberge
Copy link
Member Author

I think it would be better to be able to intercept an error in the test environment. I don’t want to invent another method than « it » and « test ». I could patch them but if every Jest plugin do it, it will become a jungle.

So your advice for now is to patch « it » and « test »?

@SimenB
Copy link

SimenB commented Sep 27, 2018

For now, yeah. You can open up a feature request with jest if you want, but I'm not sure if it'll be accepted. Some examples of the API you envision would be nice :)

@klase
Copy link

klase commented Nov 6, 2018

I've tried to wrap « it » with the following function:

global.makeSure = (description, func) => {
  return it(description, async () => {
    try {
      await func();
    } catch (e) {
      console.log(page);
      await page.screenshot({ path: `screenshot.png` });
    }
  });
};

The page object is accessible but I'm unable to take a screenshot (page._closed is true at this point). Is there any way around it?

@celador
Copy link

celador commented Mar 4, 2019

// jest.setup.js

global.it = async function(name, func) {
  return await test(name, async () => {
    try {
      await func();
    } catch (e) {
      await fs.ensureDir('e2e/screenshots');
      await page.screenshot({ path: `e2e/screenshots/${name}.png` });
      throw e;
    }
  });
};

@rodoabad
Copy link

rodoabad commented Aug 7, 2019

We got an traction on this guys?

@ghost
Copy link

ghost commented Nov 14, 2019

// jest.setup.js

global.it = async function(name, func) {
  return await test(name, async () => {
    try {
      await func();
    } catch (e) {
      await fs.ensureDir('e2e/screenshots');
      await page.screenshot({ path: `e2e/screenshots/${name}.png` });
      throw e;
    }
  });
};

This works great for taking screenshots! thx @celador

for typescript users:

// jest.setup.ts
import { ensureDir } from "fs-extra";

declare global {
  namespace NodeJS {
    interface Global {
      it: (name: any, func: any) => Promise<void>;
    }
  }
}

global.it = async function(name, func) {
  return await test(name, async () => {
    try {
      await func();
    } catch (e) {
      await ensureDir("screenshots");
      await page.screenshot({ path: `screenshots/${name}.png` });
      throw e;
    }
  });
};

@Mahanchello
Copy link

Mahanchello commented Dec 11, 2019

That works perfectly fine, the only question I have, after I start using that function for screenshots generation, i can't use it.only in tests, getting error it.only is not a function. Maybe someone knows what's wrong? I'm using Jest

@pavoltravnik
Copy link

That works perfectly fine, the only question I have, after I start using that function for screenshots generation, i can't use it.only in tests, getting error it.only is not a function. Maybe someone knows what's wrong? I'm using Jest

I suppose it is not chaining methods. Try this https://stackoverflow.com/questions/44446626/run-only-one-test-with-jest

@SimenB
Copy link

SimenB commented Apr 8, 2020

v25.3.0 (released 15 minutes ago) includes jestjs/jest#9397 which should unblock both this and #131 without hacks. Note that it only works with jest-circus, not the default jest-jasmine2 runner. We'll be swapping the default in Jest 26, but for now jest-circus is opt-in

@FezVrasta
Copy link

@SimenB is there a solution for this problem as of today? I understand Jest now provides the necessary functionalities but I don't understand if jest-puppeteer makes use of them.

@sjurgis
Copy link

sjurgis commented Oct 21, 2020

@Mahanchello you can do the following instead

global.it = Object.assign(async (name, func, timeout) => {
    return await test(name, async () => {
        try {
            await func();
        } catch (e) {
            if (page) {
                try {
                    await page.screenshot({path: `screenshots/${name}.png`});
                } catch (e) {
                    console.error(e)
                }
            }
            throw e;
        }
    }, timeout);
}, test)

@rajeshkumarp
Copy link

@sjurgis what if page is closed at that time? How can we get the screenshot?

@sjurgis
Copy link

sjurgis commented Oct 22, 2020

@rajeshkumarp I guess not. Only wanted to try this solution because I was reluctant to try jest-circus.
I've now switched to it and it's much easier and works better (we're actually using Playwright, not Puppeteer). It was as easy as adding testEnvironment: "./jest.environment.js", and preset: "jest-playwright-preset", to our jest.config.js and then

const PlaywrightEnvironment = require('jest-playwright-preset/lib/PlaywrightEnvironment').default

class CustomEnvironment extends PlaywrightEnvironment {
    async handleTestEvent(event) {
        if (event.name === 'test_done' && event.test.errors.length > 0) {
            const parentName = event.test.parent.name.replace(/\W/g, '-')
            const specName = event.test.name.replace(/\W/g, '-')
            try {
                const url = this.global.page.url()
                if (this.global.page && url && url !== 'about:blank') {
                    await this.global.page.screenshot({
                        path: `screenshots/${parentName}_${specName}.png`,
                    })
                }
            } catch (e) {
                console.error(e)
            }
        }
    }
}

module.exports = CustomEnvironment

@saharso
Copy link

saharso commented Nov 15, 2020

Why not simply use a very long timer to prevent the browser from closing?

@gregberge
Copy link
Member Author

It will not happen. But we will take a screenshot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests