What UI testing with Puppeteer is genuinely good at
Direct browser control. Screenshots, PDFs, network interception, performance traces. When you need the browser to do something specific, this is the shortest path.
Scraping and automation. A large share of Puppeteer use is not testing at all, and it is excellent at it.
A small, learnable surface. You can hold the whole API in your head, which is rarer than it should be.
The three costs of a browser suite
Selectors break. A redesign that changes nothing functional turns the suite red. This is where most maintenance time actually goes.
Waiting is subtle. Fixed delays are slow and still flaky; correct waits require knowing what to wait for. Most flakiness traces back to this.
Coverage is authored. You cover what someone wrote, which is the flows that were interesting rather than the ones that break.
Deciding what to automate
The instinct is to start with the most important feature. A better filter is how quietly something would fail. A checkout breaking is loud and you will hear about it within the hour. An export, an invite or a settings page breaking is quiet, and quiet failures are the ones worth automating first.
Second filter: how often does it change. A flow that changes every sprint will cost more in maintenance than it returns. Cover it later, once it settles.
Three habits that save the most time
Use stable attributes. A dedicated test attribute rather than a CSS path. This single change removes most redesign breakage.
Wait for state, not for time. Wait for the element or the response, never for a number of milliseconds.
Assert something a reload would confirm. A success toast is not evidence that anything persisted.
Where intention-based verification fits
Selector breakage and authored coverage are structural rather than fixable with better discipline. A step expressed as an intention survives a redesign that a selector does not, and coverage generated from your product rather than from someone's memory includes flows nobody would have written.
This is not an argument against Puppeteer, which remains the right tool for direct browser control. It is an argument for not hand-writing the breadth.
Terminal
npm install -g @testsprite/testsprite-cli
testsprite setup
If you would rather not install anything, the dashboard does the same thing. Everything else the command line can do is in the CLI repository.
The three things that make a Puppeteer script fragile
Scripts written quickly break for the same three reasons, and each has a fix that costs nothing at the time and a lot later.
Chained CSS paths are the first. A selector that walks four levels of structure encodes the layout rather than the element, so any wrapper anybody adds breaks it. Anchor on something that describes what the element is, not where it sits.
Fixed waits are the second. A delay long enough to be reliable on a slow day is a delay you pay on every fast day, and it still fails on the slowest one. Wait for the element, the response, or the state change.
Asserting on what you just did is the third. Clicking save and then checking the save button exists proves nothing. The assertion has to be something that only becomes true if the operation actually completed, which usually means fetching the thing back.
Run it on every change
If the pipeline belongs to another team, the GitHub App is the path of least resistance: it is a webhook, it changes nothing in your repository, and it fires when your build reports the new version live. If you want the check visible in the repo instead, a GitHub Actions step does that.
Where TestSprite fits alongside Puppeteer
Puppeteer stays for direct browser control: screenshots, PDFs, network interception, scraping. TestSprite takes the part that does not scale with author time, which is deciding what to cover and keeping it alive.
Steps are stored as intentions rather than selectors, which removes most redesign breakage, and waiting is handled rather than being something you tune per test. Coverage is generated from your product, so the quiet flows that would never make it onto anyone's list are included.
What that changes in practice: the ratio of red builds that are real bugs stays high enough that people keep reading them, which is the thing that actually determines whether a browser suite survives its second year.
Is there a free epub of a Puppeteer book?
That depends on the publisher and changes over time. This page is the current working knowledge rather than a copy of a book.
Puppeteer or Playwright?
Playwright has broader browser support and better built-in waiting. Puppeteer is simpler and excellent for Chrome-specific work and scraping.
How do I reduce flakiness?
Stable attributes and state-based waits remove most of it. What remains is usually a genuinely unstable environment, which no framework fixes.
How many UI tests should we have?
Fewer than you think, chosen by how quietly they would fail. A small suite people trust beats a large one people ignore.
Can Puppeteer coexist with agent verification?
Yes, and it is the usual arrangement. Keep Puppeteer for direct browser control, let generated coverage carry the breadth.
The API is easy. Choosing and maintaining is not.
UI testing with Puppeteer is mostly about which flows to automate and how to keep them alive. Use stable attributes, wait for state, assert what a reload would confirm, and do not hand-write the breadth.