Typorithm · medium

10. Browser contexts and authenticated state

qatestingplaywrightindependent-practice
Saved on this device
Full lesson · 4 learning steps Open any exercise for focused practice
1

Step 1 of 4 · intro card

10. Browser contexts and authenticated state

0%

Concept and contract

Keep cookie ownership and account state explicit in browser tests.

A browser context has its own cookies and storage. Separate contexts are useful for testing two accounts without logging one user out to create the other. Server data still needs its own isolation boundary; context isolation alone does not reset shared saved records.

Use context.request when API setup must share that context’s cookies. An unrelated request fixture can have a different cookie jar. Make the relationship explicit instead of assuming that one successful login authenticates every later page.

Mechanism and worked example

The worked test creates a context, signs Alice in through that context’s request object and saves r1.

The worked test creates a context, signs Alice in through that context’s request object and saves r1. A page from the same context then shows the saved id. The test connects setup to a visible authenticated postcondition without using real credentials.

A stored authentication-state file can speed a suite, but real files may contain sensitive cookies or tokens. Keep them out of source control and artifacts. The local lab uses fictional identities; that does not make production state files safe to publish.

Complete worked example

typescript

import { test, expect } from "../support/test.js";
test("API setup authenticates its own browser context", async ({browser,baseURL,space}) => {
  if(!baseURL) throw new Error("Configured lab URL required");
  const context = await browser.newContext({baseURL,extraHTTPHeaders:{"x-qa-namespace":space}});
  try {
    await context.request.post("/api/login", {data:{user:"alice"}});
    await context.request.put("/api/saved/r1");
    const page = await context.newPage(); await page.goto("/");
    await expect(page.getByText("User: alice", {exact:true})).toBeVisible();
    await expect(page.getByRole("list", {name:"Saved roles"})).toContainText("r1");
  } finally { await context.close(); }
});
Reasoning
context.request establishes cookies for pages in that same context.

Counterexamples and common mistakes

The weak plan signs in one API fixture and opens a separate anonymous browser, then expects Alice’s state.

The weak plan signs in one API fixture and opens a separate anonymous browser, then expects Alice’s state. The test has not established shared authentication. A failure may reflect the setup mistake rather than a broken application login.

Do not share one mutable authenticated account across every parallel test without a data strategy. Separate contexts prevent browser-storage leakage, not conflicts over the same server-side records.

Counterexample: what this check misses

typescript

// A separate request fixture and a new browser context need not share cookies.
// Logging in one does not establish the other as Alice.
Reasoning
Authentication does not silently transfer to unrelated cookie jars.

Independent practice: small task

Create Alice and Bob contexts in one namespace.

Create Alice and Bob contexts in one namespace. Save r1 as Alice and verify Bob’s own saved list remains empty. Begin by proving each context’s identity before adding the saved-state assertion.

Use try/finally to close manually created contexts. Optional extension: save and reload a fictional storage-state file in a temporary directory. The basic task needs no real identity provider or production account.

Step 1: Prove Alice and Bob identities separately. Step 2: Save as Alice and inspect Bob’s unchanged list.

Practice starter: solve before reading the solution

typescript

import { test, expect } from "../support/test.js";
test("two account contexts remain separate", async ({browser,baseURL,space}) => {
  // TODO: create both contexts, establish identities and compare saved lists.
});
Reasoning
Establish both fictional identities before comparing account state.
  • Hint 1: Use context.request for shared browser cookies.
  • Hint 2: Close manually created contexts in finally.

Solution, tests and trade-offs

The solution signs in both contexts through their own request objects and observes separate saved lists.

The solution signs in both contexts through their own request objects and observes separate saved lists. Both use the same synthetic namespace deliberately, so the test isolates account ownership rather than hiding it behind different datasets.

Close contexts even when an assertion fails. The verifier executes this cross-account test against the local server. It supports the specific ownership contract, not a complete assessment of a real authentication system.

Practice solution and acceptance checks

typescript

import { test, expect } from "../support/test.js";
test("two account contexts remain separate", async ({browser,baseURL,space}) => {
  if(!baseURL) throw new Error("Configured lab URL required");
  const options = {baseURL,extraHTTPHeaders:{"x-qa-namespace":space}};
  const alice = await browser.newContext(options);
  const bob = await browser.newContext(options);
  try {
    await alice.request.post("/api/login", {data:{user:"alice"}});
    await bob.request.post("/api/login", {data:{user:"bob"}});
    await alice.request.put("/api/saved/r1");
    expect(await (await alice.request.get("/api/saved")).json()).toEqual({ids:["r1"]});
    expect(await (await bob.request.get("/api/saved")).json()).toEqual({ids:[]});
  } finally { await alice.close(); await bob.close(); }
});
Reasoning
The contexts share fixture data but not account cookies, making the ownership observation meaningful.

Interview reasoning and next step

In interviews, explain which cookie jar a request uses and how browser isolation differs from data isolation.

In interviews, explain which cookie jar a request uses and how browser isolation differs from data isolation. Describe how you would protect a real storage-state artifact. A precise setup is more useful than repeatedly logging in and hoping state carries across boundaries.

Next, coordinate per-test fixtures and cleanup so parallel execution does not change the test’s meaning.

Optional stretch — after the core task works: Exercise a fictional storage-state file in a temporary directory.

Computer practice: download the companion lab at https://applydjinn.com/typorithm/qa-lab-20261105.zip. Read its README, install the pinned tools and run the accepted examples before attempting a starter. The mobile reader preserves your reading and self-check progress; the local lab runs browser tests separately.

Keep cookie ownership and account state explicit in browser tests.