Agent Wranglers

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

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.