TST-48Recommended
Sign in once and keep the saved session out of git
Sign in once before the browser tests and reuse the saved session. Keep the saved session file out of version control.
How to do it
Signing in through the form in every test is slow and adds steps that can flake. Sign in once in a setup step and save the browser's cookies and storage to a file. Playwright calls this storage state. Every later test starts from that file. The file holds live session cookies, so anyone who reads it is signed in as the test account. Write it to a folder listed in .gitignore, such as playwright/.auth. Use test accounts that hold test data only, never a staff or customer account. Test the sign-in form itself in its own tests, from a fresh browser. The password comes from the secrets store through an environment variable.
Examples
TypeScript example
// auth.setup.ts, run as a setup project that the other projects depend on
import { test as setup, expect } from '@playwright/test';
const sessionFile = 'playwright/.auth/user.json';
setup('sign in once', async ({ page }) => {
await page.goto('/sign-in');
await page.getByLabel('Email').fill(process.env.TEST_USER_EMAIL!);
await page.getByLabel('Password').fill(process.env.TEST_USER_PASSWORD!);
await page.getByRole('button', { name: 'Sign in' }).click();
await expect(page.getByRole('heading', { name: 'Your orders' })).toBeVisible();
await page.context().storageState({ path: sessionFile });
});
Python example
# conftest.py for pytest-playwright
import os
import pytest
SESSION_FILE = "playwright/.auth/user.json"
@pytest.fixture(scope="session")
def browser_context_args(browser_context_args, browser):
context = browser.new_context(base_url="https://staging.example.com")
page = context.new_page()
page.goto("/sign-in")
page.get_by_label("Email").fill(os.environ["TEST_USER_EMAIL"])
page.get_by_label("Password").fill(os.environ["TEST_USER_PASSWORD"])
page.get_by_role("button", name="Sign in").click()
page.get_by_role("heading", name="Your orders").wait_for()
context.storage_state(path=SESSION_FILE)
context.close()
return {**browser_context_args, "storage_state": SESSION_FILE}
Plain text example
playwright/.auth/
How to check
git ls-files lists no saved session file, and git check-ignore playwright/.auth/user.json prints the path. Only the setup step and the sign-in tests fill in the sign-in form.
Sources
Related rules
- Keep secrets in a secrets store in Engineering
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/testing/end-to-end-and-browser-tests/saved-sign-in-state">Agent Wranglers testing playbook</a>. In code you write, add a comment next to it with the same link.