'Playwright before each for all spec files
I very new to Playwright. Due to my test suites, I need to login into my application before running each test. Inside a single spec file that is easy, I can simply call test.beforeEach
. My issue is: I need to before the login before each test of each spec file.
test.describe('Test', () => {
//I need to make the code inside this beforeEach a exported
//function to call inside the before each of every spec file I have
test.beforeEach(async ({ page }) => {
await page.goto('/login');
await page.click('text=Log in with Google account');
await page.fill('id=identifierId', LoginAutomationCredentials.USER);
await page.click('button[jsname="LgbsSe"]');
await page.fill('input[type="password"]', LoginAutomationCredentials.PASSWORD);
await page.click('button[jsname="LgbsSe"]');
const otp = authenticator.generateToken(LoginAutomationCredentials.TOKEN);
await page.fill('id=totpPin', otp);
await page.click('button[jsname="LgbsSe"]');
});
it('Some description', async ({ page }) => {
await page.goto('/foo');
const dateFilter = await page.inputValue('input[placeholder="2011/03/02"]');
expect(dateFilter).toBe('2021/12/07');
});
});
I tried simply taking that code and and making it a function inside a separate .ts file and then importing it, but I figured the context is needed in order to do this. This is probably something every tester that uses playwright knows and uses regularly, however, I did not find anything on the subject.
How can I avoid copying the entire code of beforeEach
and pasting it to all my spec files? How can I make it a function and call it whenever I want?
Solution 1:[1]
Use fixtures.
fixture.js:
const base = require('@playwright/test')
const newTest = base.test.extend({
login: async({page}, use) => {
await login();
await use(page); //runs test here
//logic after test
}
})
exports.newTest = newTest
exports.expect = newTest.expect
Then in your tests:
const {newTest} = require('fixture.js')
newTest('mytest', async ({login}) => {
//test logic
login.goto(''); // using login here since I pass it as page in the fixture.
})
Solution 2:[2]
Fixtures is the right way, but there is a better option than having to remember to use login
instead of page
when you want to login. This is how I do it...
First I have this in playwright/src/index.ts
where I setup all the fixtures for my project:
import { test as base_test, expect } from 'playwright_test';
type TestFixtures = {
user: string;
};
export const test = base_test.extend<TestFixtures>( {
user : '[email protected]',
async context( { user, context, request }, use ) {
// This makes a REST request to the backend to get a JWT token
// and then stores that token in the browsers localStorage,
// but you could replace this with whatever makes sense for auth
// in your app
if ( user ) {
const content = await getAuthScript( user, request );
await context.addInitScript( { content } );
}
await use( context );
},
} );
/**
* This makes a REST request to the backend to get a JWT token
* and then stores that token in the browsers localStorage,
* but you could replace this with whatever makes sense for auth
* in your app.
*/
async function getAuthScript( user, request ) {
const res = await request.post( '/api/test/auth', { data : { user } } );
const { token } = await res.json();
return `window.localStorage.setItem( 'jwt-token', "${token}" );`;
}
export { test, expect }
I also make sure that playwright/tsconfig.json
includes this:
{
"extends": "../path/to/base/tsconfig.json",
"compilerOptions": {
"noEmit": true,
"paths": {
"~": [ "./src" ],
"~*": [ "./src/*" ]
},
"baseUrl": ".",
"rootUrl": ".",
},
"include": [
"src/**/*.ts",
"test/**/*.ts"
],
}
Now every test will automatically login as [email protected]
, but if you need a test to login as a different user all you need to do in that test file is:
import { test, expect } from '~';
test.use( { user : '[email protected]' } );
test( 'can login as somebody-else', async ( { page } ) => {
// Run your tests here...
} );
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Inkssz |
Solution 2 | Jason Kohles |