home / skills / pluginagentmarketplace / custom-plugin-vue / vue-testing

vue-testing skill

/skills/vue-testing

This skill helps you master Vue testing with Vitest, Vue Test Utils, and Playwright to deliver reliable unit, component, and e2e tests.

npx playbooks add skill pluginagentmarketplace/custom-plugin-vue --skill vue-testing

Review the files below or copy the command above to add this skill to your agents.

Files (6)
SKILL.md
6.7 KB
---
name: vue-testing
description: Master Vue Testing - Vitest, Vue Test Utils, Component Testing, E2E with Playwright
sasmp_version: "1.3.0"
bonded_agent: 06-vue-testing
bond_type: PRIMARY_BOND
version: "2.0.0"
last_updated: "2025-01"
---

# Vue Testing Skill

Production-grade skill for mastering Vue application testing with Vitest, Vue Test Utils, and Playwright.

## Purpose

**Single Responsibility:** Teach comprehensive testing strategies for Vue applications including unit, component, integration, and E2E testing.

## Parameter Schema

```typescript
interface VueTestingParams {
  topic: 'unit' | 'component' | 'integration' | 'e2e' | 'mocking' | 'all';
  level: 'beginner' | 'intermediate' | 'advanced';
  context?: {
    test_runner?: 'vitest' | 'jest';
    e2e_tool?: 'playwright' | 'cypress';
    coverage_target?: number;
  };
}
```

## Learning Modules

### Module 1: Testing Fundamentals
```
Prerequisites: vue-fundamentals
Duration: 2 hours
Outcome: Set up testing environment
```

| Topic | Tool | Exercise |
|-------|------|----------|
| Setup | Vitest + VTU | Configure project |
| Test structure | describe/it/expect | First test |
| Assertions | expect matchers | Various assertions |
| Test naming | Descriptive names | Convention practice |

**Vitest Configuration:**
```typescript
// vitest.config.ts
export default defineConfig({
  plugins: [vue()],
  test: {
    globals: true,
    environment: 'jsdom',
    coverage: {
      provider: 'v8',
      thresholds: { lines: 80 }
    }
  }
})
```

### Module 2: Component Testing
```
Prerequisites: Module 1
Duration: 4-5 hours
Outcome: Test Vue components thoroughly
```

| Test Type | What to Test | Example |
|-----------|--------------|---------|
| Rendering | DOM output | Text content |
| Props | Input handling | Prop values |
| Events | Emitted events | Button clicks |
| Slots | Slot content | Custom content |
| Async | Loading states | API responses |

**Component Test Template:**
```typescript
import { mount } from '@vue/test-utils'
import MyComponent from './MyComponent.vue'

describe('MyComponent', () => {
  it('renders correctly', () => {
    const wrapper = mount(MyComponent, {
      props: { title: 'Test' }
    })
    expect(wrapper.text()).toContain('Test')
  })

  it('emits event on click', async () => {
    const wrapper = mount(MyComponent)
    await wrapper.find('button').trigger('click')
    expect(wrapper.emitted('action')).toHaveLength(1)
  })
})
```

### Module 3: Mocking Strategies
```
Prerequisites: Module 2
Duration: 3 hours
Outcome: Mock dependencies effectively
```

| Mock Type | Use Case | Example |
|-----------|----------|---------|
| Modules | API services | vi.mock() |
| Composables | Custom hooks | Return mocks |
| Timers | Debounce/setTimeout | vi.useFakeTimers() |
| HTTP | API calls | MSW or vi.mock |
| Router | Navigation | Mock router |
| Store | Pinia stores | createTestingPinia |

### Module 4: Testing Composables & Stores
```
Prerequisites: Module 3
Duration: 3 hours
Outcome: Test reusable logic
```

**Composable Testing:**
```typescript
import { useCounter } from './useCounter'

it('increments count', () => {
  const { count, increment } = useCounter()
  increment()
  expect(count.value).toBe(1)
})
```

**Store Testing:**
```typescript
import { setActivePinia, createPinia } from 'pinia'
import { useUserStore } from './useUserStore'

beforeEach(() => setActivePinia(createPinia()))

it('logs in user', async () => {
  const store = useUserStore()
  await store.login(credentials)
  expect(store.isLoggedIn).toBe(true)
})
```

### Module 5: E2E Testing with Playwright
```
Prerequisites: Modules 1-4
Duration: 4 hours
Outcome: Write reliable E2E tests
```

| Concept | Playwright API | Exercise |
|---------|----------------|----------|
| Navigation | page.goto() | Page visits |
| Selectors | getByRole() | Element selection |
| Actions | click(), fill() | User interactions |
| Assertions | expect().toBeVisible() | Verify state |
| Fixtures | test.use() | Reusable setup |

