cswork / libraryOpen practice workspace

Articles

WebdriverIO Interview Questions: Auto-Waiting, Selectors, and Worker Isolation

Practice WebdriverIO interview questions with auto-wait boundaries, resilient selectors, retrying assertions, checkout evidence, and isolated worker data.

WebdriverIO interview questions become more useful when you can explain why a test passed. A successful click establishes one condition; a completed purchase establishes another. Two green tests running in separate browser sessions can still corrupt each other's shopping cart.

The working rule in this guide is to separate interaction readiness, operation completion, and data ownership. We will trace a checkout through those three contracts, then repair a collision between two Local Runner workers. The timelines and fixtures are original interview exercises, not reported employer questions. Official API behavior is linked where it first matters; preparation advice is labeled as reasoning. Start with Testing a New Feature: Planning Test Cases and Handling Flaky Tests to practice explaining the evidence behind a flaky-test repair.

What Does WebdriverIO Auto-Waiting Actually Guarantee?

Official behavior: WebdriverIO's auto-waiting documentation describes waiting for interaction commands such as click and setValue to operate on visible, interactable elements. This reduces the need to insert a separate readiness wait before every action. It does not give an application transaction a completion contract.

Imagine a checkout button that exists immediately but becomes enabled after a shipping estimate loads. Clicking it starts an asynchronous request. The server then commits an order, and the application eventually renders a receipt. Those are different events even when they usually happen within one second.

A strong answer therefore starts with the operation: “Before clicking, I need the intended button to be interactable. After clicking, I need evidence that this checkout completed.” Saying only “WebdriverIO waits automatically” leaves the second requirement unexplained.

Auto-waiting also cannot rescue a selector aimed at the wrong control. If the header and checkout panel both contain a Buy button, an interactable header button does not become the intended checkout button because it was easy to click. Locating the right object precedes waiting on its state.

Interview reasoning: diagnose which contract failed before changing a timeout. A control that never becomes enabled may indicate missing fixture data. A click that succeeds without a receipt may indicate a backend failure. A receipt for someone else's order may indicate shared state. These observations require different repairs.

Choose a Wait That Matches the Missing Evidence

Official behavior: waitForExist waits for DOM presence or, with its reverse option, absence. Presence alone does not establish visibility, enabled state, or successful application work. A hidden receipt retained from an earlier screen can satisfy an existence check while proving nothing about the new checkout.

isClickable checks conditions including display, enabled state, viewport access, and whether another element covers the center. Its documented scope matters: it is not supported in native mobile app contexts. Treat a single boolean read as an observation, not as an application completion signal.

For a condition that spans several observations, browser.waitUntil accepts a condition function and options such as timeout, interval, and timeoutMsg. An asynchronous predicate can read a status and compare it with the expected checkout identity. Keep that predicate read-only: a retrying condition must not submit another order every time it polls.

A timeout should say what evidence was missing. “Checkout C42 did not produce its receipt” is more actionable than “wait failed.” On failure, capture the relevant element state, screenshot, checkout identifier, and available request or server correlation identifiers. Avoid putting credentials or payment details in logs.

Separate the test deadline from the polling interval. A short interval gives more observations; it does not make the service commit sooner. Set the deadline from the operation's expected behavior and the test environment, then use failure evidence to decide whether that expectation remains appropriate.

Repair the Checkout Without Guessing a Sleep

Original exercise: these are hypothetical event times, measured from opening checkout. The slow run has the same valid outcome with a later receipt.

EventOrdinary runSlow runWhat it establishes
Button enters the DOM0 ms0 msPresence
Shipping completes; button enabled80 ms180 msOne readiness condition
Click is performed200 ms300 msAction occurred
Order is committed800 ms1,350 msServer-side outcome
Receipt for checkout C42 appears950 ms1,600 msCorrelated UI evidence

A 400 ms sleep after the ordinary click ends at 600 ms, before the order commits. An 800 ms sleep ends at 1,000 ms and happens to pass that run. In the slow run, the same 800 ms sleep ends at 1,100 ms and still fails. Increasing it again trades a timing guess for a larger timing guess.

The fixture below assumes the application exposes a unique checkout ID and writes that ID on its final receipt. These attributes are an explicit test contract, not built-in WebdriverIO features.

import { $, browser, expect } from '@wdio/globals';

const checkoutId = 'C42'; // unique fixture-owned checkout
const panel = $(`[data-testid="checkout"][data-checkout-id="${checkoutId}"]`);
await panel.$('[data-testid="place-order"]').click();

await browser.waitUntil(async () => {
  const receipt = $(`[data-testid="receipt"][data-checkout-id="${checkoutId}"]`);
  if (!(await receipt.isExisting())) return false;
  return (await receipt.getAttribute('data-status')) === 'complete';
}, {
  timeout: 5000,
  interval: 100,
  timeoutMsg: `No completed receipt for checkout ${checkoutId}`
});

await expect($(`[data-testid="receipt"][data-checkout-id="${checkoutId}"]`))
  .toHaveText('Order confirmed');

