- Jul 20, 2026
- admin
- 0

- Why is Playwright faster than Selenium?
- Direct communication with browser using browser protocols (CDP/WebSocket)
- No WebDriver dependency
- Auto-waiting reduces unnecessary waits
- Parallel execution by default
- Multiple browser contexts instead of launching new browsers
- Explain Browser, BrowserContext, and Page.
Browser
|
|—- BrowserContext 1
| |
| |—- Page 1
| |—- Page 2
|
|—- BrowserContext 2
|
|—- Page 3
BrowserContext is an isolated browser profile.
- Difference between BrowserContext and Incognito window?
BrowserContext is Playwright’s isolated environment.
One browser can have many contexts.
Contexts don’t share
- Cookies
- Local Storage
- Session Storage
- Cache
- Why should you avoid page.waitForTimeout()?
Because
- Hard waits slow execution
- Causes flaky tests
- Doesn’t guarantee element readiness
Instead use
await locator.click();
or
await expect(locator).toBeVisible();
- Explain Auto Waiting.
Playwright automatically waits for
- Visible
- Stable
- Enabled
- Receives Events
before performing actions.
Example
await page.locator(“#submit”).click();
No explicit wait required.
- Locator vs ElementHandle
Locator
const btn = page.locator(“#save”);
await btn.click();
ElementHandle
const btn = await page.$(“#save”);
await btn.click();
Locator re-evaluates the DOM and is recommended.
- What happens if DOM changes after locating an element?
Locator automatically finds the updated element.
ElementHandle becomes stale.
- Explain Strict Mode.
If locator matches multiple elements
page.locator(“button”)
Playwright throws
Strict mode violation
Need
locator.first()
locator.nth(0)
locator.filter()
- Explain Shadow DOM handling.
No special syntax.
await page.locator(“my-component button”).click();
Playwright pierces open shadow roots automatically.
- Difference between page.locator() and page.$()
page.$()
- Old API
- Returns ElementHandle
locator()
- Modern API
- Auto waits
- Retry
- Recommended
- How does Playwright retry assertions?
await expect(locator).toHaveText(“Success”);
It retries until
- Passes
- Timeout occurs
- How do you handle multiple tabs?
const pagePromise =
context.waitForEvent(‘page’);
await page.click(“text=Open”);
const newPage = await pagePromise;
await newPage.waitForLoadState();
- How do you handle file downloads?
const downloadPromise =
page.waitForEvent(‘download’);
await page.click(“#download”);
const download =
await downloadPromise;
await download.saveAs(“report.xlsx”);
- How do you upload files?
await page.locator(“input[type=file]”)
.setInputFiles(“sample.pdf”);
- How to intercept API requests?
await page.route(“**/users”, route =>
route.fulfill({
status:200,
body:JSON.stringify({
name:”Anand”
})
}));
- Difference between route.continue(), fulfill(), abort()
continue()
→ Sends request to server
fulfill()
→ Mock response
abort()
→ Cancel request
- How do you validate API responses?
const response =
await page.waitForResponse(
res=>res.url().includes(“/users”)
);
expect(response.status()).toBe(200);
- Explain Storage State.
Used to avoid repeated login.
await context.storageState({
path:”state.json”
});
Reuse
storageState:”state.json”
- Explain Trace Viewer.
Captures
- Screenshots
- DOM snapshots
- Network
- Console
- Timeline
- Actions
- Difference between Screenshot and Trace?
Screenshot
Only one image.
Trace
Complete execution history.
- How do you run tests in parallel?
test.describe.configure({
mode:’parallel’
});
or
workers:4
- What causes flaky Playwright tests?
- Hard waits
- Poor locators
- Dynamic data
- Race conditions
- Shared state
- Network delays
- Explain fixtures.
Fixtures manage reusable setup and teardown.
test.extend({
loginPage: async ({ page }, use) => {
await use(new LoginPage(page));
}
});
- How do you share login across tests?
Use
storageState
or
globalSetup
- Explain globalSetup and globalTeardown.
globalSetup
Runs once before all tests.
globalTeardown
Runs once after all tests.
- Difference between beforeAll() and globalSetup()
beforeAll()
Runs per test file (or describe block).
globalSetup()
Runs once for the entire suite.
- How would you design a Playwright framework?
A typical enterprise framework includes:
- Page Object Model (POM)
- Fixtures
- Utility classes
- API helpers
- Environment configuration
- Custom reporters
- Logging
- Screenshot and trace capture
- CI/CD integration (Azure DevOps, GitHub Actions, Jenkins)
- Data-driven testing
- Parallel execution
- Cross-browser execution
- How do you test microservices with Playwright?
- Use Playwright’s APIRequestContext for API testing.
- Mock dependent services using page.route().
- Validate UI and backend responses together.
- Run API setup before UI flows to create test data.
- How would you reduce execution time for a suite with 2,000 tests?
- Increase parallel workers based on available CPU.
- Reuse authentication with storageState.
- Optimize slow or brittle locators.
- Avoid unnecessary browser launches by using contexts.
- Mock slow external services when appropriate.
- Split tests across CI agents (sharding).
- What are the limitations of Playwright?
- Cannot automate native desktop applications.
- Limited support for browser extensions compared to Selenium ecosystems.
- Closed Shadow DOM cannot be accessed.
- Requires Node.js (or supported language bindings) and browser binaries.
- Native mobile app automation requires tools like Appium.

