or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

angular-testing.mdcli-integration.mdconfiguration.mdcustom-frameworks.mdindex.mdinteractive-testing.mdprogrammatic-execution.mdreact-testing.mdvue-testing.md
tile.json

vue-testing.mddocs/

Vue Component Testing

Mount and test Vue components with Vue Test Utils integration and Cypress commands. The @cypress/vue package provides seamless integration between Vue components and Cypress's powerful testing capabilities.

Capabilities

Mount Vue Components

Mount Vue components for isolated testing with props, slots, and full Cypress command support.

// From cypress/vue
import { mount } from '@cypress/vue';

/**
 * Mount a Vue component for testing
 * @param component - Vue component to mount
 * @param options - Vue Test Utils mounting options plus Cypress-specific options
 * @returns Cypress chainable with wrapper and component access
 */
function mount<T>(
  component: T,
  options?: VueMountOptions<T>
): Cypress.Chainable<VueMountReturn<T>>;

interface VueMountOptions<T> {
  /** Props to pass to the component */
  props?: Record<string, any>;
  /** Slots content */
  slots?: Record<string, any>;
  /** Global configuration */
  global?: {
    plugins?: any[];
    components?: Record<string, any>;
    directives?: Record<string, any>;
    mixins?: any[];
    provide?: Record<string, any>;
    config?: {
      globalProperties?: Record<string, any>;
      errorHandler?: (err: Error) => void;
    };
  };
  /** Whether to log the mount command */
  log?: boolean;
}

interface VueMountReturn<T> {
  /** Vue Test Utils wrapper for advanced interactions */
  wrapper: VueWrapper<ComponentPublicInstance>;
  /** Direct access to the component instance */
  component: ComponentPublicInstance;
}

Usage Examples:

// cypress/component/Button.cy.js
import { mount } from '@cypress/vue';
import Button from './Button.vue';

describe('Button Component', () => {
  it('renders with text', () => {
    mount(Button, {
      slots: {
        default: 'Click me'
      }
    });
    
    cy.contains('Click me').should('be.visible');
  });

  it('emits click events', () => {
    const onClickSpy = cy.stub();
    
    mount(Button, {
      props: {
        onClick: onClickSpy
      },
      slots: {
        default: 'Click me'
      }
    });
    
    cy.contains('Click me').click();
    cy.wrap(onClickSpy).should('have.been.called');
  });

  it('supports different variants', () => {
    mount(Button, {
      props: {
        variant: 'primary'
      },
      slots: {
        default: 'Primary Button'
      }
    });
    
    cy.get('button').should('have.class', 'btn-primary');
  });
});

Mount with Props and Reactive Data

Test components with props and watch for reactive updates.

// Testing reactive props
describe('Counter Component', () => {
  it('displays initial count', () => {
    mount(Counter, {
      props: {
        initialCount: 5
      }
    });
    
    cy.get('[data-cy=count]').should('contain', '5');
  });

  it('updates when props change', () => {
    mount(Counter, {
      props: {
        initialCount: 0
      }
    }).then(({ wrapper }) => {
      cy.get('[data-cy=count]').should('contain', '0');
      
      // Update props programmatically
      wrapper.setProps({ initialCount: 10 });
      cy.get('[data-cy=count]').should('contain', '10');
    });
  });

  it('handles user interactions', () => {
    mount(Counter, {
      props: {
        initialCount: 0
      }
    });
    
    cy.get('[data-cy=increment]').click();
    cy.get('[data-cy=count]').should('contain', '1');
    
    cy.get('[data-cy=decrement]').click();
    cy.get('[data-cy=count]').should('contain', '0');
  });
});

Mount with Slots

Test components that use Vue slots for content projection.

import { mount } from '@cypress/vue';
import Card from './Card.vue';

