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.
Inherits all available tools
Additional assets for this skill
This skill inherits all available tools. When active, it can use any tool Claude has access to.
debugging/common-issues.mde2e/acceptance-criteria.mde2e/playwright-patterns.mdpatterns/composition-api.mdpatterns/nuxt3.mdpatterns/typescript.mdqa/report-template.jsonqa/vue-checklist.mdtdd/testing-patterns.mdtdd/workflow.mdThis 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.
Use this skill when:
.vue filesuse*.ts)pages/, layouts/, middleware/, composables/)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
This skill accepts user stories with Gherkin acceptance criteria:
## 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}
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:
npm run test -- MyComponent.spec.ts
Write the minimal code to make tests pass:
<script setup lang="ts">
interface Props {
label?: string
}
const props = withDefaults(defineProps<Props>(), {
label: 'Button'
})
const emit = defineEmits<{
click: []
}>()
function handleClick() {
emit('click')
}
</script>
<template>
<button @click="handleClick">
{{ label }}
</button>
</template>
npm run test -- MyComponent.spec.ts
All tests must be green before proceeding.
Go through the Vue QA Checklist (see qa/vue-checklist.md):
defineEmits<{...}>()any typesGenerate Playwright test files from Gherkin acceptance criteria.
For each user story, create a test file:
Location: tests/e2e/{feature-slug}.spec.ts
// 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 | 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() |
{story-id}-{feature-slug}.spec.tsus-001-user-login.spec.tsus-042-password-reset.spec.tsus-103-checkout-flow.spec.tsSee: e2e/playwright-patterns.md for complete mapping reference.
Execute the generated Playwright tests to validate acceptance criteria.
# 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
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)
If tests fail:
If AC fails → Fix implementation, NOT the test
If AC is wrong → Update user story first, then regenerate test
REQUIRED: Create a JSON report with E2E validation results.
Location: .qa-reports/{uuid}.vue-development-skill.json
Generate a UUID and write the report:
{
"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"
}
}
| 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
qa/vue-checklist.md for full criteriaqa/report-template.json for JSON structuretdd/workflow.md for detailed processtdd/testing-patterns.md for Vitest examplespatterns/composition-api.mdpatterns/nuxt3.mdpatterns/typescript.mddebugging/common-issues.mde2e/playwright-patterns.md for Gherkin-to-Playwright mappinge2e/acceptance-criteria.md for parsing user storiesany