πŸ’‘ If you like this website, please share it with your friends and network! πŸš€
Back to 100 Questions
Interview Prep
3-4 Years Exp
2026 Edition

Most Asked Playwright Interview Questions (3-4 Years Exp)

If you have 3-4 years of QA/SDET experience and are preparing for interviews, these are the areas you must master.

Companies are not asking basics anymore. They're testing depth + JavaScript + Architecture.

🧠
Question 1 of 9

JavaScript Fundamentals (Very Important)

Reverse a stringCount words in a stringRemove duplicate charactersString β†’ Array conversionUse of map(), filter(), reduce(), join()Promise handlingRecursion with asyncException handling (try/catch/finally)

Playwright is fundamentally a Node.js library. If you have 3–4 years of experience, interviewers will test your raw JavaScript capabilities before diving into automation concepts. You must be comfortable with array manipulation, string manipulation, and error handling.

TypeScript
// Common interview task: Use map/filter to process data
const users = [
  { name: 'Alice', active: true },
  { name: 'Bob', active: false },
  { name: 'Charlie', active: true }
];

// Get names of active users
const activeNames = users
  .filter(u => u.active)
  .map(u => u.name)
  .join(', ');

console.log(activeNames); // "Alice, Charlie"

// Handling Exceptions Properly
try {
  await page.getByRole('button', { name: 'Submit' }).click({ timeout: 5000 });
} catch (error) {
  console.error('Submission failed, attempting recovery...', error);
  await page.screenshot({ path: 'error.png' });
} finally {
  console.log('Action complete.');
}

πŸ’‘ Practice raw JavaScript algorithms on sites like LeetCode or HackerRank (easy level). You will often be asked to solve these in a live coding pad without auto-complete.

🚩

If your JS basics are weak, Playwright interviews become difficult.

🎭
Question 2 of 9

Playwright Core Concepts

Locators: getByRole vs locatorStrict modeAuto-wait behaviorHow to switch frames? Nested frames?Handling dialogs (alerts)File Upload: setInputFiles()Mouse Actions: Hover, double click, drag drop

Interviewers will test your depth on the Playwright API. You need to know why `getByRole` is preferred over XPath, how strict mode prevents interacting with the wrong element, and how to handle native browser events like file uploads and alerts.

TypeScript
// ─── Locators: getByRole over CSS/XPath
// βœ… Best practice
await page.getByRole('button', { name: 'Sign in' }).click();

// ─── Handling native browser alerts automatically
page.on('dialog', async dialog => {
  console.log(`Dialog message: ${dialog.message()}`);
  await dialog.accept(); // or dialog.dismiss()
});

// ─── Handling iFrames
const frame = page.frameLocator('#payment-frame');
await frame.getByRole('textbox', { name: 'Card Number' }).fill('4242');

// ─── File Uploads (Multiple)
await page.getByLabel('Upload documents').setInputFiles([
  'file1.pdf',
  'file2.png'
]);

πŸ’‘ The biggest mistake is explaining Playwright as if it were Selenium. Playwright does NOT need `switchTo().frame()` β€” you use `frameLocator`. It does NOT need explicit waits β€” it auto-waits.

🌐
Question 3 of 9

Browser Architecture Understanding

Difference between Browser, BrowserContext, and PageWhy BrowserContext is important for parallel execution?Isolation strategy?

You must deeply understand Playwright's architecture. A `Browser` is the physical browser process (expensive). A `BrowserContext` is an isolated incognito-like session (cheap). A `Page` is a single tab within that context.

TypeScript
// Launching browser once (Expensive - worker scoped)
const browser = await chromium.launch();

// Creating completely isolated contexts (Cheap - test scoped)
const contextA = await browser.newContext(); // User A (no cookies)
const contextB = await browser.newContext(); // User B (no cookies)

// Pages within contexts share cookies
const pageA1 = await contextA.newPage(); // User A tab 1
const pageA2 = await contextA.newPage(); // User A tab 2

πŸ’‘ This architecture is why Playwright can run tests in parallel so quickly. It reuses the Browser process but creates a fresh, isolated BrowserContext for every single test.

🚩

These questions test real framework understanding.

βš™οΈ
Question 4 of 9

Playwright Configuration (Very Common)

RetriesTimeouts (test vs expect timeout)BaseURLParallel execution & ProjectsHeadless vs headedDefault reporter behavior

At 3-4 years of experience, you are expected to be the one configuring the framework, not just writing tests within it. You must know the `playwright.config.ts` file inside out.

TypeScript
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  timeout: 30000,          // Global test timeout (30s)
  expect: { timeout: 5000 }, // Assertion timeout (5s)
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 4 : undefined,
  reporter: [
    ['html'],              // Built-in HTML
    ['list'],              // Terminal output
    ['./custom-reporter.ts'] // Custom reporter implementation
  ],
  use: {
    baseURL: 'https://staging.myapp.com',
    headless: true,
  },
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'webkit', use: { ...devices['Desktop Safari'] } },
  ],
});

πŸ’‘ Be prepared to explain the difference between `timeout` (the maximum time the whole test can run) and `expect.timeout` (the maximum time a single assertion will wait).

🚩

Interviewers may ask: β€œHow do you generate custom reports?”

πŸ“Š
Question 5 of 9

Reporting & Debugging

Generate HTML reportsCapture screenshot on failureCapture traceVideo recordingRerun failed tests

Debugging in CI is a core senior skill. You must know how to configure Playwright to automatically collect forensic evidence (Traces, Videos, Screenshots) ONLY when a test fails to save disk space.

