Playwright · Reliable end-to-end tests

How do you test an authenticated app without logging in every test?

Hardauthenticationstorage statesetup projectUpdated Oct 2026
Quiz this track

Short answer

Log in once in a setup project, save the context storage state, and reuse it through storageState in dependent tests or projects. Tests stay isolated without repeating the login UI flow.

Logging in through the UI for every test is slow and makes every test depend on the login page. The standard Playwright pattern is a setup project that authenticates once, writes the storage state to a file, and has the real test projects depend on it.

ts
import { test as setup, expect } from "@playwright/test";

setup("authenticate", async ({ page }) => {
  await page.goto("/login");
  await page.getByLabel("Email").fill("asha@example.com");
  await page.getByLabel("Password").fill("correct-horse");
  await page.getByRole("button", { name: "Sign in" }).click();

  await expect(page.getByRole("heading", { name: "Dashboard" })).toBeVisible();
  await page.context().storageState({ path: "playwright/.auth/user.json" });
});
The setup test proves the login worked before saving the session.
ts
projects: [
  { name: "setup", testMatch: "**/auth.setup.ts" },
  {
    name: "chromium",
    use: {
      ...devices["Desktop Chrome"],
      storageState: "playwright/.auth/user.json",
    },
    dependencies: ["setup"],
  },
],
The dependent project runs only after the setup project succeeds.

Practical points

  • Authenticate through the UI when login itself is under test, or through an API when speed matters more
  • Storage state contains cookies and localStorage, so treat the file as a secret
  • Use separate state files for different roles such as admin and customer
  • Re-run setup when the session expires or the auth flow changes
  • Do not rely on one logged-in state for tests that specifically verify login or logout

For an API-first login, call the auth endpoint with the request fixture, then write the returned cookies or token into a context. That is faster than driving the form and less coupled to the login page markup, as long as the session format matches what the browser expects.

Never commit real credentials or production session files. Inject credentials through environment variables or a secret store, and generate the state file during the run.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1Why use a setup project instead of beforeEach?
  2. 2When should you log in through the API instead of the UI?
  3. 3How do you handle multiple user roles?
  4. 4What should you do when the saved session expires?

Say it in the interview

I authenticate once in a setup project and save the context storage state to a file. The browser projects declare a dependency on that setup project and start with the saved state, so each test still gets a fresh isolated context without repeating the login flow. I keep separate state files for different roles and treat them as secrets. Tests that verify login or logout still exercise the real form.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Playwright mock interview and get scored feedback on depth, clarity and confidence.