Guides · 3 min
Testing
One command that drives a real browser against a real database, because the failures worth catching are between the parts.
The bugs that reach customers in an app like this are almost never inside a function. They are between two of them: the cookie that did not survive a redirect, the policy that lets the wrong row through, the panel that overflows at 360 pixels. Unit tests do not see any of those.
So the suite is one file that signs in for real, pays for real, and reads the page the way a customer would.
BASE=http://localhost:3000 node qa/buyer-flow.jsWhat it does
Creates a user through the admin API
Then deletes it first if it is left over from the last run, so the suite is re-runnable rather than passing once.
Signs in with a genuine magic link
Generated the same way the email template builds it, a token hash aimed at your own callback. If the templates are wrong, this fails, which is the point.
Grants an entitlement the way the webhook does
Then asserts the dashboard shows it: the key, the plan, the price formatted in the right currency.
Attacks its own policies
Reads every table with the publishable key alone and asserts it gets nothing. Posts an unsigned webhook and asserts a 400.
Measures the phone
Resizes to 360 wide and asserts scrollWidth never exceeds clientWidth, on
every page, naming the offending element when it does.
The overflow check
This one earns its keep more than any other:
const over = await page.evaluate(() => {
const doc = document.documentElement;
return {
scrollW: doc.scrollWidth,
clientW: doc.clientWidth,
wide: [...document.querySelectorAll("body *")]
.filter((el) => el.getBoundingClientRect().right > doc.clientWidth + 1)
.slice(0, 3)
.map((el) => `${el.tagName}.${el.className}`),
};
});It does not just say the page is too wide. It names the three elements sticking out, which turns a twenty minute hunt into a one line fix.
Trust the test before you trust the fix
When a check fails, prove the check is right before changing the code. A failing assertion is a claim, not a verdict, and half an hour spent fixing a bug that was really a bad selector is half an hour you do not get back.
What is not here
There are no unit tests, and that is a choice rather than an omission. Add them where you have real logic: pricing arithmetic, entitlement rules, anything with branches worth enumerating. Do not add them to assert that a component renders.
Something wrong or missing on this page? Tell us.