TypeScript
export default defineConfig({
  use: {
    // Collect trace when retrying the failed test
    trace: 'on-first-retry',
    
    // Take screenshot automatically on failure
    screenshot: 'only-on-failure',
    
    // Record video of failing tests
    video: 'retain-on-failure',
  },
});

// To debug locally step-by-step:
// npx playwright test --debug

// To view a trace file generated in CI:
// npx playwright show-trace path/to/trace.zip

πŸ’‘ Trace Viewer is Playwright's killer feature. It captures DOM snapshots, console logs, and network traffic for every action. If you don't mention Trace Viewer in an interview, you are leaving points on the table.

🚩

Understanding Playwright trace viewer is a massive plus.

πŸ₯’
Question 6 of 9

Playwright + Cucumber

Given/When/Then execution orderHow are hooks executed?Difference between Before and BeforeAllHow do you share data using World?

If the company uses BDD, they will drill you on Cucumber mechanics. You must understand state sharing between steps and the lifecycle of hooks.

TypeScript
import { setWorldConstructor, Before, After, Given, When, Then } from '@cucumber/cucumber';
import { chromium, Browser, BrowserContext, Page } from 'playwright';

// ─── Using World to share data between steps
class CustomWorld {
  browser: Browser;
  context: BrowserContext;
  page: Page;
  sharedData: string; // share state across Given/When/Then
}
setWorldConstructor(CustomWorld);

// ─── Hooks
Before(async function () {
  // Runs before EVERY scenario
  this.browser = await chromium.launch();
  this.context = await this.browser.newContext();
  this.page = await this.context.newPage();
});

After(async function () {
  // Runs after EVERY scenario
  await this.browser.close();
});

πŸ’‘ `BeforeAll` runs once before the entire test suite (good for starting servers or DB connections). `Before` runs before every single scenario (good for launching a fresh browser context).

πŸ”
Question 7 of 9

Promise & Async Handling

async/await mechanicsWhat happens if you forget await?How Playwright handles auto-wait internally?Recursive async pollingCustom wait functions

Playwright is entirely async. If you forget an `await`, the promise will execute in the background, your test will pass prematurely, and the action will happen later, causing massive flakiness. Interviewers will look for this.

TypeScript
// ❌ JUNIOR MISTAKE: Forgetting await
page.getByRole('button').click(); // Test continues immediately without waiting!

// βœ… SENIOR FIX
await page.getByRole('button').click();

// ─── Custom Polling (Wait until a backend process finishes)
await expect(async () => {
  const res = await page.request.get('/api/status');
  const data = await res.json();
  expect(data.status).toBe('COMPLETED');
}).toPass({
  intervals: [1000, 2000, 5000], // poll after 1s, then 2s, then 5s
  timeout: 30000
});

πŸ’‘ Playwright auto-waits by injecting JavaScript into the browser that polls the DOM using `requestAnimationFrame`. If you need to wait for a non-DOM event (like an email arriving), use `expect().toPass()`.

🚩

Most candidates fail here.

πŸ—οΈ
Question 8 of 9

Framework-Level Questions

Page Object Model designReusable utilitiesError handling strategyLogging integrationEnvironment-based executionCI/CD integration

You must be able to design a framework from scratch. This means separating concerns: Tests should only contain assertions and flow logic. Page Objects should only contain locators and actions. Fixtures should handle setup/teardown.

TypeScript
// ─── Creating a Custom Reusable Fixture
import { test as base } from '@playwright/test';
import { LoginPage } from './pages/LoginPage';

// Define the type of our fixtures
type MyFixtures = { loginPage: LoginPage };

// Extend base test to include our custom fixture
export const test = base.extend<MyFixtures>({
  loginPage: async ({ page }, use) => {
    // Setup: instantiate POM
    const loginPage = new LoginPage(page);
    
    // Inject fixture into the test
    await use(loginPage);
    
    // Teardown logic here if needed
  },
});

export { expect } from '@playwright/test';

πŸ’‘ Custom fixtures are the "Playwright Way" to build frameworks, replacing traditional Page Object instantiation in `beforeEach` hooks. They are lazy, composable, and type-safe.

🚩

At 3–4 years experience, they expect you to architect the solution.

πŸ’‘
Question 9 of 9

Best Practices (They Always Ask)

Avoid hard waitsUse proper locatorsIsolate test dataUse fixturesKeep tests atomicSeparate test logic from page logic

Interviewers will ask "What makes automation stable?" Your answer should hit these core pillars: Atomic tests (no dependencies between tests), Data isolation (creating unique data per test), and Web-First assertions.

TypeScript
// ❌ ANTI-PATTERNS (Never do this)
await page.waitForTimeout(5000); // hard wait
await page.locator('.btn-primary.submit-form').click(); // brittle CSS
test.describe.serial('user flow', () => { ... }); // relying on previous tests

// βœ… BEST PRACTICES
// Wait for specific network response instead of hard wait
await Promise.all([
  page.waitForResponse('/api/submit'),
  page.getByRole('button', { name: 'Submit' }).click()
]);

// Use accessibility locators
await page.getByRole('button', { name: 'Submit' }).click();

// Generate unique test data per run
const uniqueEmail = `user_${Date.now()}@test.com`;

πŸ’‘ Atomic tests mean Test A should not fail because Test B failed. Always generate fresh data via API in the `beforeEach` hook or within the test itself.

⚑ Reality Check

If you only know "how to click and type", you won't clear mid-level interviews.
Want to master all these areas? Check out our complete list.

View All 100 Questions