describe('Card Component', () => {
  it('renders default slot content', () => {
    mount(Card, {
      slots: {
        default: '<p>Card content</p>'
      }
    });
    
    cy.contains('Card content').should('be.visible');
  });

  it('renders named slots', () => {
    mount(Card, {
      slots: {
        header: '<h2>Card Title</h2>',
        default: '<p>Card body content</p>',
        footer: '<button>Action</button>'
      }
    });
    
    cy.contains('Card Title').should('be.visible');
    cy.contains('Card body content').should('be.visible');
    cy.contains('Action').should('be.visible');
  });

  it('renders scoped slots', () => {
    mount(Card, {
      slots: {
        default: `
          <template #default="{ user }">
            <p>Hello, {{ user.name }}!</p>
          </template>
        `
      },
      props: {
        user: { name: 'John Doe' }
      }
    });
    
    cy.contains('Hello, John Doe!').should('be.visible');
  });
});

Mount with Vue Plugins

Test components that depend on Vue plugins like Vue Router or Vuex/Pinia.

import { mount } from '@cypress/vue';
import { createRouter, createWebHistory } from 'vue-router';
import Navigation from './Navigation.vue';

describe('Navigation Component', () => {
  const routes = [
    { path: '/', component: { template: '<div>Home</div>' } },
    { path: '/about', component: { template: '<div>About</div>' } },
    { path: '/contact', component: { template: '<div>Contact</div>' } }
  ];

  it('highlights active route', () => {
    const router = createRouter({
      history: createWebHistory(),
      routes
    });

    mount(Navigation, {
      global: {
        plugins: [router]
      }
    });
    
    cy.get('[data-cy=nav-home]').should('have.class', 'router-link-active');
  });

  it('navigates to different routes', () => {
    const router = createRouter({
      history: createWebHistory(),
      routes
    });

    mount(Navigation, {
      global: {
        plugins: [router]
      }
    });
    
    cy.get('[data-cy=nav-about]').click();
    cy.location('pathname').should('eq', '/about');
  });
});

Mount with Pinia Store

Test components that use Pinia for state management.

import { mount } from '@cypress/vue';
import { createPinia, setActivePinia } from 'pinia';
import { useUserStore } from './stores/user';
import UserProfile from './UserProfile.vue';

describe('UserProfile Component', () => {
  beforeEach(() => {
    setActivePinia(createPinia());
  });

  it('displays user information from store', () => {
    const pinia = createPinia();
    
    mount(UserProfile, {
      global: {
        plugins: [pinia]
      }
    }).then(() => {
      // Access store and set user data
      const userStore = useUserStore();
      userStore.setUser({
        name: 'Jane Doe',
        email: 'jane@example.com'
      });
      
      cy.contains('Jane Doe').should('be.visible');
      cy.contains('jane@example.com').should('be.visible');
    });
  });

  it('updates when store state changes', () => {
    const pinia = createPinia();
    
    mount(UserProfile, {
      global: {
        plugins: [pinia]
      }
    }).then(() => {
      const userStore = useUserStore();
      
      // Initial state
      userStore.setUser({ name: 'John', email: 'john@example.com' });
      cy.contains('John').should('be.visible');
      
      // Update state
      userStore.updateName('Johnny');
      cy.contains('Johnny').should('be.visible');
    });
  });
});

Mount with Global Components and Directives

Test components that depend on globally registered components or directives.

import { mount } from '@cypress/vue';
import MyComponent from './MyComponent.vue';
import GlobalButton from './GlobalButton.vue';

describe('MyComponent', () => {
  it('uses global components', () => {
    mount(MyComponent, {
      global: {
        components: {
          'global-button': GlobalButton
        }
      }
    });
    
    cy.get('global-button').should('exist');
  });

  it('uses custom directives', () => {
    const focusDirective = {
      mounted(el) {
        el.focus();
      }
    };

    mount(MyComponent, {
      global: {
        directives: {
          focus: focusDirective
        }
      }
    });
    
    cy.get('[data-cy=input-with-focus]').should('be.focused');
  });
});

