When to use: Validate component behavior in isolation (props, events, conditional rendering, state transitions) with fast feedback.
- Runs components in a real browser.
- Uses the same assertion and selector style as E2E tests.
- Faster and more focused than full-route tests.
Use framework-specific mount utilities:
- React:
cypress/react - Vue:
cypress/vue - Angular:
cypress/angular
- Assert visible behavior, not internal implementation.
- Keep one behavior per test.
- Stub network calls when the component fetches data.
- Prefer accessible selectors (
findByRole,findByLabelText,findByText).
import { mount } from 'cypress/react';
import { CounterButton } from '../../src/components/CounterButton';
it('increments count on click', () => {
mount(<CounterButton initialCount={0} />);
cy.findByRole('button', { name: /count: 0/i }).click();
cy.findByRole('button', { name: /count: 1/i }).should('be.visible');
});import { mount } from 'cypress/vue';
import CounterButton from '../../src/components/CounterButton.vue';
it('increments count on click', () => {
mount(CounterButton, { props: { initialCount: 0 } });
cy.findByRole('button', { name: /count: 0/i }).click();
cy.findByRole('button', { name: /count: 1/i }).should('be.visible');
});import { mount } from 'cypress/angular';
import { CounterComponent } from '../../src/app/counter/counter.component';
it('increments count on click', () => {
mount(CounterComponent, { componentProperties: { count: 0 } });
cy.findByRole('button', { name: /increment/i }).click();
cy.findByText('1').should('be.visible');
});it('shows validation error and then clears it', () => {
mount(<ProfileForm onSave={cy.stub().as('onSave')} />);
cy.findByRole('button', { name: /save/i }).click();
cy.findByText('Display name is required').should('be.visible');
cy.findByLabelText('Display name').clear().type('Jane Doe');
cy.findByRole('button', { name: /save/i }).click();
cy.get('@onSave').should('have.been.calledOnce');
});it('renders API data in list component', () => {
cy.intercept('GET', '**/api/items', {
statusCode: 200,
body: [{ id: '1', name: 'Item A' }]
}).as('items');
mount(<ItemsList />);
cy.wait('@items');
cy.findByRole('listitem', { name: /item a/i }).should('be.visible');
});Use component screenshots for stable, focused visual checks.
it('captures card visual state', () => {
mount(<PricingCard plan="Pro" price="$29" />);
cy.findByTestId('pricing-card').screenshot('pricing-card-pro');
});- Mounting entire app shell when only one component behavior is under test.
- Asserting CSS class internals instead of user-visible outcomes.
- Reusing mutable global state across component tests.
- Mixing component-level and full E2E concerns in one spec.