Back in 2017, Paul Hammant argued — in UI Component Testing — for something that’s since become mainstream: stop driving whole pages through Selenium for everything. Test the smallest rectangle you reasonably can — the control — in a throwaway harness that never ships to production, cut off from the slow down-stack, fast enough to run whole tests by the second. Storybook, Cypress Component Testing and Playwright Component Testing all landed in that frame in the years after. (He revisited the idea in 2025.)
Every component test has to decide one thing: where to cut the down-stack. There are two seams.
mutate(...). Fast and low, but it bypasses the control’s real wire behaviour.The demo lives in the monorepo at integration/vue-storybook. There are two small Vue controls, and for each one the same source component is:
One component, two consumers — no parallel widget, no doubled test. And in both cases the mock backend is a Servirtium VCR: it serves the built page from its own static-content mount, so the control’s request is same-origin (no CORS, no preflight) and lands straight on the VCR — which either records it (forwarding once to a throwaway upstream) or replays it from a committed Markdown tape. Record vs playback is just which script you run.
PostForm.vue is the minimal case — a “Leave a message” field and a Post button. Submitting fires a POST /api/messages and the control renders the server’s reply: Created #1: “hello from servirtium” (created). One request, one response, round-tripped through a tape.
fetch with the same response shape the tape carries, so the control is live in Storybook too.tapes/post.md — a single interaction; the POST body and the JSON reply sit right there in the Markdown, diffable in a pull request.This is the “is a POST even mockable at the HTTP seam?” proof, and the answer is yes: the control runs disconnected from any backend, the test is offline and deterministic, and it’s fast — exactly the 2017 brief, with the down-stack cut at the network rather than the model.
The second control makes a sharper point: the backend is the source of truth, and the UI renders only what the server says — never an optimistic local flip. It’s the old engineering joke as three checkboxes over a Venn diagram. Every toggle is a POST; pick two and the server names the pair (Slow / Expensive / Low Quality); reach for a third and the server evicts the oldest — you watch a ticked box pop back off. The control can’t hold all three because the backend won’t let it.
tapes/triple-pick-two.md — three interactions, the last one dropping good so cheap+fast win.Because the eviction is the server’s decision, recorded and replayed, the control’s unchecking behaviour is tested for free: the same Markdown tape that drives the green ticks also drives a box back to empty. A model-seam test that shoved state straight into the component would never have exercised that round-trip.
Cutting at the HTTP seam costs you a real request that the model seam skips. In return you exercise the control’s actual wire behaviour — the POST body it builds, the headers it sends, the response it parses — against a conversation that was once a real backend. And because the recording is Markdown:
None of that is new in spirit; it’s the 2017 component-testing argument with the boundary moved to where a lot of real flakiness actually lives — the network — and a recording format built for being read, reviewed and shared. Which is the job Servirtium was made for.
Credits: © 2019 Servirtium committers.
Jekyll theme by Jalpc by Jarrekk.
Hosting by Netlify