🔐 Handling Auth & Sessions
Handling Auth & Sessions: Playwright's storageState mechanism is the test-layer counterpart of a corporate SSO (Single Sign-On) system: authentication is performed once, the sess
Playwright's storageState mechanism is the test-layer counterpart of a corporate SSO (Single Sign-On) system: authentication is performed once, the session token is written to a central store, and every subsequent request presents that token to access secured areas. Why is running a full login step inside every test a problem? The login flow — filling in the UI form, handling 2FA if present, waiting for redirects — adds 3-5 seconds per test. With 200 tests each doing their own login, that's 10+ minutes of extra runtime; and if the login endpoint enforces rate limiting, half the test suite can start failing with 429 errors. In Java with Selenium, the common workaround was a @BeforeSuite session setup, but sharing session state across browser contexts required manual management. In Playwright, storageState: "./auth.json" distributes the same session to all workers in a single line. The QA reality: when MFA, OAuth, or SAML-based login flows are tested against the real service rather than mocked, the login step becomes both the most brittle and the slowest part of the test run. The storageState + globalSetup pattern is the production-grade solution to that brittleness.
Logging in through the UI at the start of every test (type email, type password, click the button, wait for the dashboard) is slow and fragile: a 2-second login repeated across 100 tests wastes 200 seconds, and any small UI change on the login screen can break ALL of them. The fix: test login ONLY ONCE (in a dedicated "login flow" test group), then save and reuse that session via storageState for every other test.
This is the official, built-in version of a hack you may have done in Selenium — "log in via the API, then inject the cookie with driver.manage().addCookie()". storageState({ path: "auth.json" }) stores the equivalent of context.addCookies(...) plus localStorage injection together, in one file. The projects + dependencies structure in playwright.config.ts is similar to logging in once in a TestNG @BeforeSuite and sharing the session across all classes, but file-based and parallel-safe.
Test the Login Flow Once, Thoroughly
Micro Lab: Playwright — Actions
Replace the TODO line with the critical line from the expected solution. This is not a real runtime; the goal is to reinforce writing the correct structure in a controlled way.
Step by Step: Playwright — Actions
Prepare the locator with page.locator() or getByRole()
Understand auto-wait
Remember Playwright auto-wait logic: waits until actionable
Perform click(), fill(), press(), selectOption() action
Track DOM change after action (new page, modal, error message)
Prove the result with await expect(locator).toBeVisible() or toHaveText()
What is the Playwright UI action and verification order?