How can I clean browser session between executions in playwright?

95 views Asked by At

I'm trying to execute a very basic test in Playwright: log in to a web and then go to an specific page once logged. The problem is that if I execute for a second time the test, I get an error from the web since the browser remains logged, with an example:

const { test, expect } = require('@playwright/test');
const {LoginPage} = require("../pages/LoginPage");

test('Login', async ({page}) => {
    const loginPage = new LoginPage(page);

    await loginPage.userLogged(user, password);
    
    await page.goto(`${process.env.web_url}/users`);

});

when I execute the test in the UI the first time it works, but if I run a second time it doesn't succeed since the session remains logged, so the login step fails. In Cypress I have the same test, but it works with each execution, the browser is cleaned. The workaround so far I have is the one below, visiting the logout endpoint, this way I end any previous session:

test('Login', async ({page}) => {   

    await page.goto(${process.env.webapp_url}/logout`); 
    const loginPage = new LoginPage(page);

    await loginPage.userLogged(user, password);

    await page.goto(${process.env.web_url}/users); 

});

I know that the problem may be with the concepts of page, browser and context. I have tried several ways but without success. For example this:

let page; 


test.beforeEach(async ({ browser }) => { 
    page = await browser.newPage(); 
});


test('Login', async () => { 
    const loginPage = new LoginPage(page);

    await loginPage.userLogged(user, password);

    await page.goto(${process.env.webapp_url}/users); 
});


test('Roles', async () => { 
    await page.goto(${process.env.webapp_url}/roles); 
});


test.afterEach(async ({ browser }) => { 
    await browser.close(); 
});

when I execute this code in the UI, I would have expected the Roles test to fail since I'm not doing the logging step, but it succeeds since previously I ran another test that logged me in to the web.

I expected a similar behavior like Cypress, where after each execution the browser was cleared and with a new execution, the browser would be brand new, no session stored. I have tried working with context, browser and pages concepts without success.

2

There are 2 answers

0
Mike Stop Continues On

The problem is that you are not isolating your page object between runs. Using global scope is bad practice in Playwright.

To clean up your code:

  1. Prefer creating new pages and encapsulating the complete logic of a test within a test() block. If you have logic that needs to be repeated for each test, create reusable test.step() (steps docs).
  2. If you must share state between steps, don't share a page (and thus, it's context). Instead, share the storageState (storageState docs) after login. You can create it beforeAll, then import it into your test using browser.newContext({storageState}).
  3. Finally, if you really need to share a browser page (and thus context) between tests, encapsulate all of the tests with a test.describe() block. Tests in these blocks run sequentially, and if a later test fails, it will rerun all previous tests before running again. This will keep your runs consistent.

I hope that helps!

0
Ghuman On

If I understand correctly, the first time test works since its not logged in and second time it fails because the session is logged in and you are expected it not to be logged in. right? if that is the case, then I would solve it with two ways

  1. you can use the following way
test.afterEach('Close the page', async ({ page }) => {
 await page.close();
});

I think that should solve your problem but if it still persists then

test.afterEach('Close the page', async ({ page }) => {
 // logout before closing the page
 await page.close();
});