specweave 0.23.18 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +93 -49
- package/CLAUDE.md +137 -4
- package/dist/src/cli/helpers/ado-area-path-mapper.d.ts +89 -0
- package/dist/src/cli/helpers/ado-area-path-mapper.d.ts.map +1 -0
- package/dist/src/cli/helpers/ado-area-path-mapper.js +213 -0
- package/dist/src/cli/helpers/ado-area-path-mapper.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.d.ts +29 -0
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.d.ts.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.js +109 -0
- package/dist/src/cli/helpers/issue-tracker/ado-auto-discover.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado.d.ts +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/ado.js +2 -0
- package/dist/src/cli/helpers/issue-tracker/ado.js.map +1 -1
- package/dist/src/cli/helpers/smart-filter.d.ts +83 -0
- package/dist/src/cli/helpers/smart-filter.d.ts.map +1 -0
- package/dist/src/cli/helpers/smart-filter.js +265 -0
- package/dist/src/cli/helpers/smart-filter.js.map +1 -0
- package/dist/src/core/qa/quality-gate-decider.d.ts +1 -1
- package/dist/src/core/qa/quality-gate-decider.js +2 -2
- package/dist/src/core/qa/quality-gate-decider.js.map +1 -1
- package/dist/src/core/qa/risk-calculator.d.ts +2 -2
- package/dist/src/core/qa/risk-calculator.js +2 -2
- package/dist/src/core/validators/ac-presence-validator.d.ts +56 -0
- package/dist/src/core/validators/ac-presence-validator.d.ts.map +1 -0
- package/dist/src/core/validators/ac-presence-validator.js +149 -0
- package/dist/src/core/validators/ac-presence-validator.js.map +1 -0
- package/dist/src/integrations/ado/area-path-mapper.d.ts +137 -0
- package/dist/src/integrations/ado/area-path-mapper.d.ts.map +1 -0
- package/dist/src/integrations/ado/area-path-mapper.js +267 -0
- package/dist/src/integrations/ado/area-path-mapper.js.map +1 -0
- package/dist/src/integrations/jira/filter-processor.d.ts +126 -0
- package/dist/src/integrations/jira/filter-processor.d.ts.map +1 -0
- package/dist/src/integrations/jira/filter-processor.js +207 -0
- package/dist/src/integrations/jira/filter-processor.js.map +1 -0
- package/dist/src/integrations/jira/jira-client.d.ts +13 -0
- package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-client.js +33 -0
- package/dist/src/integrations/jira/jira-client.js.map +1 -1
- package/dist/src/utils/ac-embedder.d.ts +63 -0
- package/dist/src/utils/ac-embedder.d.ts.map +1 -0
- package/dist/src/utils/ac-embedder.js +217 -0
- package/dist/src/utils/ac-embedder.js.map +1 -0
- package/dist/src/utils/env-manager.d.ts +86 -0
- package/dist/src/utils/env-manager.d.ts.map +1 -0
- package/dist/src/utils/env-manager.js +188 -0
- package/dist/src/utils/env-manager.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave/agents/AGENTS-INDEX.md +1 -1
- package/plugins/specweave/agents/increment-quality-judge-v2/AGENT.md +9 -9
- package/plugins/specweave/commands/specweave-do.md +37 -0
- package/plugins/specweave/commands/specweave-done.md +159 -0
- package/plugins/specweave/commands/specweave-embed-acs.md +446 -0
- package/plugins/specweave/commands/specweave-next.md +148 -3
- package/plugins/specweave/commands/specweave-qa.md +2 -2
- package/plugins/specweave/hooks/pre-increment-start.sh +168 -0
- package/plugins/specweave/skills/SKILLS-INDEX.md +1 -1
- package/plugins/specweave-ado/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-ado/commands/specweave-ado-import-projects.md +331 -0
- package/plugins/specweave-alternatives/.claude-plugin/plugin.json +10 -0
- package/plugins/specweave-alternatives/commands/alternatives-analyze.md +336 -0
- package/plugins/specweave-alternatives/skills/architecture-alternatives/SKILL.md +651 -0
- package/plugins/specweave-alternatives/skills/bmad-method/SKILL.md +420 -0
- package/plugins/specweave-alternatives/skills/spec-kit-expert/SKILL.md +487 -0
- package/plugins/specweave-backend/commands/api-scaffold.md +80 -0
- package/plugins/specweave-backend/commands/crud-generate.md +109 -0
- package/plugins/specweave-backend/commands/migration-generate.md +139 -0
- package/plugins/specweave-confluent/commands/connector-deploy.md +154 -0
- package/plugins/specweave-confluent/commands/ksqldb-query.md +179 -0
- package/plugins/specweave-confluent/commands/schema-register.md +123 -0
- package/plugins/specweave-core/.claude-plugin/plugin.json +21 -0
- package/plugins/specweave-core/commands/architecture-review.md +288 -0
- package/plugins/specweave-core/commands/code-review.md +213 -0
- package/plugins/specweave-core/commands/refactor-plan.md +249 -0
- package/plugins/specweave-core/skills/code-quality/SKILL.md +157 -0
- package/plugins/specweave-core/skills/design-patterns/SKILL.md +244 -0
- package/plugins/specweave-core/skills/software-architecture/SKILL.md +83 -0
- package/plugins/specweave-cost-optimizer/.claude-plugin/plugin.json +22 -0
- package/plugins/specweave-cost-optimizer/commands/cost-analyze.md +360 -0
- package/plugins/specweave-cost-optimizer/commands/cost-optimize.md +480 -0
- package/plugins/specweave-cost-optimizer/skills/aws-cost-expert/SKILL.md +416 -0
- package/plugins/specweave-cost-optimizer/skills/cloud-pricing/SKILL.md +325 -0
- package/plugins/specweave-cost-optimizer/skills/cost-optimization/SKILL.md +337 -0
- package/plugins/specweave-diagrams/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-diagrams/commands/diagrams-generate.md +168 -0
- package/plugins/specweave-docs/.claude-plugin/plugin.json +10 -0
- package/plugins/specweave-docs/commands/docs-generate.md +441 -0
- package/plugins/specweave-docs/commands/docs-init.md +334 -0
- package/plugins/specweave-docs/skills/docusaurus/SKILL.md +581 -0
- package/plugins/specweave-docs/skills/spec-driven-brainstorming/SKILL.md +689 -0
- package/plugins/specweave-docs/skills/technical-writing/SKILL.md +1039 -0
- package/plugins/specweave-docs-preview/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-figma/.claude-plugin/plugin.json +23 -0
- package/plugins/specweave-figma/commands/figma-import.md +690 -0
- package/plugins/specweave-figma/commands/figma-to-react.md +834 -0
- package/plugins/specweave-figma/commands/figma-tokens.md +815 -0
- package/plugins/specweave-frontend/.claude-plugin/plugin.json +21 -0
- package/plugins/specweave-frontend/agents/frontend-architect/AGENT.md +387 -0
- package/plugins/specweave-frontend/agents/frontend-architect/README.md +385 -0
- package/plugins/specweave-frontend/agents/frontend-architect/examples.md +590 -0
- package/plugins/specweave-frontend/agents/frontend-architect/templates/component-template.tsx +152 -0
- package/plugins/specweave-frontend/agents/frontend-architect/templates/hook-template.ts +311 -0
- package/plugins/specweave-frontend/agents/frontend-architect/templates/page-template.tsx +228 -0
- package/plugins/specweave-frontend/commands/component-generate.md +510 -0
- package/plugins/specweave-frontend/commands/design-system-init.md +494 -0
- package/plugins/specweave-frontend/commands/frontend-scaffold.md +207 -0
- package/plugins/specweave-frontend/commands/nextjs-setup.md +396 -0
- package/plugins/specweave-frontend/skills/design-system-architect/SKILL.md +278 -0
- package/plugins/specweave-frontend/skills/frontend/SKILL.md +420 -0
- package/plugins/specweave-frontend/skills/nextjs/SKILL.md +546 -0
- package/plugins/specweave-github/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +194 -0
- package/plugins/specweave-infrastructure/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-jira/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-jira/commands/import-projects.js +183 -0
- package/plugins/specweave-jira/commands/import-projects.md +97 -0
- package/plugins/specweave-jira/commands/import-projects.ts +288 -0
- package/plugins/specweave-jira/commands/specweave-jira-import-projects.md +298 -0
- package/plugins/specweave-kafka/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-kafka-streams/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-kubernetes/commands/cluster-setup.md +262 -0
- package/plugins/specweave-kubernetes/commands/deployment-generate.md +242 -0
- package/plugins/specweave-kubernetes/commands/helm-scaffold.md +333 -0
- package/plugins/specweave-ml/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-mobile/commands/app-scaffold.md +233 -0
- package/plugins/specweave-mobile/commands/build-config.md +256 -0
- package/plugins/specweave-mobile/commands/screen-generate.md +289 -0
- package/plugins/specweave-n8n/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-plugin-dev/.claude-plugin/plugin.json +13 -12
- package/plugins/specweave-plugin-dev/commands/plugin-create.md +333 -0
- package/plugins/specweave-plugin-dev/commands/plugin-publish.md +339 -0
- package/plugins/specweave-plugin-dev/commands/plugin-test.md +293 -0
- package/plugins/specweave-plugin-dev/skills/claude-sdk/SKILL.md +162 -0
- package/plugins/specweave-plugin-dev/skills/marketplace-publishing/SKILL.md +263 -0
- package/plugins/specweave-plugin-dev/skills/plugin-development/SKILL.md +316 -0
- package/plugins/specweave-release/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-release/commands/specweave-release-npm.md +110 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +168 -0
- package/plugins/specweave-testing/.claude-plugin/plugin.json +21 -0
- package/plugins/specweave-testing/agents/qa-engineer/AGENT.md +797 -0
- package/plugins/specweave-testing/agents/qa-engineer/README.md +443 -0
- package/plugins/specweave-testing/agents/qa-engineer/templates/playwright-e2e-test.ts +470 -0
- package/plugins/specweave-testing/agents/qa-engineer/templates/test-data-factory.ts +507 -0
- package/plugins/specweave-testing/agents/qa-engineer/templates/vitest-unit-test.ts +400 -0
- package/plugins/specweave-testing/agents/qa-engineer/test-strategies.md +726 -0
- package/plugins/specweave-testing/commands/e2e-setup.md +1081 -0
- package/plugins/specweave-testing/commands/test-coverage.md +979 -0
- package/plugins/specweave-testing/commands/test-generate.md +1156 -0
- package/plugins/specweave-testing/commands/test-init.md +409 -0
- package/plugins/specweave-testing/skills/e2e-playwright/SKILL.md +769 -0
- package/plugins/specweave-testing/skills/tdd-expert/SKILL.md +934 -0
- package/plugins/specweave-testing/skills/unit-testing-expert/SKILL.md +1011 -0
- package/plugins/specweave-tooling/.claude-plugin/plugin.json +22 -0
- package/plugins/specweave-tooling/commands/specweave-tooling-skill-create.md +691 -0
- package/plugins/specweave-tooling/commands/specweave-tooling-skill-package.md +751 -0
- package/plugins/specweave-tooling/commands/specweave-tooling-skill-validate.md +858 -0
- package/plugins/specweave-ui/.claude-plugin/plugin.json +10 -0
- package/plugins/specweave-ui/commands/ui-automate.md +199 -0
- package/plugins/specweave-ui/commands/ui-inspect.md +70 -0
- package/plugins/specweave-ui/skills/browser-automation/SKILL.md +314 -0
- package/plugins/specweave-ui/skills/ui-testing/SKILL.md +716 -0
- package/plugins/specweave-ui/skills/visual-regression/SKILL.md +728 -0
- package/plugins/specweave/commands/check-hooks.md +0 -257
- package/plugins/specweave/commands/specweave-archive-increments.md +0 -82
- package/plugins/specweave-plugin-dev/skills/plugin-expert/SKILL.md +0 -1231
- /package/plugins/specweave/{agents/code-reviewer.md → skills/code-reviewer/SKILL.md} +0 -0
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
# /specweave-testing:test-init
|
|
2
|
+
|
|
3
|
+
Initialize comprehensive testing infrastructure with Vitest, Playwright, and testing best practices.
|
|
4
|
+
|
|
5
|
+
You are an expert testing engineer who sets up production-ready test infrastructure.
|
|
6
|
+
|
|
7
|
+
## Your Task
|
|
8
|
+
|
|
9
|
+
Set up a complete testing framework covering unit tests, integration tests, and E2E tests.
|
|
10
|
+
|
|
11
|
+
### 1. Testing Stack
|
|
12
|
+
|
|
13
|
+
**Unit Testing (Vitest)**:
|
|
14
|
+
- Fast, Vite-powered test runner
|
|
15
|
+
- Compatible with Jest API
|
|
16
|
+
- Built-in coverage (c8/istanbul)
|
|
17
|
+
- ESM and TypeScript support
|
|
18
|
+
- Watch mode for TDD
|
|
19
|
+
|
|
20
|
+
**E2E Testing (Playwright)**:
|
|
21
|
+
- Cross-browser testing (Chromium, Firefox, WebKit)
|
|
22
|
+
- Reliable auto-wait mechanisms
|
|
23
|
+
- Powerful selectors and assertions
|
|
24
|
+
- Parallel test execution
|
|
25
|
+
- Screenshots and video recording
|
|
26
|
+
|
|
27
|
+
**Component Testing**:
|
|
28
|
+
- React Testing Library
|
|
29
|
+
- Vue Testing Library
|
|
30
|
+
- User-centric testing approach
|
|
31
|
+
- Accessibility testing integration
|
|
32
|
+
|
|
33
|
+
### 2. Vitest Configuration
|
|
34
|
+
|
|
35
|
+
**vitest.config.ts**:
|
|
36
|
+
```typescript
|
|
37
|
+
import { defineConfig } from 'vitest/config';
|
|
38
|
+
import react from '@vitejs/plugin-react';
|
|
39
|
+
import path from 'path';
|
|
40
|
+
|
|
41
|
+
export default defineConfig({
|
|
42
|
+
plugins: [react()],
|
|
43
|
+
test: {
|
|
44
|
+
globals: true,
|
|
45
|
+
environment: 'jsdom',
|
|
46
|
+
setupFiles: ['./tests/setup.ts'],
|
|
47
|
+
include: ['**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
|
48
|
+
exclude: ['node_modules', 'dist', '.idea', '.git', '.cache'],
|
|
49
|
+
coverage: {
|
|
50
|
+
provider: 'v8',
|
|
51
|
+
reporter: ['text', 'json', 'html', 'lcov'],
|
|
52
|
+
exclude: [
|
|
53
|
+
'node_modules/',
|
|
54
|
+
'tests/',
|
|
55
|
+
'**/*.d.ts',
|
|
56
|
+
'**/*.config.*',
|
|
57
|
+
'**/mockData',
|
|
58
|
+
],
|
|
59
|
+
all: true,
|
|
60
|
+
lines: 80,
|
|
61
|
+
functions: 80,
|
|
62
|
+
branches: 80,
|
|
63
|
+
statements: 80,
|
|
64
|
+
},
|
|
65
|
+
testTimeout: 10000,
|
|
66
|
+
},
|
|
67
|
+
resolve: {
|
|
68
|
+
alias: {
|
|
69
|
+
'@': path.resolve(__dirname, './src'),
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**tests/setup.ts**:
|
|
76
|
+
```typescript
|
|
77
|
+
import '@testing-library/jest-dom';
|
|
78
|
+
import { cleanup } from '@testing-library/react';
|
|
79
|
+
import { afterEach, vi } from 'vitest';
|
|
80
|
+
|
|
81
|
+
// Cleanup after each test
|
|
82
|
+
afterEach(() => {
|
|
83
|
+
cleanup();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Mock window.matchMedia
|
|
87
|
+
Object.defineProperty(window, 'matchMedia', {
|
|
88
|
+
writable: true,
|
|
89
|
+
value: vi.fn().mockImplementation((query) => ({
|
|
90
|
+
matches: false,
|
|
91
|
+
media: query,
|
|
92
|
+
onchange: null,
|
|
93
|
+
addListener: vi.fn(),
|
|
94
|
+
removeListener: vi.fn(),
|
|
95
|
+
addEventListener: vi.fn(),
|
|
96
|
+
removeEventListener: vi.fn(),
|
|
97
|
+
dispatchEvent: vi.fn(),
|
|
98
|
+
})),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Mock IntersectionObserver
|
|
102
|
+
global.IntersectionObserver = class IntersectionObserver {
|
|
103
|
+
constructor() {}
|
|
104
|
+
disconnect() {}
|
|
105
|
+
observe() {}
|
|
106
|
+
takeRecords() {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
unobserve() {}
|
|
110
|
+
} as any;
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 3. Playwright Configuration
|
|
114
|
+
|
|
115
|
+
**playwright.config.ts**:
|
|
116
|
+
```typescript
|
|
117
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
118
|
+
|
|
119
|
+
export default defineConfig({
|
|
120
|
+
testDir: './tests/e2e',
|
|
121
|
+
fullyParallel: true,
|
|
122
|
+
forbidOnly: !!process.env.CI,
|
|
123
|
+
retries: process.env.CI ? 2 : 0,
|
|
124
|
+
workers: process.env.CI ? 1 : undefined,
|
|
125
|
+
reporter: 'html',
|
|
126
|
+
use: {
|
|
127
|
+
baseURL: 'http://localhost:3000',
|
|
128
|
+
trace: 'on-first-retry',
|
|
129
|
+
screenshot: 'only-on-failure',
|
|
130
|
+
video: 'retain-on-failure',
|
|
131
|
+
},
|
|
132
|
+
projects: [
|
|
133
|
+
{
|
|
134
|
+
name: 'chromium',
|
|
135
|
+
use: { ...devices['Desktop Chrome'] },
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: 'firefox',
|
|
139
|
+
use: { ...devices['Desktop Firefox'] },
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: 'webkit',
|
|
143
|
+
use: { ...devices['Desktop Safari'] },
|
|
144
|
+
},
|
|
145
|
+
// Mobile viewports
|
|
146
|
+
{
|
|
147
|
+
name: 'Mobile Chrome',
|
|
148
|
+
use: { ...devices['Pixel 5'] },
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: 'Mobile Safari',
|
|
152
|
+
use: { ...devices['iPhone 12'] },
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
webServer: {
|
|
156
|
+
command: 'npm run dev',
|
|
157
|
+
url: 'http://localhost:3000',
|
|
158
|
+
reuseExistingServer: !process.env.CI,
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 4. Test Utilities
|
|
164
|
+
|
|
165
|
+
**tests/utils/test-utils.tsx** (React):
|
|
166
|
+
```typescript
|
|
167
|
+
import { render, RenderOptions } from '@testing-library/react';
|
|
168
|
+
import { ReactElement } from 'react';
|
|
169
|
+
import { BrowserRouter } from 'react-router-dom';
|
|
170
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
171
|
+
|
|
172
|
+
const queryClient = new QueryClient({
|
|
173
|
+
defaultOptions: {
|
|
174
|
+
queries: { retry: false },
|
|
175
|
+
mutations: { retry: false },
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
function AllTheProviders({ children }: { children: React.ReactNode }) {
|
|
180
|
+
return (
|
|
181
|
+
<QueryClientProvider client={queryClient}>
|
|
182
|
+
<BrowserRouter>
|
|
183
|
+
{children}
|
|
184
|
+
</BrowserRouter>
|
|
185
|
+
</QueryClientProvider>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function customRender(ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>) {
|
|
190
|
+
return render(ui, { wrapper: AllTheProviders, ...options });
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export * from '@testing-library/react';
|
|
194
|
+
export { customRender as render };
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**tests/utils/mocks/handlers.ts** (MSW):
|
|
198
|
+
```typescript
|
|
199
|
+
import { http, HttpResponse } from 'msw';
|
|
200
|
+
|
|
201
|
+
export const handlers = [
|
|
202
|
+
http.get('/api/users', () => {
|
|
203
|
+
return HttpResponse.json([
|
|
204
|
+
{ id: '1', name: 'John Doe' },
|
|
205
|
+
{ id: '2', name: 'Jane Smith' },
|
|
206
|
+
]);
|
|
207
|
+
}),
|
|
208
|
+
|
|
209
|
+
http.post('/api/login', async ({ request }) => {
|
|
210
|
+
const { email, password } = await request.json();
|
|
211
|
+
|
|
212
|
+
if (email === 'test@example.com' && password === 'password') {
|
|
213
|
+
return HttpResponse.json({
|
|
214
|
+
token: 'mock-jwt-token',
|
|
215
|
+
user: { id: '1', email },
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return HttpResponse.json(
|
|
220
|
+
{ error: 'Invalid credentials' },
|
|
221
|
+
{ status: 401 }
|
|
222
|
+
);
|
|
223
|
+
}),
|
|
224
|
+
];
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**tests/utils/mocks/server.ts**:
|
|
228
|
+
```typescript
|
|
229
|
+
import { setupServer } from 'msw/node';
|
|
230
|
+
import { handlers } from './handlers';
|
|
231
|
+
|
|
232
|
+
export const server = setupServer(...handlers);
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### 5. Package Dependencies
|
|
236
|
+
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"devDependencies": {
|
|
240
|
+
"@playwright/test": "^1.40.0",
|
|
241
|
+
"@testing-library/jest-dom": "^6.1.5",
|
|
242
|
+
"@testing-library/react": "^14.1.2",
|
|
243
|
+
"@testing-library/user-event": "^14.5.1",
|
|
244
|
+
"@vitest/coverage-v8": "^1.0.4",
|
|
245
|
+
"@vitest/ui": "^1.0.4",
|
|
246
|
+
"jsdom": "^23.0.1",
|
|
247
|
+
"msw": "^2.0.0",
|
|
248
|
+
"vitest": "^1.0.4"
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### 6. NPM Scripts
|
|
254
|
+
|
|
255
|
+
```json
|
|
256
|
+
{
|
|
257
|
+
"scripts": {
|
|
258
|
+
"test": "vitest",
|
|
259
|
+
"test:ui": "vitest --ui",
|
|
260
|
+
"test:coverage": "vitest --coverage",
|
|
261
|
+
"test:e2e": "playwright test",
|
|
262
|
+
"test:e2e:ui": "playwright test --ui",
|
|
263
|
+
"test:e2e:debug": "playwright test --debug",
|
|
264
|
+
"test:all": "npm run test:coverage && npm run test:e2e"
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### 7. CI/CD Configuration
|
|
270
|
+
|
|
271
|
+
**GitHub Actions (.github/workflows/test.yml)**:
|
|
272
|
+
```yaml
|
|
273
|
+
name: Tests
|
|
274
|
+
|
|
275
|
+
on: [push, pull_request]
|
|
276
|
+
|
|
277
|
+
jobs:
|
|
278
|
+
test:
|
|
279
|
+
runs-on: ubuntu-latest
|
|
280
|
+
steps:
|
|
281
|
+
- uses: actions/checkout@v4
|
|
282
|
+
- uses: actions/setup-node@v4
|
|
283
|
+
with:
|
|
284
|
+
node-version: '20'
|
|
285
|
+
cache: 'npm'
|
|
286
|
+
|
|
287
|
+
- name: Install dependencies
|
|
288
|
+
run: npm ci
|
|
289
|
+
|
|
290
|
+
- name: Run unit tests
|
|
291
|
+
run: npm run test:coverage
|
|
292
|
+
|
|
293
|
+
- name: Install Playwright Browsers
|
|
294
|
+
run: npx playwright install --with-deps
|
|
295
|
+
|
|
296
|
+
- name: Run E2E tests
|
|
297
|
+
run: npm run test:e2e
|
|
298
|
+
|
|
299
|
+
- name: Upload coverage
|
|
300
|
+
uses: codecov/codecov-action@v3
|
|
301
|
+
with:
|
|
302
|
+
files: ./coverage/lcov.info
|
|
303
|
+
|
|
304
|
+
- name: Upload test results
|
|
305
|
+
if: always()
|
|
306
|
+
uses: actions/upload-artifact@v3
|
|
307
|
+
with:
|
|
308
|
+
name: playwright-report
|
|
309
|
+
path: playwright-report/
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### 8. Testing Best Practices
|
|
313
|
+
|
|
314
|
+
**Unit Test Example**:
|
|
315
|
+
```typescript
|
|
316
|
+
import { render, screen, fireEvent } from './utils/test-utils';
|
|
317
|
+
import { LoginForm } from '@/components/LoginForm';
|
|
318
|
+
|
|
319
|
+
describe('LoginForm', () => {
|
|
320
|
+
it('renders login form correctly', () => {
|
|
321
|
+
render(<LoginForm />);
|
|
322
|
+
expect(screen.getByLabelText(/email/i)).toBeInTheDocument();
|
|
323
|
+
expect(screen.getByLabelText(/password/i)).toBeInTheDocument();
|
|
324
|
+
expect(screen.getByRole('button', { name: /login/i })).toBeInTheDocument();
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('shows validation errors for empty fields', async () => {
|
|
328
|
+
render(<LoginForm />);
|
|
329
|
+
fireEvent.click(screen.getByRole('button', { name: /login/i }));
|
|
330
|
+
|
|
331
|
+
expect(await screen.findByText(/email is required/i)).toBeInTheDocument();
|
|
332
|
+
expect(await screen.findByText(/password is required/i)).toBeInTheDocument();
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it('submits form with valid data', async () => {
|
|
336
|
+
const onSubmit = vi.fn();
|
|
337
|
+
render(<LoginForm onSubmit={onSubmit} />);
|
|
338
|
+
|
|
339
|
+
fireEvent.change(screen.getByLabelText(/email/i), {
|
|
340
|
+
target: { value: 'test@example.com' },
|
|
341
|
+
});
|
|
342
|
+
fireEvent.change(screen.getByLabelText(/password/i), {
|
|
343
|
+
target: { value: 'password123' },
|
|
344
|
+
});
|
|
345
|
+
fireEvent.click(screen.getByRole('button', { name: /login/i }));
|
|
346
|
+
|
|
347
|
+
await waitFor(() => {
|
|
348
|
+
expect(onSubmit).toHaveBeenCalledWith({
|
|
349
|
+
email: 'test@example.com',
|
|
350
|
+
password: 'password123',
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
**E2E Test Example**:
|
|
358
|
+
```typescript
|
|
359
|
+
import { test, expect } from '@playwright/test';
|
|
360
|
+
|
|
361
|
+
test.describe('Authentication Flow', () => {
|
|
362
|
+
test('should allow user to login', async ({ page }) => {
|
|
363
|
+
await page.goto('/login');
|
|
364
|
+
|
|
365
|
+
await page.fill('input[name="email"]', 'test@example.com');
|
|
366
|
+
await page.fill('input[name="password"]', 'password123');
|
|
367
|
+
await page.click('button[type="submit"]');
|
|
368
|
+
|
|
369
|
+
await expect(page).toHaveURL('/dashboard');
|
|
370
|
+
await expect(page.locator('h1')).toContainText('Dashboard');
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
test('should show error for invalid credentials', async ({ page }) => {
|
|
374
|
+
await page.goto('/login');
|
|
375
|
+
|
|
376
|
+
await page.fill('input[name="email"]', 'wrong@example.com');
|
|
377
|
+
await page.fill('input[name="password"]', 'wrongpassword');
|
|
378
|
+
await page.click('button[type="submit"]');
|
|
379
|
+
|
|
380
|
+
await expect(page.locator('[role="alert"]')).toContainText(
|
|
381
|
+
'Invalid credentials'
|
|
382
|
+
);
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
## Workflow
|
|
388
|
+
|
|
389
|
+
1. Ask about testing requirements and existing setup
|
|
390
|
+
2. Install testing dependencies (Vitest, Playwright, Testing Library)
|
|
391
|
+
3. Create Vitest configuration
|
|
392
|
+
4. Create Playwright configuration
|
|
393
|
+
5. Set up test utilities and helpers
|
|
394
|
+
6. Configure MSW for API mocking
|
|
395
|
+
7. Add test scripts to package.json
|
|
396
|
+
8. Create example tests
|
|
397
|
+
9. Set up CI/CD workflow
|
|
398
|
+
10. Provide testing guidelines and best practices
|
|
399
|
+
|
|
400
|
+
## When to Use
|
|
401
|
+
|
|
402
|
+
- Starting new projects with testing
|
|
403
|
+
- Migrating from Jest to Vitest
|
|
404
|
+
- Adding E2E testing to existing projects
|
|
405
|
+
- Setting up CI/CD testing pipeline
|
|
406
|
+
- Improving test coverage
|
|
407
|
+
- Implementing TDD workflow
|
|
408
|
+
|
|
409
|
+
Initialize production-ready testing infrastructure with modern tools!
|