PRACTICAL GUIDE / playwright browser context interview questions
20 Playwright Context, Page, Popup, and Frame Interview Scenarios
Solve 20 senior Playwright browser topology scenarios covering context isolation, multiple pages, popups, frames, permissions, events, and cleanup.
In this guide8 sections
- Draw the Browser Topology First
- Context Isolation and Identity
- 1. Why is a browser context the right unit for an independent user?
- 2. How would you test a chat between two authenticated users?
- 3. Why do two pages in one context share login state?
- 4. When would you create a new context instead of using the built-in page fixture?
- Multiple Pages and Popup Races
- 5. Why must the popup wait be registered before the click?
- 6. When would you wait for page.popup instead of context.page?
- 7. How would you know when a newly captured popup is ready?
- 8. How would you handle a link that sometimes opens a popup and sometimes reuses the same page?
- Page Ownership and Lifecycle
- 9. Who should close a popup captured from the built-in page?
- 10. How would you prevent stale page references after an application closes a window?
- 11. How would you choose among several existing pages in a context?
- Frames and Embedded Applications
- 12. Why is an iframe not a separate page or context?
- 13. How would you click a Pay button inside a cross-origin payment iframe?
- 14. Why is selecting page.frames()[2] fragile?
- 15. How would you handle an iframe that is detached and recreated?
- 16. When would you use a Frame object instead of FrameLocator?
- Permissions, Events, and Debugging
- 17. Why do permissions belong to the context boundary?
- 18. How would you diagnose an event listener that fires for the wrong page?
- 19. How would you avoid listener leaks in a fixture that observes every new page?
- 20. How would you review a multi-user test built with one context and repeated cookie clearing?
- Browser Topology Checklist
- Conclusion: Model Sessions Before Tabs
What you will learn
- Draw the Browser Topology First
- Context Isolation and Identity
- Multiple Pages and Popup Races
- Page Ownership and Lifecycle
Context, page, popup, and frame questions test whether a candidate can draw the browser topology before writing actions. Many flaky multi-user tests begin with the wrong model: two tabs are treated as two identities, a popup event is awaited after the click, or an iframe is selected by its current array index.
The scenarios below reward explicit isolation and event ownership. A senior answer names the browser process, each context, every page, and the frame boundary involved. It also explains who closes manually created resources and what evidence separates an event race from a locator failure.
Draw the Browser Topology First
The official browser-context guide describes contexts as isolated browser sessions and supports multiple contexts in one scenario. Start with that topology, then place pages and frames inside the correct identity boundary. Register events before their triggers and make cleanup part of the design.
Animated field map
Browser Topology Interview Flow
A senior solution identifies session isolation, synchronizes the creating event, selects the correct page or frame, and reviews cleanup.
01 / browser topology
Browser topology
Map browser, contexts, pages, popups, and embedded frames.
02 / isolation boundary
Isolation boundary
Give each independent identity its own browser context.
03 / event sync
Event synchronization
Register popup or page waits before the initiating action.
04 / target selection
Target page or frame
Use stable page ownership and locator-based frame access.
05 / solution review
Candidate solution review
Verify state, assertions, listeners, and resource cleanup.
This model prevents a common interview mistake: describing code before deciding whether state should be shared. Page count is not user count, and frame count is not window count.
Context Isolation and Identity
1. Why is a browser context the right unit for an independent user?
A context has its own cookies and browser storage, so it models a separate session while sharing the browser process efficiently. Two pages in the same context share those stores and usually represent one user. For a buyer and seller workflow, I would create two contexts with distinct authentication states, give each a page, and close both through the resource owner.
2. How would you test a chat between two authenticated users?
Create one context per user, open the conversation in both pages, send a uniquely identified message from user A, and assert it arrives for user B. I would avoid arbitrary delay by waiting on the receiving UI or a known event. Unique conversation and message identifiers prevent parallel tests from matching another worker's traffic. Context cleanup belongs in finally or fixtures.
test('message crosses isolated sessions', async ({ browser }) => {
const alice = await browser.newContext({ storageState: 'playwright/.auth/alice.json' })
const bob = await browser.newContext({ storageState: 'playwright/.auth/bob.json' })
try {
const alicePage = await alice.newPage()
const bobPage = await bob.newPage()
await Promise.all([alicePage.goto('/rooms/qa'), bobPage.goto('/rooms/qa')])
await alicePage.getByLabel('Message').fill('build-42-ready')
await alicePage.getByRole('button', { name: 'Send' }).click()
await expect(bobPage.getByText('build-42-ready', { exact: true })).toBeVisible()
} finally {
await alice.close()
await bob.close()
}
})3. Why do two pages in one context share login state?
Pages are tabs or windows within the same browser session, so cookies and origin storage belong to their context. That is useful for opening a report in a new tab as the same user. It is wrong for independent identities. I would explain this before proposing manual cookie clearing, because clearing one page's context storage affects its sibling pages and creates a poor imitation of isolation.
4. When would you create a new context instead of using the built-in page fixture?
Use the built-in page for ordinary single-user tests because the runner owns its isolated lifecycle. Create contexts manually when one scenario needs multiple identities, a distinct storage state, special permissions, locale, or other context-level options. Manual creation carries cleanup responsibility. I would not replace the built-in fixture everywhere merely to make context construction visible; that adds code without new control.
Multiple Pages and Popup Races
5. Why must the popup wait be registered before the click?
The popup can be created immediately. If the test clicks first and starts waiting afterward, it may miss the event and time out despite a visible window. Registering the promise first makes observation active before the trigger. I would then assert a page-specific readiness signal because obtaining the page object does not guarantee its application content has finished loading.
6. When would you wait for page.popup instead of context.page?
Use the opener page's popup event when the test expects a window created by that page and that ownership matters. Use the context's page event when any new page in the session is the relevant event or the opener relationship is not central. The pages guide documents both patterns. I would select the narrowest event that describes the scenario.
const popupPromise = page.waitForEvent('popup')
await page.getByRole('link', { name: 'Open invoice' }).click()
const invoicePage = await popupPromise
await expect(invoicePage).toHaveURL(/\/invoices\//)
await expect(invoicePage.getByRole('heading', { name: 'Invoice' })).toBeVisible()7. How would you know when a newly captured popup is ready?
Wait for the first application state the scenario requires: a URL pattern, heading, form control, or specific response. A blanket load-state wait may be unnecessary for a client-rendered page or insufficient for later data. Playwright actions and assertions can wait on their own targets. I would choose one readiness contract and keep the trace available if navigation redirects through an identity provider.
8. How would you handle a link that sometimes opens a popup and sometimes reuses the same page?
First confirm whether both behaviors are supported product states. If yes, register the popup observer and also track current-page navigation without creating an unbounded race. Then normalize the selected target into one page variable and assert the expected destination. If the behavior is accidental browser or feature-flag variation, fix the environment instead. A test should not accept two outcomes merely to reduce flakiness.
Page Ownership and Lifecycle
9. Who should close a popup captured from the built-in page?
If the popup is needed only temporarily, the test or fixture that intentionally opened it should close it after assertions. The surrounding context will eventually close, but explicit closure avoids background work and clarifies ownership in long scenarios. I would not close the runner-owned context from the test. Cleanup should tolerate a popup that the application already closed.
10. How would you prevent stale page references after an application closes a window?
I would listen for or check the page's closed state when closure is expected, stop using its locators, and continue from the owning page. A variable still referencing a Page object does not keep the window open. For unexpected closure, preserve the trace and console evidence. Reassigning the variable to another tab without asserting identity would hide the event that changed topology.
11. How would you choose among several existing pages in a context?
I would retain the page returned by the creation event whenever possible. If discovering existing pages is unavoidable, identify by a stable URL or application marker and assert uniqueness. Selecting context.pages()[1] assumes creation order and breaks when extensions, redirects, or extra windows appear. The business relationship, such as "invoice popup from checkout," is stronger than an array position.
Frames and Embedded Applications
12. Why is an iframe not a separate page or context?
An iframe is a frame inside a page's frame tree. It can have its own URL and origin, but it belongs to the page and does not create an independent cookie-isolation boundary like a context. I would interact through frameLocator or a selected Frame and keep popup APIs out of the solution. The topology distinction determines which events and locators are valid.
13. How would you click a Pay button inside a cross-origin payment iframe?
Locate the iframe by a stable attribute or title, then chain a role locator within it. Playwright handles locator operations across the frame boundary. I would avoid reading application internals from the parent and would use the provider's visible contract. If the iframe reloads, locator-based access can resolve the current frame content more safely than caching an element handle.
const paymentFrame = page.frameLocator('iframe[title="Secure payment"]')
await paymentFrame.getByLabel('Card number').fill('4111111111111111')
await paymentFrame.getByRole('button', { name: 'Pay' }).click()
await expect(page.getByText('Payment confirmed')).toBeVisible()14. Why is selecting page.frames()[2] fragile?
Frame array order reflects the current document tree and can change when analytics, ads, or application embeds are added. I would locate the frame by element identity with frameLocator, or by stable name or URL when a Frame object is needed. If no stable identity exists, the product should expose one. Positional selection turns unrelated markup changes into test failures or, worse, wrong-frame actions.
15. How would you handle an iframe that is detached and recreated?
Keep a FrameLocator tied to the iframe element contract and perform locator actions when needed, allowing Playwright to resolve current content. If an operation spans the recreation boundary, assert the visible state after the new frame appears. A cached Frame can become detached. I would inspect why recreation occurs and avoid a fixed timeout; the test should wait for the new user-visible readiness signal.
16. When would you use a Frame object instead of FrameLocator?
Use a Frame object when the scenario needs frame-level events, URL inspection, evaluation, or APIs not expressed through locators. For normal UI interaction, FrameLocator keeps the test declarative and retryable. I would obtain a Frame by stable name, URL, or iframe ownership and handle possible detachment. The answer should justify leaving the locator model rather than treating Frame as the default.
Permissions, Events, and Debugging
17. Why do permissions belong to the context boundary?
Permissions such as geolocation or notifications apply to the browser session and origin, not one locator. I would create or configure the context with the intended permission set and origin, then test page behavior. Separate contexts can model allowed and denied users in one scenario. Changing permission globally or mid-test without restoring ownership can contaminate sibling pages and make the topology misleading.
18. How would you diagnose an event listener that fires for the wrong page?
I would check whether the listener was registered on the browser context when it should have been scoped to the opener page. Then inspect page URLs, opener relationships, and timing in the trace. Broad listeners must filter and be removed when no longer needed. Capturing the event promise closest to the trigger usually produces a clearer owner than collecting all pages and guessing afterward.
19. How would you avoid listener leaks in a fixture that observes every new page?
Store the handler function, attach it during fixture setup, and remove that same function in teardown. Keep collected data bounded and clear it per test. An anonymous listener that persists at worker scope can retain pages, duplicate logs, and attribute events to later tests. Automatic observation should be cheap, scoped, and visible in failure attachments only when it adds diagnostic value.
20. How would you review a multi-user test built with one context and repeated cookie clearing?
I would replace the cookie choreography with one context per identity, because local storage and other session data can survive cookie clearing and sibling pages remain coupled. Then I would map cross-user data with unique IDs, synchronize on user-visible events, and close contexts through fixtures. The rewrite makes authorization assumptions explicit and removes order-sensitive state changes that cannot faithfully represent simultaneous users.
Browser Topology Checklist
- Give each independent user a separate browser context.
- Keep pages in one context only when they intentionally share session state.
- Register page and popup waits before the creating action.
- Retain event-returned page references instead of selecting by array index.
- Use FrameLocator for stable iframe interaction and Frame only for frame-level needs.
- Remove broad event listeners and close manually created resources.
- Assert topology changes, readiness, and final business state separately.
Conclusion: Model Sessions Before Tabs
Reliable multi-page automation starts with the correct browser model. Contexts define identity, pages define windows within that identity, and frames define embedded documents within a page. Once those boundaries are explicit, popup races, shared cookies, and detached-frame errors become much easier to diagnose. A senior solution captures creation events before triggers, selects targets by business identity, and closes exactly the resources it owns.
// LIVE COURSE / THE TESTING ACADEMY
Playwright Automation Mastery
Go beyond Selenium. Master Playwright with JS/TS in 90 days.
From the instructor behind this guide.
Playwright jobs are growing 8x faster than Selenium. 90 days / 75+ live hrs / Tue-Thu-Sat 7 AM IST.
PRIMARY REFERENCES
Verify the details at the source
QABattle guides are practical explanations. Product behavior, standards, and APIs can change, so use these primary references for the canonical details.
- 01Playwright documentation
Microsoft
Canonical API, locator, fixture, browser, and test-runner behavior.
- 02Playwright best practices
Microsoft
Official guidance for resilient tests, isolation, and user-facing locators.
- 03
FAQ / QUICK ANSWERS
Questions testers ask
What is the difference between a Playwright browser context and a page?
A context is an isolated browser session with its own cookies, storage, permissions, and pages. A page is one tab or window inside that session and shares context state with sibling pages.
Should two users be modeled as two pages or two contexts?
Use two contexts. Pages inside one context share authentication state, so they represent the same browser session. Separate contexts preserve independent identities while reusing the browser process.
How should a Playwright test wait for a popup?
Register the popup promise before the click that opens it, then await the promise and assert readiness on the returned page. This avoids missing a popup that appears immediately.
When should frameLocator be preferred over page.frames?
Prefer frameLocator when the iframe has a stable DOM identity and the test needs elements inside it. It remains locator-based and avoids selecting a frame by fragile array position.
Who should close manually created contexts and pages?
The fixture or test that creates them should close them, ideally in teardown or finally. Built-in test fixtures remain runner-owned, while manually created resources need explicit lifecycle ownership.
RELATED GUIDES
Continue the learning route
GUIDE 01
Test Cases for Chat Application: Messaging QA Guide
Test cases for chat application QA covering sending, delivery, read receipts, typing, offline sync, attachments, moderation, and scale risks.
GUIDE 02
Playwright Tutorial: End-to-End Testing from Scratch
Playwright tutorial for beginners: install, write your first test, TypeScript setup, codegen, fixtures, API testing, debugging, and CI tips in one guide.
GUIDE 03
How to Run Tests in Parallel with Playwright
Learn how to run tests in parallel with Playwright: workers, sharding, isolation, CI config, flakiness fixes, and a practical checklist for faster suites.
GUIDE 04
Playwright Locators Guide: Find Elements Reliably
Playwright locators guide for stable UI tests with role selectors, filters, assertions, strict mode, debugging, and flaky selector fixes in CI.