Testing Composition API

Test components that use Vue 3's Composition API.

import { mount } from '@cypress/vue';
import CompositionComponent from './CompositionComponent.vue';

describe('CompositionComponent', () => {
  it('handles reactive refs', () => {
    mount(CompositionComponent);
    
    cy.get('[data-cy=counter]').should('contain', '0');
    cy.get('[data-cy=increment]').click();
    cy.get('[data-cy=counter]').should('contain', '1');
  });

  it('handles computed properties', () => {
    mount(CompositionComponent, {
      props: {
        items: ['apple', 'banana', 'cherry']
      }
    });
    
    cy.get('[data-cy=item-count]').should('contain', '3');
    cy.get('[data-cy=first-item]').should('contain', 'apple');
  });

  it('handles watchers', () => {
    mount(CompositionComponent);
    
    cy.get('[data-cy=search-input]').type('test');
    cy.get('[data-cy=search-results]').should('contain', 'Searching for: test');
  });
});

Vue Test Utils Integration

Access Vue Test Utils functionality through the wrapper returned by mount.

// Re-exported Vue Test Utils (excluding mount and shallowMount)
import { VueTestUtils } from '@cypress/vue';

// Available Vue Test Utils methods:
interface VueWrapper {
  /** Find component by selector */
  find(selector: string): DOMWrapper;
  /** Find component by component definition */
  findComponent(component: any): VueWrapper;
  /** Find all matching elements */
  findAll(selector: string): DOMWrapper[];
  /** Set component props */
  setProps(props: Record<string, any>): Promise<void>;
  /** Set component data */
  setData(data: Record<string, any>): Promise<void>;
  /** Trigger an event */
  trigger(event: string, options?: any): Promise<void>;
  /** Get component's emitted events */
  emitted(): Record<string, any[]>;
  /** Check if component exists */
  exists(): boolean;
  /** Get component HTML */
  html(): string;
  /** Get component text */
  text(): string;
  /** Unmount the component */
  unmount(): void;
}

Advanced Testing with Vue Test Utils:

describe('Advanced Component Testing', () => {
  it('uses wrapper methods for detailed testing', () => {
    mount(ComplexComponent, {
      props: {
        items: ['item1', 'item2', 'item3']
      }
    }).then(({ wrapper }) => {
      // Use Vue Test Utils methods
      expect(wrapper.findAll('[data-cy=item]')).to.have.length(3);
      
      // Check emitted events
      wrapper.find('[data-cy=delete-button]').trigger('click');
      expect(wrapper.emitted()).to.have.property('delete');
      
      // Update props and verify changes
      wrapper.setProps({ items: ['item1', 'item2'] });
      cy.get('[data-cy=item]').should('have.length', 2);
    });
  });
});

Component Testing Configuration

Configure Vue component testing in your Cypress configuration:

// cypress.config.js
const { defineConfig } = require('cypress');

module.exports = defineConfig({
  component: {
    devServer: {
      framework: 'vue',
      bundler: 'vite', // or 'webpack'
    },
    specPattern: 'src/**/*.cy.{js,ts}',
    supportFile: 'cypress/support/component.js'
  }
});

Custom Component Commands

Create custom commands for Vue-specific testing patterns:

// cypress/support/component.js
import { mount } from '@cypress/vue';

Cypress.Commands.add('mountVue', (component, options = {}) => {
  // Add default global configuration
  const defaultOptions = {
    global: {
      stubs: {
        // Stub router-link by default
        'router-link': true
      }
    }
  };
  
  const mergedOptions = { ...defaultOptions, ...options };
  return mount(component, mergedOptions);
});

// Usage in tests
cy.mountVue(MyComponent, {
  props: { title: 'Test Title' }
});

The Vue component testing integration provides comprehensive support for testing Vue.js components in isolation while maintaining access to Vue's reactive system, component lifecycle, and ecosystem tools.