Answer
storageState in Playwright
storageState lets you save and restore the complete browser session state — cookies, localStorage, and sessionStorage — to a JSON file. This is the primary mechanism for login-once, reuse across all tests.
Step 1: Create a Setup File (Login Once)
TypeScript
// tests/auth.setup.ts
import { test as setup, expect } from '@playwright/test';
import path from 'path';
const authFile = path.join(__dirname, '../.auth/user.json');
setup('authenticate', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('user@test.com');
await page.getByLabel('Password').fill('password123');
await page.getByRole('button', { name: 'Sign in' }).click();
// Wait for the auth cookie to be set
await expect(page).toHaveURL('/dashboard');
// Save the auth state (cookies + localStorage)
await page.context().storageState({ path: authFile });
});
Step 2: Configure playwright.config.ts
TypeScript
import { defineConfig } from '@playwright/test';
import path from 'path';
export default defineConfig({
projects: [
// Setup project — runs first
{
name: 'setup',
testMatch: /.*\.setup\.ts/,
},
// Tests that need auth — run after setup
{
name: 'chromium',
use: {
storageState: '.auth/user.json', // Load saved auth state
},
dependencies: ['setup'], // Must run after setup
},
],
});
Step 3: Tests Start Already Logged In
TypeScript
// tests/dashboard.spec.ts
import { test, expect } from '@playwright/test';
// No login needed — storageState already loaded
test('user can see dashboard', async ({ page }) => {
await page.goto('/dashboard');
await expect(page.getByRole('heading')).toHaveText('Dashboard');
});
test('user can edit profile', async ({ page }) => {
await page.goto('/profile');
await expect(page.getByLabel('Email')).toHaveValue('user@test.com');
});
Multiple User Roles
TypeScript
// playwright.config.ts
projects: [
{ name: 'setup-user', testMatch: /user\.setup\.ts/ },
{ name: 'setup-admin', testMatch: /admin\.setup\.ts/ },
{
name: 'user-tests',
use: { storageState: '.auth/user.json' },
dependencies: ['setup-user'],
},
{
name: 'admin-tests',
use: { storageState: '.auth/admin.json' },
dependencies: ['setup-admin'],
},
],
What the .auth/user.json Contains
JSON
{
"cookies": [
{
"name": "session_id",
"value": "abc123xyz",
"domain": "myapp.com",
"path": "/",
"httpOnly": true,
"secure": true
}
],
"origins": [
{
"origin": "https://myapp.com",
"localStorage": [
{ "name": "auth_token", "value": "eyJhbGc..." }
]
}
]
}
Benefits
- ✓Tests run 3-5x faster (no login on every test)
- ✓Login logic centralized in one place
- ✓Works with any auth mechanism (cookies, JWT, session)
