React Forum
Blog & Guide Responses
Feb 17, 2023 · 04:00 PM

[Guide] Build a Code Snippets Manager (Snapshot Testing) - implementation notes

Started by Jules Kwon
guidesnippetssnapshotstestingrender logroute flow testsderived tagsdebug panelsevidence

The Code Snippets Manager guide is basically a love letter to snapshots: snapshot the render story, snapshot the route flow, snapshot derived tags so debugging has something concrete to hold on to. I like that it's unapologetically "tests read the contract from the UI" instead of spelunking internal state.

Read the guide

How granular were your snapshots (whole page, per panel, per snippet row) before churn became annoying? Did you store derived tags (language, topic, lint hints), or did you derive them at render and only store evidence tokens/revisions? What did your route-flow tests assert on: evidence keys, rendered text, or log lines? How did you keep debug panels from turning into a second UI with its own state bugs?

Comments (22)

Back to latest
Mei Tan
Feb 21, 2023 · 07:10 AM

We started with full-page snapshots and regretted it immediately.

The sweet spot was per-panel snapshots (list, editor, preview) plus one route-flow snapshot that pins the overall posture.

Rafael Soto
Feb 25, 2023 · 05:05 AM

Route-flow tests were easier once we logged the story as tips lines and asserted on those.

txt
[tips] routeEnter path=/snippets lane=ok reason=nav
[tips] select snippetId=sn:42 source=listClick
[tips] derive tags rev=18 reason=snippet:parse
[tips] snapshot write name=snippet:sn:42:editor rev=18

When the story changed, the diff was meaningful (behavior changed), not just "the DOM moved".

Grace McCoy
Mar 04, 2023 · 03:45 AM

We stored derived tags, but only as a normalized array + a revision id.

The UI renders tags from the stored shape so list views are stable, and we can re-derive in the background if parsing rules change.

Jun Park
Mar 07, 2023 · 07:20 AM

Concrete alternative: don't store derived tags at all, store an evidence token for the parse inputs.

We did parseReceipt = hash(content + parserVersion) and derived tags at render. That reduced invalidation complexity.

Jules Kwon
Mar 09, 2023 · 09:10 AM

That makes sense if you don't need tag stability for search/indexing.

Did you ever see perceptible tag flicker when content changes quickly (typing in editor)?

Jun Park
Mar 10, 2023 · 10:10 AM

A bit. We throttled derivation and rendered an evidence chip like tags:pending during fast edits.

Users preferred "pending" over wrong tags.

Nina Kapoor
Mar 22, 2023 · 02:14 PM

We kept debug panels stateless by making them read only from existing contracts (route state + live state) and never write.

Once debug panels can write, they become admin tools, and you start debugging the debugger.

Arman Qadir
Apr 02, 2023 · 12:00 PM

Linking to the docs helped on our team because the guide uses the same vocabulary.

Related: Testing and Debugging and Patterns Library.

Amina Farouk
Apr 18, 2023 · 06:30 AM

We used small snapshot helpers and kept them boring:

ts
export function assertEvidence(ui: HTMLElement, key: string) {
  if (!ui.querySelector(`[data-evidence~="${key}"]`)) throw new Error(`missing evidence: ${key}`);
}

Even though it's crude, it made our tests align with the guide: assert on evidence, not internals.

Tomas Rivera
May 07, 2023 · 05:55 AM

Short take: snapshot the contract, not the markup.

Dmitri Kline
May 25, 2023 · 08:08 AM

Long-form: the guide's premise works because snippets are inherently textual artifacts with stable identity.

If your snippet id is stable and your editor route doc is stable, snapshot testing stops feeling like fragile UI testing and starts feeling like contract pinning.

The failure mode is letting the editor route doc drift. People add "just one more" derived field, then the snapshot becomes a dump. Keep the doc small and narratable.

Lina Ortega
Jun 08, 2023 · 06:18 PM

We added a render log and made it part of the product story for power users.

It sounds weird, but devs love seeing a small list of what the app decided.

Harper Iqbal
Jun 28, 2023 · 03:20 AM

Our snapshots were versioned. When we changed parsing rules, we bumped the snapshot version and logged it as a tips line:

txt
[tips] snapshotVersion bump from=3 to=4 reason=parser:keywordRules

Without that, it felt like random diffs.

Rowan Pierce
Jul 10, 2023 · 10:40 AM

Concrete alternative: do route-flow tests only, no snapshots.

We tried it, and it was too vague. Snapshots made regressions visible.

Keira Santos
Jul 23, 2023 · 09:09 AM

I agree with the guide that storing derived tags can be good for list stability, but you need invalidation discipline.

We attach tagRev to each snippet and only re-derive tags when the snippet content hash changes.

Salma Qureshi
Aug 12, 2023 · 12:12 PM

We kept debug panels behind a query param and rendered data-debug=1 as evidence.

Evan Brooks
Aug 28, 2023 · 04:04 AM

If you want authenticity: we had a bug where snapshots passed but users still saw stale tags.

The fix was to make the UI print the tag revision in the list. Turns out our tests weren't asserting the right evidence.

Kaitlyn Wells
Sep 12, 2023 · 12:30 PM

We made the editor show parse lane (pending/ok/error) so users could tell if tag derivation was trustworthy.

It reduced bug reports because people stopped assuming tags were final while typing.

Priya Liao
Oct 04, 2023 · 07:07 AM

Small disagreement: I don't like asserting on log lines in tests.

Logs are for humans. Evidence keys are for tests. If you test log lines, you'll freeze your debugging vocabulary.

Rafael Soto
Oct 06, 2023 · 06:06 AM

That's fair. We treat the tips vocabulary as part of the contract (like HTTP status codes).

But I agree you need discipline: logs should be stable, not chatty.

Benji Rios
Oct 22, 2023 · 10:22 PM

The guide's approach feels like it turns debugging into a first-class feature, which is rare.

Even if you don't adopt everything, adopt the idea that the app should narrate itself.

Marisol Vega
Nov 09, 2023 · 09:09 AM

We also used snapshots to onboard new devs. It's a weird but effective tour of the product contract.

You run a route-flow test and read the story like a script.

Theo Bennett
Nov 20, 2023 · 06:18 PM

We ended up storing derived tags because we wanted search to be instantaneous.

If you derive at render, search gets expensive unless you add another cache, which becomes its own system anyway.

Liam Osei
Dec 09, 2023 · 12:12 PM

This guide pairs well with the forum's general bias toward visible contracts.

Even when the patterns are controversial, the consistency makes teams faster.

Anika Sharma
Dec 29, 2023 · 04:55 AM

Takeaway: the moment snapshots feel too noisy, shrink what you're snapshotting until it becomes a contract again.

If your snapshots are a dump, it's not a testing problem, it's a boundary problem.