---
name: vue-development
description: Vue 3 and Nuxt 3 development with TDD workflow, QA gates, and E2E test generation. Enforces unit testing before implementation, generates Playwright E2E tests from Gherkin acceptance criteria, and produces JSON reports.
---
# Vue Development Skill
This skill guides development of Vue 3 and Nuxt 3 applications using a **test-driven development** approach with **quality assurance gates** and **E2E test generation from acceptance criteria**.
## When This Skill Activates
Use this skill when:
- Creating or modifying `.vue` files
- Writing composables (`use*.ts`)
- Working with Nuxt-specific files (`pages/`, `layouts/`, `middleware/`, `composables/`)
- User mentions Vue, Nuxt, or component development
- Building reactive UI components
- **Implementing user stories with Gherkin acceptance criteria**
## Core Workflow: TDD + QA + E2E
**ALWAYS follow this workflow:**
```
1. UNDERSTAND → Parse user story + Gherkin acceptance criteria
2. TEST FIRST → Write failing unit tests (Vitest + Vue Test Utils)
3. IMPLEMENT → Write minimal code to pass tests
4. REFACTOR → Clean up while keeping tests green
5. QA CHECK → Validate against Vue checklist (see qa/vue-checklist.md)
6. E2E WRITE → Generate Playwright test files from Gherkin AC
7. E2E RUN → Execute tests and verify all AC pass
8. REPORT → Generate JSON report with E2E results
```
---
## Input: User Story Format
This skill accepts user stories with Gherkin acceptance criteria:
````markdown
## US-001: {Story Title}
> **As a** {persona},
> **I want** {goal},
> **So that** {benefit}.
### Acceptance Criteria
#### AC1: {Happy Path}
```gherkin
Given {precondition}
When {action}
Then {expected result}
```
````
#### AC2: {Error Scenario}
```gherkin
Given {precondition}
When {invalid action}
Then {error handling}
```
````
**See:** `e2e/acceptance-criteria.md` for detailed parsing guide.
## Step-by-Step Instructions
### Step 1: Understand Requirements
Before writing any code:
- **Parse the user story** to understand persona, goal, and benefit
- **Extract acceptance criteria** (Gherkin Given/When/Then)
- Identify props, emits, and slots needed
- Determine reactive state requirements
- Map acceptance criteria to testable behaviors
### Step 2: Write Tests First
**Create test file BEFORE implementation:**
```typescript
// src/components/__tests__/MyComponent.spec.ts
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import MyComponent from '../MyComponent.vue'
describe('MyComponent', () => {
it('renders with default props', () => {
const wrapper = mount(MyComponent)
expect(wrapper.exists()).toBe(true)
})
it('displays label prop correctly', () => {
const wrapper = mount(MyComponent, {
props: { label: 'Click me' }
})
expect(wrapper.text()).toContain('Click me')
})
it('emits click event when clicked', async () => {
const wrapper = mount(MyComponent)
await wrapper.trigger('click')
expect(wrapper.emitted('click')).toBeTruthy()
})
})
````
**Run tests to confirm they fail:**
```bash
npm run test -- MyComponent.spec.ts
```
### Step 3: Implement Component
Write the **minimal code** to make tests pass:
```vue
```
### Step 4: Verify Tests Pass
```bash
npm run test -- MyComponent.spec.ts
```
All tests must be green before proceeding.
### Step 5: QA Validation
Go through the **Vue QA Checklist** (see `qa/vue-checklist.md`):
- [ ] Props typed with TypeScript
- [ ] Emits typed with `defineEmits<{...}>()`
- [ ] No `any` types
- [ ] Computed for derived state
- [ ] Single responsibility
- [ ] Tests cover all behaviors
### Step 6: Write E2E Test Files
**Generate Playwright test files from Gherkin acceptance criteria.**
For each user story, create a test file:
**Location:** `tests/e2e/{feature-slug}.spec.ts`
#### Test File Structure
```typescript
// tests/e2e/user-login.spec.ts
import { test, expect } from '@playwright/test';
/**
* US-001: User Login
* As a registered user, I want to login with my credentials,
* so that I can access my account.
*/
test.describe('US-001: User Login', () => {
test('AC1: Successful login', async ({ page }) => {
// Given I am on the login page
await page.goto('/login');
// When I fill "email" with "user@example.com"
await page.fill('[name="email"]', 'user@example.com');
// And I fill "password" with "password123"
await page.fill('[name="password"]', 'password123');
// And I click "Login"
await page.click('button:has-text("Login")');
// Then I am redirected to the dashboard
await expect(page).toHaveURL(/dashboard/);
// And I see "Welcome back"
await expect(page.locator('text=Welcome back')).toBeVisible();
});
test('AC2: Invalid password', async ({ page }) => {
// Given I am on the login page
await page.goto('/login');
// When I fill "email" with "user@example.com"
await page.fill('[name="email"]', 'user@example.com');
// And I fill "password" with "wrong"
await page.fill('[name="password"]', 'wrong');
// And I click "Login"
await page.click('button:has-text("Login")');
// Then I see "Invalid credentials"
await expect(page.locator('text=Invalid credentials')).toBeVisible();
});
});
```
#### Gherkin to Playwright Mapping
| Gherkin | Playwright Code |
| ----------------------------------------- | ----------------------------------------------------------- |
| `Given I am on "{url}"` | `await page.goto('{url}')` |
| `When I click "{text}"` | `await page.click('text={text}')` |
| `When I click the "{selector}" button` | `await page.click('{selector}')` |
| `When I fill "{field}" with "{value}"` | `await page.fill('[name="{field}"]', '{value}')` |
| `When I select "{option}" from "{field}"` | `await page.selectOption('[name="{field}"]', '{option}')` |
| `When I press "{key}"` | `await page.keyboard.press('{key}')` |
| `Then I see "{text}"` | `await expect(page.locator('text={text}')).toBeVisible()` |
| `Then I am redirected to "{url}"` | `await expect(page).toHaveURL(/{url}/)` |
| `Then the "{element}" is visible` | `await expect(page.locator('{element}')).toBeVisible()` |
| `Then the "{element}" is not visible` | `await expect(page.locator('{element}')).not.toBeVisible()` |
#### File Naming Convention
- Story ID in filename: `{story-id}-{feature-slug}.spec.ts`
- Examples:
- `us-001-user-login.spec.ts`
- `us-042-password-reset.spec.ts`
- `us-103-checkout-flow.spec.ts`
**See:** `e2e/playwright-patterns.md` for complete mapping reference.
### Step 7: Run E2E Tests
**Execute the generated Playwright tests to validate acceptance criteria.**
#### Run Tests
```bash
# Run specific test file
npx playwright test tests/e2e/user-login.spec.ts
# Run all E2E tests
npx playwright test tests/e2e/
# Run with UI mode for debugging
npx playwright test tests/e2e/user-login.spec.ts --ui
```
#### Verify Results
All acceptance criteria must pass:
```
Running 2 tests using 1 worker
✓ US-001: User Login › AC1: Successful login (2.1s)
✓ US-001: User Login › AC2: Invalid password (1.8s)
2 passed (4.2s)
```
#### Handle Failures
If tests fail:
1. **Review the error** - Check which AC failed and why
2. **Fix the implementation** - Update component/page code
3. **Re-run tests** - Verify fix works
4. **Do NOT modify the test** unless the AC was wrong
```
If AC fails → Fix implementation, NOT the test
If AC is wrong → Update user story first, then regenerate test
```
### Step 8: Generate Report
**REQUIRED:** Create a JSON report with E2E validation results.
**Location:** `.qa-reports/{uuid}.vue-development-skill.json`
Generate a UUID and write the report:
```json
{
"id": "generated-uuid-here",
"skill": "vue-development",
"timestamp": "2025-12-01T10:30:00Z",
"task_description": "Created MyComponent button with click handling",
"user_story": {
"id": "US-001",
"title": "User Login",
"persona": "registered user",
"goal": "to login with my credentials",
"benefit": "I can access my account"
},
"files": {
"created": ["src/components/MyComponent.vue"],
"modified": [],
"test_files": ["src/components/__tests__/MyComponent.spec.ts"],
"e2e_test_files": ["tests/e2e/us-001-user-login.spec.ts"]
},
"tdd": {
"tests_written_first": true,
"test_command": "npm run test -- MyComponent.spec.ts",
"tests_passing": true,
"coverage_estimate": "high"
},
"qa": {
"score": 9.0,
"status": "PASS",
"checklist": {
"component_quality": { "passed": 5, "total": 5, "issues": [] },
"reactivity": { "passed": 4, "total": 4, "issues": [] },
"composables": { "passed": 0, "total": 0, "issues": ["N/A"] },
"nuxt_specific": {
"passed": 0,
"total": 0,
"issues": ["N/A - plain Vue"]
},
"typescript": { "passed": 4, "total": 4, "issues": [] },
"unit_tests": { "passed": 6, "total": 6, "issues": [] }
}
},
"e2e_validation": {
"test_file": "tests/e2e/us-001-user-login.spec.ts",
"test_command": "npx playwright test tests/e2e/us-001-user-login.spec.ts",
"executed": true,
"acceptance_criteria": [
{
"id": "AC1",
"title": "Successful login",
"gherkin": "Given I am on login page\nWhen I fill credentials\nThen I see dashboard",
"status": "PASS"
},
{
"id": "AC2",
"title": "Invalid password",
"gherkin": "Given I am on login page\nWhen I enter wrong password\nThen I see error",
"status": "PASS"
}
],
"passed": 2,
"failed": 0,
"status": "PASS"
},
"completion": {
"unit_tests": "PASS",
"qa_checklist": "PASS",
"e2e_validation": "PASS",
"overall": "COMPLETE"
}
}
```
## Quality Thresholds
| Score | Status | Action |
| ----- | ---------- | ------------------------- |
| 9-10 | PASS | Ready for E2E validation |
| 7-8 | ACCEPTABLE | Ready, but note issues |
| 0-6 | NEEDS_WORK | Fix issues before handoff |
**Formula:** `score = (checks_passed / total_applicable_checks) × 10`
## File References
- **QA Checklist:** See `qa/vue-checklist.md` for full criteria
- **Report Schema:** See `qa/report-template.json` for JSON structure
- **TDD Guide:** See `tdd/workflow.md` for detailed process
- **Testing Patterns:** See `tdd/testing-patterns.md` for Vitest examples
- **Vue Patterns:** See `patterns/composition-api.md`
- **Nuxt Patterns:** See `patterns/nuxt3.md`
- **TypeScript:** See `patterns/typescript.md`
- **Debugging:** See `debugging/common-issues.md`
- **E2E Patterns:** See `e2e/playwright-patterns.md` for Gherkin-to-Playwright mapping
- **Acceptance Criteria:** See `e2e/acceptance-criteria.md` for parsing user stories
## Important Rules
1. **NEVER skip tests** - Write tests before implementation
2. **NEVER skip E2E validation** - Validate all acceptance criteria with Playwright
3. **NEVER skip the report** - Include E2E results in report
4. **NEVER leave tests failing** - All unit tests AND E2E must pass
5. **ALWAYS use TypeScript** - No JavaScript, no `any`
6. **ALWAYS follow Composition API** - No Options API
7. **ALWAYS validate against Gherkin AC** - If user story provided, all AC must pass