Interview Insights · Playwright
The Playwright Question That Ninety Percent of Candidates Fumble
Quick summary — Playwright flakiness
Auto-waiting makes elements ready; it does not make your app's state ready. Saying that clearly is most of the answer. Most candidates either deny that Playwright tests can flake or jump straight to retries. The answer I want explains the boundary: Playwright waits for an element to be actionable and retries web-first assertions, but it cannot know that a list is still loading, that a page has not hydrated, or that two tests are editing the same account. Then it shows how you would find the real cause with a trace and fix it by waiting on the right signal.
In this guide you will learn:
- Why this question trips up so many Playwright candidates
- Exactly what auto-waiting covers and what it leaves to you
- Four real causes of flaky Playwright tests, with fixes
- How expect.poll, toPass and page.route fit into the answer
- A spoken model answer you can adapt in under two minutes
SECTION 01Why the auto-wait question catches so many people
I ask some version of this in nearly every Playwright round: 'Playwright waits automatically. So why would a Playwright test ever be flaky?' The question is unfair only to people who learned Playwright from marketing pages. Anyone who has kept a real suite green for a few weeks has a story ready.
The common wrong answers fall into patterns. Some candidates insist Playwright is never flaky, which tells me they have only run demo tests. Some say 'I set retries to three', which tells me they hide failures. Some list random commands. The answers that work all start the same way: by naming the limit of auto-waiting.
| Typical answer | What it reveals | Follow-up I ask | Usually recovers? |
|---|---|---|---|
| Playwright tests are never flaky | Only toy projects so far | What if the API is slow on Mondays? | Rarely |
| I set retries to 3 in config | Treats symptoms, not causes | How do you know the bug is not real? | Sometimes, if they mention traces |
| I add waitForTimeout | Old Selenium habit | What exactly are you waiting for? | Rarely |
| Auto-wait covers elements, not app state | Has debugged real flakes | Give me one example from your suite | Usually goes well |
Interviewer: Playwright auto-waits. Why would a test still be flaky?
Candidate: Actually Playwright is very stable, sir.
It waits automatically, so flakiness is mostly a Selenium problem.
If something fails I re-run it, and usually it passes.
Interviewer: And if it passes on re-run, what do you report?
Candidate: ... that it passed.Interviewer: Playwright auto-waits. Why would a test still be flaky?
Candidate: Auto-waiting checks that an element is visible,
stable and enabled, and expect() retries assertions.
But it does not know my app's business state.
For example, a results table can be visible with the
old rows while the new search is still loading.
Playwright sees a ready table and my count check reads
the wrong data. So I wait for the right signal, like
the search response or the final row count.
The strong answer does not need to be long. It needs a boundary and one concrete example. Everything after that is a conversation, and conversations are where interviewers decide.
SECTION 02Four flaky causes that auto-waiting cannot see
Once you have named the boundary, the interviewer will usually ask for causes. Have four ready, each with a fix that uses the right Playwright tool. These are the categories I see most often when reviewing suites; your own project will have its own variations.
Notice that none of the fixes is a fixed sleep. Each one replaces 'wait some time' with 'wait for this specific thing'. That shift is the heart of the answer.
| Cause | What goes wrong | Playwright fix | Tool or API |
|---|---|---|---|
| Stale data on screen | Old list visible while new results load | Assert the final state, such as row count | expect(rows).toHaveCount(n) |
| Backend still processing | Status changes after a background job | Poll the API or the UI until it settles | expect.poll or expect(...).toPass() |
| Unstable third-party API | Real network varies run to run | Mock the call with fixed data | page.route with route.fulfill |
| Shared test accounts | Parallel tests edit the same user | Create unique data per test | request fixture, unique IDs |
import { test, expect } from '@playwright/test';
test('search filters the table', async ({ page }) => {
await page.goto('/products');
const searchDone = page.waitForResponse(
r => r.url().includes('/api/products?q=lamp') && r.ok()
);
await page.getByRole('searchbox', { name: 'Search' }).fill('lamp');
await page.getByRole('button', { name: 'Search' }).click();
await searchDone;
const rows = page.getByRole('row').filter({ hasText: 'Lamp' });
await expect(rows).toHaveCount(3);
});
test('report finishes processing', async ({ page, request }) => {
await page.goto('/reports/42');
await expect.poll(async () => {
const res = await request.get('/api/reports/42');
return (await res.json()).status;
}, { timeout: 30_000 }).toBe('READY');
await page.reload();
await expect(page.getByText('Download report')).toBeVisible();
});import { test, expect } from '@playwright/test';
test('shows exchange rate from mocked API', async ({ page }) => {
await page.route('**/api/rates*', route =>
route.fulfill({ json: { base: 'USD', rate: 83.1 } })
);
await page.goto('/converter');
await page.getByLabel('Amount in USD').fill('10');
await expect(page.getByTestId('converted-amount'))
.toHaveText('831.00');
});
// The rate here is fixed test data, not a real value.
// Mocking removes the network as a source of flakiness
// for tests that are about the UI, not the rates service.
Be ready for the follow-up 'doesn't mocking hide real bugs?'. A good answer: yes, so you keep a small number of end-to-end tests against the real service, and mock in the tests whose purpose is the UI logic. That balance is a design decision, and interviewers like hearing you make one.
A fifth cause worth knowing is a click before hydration: the button is visible in server-rendered HTML, but its JavaScript handler is not attached yet, so the click does nothing. Wait for a ready signal, such as the response that loads the page data, before interacting.
Also watch for strict mode errors. If getByRole('button', { name: 'Delete' }) matches two buttons, Playwright throws a strict mode violation instead of guessing. That is not flakiness, but candidates often describe it as such. Narrow the locator to a row or region instead of adding .first() everywhere.
SECTION 03The full model answer, spoken in under two minutes
Put the pieces together into one spoken answer with a clear shape: boundary, example, diagnosis, fix, prevention. Practise it until it sounds like you, not like a script. Interviewers can hear memorised paragraphs, so change the example to one from your own project.
The diagnosis step matters more than most candidates think. Saying 'I open the trace' is good. Saying what you look for in the trace is better: the action that failed, the DOM snapshot before it, and the network requests around it.
| Part of answer | Purpose | What to say | Time |
|---|---|---|---|
| Boundary | Show you know the tool's limits | Auto-wait covers elements, not app state | 15 s |
| Example | Prove real experience | One flake from your own project | 30 s |
| Diagnosis | Show method | Trace: failing action, snapshot, network | 30 s |
| Fix and prevention | Show judgement | Wait on signal, mock or isolate data, no blind retries | 30 s |
"Auto-waiting makes sure an element is visible, stable and
enabled before an action, and web-first assertions retry.
What it cannot know is my app's state.
In my project, a cart total test failed about once a week in CI.
The trace showed the total was visible but still showing the
old value, because the price API was slower in CI.
I was reading the text once with textContent().
I changed it to await expect(total).toHaveText(...), and waited
on the cart update response. I also gave each test its own
cart through the API so parallel runs stopped colliding.
We keep retries at one in CI only to collect a trace,
and we treat any test that needs the retry as a bug to fix."Likely follow-ups after your answer:
1. What does a strict mode violation mean?
-> Locator matched more than one element; narrow it.
2. When would you use networkidle?
-> Rarely. It is discouraged; wait for a specific
response or a visible state instead.
3. Difference between expect.poll and toPass?
-> poll retries a value-returning function;
toPass retries a whole block of assertions.
4. How do you stop parallel tests colliding?
-> Unique data per test, created via API fixtures.
5. How do you find flaky tests across runs?
-> CI reports that flag tests passing only on retry.
If you have never debugged a real flake, say so honestly and describe how you would approach one. Then go home and create one on purpose in a practice project so that next time you have a story. A made-up story falls apart within two follow-up questions.
SECTION 04Practice kit: rehearse the flaky-test answer
Use this kit for a few evenings before your interview. The aim is to have one real story, one clear boundary sentence and a calm diagnosis routine you can describe without notes.
BREAK IT ON PURPOSE (practice project)
1. Add a slow route to a local demo app, or mock an API
with a random delay:
await page.route('**/api/cart', async route => {
await new Promise(r => setTimeout(r, Math.random() * 3000));
await route.continue();
});
2. Write the assertion the wrong way (textContent once).
3. Run it 20 times: npx playwright test --repeat-each=20
4. Watch it fail sometimes. Open the trace.
5. Fix it with a web-first assertion. Run 20 times again.
Now you have a real story to tell.FLAKY TEST ANSWER CARD
Boundary: auto-wait = element ready, not app ready
Example: ______________________________________
Diagnosis: trace -> failing step -> snapshot -> network
Cause: ______________________________________
Fix: wait for ____ / mock ____ / isolate data
Prevention: retry-only-passes are bugs, tracked in ____
Say it aloud 3 times. Record the third one.SCORE YOUR RECORDING (1-5 each)
[ ] Named the auto-wait boundary in the first 20 seconds
[ ] Gave a specific example, not a general claim
[ ] Mentioned the trace and what I looked at in it
[ ] Fix waited on a signal, not on time
[ ] Did not present retries as the solution
[ ] Ended with how the team prevents repeats
Below 20? Re-record tomorrow with a sharper example.
SECTION 05Small habits that make this answer land
A good answer can still sound weak if the delivery is shaky. These habits keep it crisp.
- Lead with the boundary — Your first sentence should say what auto-waiting does and does not do. Interviewers decide early whether you understand the question.
- Use one example, not five — One real flake told well is stronger than a list of possible causes recited quickly.
- Name the API you used — Saying toHaveCount, expect.poll or page.route shows you have typed these, not just read about them.
- Separate flaky from broken — If a test fails every time, it is a bug or a bad locator, not a flake. Making that distinction impresses reviewers.
- Admit trade-offs — Mocking speeds tests up but can hide integration bugs. Saying so shows maturity.
SECTION 06Interview Q&A — Playwright flakiness
Q1If Playwright auto-waits, why do Playwright tests become flaky?
Auto-waiting checks that elements are actionable and retries web-first assertions, but it does not know the application's business state. A table can be visible with old data, a button can be visible before its handler is attached, or a background job may not have finished. Shared test data and unstable external APIs also cause flakes. The fix is to wait for the specific signal that the state is ready.
Q2What is the difference between expect.poll and toPass?
expect.poll repeatedly calls a function that returns a value, such as an API status, and checks that value with a matcher until it passes or times out. toPass wraps a whole block of code, including several assertions, and retries the block. I use poll when the truth is outside the page, and toPass when a group of checks must eventually succeed together.
Q3Is it acceptable to use retries in Playwright?
A small retry count in CI is acceptable as a way to capture a trace on the second attempt. It is not acceptable as a fix. Any test that passes only on retry should be investigated, because it may be hiding a real race condition in the application or in the test itself.
Q4When should you mock network calls in Playwright tests?
When the test is about UI behaviour and the backend or a third-party API is slow, unstable or hard to put into a specific state. I use page.route with route.fulfill to return fixed data. I still keep a few end-to-end tests against the real backend so integration problems are caught.
Q5What does a strict mode violation mean?
It means a locator used for an action matched more than one element, so Playwright refuses to guess which one to use. The right fix is to make the locator more specific, for example by scoping it to a row or region, rather than adding first() everywhere without thinking.
SECTION 07Test yourself — Playwright flakiness quiz
Five questions. No sign-up.
0 / 5Pick an answer to see why it is right or wrong.
SECTION 08Frequently asked questions
Why are my Playwright tests flaky even with auto-wait?
Usually because the test checks a state the app has not reached yet, such as old data still on screen, a page that is visible but not hydrated, or a background job still running. Shared test data and unstable APIs are other common causes. Wait for the specific signal, and use the trace to confirm the cause.
How do I find flaky tests in Playwright?
Run the suspect test many times with the repeat-each option, and look at CI reports for tests marked as flaky because they passed on retry. Enable traces on retry so each flaky run leaves evidence you can open in the trace viewer.
Should I use networkidle in Playwright?
It is generally discouraged because many apps keep making background requests, and it does not tell you that the thing you care about is ready. Prefer waiting for a specific response or asserting a visible state with a web-first assertion.
What Playwright flaky test questions are asked in interviews?
Expect questions on why tests flake despite auto-waiting, how you debug a CI-only failure, when to mock network calls, how you handle retries, and how you keep parallel tests from sharing data. Interviewers usually want one real example from your work.
Is page.waitForTimeout ever acceptable?
Very rarely, for example while debugging locally to slow things down and observe. In committed tests it is almost always a sign that you should wait for a specific condition instead.
Is there a course that covers Playwright interview questions?
Yes. Uncodemy's Automation Testing Training Course in Noida (classroom and online) includes live projects, one-to-one mock interviews and resume reviews, so you practise Playwright interview questions with trainer feedback before the real interview. You can book a free demo class from this page to see how the sessions work.
SECTION 09Related reads
Classroom & online · Noida
Answer the flaky-test question like an engineer
Our Automation Testing Training Course teaches Playwright through real suites, including flaky tests, traces, mocking and CI, so you can explain causes and fixes from experience.
Talk to a counsellor for current fees- Playwright with TypeScript
- Trace and CI debugging
- Network mocking practice
- Mock technical rounds