Cypress has no built-in cy.mount(): how do you make it available to every component spec?
answer
- Some commands you install yourself
- Look in the component support file
- One adapter package per UI framework
- Registered once, not imported per spec
- The launchpad scaffolds it for you
basics
~10 sCypress ships no cy.mount command. You import mount from a framework adapter - cypress/react, cypress/vue, cypress/angular or cypress/svelte - and register it once with Cypress.Commands.add('mount', mount) in cypress/support/component.js, which loads before every spec.
solid answer
~40 sComponent testing is the one Cypress mode with a command you install yourself. Each framework renders differently, so Cypress publishes one adapter per framework - `cypress/react`, `cypress/vue`, `cypress/angular`, `cypress/svelte` - and each exports a `mount` function. In `cypress/support/component.js` you write `import { mount } from 'cypress/react'` and then `Cypress.Commands.add('mount', mount)`. That file is bundled and evaluated before every component spec, so `cy.mount` is global from then on: a spec for the design system's rating widget just calls `cy.mount(<RatingWidget />)` with no import of its own. Configuring component testing through the Cypress launchpad scaffolds that file with the registration already written. Registering rather than importing `mount` per spec is the documented recommendation, because it also gives you a single place to wrap every component in whatever context the library needs.
code
javascript · 12 lines// cypress/support/component.js
import { mount } from 'cypress/svelte'
Cypress.Commands.add('mount', mount)
// cypress/component/Toast.cy.js
import Toast from '../../src/Toast.svelte'
it('renders the design system toast', () => {
cy.mount(Toast)
cy.get('[data-cy=toast]').should('be.visible')
})go deeper
Be ready to say plainly that cy.mount is not built in, name the adapter package for your framework, and point at cypress/support/component.js as the file that registers it.
Explain why the support file is the right home: it is bundled and evaluated before every component spec, so one Cypress.Commands.add call makes cy.mount global with no per-spec import.
Expect to be asked what your registered mount does beyond calling the adapter, and to justify keeping it thin enough that a spec still reveals what the component depends on.
Own the standard for a whole library: one registration per Cypress project, what a two-framework monorepo therefore costs, and how you migrate every spec when an adapter's entry point changes.
## Why the runner cannot ship one mount Every Cypress command works against a document. `cy.get()` queries what the browser is showing, `.click()` dispatches a real event into it, `.should()` retries until the DOM agrees. Nothing in that model knows what a *component* is. Turning a `RatingWidget` module into DOM is framework work, and the four supported frameworks do it four different ways: React creates a root and renders into it, Angular boots Angular's `TestBed`, Vue goes through Vue Test Utils, Svelte calls Svelte's own `mount`. Rather than guess, Cypress ships one small adapter per framework and asks you to wire up the one your project uses. | Framework | Import path | Renders through | |---|---|---| | React | `cypress/react` | React's `createRoot` and `root.render` | | Vue | `cypress/vue` | Vue Test Utils' `mount` | | Angular | `cypress/angular` | Angular's `TestBed` | | Svelte | `cypress/svelte` | Svelte's own `mount` | All four export a function named `mount` with the same shape - the component first, an options object second - and all four return a Cypress chain. That sameness is why the registration is a one-liner. ## The registration For component testing, `supportFile` defaults to `cypress/support/component.js`. Cypress compiles and bundles that file and evaluates it before every component spec in the run, which makes it the natural home for anything all of them need: ```js // cypress/support/component.js import { mount } from 'cypress/react' Cypress.Commands.add('mount', mount) ``` `Cypress.Commands.add(name, fn)` attaches `name` to the `cy` object for the rest of the run. From that point a spec for the design system's rating widget is ordinary Cypress: ```jsx import RatingWidget from './RatingWidget' describe('<RatingWidget />', () => { it('reports the star the reviewer picked', () => { cy.mount(<RatingWidget />) cy.get('[data-cy=star-4]').click() cy.get('[data-cy=rating-value]').should('have.text', '4') }) }) ``` Notice what is **not** in that spec: no import of `mount`, no render helper, no teardown. Only the component and the same commands an end-to-end spec would use. ## Register once, or import per spec? Importing `mount` straight into a spec and calling it does work. Registering it is still the documented recommendation, for two reasons: - **No per-spec import.** `cy.mount` is global once the support file has run, so two hundred component specs carry no setup import between them. - **One place to grow.** The registered function is yours. Wrapping every component in the library's theme provider, or defaulting an option, becomes an edit in one file rather than two hundred. ## The TypeScript half `Cypress.Commands.add` is a runtime call, so TypeScript has to be told about the new command separately or `cy.mount` is a type error. The scaffolded TypeScript support file merges the declaration in place: ```ts import { mount } from 'cypress/react' declare global { namespace Cypress { interface Chainable { mount: typeof mount } } } Cypress.Commands.add('mount', mount) ``` Typing it as `typeof mount` rather than a hand-written signature keeps the adapter's own props and options checked, and keeps working when the adapter's signature changes. The same block can live in a `cypress.d.ts` at the project root, as long as your `tsconfig.json` includes it. ## What the launchpad writes for you Configuring component testing through the Cypress app detects the framework, fills in the `component` block of the config file, and scaffolds three things: 1. `cypress/support/component.js` - the registration above, plus an import of the shared commands file. 2. `cypress/support/component-index.html` - the page components are rendered into. 3. The `component` section of `cypress.config.js`, including `devServer`. Most teams therefore never type the registration; they meet it the first time they want to change it. Knowing that `cy.mount` is *just* a custom command is what makes that change unintimidating. ## When the wiring is wrong - **`cy.mount is not a function`** - the registration never ran. Usually it was put in the end-to-end support file, or `supportFile` is set to `false`. - **The adapter import path does not match the framework** - importing `mount` from `cypress/vue` in a React project fails at bundle time, not at assert time. - **As of Cypress 16, the four adapters above are the complete official set.** The separate `cypress/angular-zoneless` entry point was merged into `cypress/angular` in that release and is no longer shipped with the binary, so an Angular project upgraded from an older major must change that import to `cypress/angular`.
- Can you skip the registration and import mount directly in a spec?Yes, and it runs. You lose the two things registration buys: `cy.mount` available in every spec with no import, and a single place to change how every component is mounted. The Cypress docs recommend registering for exactly that reason, and the launchpad scaffolds it that way.
- What does the TypeScript registration need that the JavaScript one does not?A declaration merge. `Cypress.Commands.add` is a runtime call, so the `Chainable` interface has to learn about `mount` separately - `declare global { namespace Cypress { interface Chainable { mount: typeof mount } } }` - in the support file or in a `cypress.d.ts` that your `tsconfig.json` includes.
saying these in an interview costs you the question
- Says cy.mount is a built-in Cypress command like cy.get
- Imports mount into every spec instead of registering it once
- Cannot name which package the framework adapter comes from
- Puts the registration in the end-to-end support file instead