In Playwright, what does test.describe.configure({ mode: 'default' }) do in a fullyParallel project?
answer
- There are three modes, not two
- Undoes the global flag per scope
- Ordered but still independent
- No skipping after a failure
- Weaker claim than serial
basics
~20 sDefault mode opts that scope back out of test-level parallelism. The tests run in declaration order in one worker again, but stay independent: a failure skips nothing after it, and a retry reruns only the failing test.
solid answer
~40 s`test.describe.configure({ mode: 'default' })` restores Playwright's original schedule for the scope it is called in, which is what you want when `fullyParallel: true` is set globally but one file is not ready for it. Called at the top level of a spec file it applies to the whole file; called inside a `test.describe` it applies to that block. The restored behaviour is ordered execution in one worker with **independent** tests, and that middle position is the point: `mode: 'serial'` is also ordered and single-worker, but it additionally skips the tests after a failure and reruns the whole group on a retry. So `default` gives you determinism of order without buying into dependency semantics, which is the cheaper of the two ways to stabilise a file.
code
typescript · 16 lines// tests/payroll/ledger.spec.ts
import { test, expect } from '@playwright/test';
// Opt this one file out of the config's fullyParallel setting.
test.describe.configure({ mode: 'default' });
test('posts a journal entry', async ({ page }) => {
await page.goto('/payroll/ledger');
await page.getByRole('button', { name: 'Post entry' }).click();
await expect(page.getByText('Entry posted')).toBeVisible();
});
test('reconciles the ledger', async ({ page }) => {
await page.goto('/payroll/ledger');
await expect(page.getByRole('heading', { name: 'Reconciled' })).toBeVisible();
});go deeper
Know that a mode called default exists and that it puts one file back to running its tests in order on a single worker.
Explain the three-mode table from memory, especially that default keeps tests independent while serial makes them a dependent chain.
Use it deliberately during a fullyParallel rollout: quarantine the few unsafe files with the weakest override that fixes them, and track the list down.
Decide the house rule for which override is acceptable where, so that quarantine lines stay temporary rather than becoming permanent suite architecture.
## Three modes, not two `test.describe.configure({ mode })` accepts `'parallel'`, `'serial'` and `'default'`. Candidates usually know the first two and treat `default` as "do nothing", which is wrong once `fullyParallel: true` is in the config: at that point `default` is an **active override** that undoes the global flag for one scope. | mode | order inside the scope | worker | after a failure | retry granularity | |---|---|---|---|---| | `'parallel'` | none guaranteed | any free worker | later tests still run | the failing test | | `'default'` | declaration order | one worker | later tests still run | the failing test | | `'serial'` | declaration order | one worker | later tests skipped | the whole group | Read down the *after a failure* column and the shape of the answer appears: `default` shares its **independence** with parallel mode and its **ordering** with serial mode. ## Where you call it - At the **top level of a spec file**, before any `test` or `test.describe`, it configures the entire file. - **Inside a `test.describe`**, it configures that block and the blocks nested in it. - The **innermost** configuration wins, so a serial block inside a default file stays serial. That scoping is why a large payroll suite can enable `fullyParallel` globally and still carry a handful of files that say `test.describe.configure({ mode: 'default' })` on line one while their shared-state problems get fixed. ## Why reach for default rather than serial Both pin the scope to one worker in order, so both fix a failure caused purely by two tests in the file racing each other. The difference is what happens afterwards: 1. With `default`, a failure in the third test still lets the fourth and fifth run, so one run tells you about all three. 2. With `serial`, the fourth and fifth are skipped, so one run tells you about one, and you re-run to learn about the others. 3. With `default`, a retry reruns only the failing test; with `serial`, it replays the whole chain and pays its full duration again. So `serial` is the stronger claim — *these tests depend on each other* — and `default` is the weaker one — *these tests must not run at the same time*. Choosing the weaker claim when it is true keeps reporting sharper and retries cheaper. ## A worked payroll case A ledger spec has ten tests that each post an entry against the same demo company. Under `fullyParallel` they interleave and two of them fight over the same period, producing an intermittent failure. Adding one line at the top of that file, `test.describe.configure({ mode: 'default' })`, restores the pre-flag behaviour for that file only: ten ordered tests on one worker, every one still reported on its own merits, and the other thirty-nine spec files still running fully parallel around it. ## Things to get right when explaining it - `default` is not "the mode you get when you write nothing" once a global flag is set; it is the way to *get back* there. - It does not turn parallelism off for the run, only for its scope. Other files are untouched. - It does not weaken or strengthen retries; it just leaves retry granularity at the individual test, where the ordinary schedule has it. - It is a scheduling instruction, not a synchronisation primitive: it stops tests **in that scope** from overlapping, and says nothing about a test in another file touching the same payroll record. ## How to answer Name the three modes, place `default` between them, and finish on the practical rule: reach for `default` when tests merely must not overlap, and reserve `serial` for the case where a later test genuinely cannot mean anything if an earlier one failed.
- If a file is configured default, can a describe block inside it still be serial?Yes. The innermost configuration wins, so a `test.describe` inside that file can call `test.describe.configure({ mode: 'serial' })` and get skip-on-failure and group retries for its own tests while the rest of the file keeps the ordered, independent schedule.
- Does default mode stop a test in another file from touching the same data?No. It only constrains scheduling within its own scope, so its tests do not overlap each other. Files around it still run concurrently, and any collision with them has to be solved by the test data, not by this mode.
saying these in an interview costs you the question
- Thinks default mode is a no-op with fullyParallel on
- Says default mode skips tests after a failure
- Confuses default mode with serial because both are ordered
- Believes it disables parallelism for the whole run
- Treats it as a lock against other spec files