Use the application's actual receipt text and identity contract. A production test should obtain the unique ID from its setup rather than reuse C42 across runs. If the application does not expose one, discuss a suitable correlation mechanism with its owner instead of inventing an unsupported selector.

This example is source-reviewed JavaScript, not a recorded WebdriverIO run. Our local model checks the timeline arithmetic and the shared-cart counterexample below. It does not prove driver behavior or the application's commit semantics. A UI receipt is also insufficient if the requirement is specifically durable backend persistence; verify that requirement through an appropriate backend test.

How Should Selectors and Assertions Survive UI Changes?

Official behavior: the current selector documentation recommends stable identifying attributes and meaningful accessible names. It also documents a version-sensitive change: in v10, $ is strict when a selector matches multiple elements. Confirm the installed major version before predicting the exact failure; do not assume this strictness for every older suite.

In the checkout example, a stable test ID identifies the kind of control, while the checkout identity selects its instance. A CSS class such as .green-button describes styling. An index such as “the third button” describes incidental layout. Both may keep matching something after the intended element moves.

An accessible-name selector can express what a user perceives, but localization or deliberate copy changes may change that name. A test ID can stay stable, but it does not itself verify accessibility. Explain which contract your selector is meant to protect. Test both separately when both matter.

Official behavior: WebdriverIO's best practices recommend its retrying assertions. Comparing an immediately sampled value with a generic assertion can lose that retry behavior. Prefer an element matcher when the expected condition is supported, and avoid adding several redundant presence and visibility waits before the same assertion.

The expect reference documents available matchers and options. Verify which expect is imported when a project mixes assertion libraries. Identical names do not imply identical waiting semantics.

Interview reasoning: keep page objects focused on meaningful operations and locators. A method called completeCheckout should expose or verify a completion condition. Hiding a fixed sleep inside that method makes the test shorter while leaving its weakest assumption intact.

What Do Separate Workers Isolate—and What Do They Share?

Official behavior: the Local Runner documentation describes test execution in worker processes, with an independent browser session for each worker. That protects browser execution boundaries. It does not create separate accounts, carts, inventory, databases, or external services.

Original counterexample: workers W1 and W2 authenticate as the same test account. Both use its single server-side cart. Each browser has its own cookies, but those cookies identify the same backend user.

StepWorker actionShared cart after action
1W1 clears the cartEmpty
2W2 adds item BB
3W1 adds item AB, A
4W2 checks out, expecting only BB and A are purchased

No element wait fixes this result. The server executed the shared operations correctly; the test fixtures violated ownership. Running with one worker can conceal the collision, which makes serial success weak evidence of a parallel-safe suite.

Assign each execution an owned namespace derived from a run identifier, capability, spec, and attempt. Provision its own account or cart where the application supports that model. Include the attempt dimension when retries may overlap with delayed work from a previous attempt. Record the namespace in diagnostics so a failure can be traced to its actual fixture.

Not every resource can be duplicated cheaply. A test for globally limited inventory may intentionally share stock. In that case, reserve a controlled quantity or serialize that specific scenario and explain the constraint. Increasing workers without a data plan creates contention, not useful coverage.

Explain Retries, Cleanup, and Failure Recovery

A retry can help measure intermittency, but it does not establish that the failed attempt had no effects. If the first checkout commits and its response is lost, replaying the action can create a second order unless the application supports a suitable idempotency contract.

Preparation advice: distinguish a read-only polling retry, an assertion retry, and a whole-spec retry. State which operation each repeats. This makes it possible to explain why polling a receipt is acceptable while repeatedly clicking Place order is dangerous.

Cleanup needs the same ownership rule as setup. W1 should remove W1's fixtures, not every account whose name starts with test. Run cleanup even after a failure where feasible, but retain enough identifiers to investigate. If a worker crashes before teardown, an expiry or scheduled cleanup mechanism should reclaim only abandoned fixtures.

A useful investigation compares isolated and parallel runs, then examines the failed contract. Did the selector identify the wrong button? Was the button disabled? Did the receipt carry another checkout ID? Did a previous retry leave a committed order? These questions narrow the repair more effectively than making every timeout longer.

Practice Questions That Test the Three Contracts

Rehearse a concrete failure observation and a repair for each.

QuestionWhat to explain
Robust Selenium Code to Extract Text from Two ElementsLocator identity and readiness, then translate the reasoning to WebdriverIO
Testing a New Feature: Planning Test Cases and Handling Flaky TestsWhich failure evidence distinguishes timing, data collision, and a product defect
Debug a Frontend Component That Shows Wrong API ResultsCorrelate rendered output with the intended request
Design automated regression tests for an APIVerify the persistence contract outside a UI receipt
Decide When Automated Tests Are NecessaryChoose a useful layer and justify its maintenance cost

Begin with the flaky-test planning exercise. Give a short answer that names the missing condition, proposes an owned fixture, and identifies the evidence that would prove the repair. That answer demonstrates more control than memorizing a list of wait methods.

Sources and Further Reading