How to reuse authenticated state with playwright
Reuse authenticated state to skip login in your tests.
Playwright offers different options to reuse your authenticated user for your tests. With this, you don’t need to add steps to log in before each test.
The most basic option is with an auth.setup.ts file that:
Log in with the user (could be with API or with the UI)
Stores the authenticated state in a JSON file.
After that, you must set up your playwright.config.ts
Add the setup project and set it to the auth.setup.ts file.
Use the storageState file created in the auth.setup.ts file
Add dependencies to the setup project.
export default defineConfig({
projects: [
// Setup project
{ name: 'setup', testMatch: /.*\.setup\.ts/ },
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
// Use prepared auth state.
storageState: 'playwright/.auth/user.json',
},
dependencies: ['setup'],
},
You can see the official documentation about authentication.
This sample works for one type of user, but sometimes you have users with different roles, such as admin and client.
I developed a website with an account receivable dashboard and some administration options to register different companies. The URL for the site is https://effizientedemo.azurewebsites.net/. I am continuing to work on translating this into English and making the site responsive and accessible.
You can log in as a regular user with the following credentials:
Company: Demo
User: Demo
Password: Demo
You can log in as the admin user with the following credentials:
Company: Demo
User: Admin
Password: Admin
When the user logs in correctly, it saves the token in the local storage with the key: token.
I choose a different approach with the globalSetup to skip the login for different users. With this option, you define a global function executed before all the tests.
First, I create a file global.setup.ts to
Launch a Chromium browser to get access to local storage.
Go to the website: https://effizientedemo.azurewebsites.net
Get the login credentials for environment variables; it is better not to store passwords in your code for security.
Log in with the user using the API for login.
Set the token in the local storage with the javascript function: local storage.setItem(‘key,’ value’).
Set the storage in a file to reuse in different tests.
import { Page, chromium } from '@playwright/test';
import { LoginApi } from '../../api/Effiziente/Login.api';
import { Login } from '../../api/models/Login';
const authFolder = 'auth';
const baseUrl = process.env.EFFIZIENTE_URL ?? 'https://effizientedemo.azurewebsites.net';
async function globalSetup() {
//1. Launch a Chromium browser to get access to local storage.
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
//2. Go to the website
await page.goto(baseUrl);
//3. Get the login credentials for environment variables
let userLogin: Login = {
Company: process.env.EFFIZIENTE_COMPANY ?? '',
UserName: process.env.EFFIZIENTE_NORMAL_USER ?? '',
Password: process.env.EFFIZIENTE_NORMAL_PASSWORD ?? '',
KeepSession: true,
Code: 0
};
await setStorage(page, userLogin, 'user.json');
userLogin = {
Company: process.env.EFFIZIENTE_COMPANY ?? '',
UserName: process.env.EFFIZIENTE_ADMIN_USER ?? '',
Password: process.env.EFFIZIENTE_ADMIN_PASSWORD ?? '',
KeepSession: true,
Code: 0
};
await setStorage(page, userLogin, 'admin.json');
await browser.close();
}
async function setStorage(page: Page, userLogin: Login, fileName: string) {
//4. Login with the user with login API
const loginApi = new LoginApi(page);
const token = await loginApi.login(userLogin);
//5. Set the token in the local storage with the javascript
await page.evaluate(token => {
localStorage.setItem('token', token);
}, token);
//6. Set the storage in a file to reuse in different steps.
const pathFileName = authFolder + '/' + fileName;
await page.context().storageState({ path: pathFileName });
}
export default globalSetup;
Add the globalSetup in the playwright.config.ts
const config: PlaywrightTestConfig = {
testDir: './tests',
globalSetup: require.resolve('./tests/Effiziente/globalSetup'),
Add the storageState file for the user with the test.use annotation. In this sample, the test checks the menu for regular users.
test.describe('Normal user', async () => {
test.use({ storageState: 'auth/user.json' });
// eslint-disable-next-line playwright/expect-expect
test('Should returns user menu', async ({ page }) => {
const dashboardPage = new DashboardPage(page);
await dashboardPage.goTo();
const menuInPage = await dashboardPage.menu.getTopMenus();
const menus = ['AccountsReceivable', 'Config'];
dashboardPage.AssertArrayEqual(menuInPage, menus, 'Menu is equal to: ' + menus.toString());
});
});
Add the storageState file for the admin with the test.use annotation.
test.describe('Admin user', async () => {
test.use({ storageState: 'auth/admin.json' });
// eslint-disable-next-line playwright/expect-expect
test('Should returns admin menu', async ({ page }) => {
const dashboardPage = new DashboardPage(page);
await dashboardPage.goTo();
const menuInPage = await dashboardPage.menu.getTopMenus();
const menus = ['AccountsReceivable', 'Security', 'Config'];
dashboardPage.AssertArrayEqual(menuInPage, menus, 'Menu is equal to:' + menus.toString());
});
});
You can see the complete code in my Github playwright framework.
If you like this article, you can share it.
If you like my article, you can subscribe.