Cosmin Pop

A manual test case is a unit of manual labor, not of coverage, and automation inverts every economic assumption that shaped it. Porting several hundred manual cases 1:1 into Playwright buries the real coverage under hundreds of tiny specs that each re-pay full login and navigation. The rule I enforced above all: never default…

13 min read

Two aging Playwright suites for the same platform (a browser E2E suite and a separate API-only suite) had diverged into two repos with their own auth and data hacks, more expensive to touch every quarter. Not a big-bang rewrite and not an in-place refactor: a strangler-fig migration into one repo where both tiers…

13 min read

Bumping the worker count made the suite's discovery phase fan a few concurrent GET /orders calls and the shared dev environment sprayed 502s, under modest load. Nobody could answer with a number: at what concurrency does it break? I answered it with ~500 lines of TypeScript inside the Playwright repo I already had…

13 min read

A handful of test conventions lived in a standards doc enforced by code review, so they decayed. Grep-based pre-commit checks failed too: template-literal titles, multi-line calls, and JSDoc prose force regex to choose between missing violations and crying wolf, and either kills trust in the gate. What worked: four small scripts that parse every…

13 min read

Which requirement does this test cover, and which tests cover PROJ-7251? On a regulated-adjacent suite, 'let me check the spreadsheet' isn't an answer. I encode traceability as typed imperative calls inside each test body (trackingRef/testType/severity), mirror them as title tags for grep, report them automatically via an auto-fixture, generate a ticket-to-tests index, and enforce the whole convention with an AST guard in the merge gate. About four lines per test, no test-management plugin.

12 min read
Software Testing

Auth for a Playwright suite that never sleeps

Jul 31, 2026

For a Playwright suite running 24/7 against a shared Cognito+SSO environment, auth, not the product, was the top cause of red runs: tokens expiring mid-run into waves of opaque 401s, or two processes refreshing at once and leaving everyone with a dead token. The fix is a three-layer architecture: validate, refresh, recover…

13 min read

The shared dev order list opened to three pages of garbage: one leaked entity per write-path test per run, piling up since the suite first learned to POST, and tripping the discovery code that finds real entities. The fix wasn't a cleanup sprint but a one-page written policy: net-zero by default with a verified…

11 min read

On a shared dev environment where orders can't be deleted, test data drifts under other teams' deploys and curious humans. Creating fresh entities floods the box; reusing one by name breaks the moment another spec edits it. The pattern that held: find-or-create seed pools keyed on a deterministic title, resolving each slot into one of four outcomes (REUSED, REPAIRED, DEGRADED, CREATED) and repairing drift with targeted idempotent writes. Repair beats recreate.

14 min read

Fifty page objects across five domains is exactly the size where the layer usually rots: every entity form a 400-line fork, a utils/ folder nobody owns, specs reaching two layers down. Three structural decisions kept mine from rotting: one abstract base class owning entity-form mechanics so a new form costs ~40 lines not 400,…

12 min read

Angular Material abstractions make a Playwright suite go green while the app quietly does the wrong thing. The root cause every time is that the visible DOM is not the state the form will submit. fill() leaves a ReactiveForms control pristine so the PATCH drops the field and the backend still returns 200. A…

13 min read