In Cypress, how much should the single registered cy.mount for a design system wrap?
answer
- One registration serves every spec
- Convenience against honesty about dependencies
- What every component truly cannot render without
- Where the exceptions should live instead
- Failure messages get vaguer as it grows
basics
~20 sWrap only what every component genuinely needs to render at all, and let the rest be opted into per spec. A fat shared mount removes boilerplate but hides each component's real dependencies and lets components pass against context production never supplies.
solid answer
~50 sThere is one `cy.mount` per Cypress project, registered in `cypress/support/component.js`, and every spec silently inherits whatever it does. That makes the depth of the wrapper a standard, not a preference. My rule is that the shared mount supplies only what a component cannot render without - typically the design system's own theme or token provider - and nothing else. Routing, a data client, feature flags and locale go in at the call site of the specs that need them, because `cy.mount` takes the same arguments the adapter does and a spec can mount an already-wrapped component. The cost of getting this wrong is asymmetric: a thin mount costs a few repeated lines in a minority of specs, while a fat one lets a `DataGrid` pass in a context production does not provide, and makes the whole suite's failures point at the wrapper rather than the component.
go deeper
Know that the registered mount can wrap a component in providers before rendering it, and that every spec in the project silently gets whatever it does.
Explain the tradeoff concretely: a shared wrapper removes repetition but also removes the evidence a spec would otherwise give about what the component depends on.
Bring a position you have defended in review, with the failure it prevented - a component that only passed because the shared mount supplied something production did not.
Own the standard and its migration: how the shared mount may grow, who reviews changes to it, and how you re-derive the baseline when one library becomes two.
## Why the depth is a decision and not a detail A Cypress project registers `cy.mount` once. Two hundred component specs call it, none of them import it, and none of them shows what it does. That is the whole appeal - and the whole risk. Every line you add to the registered function is a line that runs before every test in the library, invisibly, for the lifetime of the suite. So the question is not "can I wrap components here" - the documentation explicitly says you can, and that is one of the reasons registration is recommended over importing `mount` per spec. The question is how much a shared, invisible, universally applied wrapper is allowed to do before it stops being helpful. ## The case for wrapping more - **Boilerplate collapses.** A `DataGrid` spec that needs a theme, a locale and a query client repeats six lines in every test until they move into the shared mount. - **Consistency by construction.** Nobody forgets the provider, so nobody debugs a null-context crash that has nothing to do with the component. - **One place to migrate.** When the design system's theme provider changes shape, the change is one file rather than a codemod across the suite. ## The case for wrapping less - **The spec stops describing the component.** Reading a `RatingWidget` spec should tell you what the widget needs. If the answer lives in a support file, the test has lost half its documentary value. - **Components pass for the wrong reason.** A component that reads from a context it never declares still works in every test, because the wrapper always supplies it - and then breaks in an application that does not. - **Failures get vaguer.** When every test mounts through a five-provider stack, a failure inside the stack fails two hundred specs identically and points at none of them. - **The wrapper accretes.** Nobody ever proposes making the shared mount fatter; they propose adding one small thing, thirty times. ## A workable standard 1. **The shared mount supplies only what no component can render without.** In a design system that is usually the theme or token provider and nothing else - if a component crashes without it, it belongs here. 2. **Everything conditional is opted into at the call site.** `cy.mount` takes whatever the adapter takes, so a spec that needs a router or a data client mounts the component already wrapped in it. Three specs paying five lines is cheaper than two hundred specs paying invisibility. 3. **A second wrapper is a named helper, not a second global.** If eight `DataGrid` specs need the same three providers, export a small function from a test helper and let those eight specs call it. It is opt-in, it is greppable, and it is deletable. 4. **Changes to the shared mount are reviewed as API changes.** They affect every test in the library and every future one; treat a pull request that touches it the way you would treat one that touches the design system's public exports. 5. **Re-derive the baseline when the library splits.** The moment the package becomes two packages with two Cypress projects, the shared mount is duplicated - and that is the cheapest time to notice which half of it was never needed. ## What to watch instead of arguing Two signals settle this argument better than opinion: | Signal | What it tells you | |---|---| | A component shipped broken while its tests were green | The wrapper supplied something the application does not | | A new engineer cannot say what a component needs from its spec | The wrapper has absorbed the component's contract | | One change to the support file turns the whole suite red | The wrapper is doing work that belongs in specs | | Specs repeat the same six setup lines many times over | The baseline is genuinely too thin - move that piece up | The last row matters: this is a tradeoff with a real cost on both sides, and a dogmatically empty shared mount is its own failure mode. The standard is not "wrap nothing"; it is "wrap what is universal, name what is shared, and inline what is local". ## The position to defend State it as a rule with a reason. The shared `cy.mount` is the design system's floor, not its ceiling: it makes components renderable, and it never makes them work. Anything that makes a component *work* - data, routing, flags, identity - belongs where a reader can see it, because the moment that context is invisible, the suite has stopped proving the component can survive outside the harness.
- What is a concrete symptom that the shared cy.mount is doing too much?A component ships broken while its tests were green, because every spec passed against context the wrapper supplied and the application does not - a theme token, a feature flag, a client with different defaults. The quieter symptom is that nobody can read a spec and say what the component actually requires.
- How do three specs opt into extra context without growing the shared mount?They wrap at the call site. `cy.mount` accepts whatever the framework adapter accepts, so those specs mount the component already inside the provider they need, or call a small named helper exported from a test-utils module. The shared registration stays the baseline, and the exception stays visible in the spec that has it.
saying these in an interview costs you the question
- Wraps every component in every provider and calls it convenient
- Refuses any shared setup, so each spec repeats twenty lines
- Thinks a fat shared mount makes component tests more realistic
- Cannot say what breaks when the shared mount changes