**Playwright Test:**
```typescript
import { test, expect } from '@playwright/test'

test.describe('Login', () => {
  test('logs in successfully', async ({ page }) => {
    await page.goto('/login')
    await page.getByLabel('Email').fill('[email protected]')
    await page.getByLabel('Password').fill('password')
    await page.getByRole('button', { name: 'Submit' }).click()

    await expect(page).toHaveURL('/dashboard')
    await expect(page.getByText('Welcome')).toBeVisible()
  })
})
```

## Validation Checkpoints

### Beginner Checkpoint
- [ ] Set up Vitest with Vue
- [ ] Write basic component test
- [ ] Test props and events
- [ ] Run tests with coverage

### Intermediate Checkpoint
- [ ] Mock API calls
- [ ] Test async components
- [ ] Test composables
- [ ] Test Pinia stores

### Advanced Checkpoint
- [ ] Write E2E tests with Playwright
- [ ] Achieve 80%+ coverage
- [ ] Test edge cases
- [ ] Set up CI testing

## Retry Logic

```typescript
const skillConfig = {
  maxAttempts: 3,
  backoffMs: [1000, 2000, 4000],
  onFailure: 'provide_test_hint'
}
```

## Observability

```yaml
tracking:
  - event: test_written
    data: [test_type, component_name]
  - event: coverage_achieved
    data: [percentage, file_count]
  - event: skill_completed
    data: [tests_written, coverage]
```

## Troubleshooting

### Common Issues

| Issue | Cause | Solution |
|-------|-------|----------|
| wrapper.vm undefined | shallowMount used | Use mount() |
| Mock not working | Wrong vi.mock path | Match import path |
| Async not resolved | Missing await | Await async ops |
| Flaky E2E | Race conditions | Add proper waits |

### Debug Steps

1. Check test isolation (beforeEach cleanup)
2. Verify mock is at file top
3. Console.log wrapper.html()
4. Use Playwright trace viewer

## Unit Test Template

```typescript
import { describe, it, expect, beforeEach, vi } from 'vitest'
import { mount, VueWrapper } from '@vue/test-utils'
import Component from './Component.vue'

describe('Component', () => {
  let wrapper: VueWrapper

  beforeEach(() => {
    wrapper = mount(Component, {
      props: {},
      global: {
        stubs: {},
        mocks: {},
        plugins: []
      }
    })
  })

  it('renders correctly', () => {
    expect(wrapper.exists()).toBe(true)
  })

  it('handles user interaction', async () => {
    await wrapper.find('button').trigger('click')
    expect(wrapper.emitted('action')).toBeTruthy()
  })
})
```

## Usage

```
Skill("vue-testing")
```

## Related Skills

- `vue-fundamentals` - Prerequisite
- `vue-composition-api` - For composable testing
- `vue-pinia` - For store testing

## Resources

- [Vitest Documentation](https://vitest.dev/)
- [Vue Test Utils](https://test-utils.vuejs.org/)
- [Playwright](https://playwright.dev/)
- [Testing Library](https://testing-library.com/docs/vue-testing-library/intro/)

Overview

This skill teaches production-grade testing for Vue applications using Vitest, Vue Test Utils, and Playwright. It covers unit, component, integration, and end-to-end strategies, plus effective mocking and store/composable testing. Outcomes include a repeatable test setup, reliable component tests, and stable E2E suites.

How this skill works

The skill guides you through progressive modules: environment setup with Vitest, component testing with Vue Test Utils, mocking strategies, composable and Pinia store testing, and Playwright E2E scenarios. It provides templates, configuration snippets, validation checkpoints, retry logic, and troubleshooting steps to turn learning into production-ready tests. Practical examples show mounting, event emission, mocking, and full-page flows.

When to use it

  • When establishing a Vue test environment and coverage targets
  • When writing or reviewing component tests and test structure
  • When mocking APIs, composables, timers, or stores for reliable unit tests
  • When validating business flows with Playwright E2E tests
  • When improving test reliability and reducing flakiness in CI

Best practices

  • Use mount() for full DOM behavior; shallowMount only when isolating child components
  • Centralize mocks at the top of test files (vi.mock) and prefer MSW for HTTP mocking
  • Set Vitest globals and jsdom environment for consistent DOM tests
  • Isolate tests with beforeEach cleanup and setActivePinia(createPinia()) for store tests
  • Add explicit awaits for async behavior and use Playwright fixtures for reusable setup

Example use cases

  • Set up Vitest with Vue, run initial component tests and enforce 80% coverage threshold
  • Test a button component: render text, assert props, trigger click, verify emitted event
  • Mock an API service and test async loading/error states in a component
  • Unit-test a composable: call functions and assert reactive values change
  • Write Playwright E2E for login flow: fill fields, submit, assert navigation to dashboard

FAQ

What test runner should I choose?

Vitest is recommended for speed and native Vite integration; Jest can be used if your project already depends on it.

How do I avoid flaky E2E tests?

Use stable selectors, add explicit waits for network or UI readiness, enable Playwright tracing, and isolate test state with fixtures.