These Playwright interview questions are answered with Java code, the combination most Selenium-to-Playwright candidates face. They run from fresher basics (objects, locators, assertions) through framework integration (JUnit 5, TestNG, storageState, Allure, data-driven tests) to advanced and architecture questions, live-coding tasks and real CI scenarios. For TypeScript-runner questions, see advanced Playwright TypeScript interview questions.

PLAYWRIGHT (JAVA)

Interview Questions & Answers

Complete Guide: Freshers to Advanced (5+ Years)

What's Inside This Guide

SectionExperience LevelTopics CoveredQ&A Count
Section 1Fresher (0-3 months)Intro, Setup, Core objects, Locators, Assertions, Actions15+
Section 2Junior (3m-1 year)Auto-wait, Dialogs, Frames, Tabs, Keyboard/Mouse, Screenshots, Trace, Network15+

30+ Detailed Q&As in this file | Framework & Advanced Q&As continue in Part 2

Introduction to Playwright

What is Playwright? Give a brief background.

Playwright is a free, open-source browser-automation library from Microsoft, first released in 2020 by the team that previously built Puppeteer.

  • Drives Chromium, Firefox and WebKit through a single API.
  • Bindings for Java, TypeScript/JavaScript, Python and .NET.
  • Designed for reliability: auto-waiting, web-first assertions, and built-in tracing.
  • Ships its own browser builds — no separate driver binaries.

How does Playwright compare to Selenium and Cypress?

