Proving a fallback actually falls back
My OG-card generator had one test. It rendered a fixture card and checked the output was a non-empty PNG. That’s a fine smoke test, and it caught a real crash once - a native panic in the PNG library I was using before switching to sharp. But it left the package’s actual configurable surface, custom dimensions and custom fonts, completely unverified.
Broadening it turned into a small lesson about what “testing an option” actually requires.
The easy 80%
Custom width and height was straightforward: generate a card at 600x400 instead of the 1200x630 default, then check the output PNG’s real pixel dimensions via sharp(png).metadata(). Not “did it render,” but “is the width literally 600.”
const png = await generateCard(markup, { width: 600, height: 400 });
const { width, height } = await sharp(png).metadata();
assert.equal(width, 600);
assert.equal(height, 400);
I went back and added the same dimensions check to the original smoke test too. It had been checking “is this a valid PNG of non-trivial size” - true, but it would have stayed true even if width and height were quietly ignored.
The part that made me stop
The fonts option is supposed to let a consumer override the bundled default font entirely. My first instinct for testing it: call generateCard with a custom font, check it still produces a valid PNG. Done, right?
Except that test would pass identically whether or not the option did anything. If fonts were silently ignored and the function fell back to its bundled default every time, the output would still be a valid PNG, because the bundled default works. A test built entirely from “does this run without crashing” can’t distinguish “the code path executed” from “the code path was skipped and something else compensated.”
The test that proves something needs a case where the two behaviors diverge. I don’t have a second real bundled font to swap in for a positive test, but I do have a way to force divergence: pass an empty fonts array.
await assert.rejects(() => generateCard(imperfectSystemsCard, { fonts: [] }));
Satori requires a font to render any text at all. If fonts: [] reaches Satori, rendering text-heavy markup throws. If the option were being silently ignored and the bundled default used instead, nothing would throw and the card would render fine. So this test can only pass if the override genuinely reaches the rendering call. A small, almost backwards-feeling test - asserting failure, not success - but it’s the one that discriminates between “works” and “looks like it works.”
The general shape of the mistake
“Pass an option, confirm nothing crashed” tests your happy path’s resilience, not the option. The tell is asking: if I silently deleted this feature and made the option a no-op, would this test still pass? If yes, it’s not testing the feature. For overrides and fallbacks specifically, the fix is almost always to construct an input where the fallback and the override would visibly disagree, then assert on which one actually happened.
Also in this batch
OgMeta’s image dimensions were hardcoded to 1200x630 even though a consumer might pass a differently-sized image; now they’re optional props defaulting to those values, plus twitter:image:alt (previously only the og: variant existed) and article:published_time/article:modified_time for blog posts. And a README note making explicit that pulling in native sharp even for meta-tags-only consumers is a deliberate tradeoff rather than an oversight. Card generation is the point of the package, and a second dependency-free package for the rare meta-tags-only case isn’t worth maintaining.
Related reading
The escaping bug that only shows up with a second query param
A rewrite function that worked in every test and every real URL it had ever seen, and would still have broken the moment someone added a second query param.
Testing the part of the codebase that documents its own footgun
A README warning about a subtle failure mode is a confession that the code isn't tested against it yet.
The 200KB decode nobody needed to redo
A one-line memoization fix, and the small test that actually proves memoization happened instead of just trusting the diff.