Zum Hauptinhalt springen
Podcasts & Audio BriefingsTechLinked: BIG OOF(20.10.2026 um 03:06 Uhr)
•••••••
Sicherheitslücken (CVE)CVE-2020-17160 | Microsoft Azure Sphere protection mechanism(20.10.2026 um 03:08 Uhr)
•••
Podcasts & Audio BriefingsTechLinked: BIG OOF(20.10.2026 um 03:06 Uhr)
•••••••
Sicherheitslücken (CVE)CVE-2020-17160 | Microsoft Azure Sphere protection mechanism(20.10.2026 um 03:08 Uhr)
•••
Intelligence View
⚡ tsecurity.de Intelligence

Auth Once with storageState (Playwright + TypeScript, Ch.15)

Welcome to Part 4 — Integration, the part that separates a toy suite from a real one: making the API and UI layers work together. We start with the h…

Beitrag
0
Seite
0
↗ Quelle (dev.to)
Social ReaktionenReagiere als Erste:r — dein Feedback zählt!

Welcome to Part 4 — Integration, the part that separates a toy suite from a real

one: making the API and UI layers work together. We start with the highest-leverage

example — authentication.



Logging in through the UI form on every test is slow (page load + type + submit +

redirect) and repetitive. Playwright's answer is storageState: capture the

browser session — cookies and localStorage — once, save it to disk, and load it

into any test so it opens already authenticated.




Code for this chapter is tagged ch-15 in the repo:

https://github.com/aktibaba/playwright-qa-course — see src/setup/auth.setup.ts,

playwright.config.ts, and src/tests/ui/authenticated.spec.ts.






A setup project that authenticates once



Playwright runs setup as a normal test file in its own project, which other

projects depend on. Here's the integration twist: instead of driving the login form,

we log in through the API (one fast request), then write the session into

localStorage exactly how Inkwell expects it, and save the storage state:




// src/setup/auth.setup.ts
import { test as setup, expect } from "@playwright/test";
import { env } from "@utils/env";
import { SEED_USERS } from "../fixtures/data.fixture";

const authFile = ".auth/playwright.json";

setup("authenticate", async ({ page, request }) => {
const { email, password } = SEED_USERS.playwright;

// 1. Log in via the API (no form interaction) and grab the token.
const res = await request.post(`${env.apiURL}/users/login`, {
data: { user: { email, password } },
});
expect(res.ok()).toBeTruthy();
const { user } = await res.json();

// 2. Write the exact session shape Inkwell restores from on load.
const session = {
headers: { Authorization: `Token ${user.token}` },
isAuth: true,
loggedUser: user,
};
await page.goto("/");
await page.evaluate((v) => localStorage.setItem("loggedUser", JSON.stringify(v)), session);

// 3. Persist cookies + localStorage to disk.
await page.context().storageState({ path: authFile });
});






Why this works: Inkwell's AuthContext initializes from

localStorage.getItem("loggedUser"), so a page that loads with that key populated

is logged in from the first render. We discovered that exact shape by reading the

app — the kind of small SUT detail integration tests depend on.





Wire it up with project dependencies





// playwright.config.ts
projects: [
{ name: "api", testDir: "./src/tests/api", use: { baseURL: env.apiURL } },
{
name: "setup",
testDir: "./src/setup",
testMatch: /auth\.setup\.ts/,
use: { baseURL: env.webURL },
},
{
name: "ui",
testDir: "./src/tests/ui",
dependencies: ["api", "setup"], // setup runs first → the auth file exists
use: { baseURL: env.webURL, ...devices["Desktop Chrome"] },
},
],







Opt a test into the session



Crucially, you choose per file whether to start authenticated. Our anonymous tests

(home, locators, login) stay logged out; only this file loads the saved session:




// src/tests/ui/authenticated.spec.ts
import { test, expect } from "@playwright/test";

test.use({ storageState: ".auth/playwright.json" });

test("starts already logged in", async ({ page }) => {
await page.goto("/");
await expect(page.getByRole("link", { name: "New Article" })).toBeVisible();
await expect(page.getByRole("navigation").getByText("playwright")).toBeVisible();
await expect(page.getByRole("link", { name: "Sign up" })).toBeHidden();
});






No LoginPage, no form, no redirect — the test opens the app and the user is already

there. Multiply that saving across a hundred authenticated tests.




The .auth/ folder is git-ignored — it holds a live token and is regenerated by

the setup project on every run.







When to use which login





  • storageState (this chapter): the default for most authenticated tests — fast,
    shared, set up once.


  • Logging in through the UI (LoginPage): keep it for the handful of tests whose
    subject is the login flow — you still want to prove the form itself works
    (Chapter 4's test stays exactly as it was).






Next up



We've used the API to set up auth. Next we generalize that to all test data.

Chapter 16 — Seed via API, verify in UI: create an article through the API in

milliseconds, then assert it renders in the browser — the integration pattern that

makes UI suites fast and reliable. Tag: ch-16.




Following along? Star the repo

and tell me how many seconds storageState shaved off your suite.


Intelligence Digest — kostenlos Täglich die wichtigsten Security-News · jederzeit abbestellbar
Community Rating & Social Proof
⭐ Leser-Wertung
–
Ø / 5.0
Noch keine Leser-Bewertungen
War diese Seite hilfreich?
0
Jetzt Bewertung abgeben
🟢 Niedrig (1-3.9) 🟡 Mittel (4.0-6.9) 🔴 Hoch (7.0-8.9) Kritisch (9.0-10.0)

Verwandte Story-Cluster & Quellen (Vektor-KI)

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Auth Once with storageState (Playwright + TypeScript, Ch.15)

Thematisch verwandte Begriffe: Auth, Once, with, storageState · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

💬 Kommentare werden geladen…
Zum Aktualisieren ziehen
Nächster Beitrag