AspectPlaywrightSeleniumCypress
LanguagesJava, TS, Python, .NETMany (Java, Python, C#...)JS/TS only
BrowsersChromium, Firefox, WebKitAll majorChromium-family, Firefox
WaitingAuto-wait built inManual waitsAuto-retry (built in)
ArchitectureWebSocket to browserHTTP via driverRuns inside the browser
IsolationCheap contextsNew driver/sessionPer-test
DebuggingTrace viewerLogs/screenshotsTime-travel

What are the advantages and limitations of Playwright?

AdvantagesLimitations
Auto-wait removes most flakinessNewer — smaller community than Selenium (though growing fast)
Bundled browsers, no driver managementNo native mobile app testing (Appium still needed)
Contexts give cheap isolation & parallelismReal Safari/IE not supported (WebKit engine, not Safari app)
Built-in trace, video, network mockingPlaywright object is not thread-safe per page/context
Same code across 3 enginesTeam may already be invested in Selenium
Advertisement

Environment Setup

How do you set up a Playwright + Java Maven project from scratch?

  1. Create a Maven project; add com.microsoft.playwright:playwright (1.63.0).
  2. Add JUnit 5 (junit-jupiter) or TestNG as the test runner.
  3. Install the browsers via the CLI command (one time).
  4. Write a test using Playwright → Browser → Context → Page.
mvn compile
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
    -D exec.args="install"

How do you launch a browser and open a page?

try (Playwright playwright = Playwright.create()) {
    Browser browser = playwright.chromium()
        .launch(new BrowserType.LaunchOptions().setHeadless(false));
    BrowserContext context = browser.newContext();
    Page page = context.newPage();
    page.navigate("https://example.com");
    System.out.println(page.title());
    browser.close();
}

What is the difference between navigate(), goBack(), reload()?

  • navigate(url) — loads a URL and waits for the load event by default.
  • goBack() / goForward() — browser history navigation.
  • reload() — reloads the current page.
  • All return an optional Response you can assert on.

Core Objects & Lifecycle

Explain Playwright, Browser, BrowserContext and Page.

  • Playwright — entry point; manages the browser binaries.
  • Browser — a launched browser process (heavy; launch few).
  • BrowserContext — an isolated session (own cookies/storage); like incognito. Create one per test.
  • Page — a tab within a context; where you navigate and interact.

Why create a new context per test instead of a new browser?

Launching a browser is expensive; creating a context is cheap.

  • A fresh context guarantees clean cookies/storage, so tests don’t leak state.
  • Many contexts can share one browser, enabling efficient parallelism.
  • This is how Playwright runs fast, isolated tests without Selenium Grid.

Locators

What locator strategies does Playwright offer? Which are preferred?

  • User-facing: getByRole, getByText, getByLabel, getByPlaceholder, getByAltText, getByTitle.
  • Test id: getByTestId (data-testid) — the most stable.
  • Engines: CSS (locator("css=...")) and XPath (locator("xpath=...")).
  • Preference order: getByRole → label/placeholder/text → getByTestId → CSS → XPath.
  • User-facing locators resist markup changes and double as accessibility checks.

What makes a Playwright Locator different from a WebElement?

  • A Locator is lazy and auto-retrying — re-resolved on every action.
  • A WebElement is a snapshot that can go stale (StaleElementReferenceException).
  • Locators therefore avoid stale-element errors entirely.

How do you work with a list of matching elements?

Locator items = page.locator(".inventory_item");
int n = items.count();
items.first().click();
items.nth(2).click();
List<String> names = items.allTextContents();

Actions & Assertions

What are the common element actions and do they wait?

  • click(), fill(), pressSequentially(), press(), check(), uncheck(), selectOption(), hover(), dragTo(), setInputFiles().
  • Every action auto-waits for actionability first (attached, visible, stable, enabled, receives events).
  • So you almost never write explicit waits before actions.

What are web-first assertions and why use them?

Assertions like assertThat(locator).isVisible() automatically retry until the condition holds or times out.

import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;

assertThat(page.getByText("Products")).isVisible();
assertThat(page.getByTestId("cart-badge")).hasText("1");
assertThat(page).hasURL(java.util.regex.Pattern.compile(".*inventory.*"));

They remove the race between the app updating and the assertion running — the top cause of flaky UI tests.

How do you assert text, value, attribute and count?

assertThat(loc).hasText("Products");        // exact text
assertThat(loc).containsText("Prod");        // substring
assertThat(input).hasValue("standard_user"); // input value
assertThat(link).hasAttribute("href", "/cart");
assertThat(items).hasCount(6);               // waits for count to settle
assertThat(loc).isVisible();  // isHidden / isEnabled / isDisabled / isChecked

What is the difference between textContent(), innerText() and allTextContents()?

  • textContent() — raw text of a single element (includes hidden text).
  • innerText() — rendered, visible text of a single element.
  • allTextContents() — a List<String> of text from ALL matching elements (great for verifying lists/sorting).

Give a full login example with a web-first assertion.

page.navigate("https://www.saucedemo.com");
page.getByPlaceholder("Username").fill("standard_user");
page.getByPlaceholder("Password").fill("secret_sauce");
page.getByRole(AriaRole.BUTTON,
    new Page.GetByRoleOptions().setName("Login")).click();
assertThat(page.getByText("Products")).isVisible();

Auto-Waiting & Synchronization

Why do Selenium tests need waits but Playwright mostly doesn’t?

  • Selenium acts immediately, so you add Implicit/Explicit/Fluent waits to avoid race conditions.
  • Playwright waits for actionability before each action and retries assertions — waiting is built in.
  • You only add explicit waits for specific events (a network call, a URL change, an element state).

How do you wait for a specific event deterministically?

page.waitForURL("**/inventory.html");
page.waitForResponse("**/api/cart", () -> {
    page.getByText("Add to cart").click();
});
page.getByRole(AriaRole.PROGRESSBAR).waitFor(
    new Locator.WaitForOptions().setState(WaitForSelectorState.HIDDEN));
Why not Thread.sleep()?

A fixed sleep is either too short (flaky) or too long (slow), and it hides real timing problems. Auto-wait plus waitForResponse/waitForURL give deterministic synchronization.

How do you handle native <select> dropdowns?

Locator sort = page.locator(".product_sort_container");
sort.selectOption("lohi");                              // by value
sort.selectOption(new SelectOption().setLabel("Name (A to Z)")); // by label
sort.selectOption(new SelectOption().setIndex(1));      // by index

How do you handle checkboxes and radio buttons?

page.getByLabel("Subscribe").check();     // idempotent — ensures checked
page.getByLabel("Subscribe").uncheck();
assertThat(page.getByLabel("Subscribe")).isChecked();

How do you handle JavaScript dialogs (alert/confirm/prompt)?

Register a dialog handler BEFORE the action that triggers it; Playwright auto-dismisses unhandled dialogs.

page.onDialog(dialog -> {
    System.out.println(dialog.type() + ": " + dialog.message());
    dialog.accept();              // confirm/alert
    // dialog.accept("text");     // prompt input
    // dialog.dismiss();          // cancel
});
page.getByText("Delete account").click();

How do you upload a file?

page.getByLabel("Resume").setInputFiles(Paths.get("data/cv.pdf"));
// Multiple files:
page.getByLabel("Docs").setInputFiles(new Path[]{p1, p2});

Frames, Windows & Tabs

How do you interact with elements inside an iframe?

FrameLocator frame = page.frameLocator("#card-iframe");
frame.getByLabel("Card number").fill("4111111111111111");
// Nested frames: chain frameLocator()
page.frameLocator("#outer").frameLocator("#inner").getByText("OK").click();

How do you handle a new tab or popup?

Page popup = page.waitForPopup(() -> {
    page.getByText("Open receipt").click();
});
popup.waitForLoadState();
assertThat(popup).hasTitle("Receipt");

Mouse, Keyboard & Scrolling

How do you perform hover, drag-and-drop and keyboard shortcuts?

page.getByText("Products").hover();
source.dragTo(target);
page.getByRole(AriaRole.TEXTBOX).press("Control+A");
page.keyboard().press("Enter");

How do you scroll in Playwright?

  • Usually you don’t — actions auto-scroll the element into view.
  • For manual scrolling: locator.scrollIntoViewIfNeeded() or page.mouse().wheel(0, 800).
page.getByText("Footer link").scrollIntoViewIfNeeded();
page.mouse().wheel(0, 1000);

Screenshots, Video & Trace

How do you capture screenshots (element and full page)?

page.screenshot(new Page.ScreenshotOptions()
    .setPath(Paths.get("home.png")).setFullPage(true));
page.getByTestId("cart").screenshot(
    new Locator.ScreenshotOptions().setPath(Paths.get("cart.png")));

How do you record video and traces?

// Video: set on the context; saved when the context closes
browser.newContext(new Browser.NewContextOptions()
    .setRecordVideoDir(Paths.get("videos/")));

// Trace: start/stop around the test
context.tracing().start(new Tracing.StartOptions()
    .setScreenshots(true).setSnapshots(true).setSources(true));
// ...
context.tracing().stop(new Tracing.StopOptions()
    .setPath(Paths.get("trace.zip")));

Open the trace with: npx playwright show-trace trace.zip

Network Basics

How do you wait for or inspect a network response?

APIResponse resp = null;
page.waitForResponse("**/api/products", () -> {
    page.getByText("Load").click();
});

How do you mock an API response?

page.route("**/api/products", route -> route.fulfill(
    new Route.FulfillOptions()
        .setStatus(200)
        .setContentType("application/json")
        .setBody("[{\"id\":1,\"name\":\"Mock\"}]")));
This makes UI tests deterministic and lets you exercise error states (e.g. force a 500) that are hard to reproduce against a live backend.

Live Coding Tasks (Be Ready to Write These)

Interviews increasingly ask you to write a few lines live. Practise these until they are automatic.

Verify a product list is sorted A-Z.

List<String> names = page.locator(".inventory_item_name").allTextContents();
List<String> expected = names.stream().sorted().collect(Collectors.toList());
assertEquals(expected, names, "List is not sorted A-Z");

Add every product to the cart and assert the badge.

Locator addButtons = page.getByRole(AriaRole.BUTTON,
        new Page.GetByRoleOptions().setName("Add to cart"));
int n = addButtons.count();
for (int i = 0; i < n; i++) addButtons.first().click();  // each click turns that button into "Remove"
assertThat(page.getByTestId("shopping-cart-badge")).hasText(String.valueOf(n));

Assert a specific row’s price in a table.

Locator row = page.getByRole(AriaRole.ROW)
        .filter(new Locator.FilterOptions().setHasText("Backpack"));
assertThat(row.getByRole(AriaRole.CELL).nth(2)).hasText("$29.99");

Mock an API to return an empty list and assert the empty state.

page.route("**/api/products", route -> route.fulfill(
    new Route.FulfillOptions().setStatus(200)
        .setContentType("application/json").setBody("[]")));
page.navigate("/products");
assertThat(page.getByText("No products found")).isVisible();
Rapid-Fire Round (One-Liners)
Short, confident answers to quick-fire questions.
  • Default action timeout? 30 seconds.
  • Default assertion timeout? 5 seconds.
  • How to run headed? LaunchOptions().setHeadless(false).
  • Most stable locator? getByTestId (data-testid).
  • How to isolate tests? A new BrowserContext per test.
  • How to skip repeated logins? storageState().
  • How to view a failed run? npx playwright show-trace trace.zip.
  • Thread.sleep alternative? waitForResponse / waitForURL / auto-wait.
  • How to test Safari on Linux? Use the WebKit engine.
  • Is a Page thread-safe? No — one Page/Context per thread.

Continue with framework integration & advanced Q&As in Part 2 →

JUnit 5 / TestNG Integration

How do you integrate Playwright with JUnit 5? Show the lifecycle.

Launch the Browser once (@BeforeAll), create a fresh Context + Page per test (@BeforeEach), close them after each test, and close the Browser/Playwright at the end.

public class BaseTest {
    protected static Playwright playwright;
    protected static Browser browser;
    protected BrowserContext context;
    protected Page page;

    @BeforeAll static void launch() {
        playwright = Playwright.create();
        browser = playwright.chromium()
            .launch(new BrowserType.LaunchOptions().setHeadless(true));
    }
    @BeforeEach void newContext() {
        context = browser.newContext();
        page = context.newPage();
    }
    @AfterEach void closeContext() { context.close(); }
    @AfterAll static void shutdown() {
        browser.close(); playwright.close();
    }
}

Where do JUnit/TestNG asserts fit vs web-first assertions?

  • Use web-first assertions (assertThat(locator)...) for anything UI-state related — they auto-retry.
  • Use JUnit/TestNG/AssertJ asserts for plain values (numbers, computed strings, API bodies).
  • Mixing correctly avoids flaky checks on the UI while keeping value checks simple.

storageState & Authentication

How do you avoid logging in on every test?

Log in once, save the session with storageState(), then load that state into each test’s context.

// One-time setup: log in and save the session
Page setup = browser.newContext().newPage();
setup.navigate(baseUrl);
new LoginPage(setup).loginAs("standard_user", "secret_sauce");
setup.context().storageState(new BrowserContext.StorageStateOptions()
    .setPath(Paths.get("auth/user.json")));

// In every test: start already authenticated
context = browser.newContext(new Browser.NewContextOptions()
    .setStorageStatePath(Paths.get("auth/user.json")));

How do you handle multiple user roles?

  • Create one storageState file per role (admin.json, user.json, guest.json).
  • Load the appropriate state when creating the context for a test.
  • This keeps role setup fast and isolated — a common architecture question.

Allure Reporting & Retry

How do you set up Allure with Playwright + JUnit 5?

<dependency>
  <groupId>io.qameta.allure</groupId>
  <artifactId>allure-junit5</artifactId>
  <version>2.29.0</version>
</dependency>
@Attachment(value = "screenshot", type = "image/png")
byte[] screenshot() { return page.screenshot(); }

@Attachment(value = "trace", type = "application/zip")
byte[] trace(Path zip) throws IOException { return Files.readAllBytes(zip); }

Generate & view: mvn test then allure serve target/allure-results

How do you retry a flaky test?

  • JUnit 5: use the RetryingTest extension (junit-pioneer) or a custom TestExecutionExceptionHandler.
  • TestNG: implement IRetryAnalyzer and attach it via @Test(retryAnalyzer = ...).
  • Better long-term fix: use auto-wait + web-first assertions to remove the flake at the source, and reserve retries for genuinely non-deterministic externals.
// TestNG retry analyzer
public class Retry implements IRetryAnalyzer {
    private int count = 0; private static final int MAX = 2;
    public boolean retry(ITestResult result) {
        return count++ < MAX;
    }
}

Data-Driven Testing

Show data-driven testing with an external file.

// logins.csv on the classpath
@ParameterizedTest
@CsvFileSource(resources = "/testdata/logins.csv", numLinesToSkip = 1)
void loginScenarios(String user, String pass, String expected) {
    LoginPage login = new LoginPage(page);
    login.attemptLogin(user, pass);
    assertThat(login.result()).containsText(expected);
}

How do you read Excel data for Playwright tests?

// Apache POI helper feeding a @MethodSource
static Stream<Arguments> excelData() throws IOException {
    List<Arguments> rows = new ArrayList<>();
    try (Workbook wb = new XSSFWorkbook(new FileInputStream("data/logins.xlsx"))) {
        Sheet sheet = wb.getSheetAt(0);
        for (int r = 1; r <= sheet.getLastRowNum(); r++) {
            Row row = sheet.getRow(r);
            rows.add(Arguments.of(
                row.getCell(0).getStringCellValue(),
                row.getCell(1).getStringCellValue()));
        }
    }
    return rows.stream();
}

Cucumber + Playwright

How do you integrate Cucumber BDD with Playwright and share the Page?

  • Add cucumber-java, cucumber-junit-platform-engine and a DI module (PicoContainer).
  • Create the Context/Page in a @Before hook; close in @After; attach a screenshot on failure.
  • Share the Page across step-definition classes via constructor injection (PicoContainer wires it).
// Shared context object injected by PicoContainer
public class TestContext {
    public Page page;
}

public class LoginSteps {
    private final TestContext ctx;
    public LoginSteps(TestContext ctx) { this.ctx = ctx; }  // injected

    @When("I log in as {string} with {string}")
    public void login(String u, String p) {
        new LoginPage(ctx.page).attemptLogin(u, p);
    }
}

How do you run tagged scenarios and capture failures?

mvn test -Dcucumber.filter.tags="@smoke"
@After
public void tearDown(Scenario scenario) {
    if (scenario.isFailed()) {
        scenario.attach(ctx.page.screenshot(), "image/png", "failure");
    }
    PlaywrightFactory.tearDown();
}

API + UI Hybrid & Network Mocking

How do you combine API calls with UI tests in Playwright?

Use the built-in APIRequestContext to set up or verify data via HTTP, then assert in the UI — no separate REST library required.

APIRequestContext api = playwright.request().newContext(
    new APIRequest.NewContextOptions().setBaseURL(apiBase));

// Seed data quickly via API
APIResponse res = api.post("/api/users",
    RequestOptions.create().setData(Map.of("name","naveed")));
assertEquals(201, res.status());

// Verify via UI
page.navigate("/users");
assertThat(page.getByText("naveed")).isVisible();

How do you mock or block network traffic?

// Mock a success response
page.route("**/api/cart", route -> route.fulfill(
    new Route.FulfillOptions().setStatus(200)
        .setContentType("application/json").setBody("{\"items\":1}")));

// Force an error to test the UI error state
page.route("**/api/checkout", route ->
    route.fulfill(new Route.FulfillOptions().setStatus(500)));

// Block heavy assets to speed up tests
page.route("**/*.{png,jpg,woff2}", route -> route.abort());

How do you validate a database value in a test?

  • Playwright has no DB client — use plain JDBC as in any Java test.
  • Run a UI/API action, then query the DB with a PreparedStatement to confirm the record.
try (Connection c = DriverManager.getConnection(url, user, pass);
     PreparedStatement ps = c.prepareStatement(
         "SELECT status FROM orders WHERE id = ?")) {
    ps.setInt(1, orderId);
    ResultSet rs = ps.executeQuery();
    rs.next();
    assertEquals("CONFIRMED", rs.getString("status"));
}

How do you run tests completely offline / without a backend?

Record network traffic to a HAR file once, then replay it so the app is served canned responses.

// Record
browser.newContext(new Browser.NewContextOptions()
    .setRecordHarPath(Paths.get("network.har")));
// Replay
context.routeFromHAR(Paths.get("network.har"),
    new BrowserContext.RouteFromHAROptions().setUpdate(false));

How do you modify a real response instead of fully mocking it?

page.route("**/api/user", route -> {
    APIResponse real = route.fetch();
    JsonNode json = mapper.readTree(real.text());
    ((ObjectNode) json).put("role", "admin");
    route.fulfill(new Route.FulfillOptions()
        .setResponse(real).setBody(json.toString()));
});

How do you speed up a slow UI suite?

  • Use storageState() to skip logins.
  • Seed preconditions via API instead of clicking through the UI.
  • Block images/fonts/analytics with route().abort().
  • Run parallel with isolated contexts and shard across CI runners.
  • Save video/trace on failure only.

Parallel Execution & Thread Safety

How do you run Playwright tests in parallel safely?

  • Enable JUnit 5 parallelism (junit-platform.properties) or TestNG parallel="methods".
  • Store Page/Context in ThreadLocal so each thread has its own — Playwright is not thread-safe on a shared Page/Context.
  • Use a separate BrowserContext per test for full isolation of cookies/storage.
# junit-platform.properties
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = concurrent
junit.jupiter.execution.parallel.config.strategy = fixed
junit.jupiter.execution.parallel.config.fixed.parallelism = 4

Contexts vs multiple browsers vs Selenium Grid — what’s the difference?

  • Contexts: cheapest isolation, many per browser — the default parallel unit.
  • Multiple browsers: needed for cross-engine coverage (Chromium/Firefox/WebKit).
  • Selenium Grid: separate infrastructure to distribute sessions across machines — Playwright rarely needs it; sharding across CI runners scales instead.

Cloud & Framework Design

How do you run Playwright on a cloud provider (BrowserStack/LambdaTest)?

  • Cloud providers expose a CDP/WebSocket endpoint; connect with playwright.chromium().connect(wsEndpoint).
  • Capabilities (browser, OS, build name) are passed in the endpoint query string.
  • This offloads infra and scales cross-browser/OS coverage.
Browser browser = playwright.chromium().connect(CLOUD_WS_ENDPOINT);
Page page = browser.newContext().newPage();

Design a Playwright framework from scratch for a large app.

  • core: PlaywrightFactory (ThreadLocal), BaseTest lifecycle, ConfigReader (singleton, multi-env).
  • pages/components: POM with BasePage; fluent actions returning next page.
  • api: APIRequestContext service classes + Jackson POJOs for setup/verification.
  • auth: per-role storageState files loaded per test.
  • reporting: Allure with screenshots + traces on failure; Slack/JIRA hooks.
  • ci: GitHub Actions/Jenkins on the official Playwright Docker image; artifacts on failure; sharding for scale.
  • quality: SonarQube gate, Checkstyle, retry analyzer for genuine externals.

Selenium vs Playwright — When to Choose Which

When would you still pick Selenium or Cypress over Playwright?

  • Selenium: mandated by the org, need real Safari/IE, existing large Selenium suite, Grid infra already in place.
  • Cypress: a JS-only front-end team that values its time-travel/dev experience and only needs Chromium-family coverage.
  • Playwright: new projects wanting speed, cross-engine (incl. WebKit), auto-wait, tracing, and API+UI in one tool.

Real-World Scenario Questions

Senior interviews test judgement, not just syntax. These situational questions come up constantly.

A test passes locally but fails intermittently in CI. How do you investigate?

  • Open the trace from the failed CI run (show-trace) — time-travel to the failing step.
  • Check for a real race: an assertion on data that arrives via a later network call — switch to a web-first assertion or waitForResponse.
  • Confirm test isolation — is state leaking from another test sharing a context?
  • Check CI-only factors: viewport, timezone/locale, animations, slower machine (raise timeouts, disable animations).
  • Only after ruling out real bugs, add a scoped retry for genuinely non-deterministic externals.

How would you migrate a large Selenium suite to Playwright?

  • Run both in parallel initially; migrate feature-by-feature, highest-flakiness first.
  • Rebuild page objects with user-facing locators; drop most explicit waits.
  • Reuse existing test data and CI; swap the execution layer.
  • Measure: flakiness rate and suite runtime before/after to justify the effort.

How do you decide what to automate at the E2E layer vs API/unit?

  • Follow the test pyramid: most coverage at unit/API, a thin layer of critical E2E journeys.
  • Automate high-value, stable, repetitive flows; avoid automating volatile UI or one-off checks.
  • Push validation down the stack where cheaper (API/contract) and keep E2E for real user journeys.

How do you keep locators maintainable across a 50-page app?

  • Locators live only inside page/component objects — never in tests.
  • Prefer getByRole/getByTestId; agree a data-testid convention with developers.
  • Extract shared widgets into component objects to avoid duplication.

Rapid-Fire Questions

Short, confident answers for quick-fire screening.

  • Default action timeout? 30s. Assertion timeout? 5s. Navigation? 30s.
  • Most stable locator? getByTestId. Most recommended? getByRole.
  • Isolate tests? New BrowserContext per test.
  • Skip logins? storageState().
  • Thread.sleep alternative? auto-wait / waitForResponse / waitForURL.
  • Safari on Linux? WebKit engine.
  • Is a Page thread-safe? No.
  • Run headed? setHeadless(false). Watch slowly? setSlowMo(ms).
  • Full-page screenshot? screenshot(setFullPage(true)).
  • View a failed run? npx playwright show-trace trace.zip.
  • Record test by clicking? CLI codegen.
  • Mock a response? route.fulfill(). Block? route.abort().
  • Run JS? page.evaluate(). Before load? addInitScript().
  • Handle dialog? page.onDialog() registered before the trigger.
  • New tab? page.waitForPopup(). iframe? page.frameLocator().
  • API testing class? APIRequestContext.
  • Parallel unit? BrowserContext + ThreadLocal.
  • Official CI image? mcr.microsoft.com/playwright/java.
  • Configure test-id name? selectors().setTestIdAttribute().
  • Negate assertion? assertThat(loc).not()...
  • Dark mode? emulateMedia(setColorScheme(DARK)).
  • Control time? page.clock().
  • Data-driven JUnit? @ParameterizedTest. TestNG? @DataProvider.
  • Retry in TestNG? IRetryAnalyzer.
  • Latest Java Playwright version? 1.63.0.

130+ questions covered — rehearse out loud until they’re automatic. 🎯

FAQs

Are Playwright interviews in Java or TypeScript?

Both are common. Teams moving from Selenium often stay with Java; newer front-end-heavy teams use TypeScript. Concepts like contexts, locators, auto-waiting and tracing are the same in both.

What is the most important Playwright concept for interviews?

Auto-waiting with web-first assertions, and isolation through browser contexts. Most follow-up questions about flakiness, parallel runs and authentication build on these two ideas.

Do I need to know Selenium for a Playwright interview?

It helps: interviewers often ask how Playwright differs from Selenium and how you would migrate a suite.