qa-skills 3.0.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/README.md +168 -0
- package/bin/cli.js +42 -0
- package/dist/agents/registry.d.ts +5 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +101 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/types.d.ts +9 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +2 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/dependencies.d.ts +21 -0
- package/dist/dependencies.d.ts.map +1 -0
- package/dist/dependencies.js +125 -0
- package/dist/dependencies.js.map +1 -0
- package/dist/installer.d.ts +25 -0
- package/dist/installer.d.ts.map +1 -0
- package/dist/installer.js +437 -0
- package/dist/installer.js.map +1 -0
- package/dist/scaffold.d.ts +27 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +182 -0
- package/dist/scaffold.js.map +1 -0
- package/package.json +40 -0
- package/skills/qa-accessibility-test-writer/SKILL.md +127 -0
- package/skills/qa-accessibility-test-writer/references/axe-core-patterns.md +349 -0
- package/skills/qa-accessibility-test-writer/references/best-practices.md +184 -0
- package/skills/qa-accessibility-test-writer/references/wcag-tests.md +331 -0
- package/skills/qa-api-contract-curator/SKILL.md +104 -0
- package/skills/qa-api-contract-curator/references/breaking-changes.md +363 -0
- package/skills/qa-api-contract-curator/references/openapi-structure.md +404 -0
- package/skills/qa-browser-data-collector/SKILL.md +132 -0
- package/skills/qa-browser-data-collector/references/data-collection-checklist.md +91 -0
- package/skills/qa-browser-data-collector/references/playwright-mcp-patterns.md +113 -0
- package/skills/qa-bug-ticket-creator/SKILL.md +148 -0
- package/skills/qa-bug-ticket-creator/references/bug-report-format.md +149 -0
- package/skills/qa-bug-ticket-creator/references/severity-guide.md +81 -0
- package/skills/qa-bug-ticket-creator/templates/bug-ticket-template.md +39 -0
- package/skills/qa-changelog-analyzer/SKILL.md +134 -0
- package/skills/qa-changelog-analyzer/references/git-analysis-patterns.md +138 -0
- package/skills/qa-changelog-analyzer/references/impact-mapping.md +120 -0
- package/skills/qa-clickup-integration/SKILL.md +166 -0
- package/skills/qa-clickup-integration/references/api-patterns.md +102 -0
- package/skills/qa-clickup-integration/references/field-mapping.md +71 -0
- package/skills/qa-codeceptjs-writer/SKILL.md +136 -0
- package/skills/qa-codeceptjs-writer/references/best-practices.md +207 -0
- package/skills/qa-codeceptjs-writer/references/config.md +255 -0
- package/skills/qa-codeceptjs-writer/references/patterns.md +285 -0
- package/skills/qa-coverage-analyzer/SKILL.md +166 -0
- package/skills/qa-coverage-analyzer/references/best-practices.md +142 -0
- package/skills/qa-coverage-analyzer/references/coverage-dimensions.md +155 -0
- package/skills/qa-coverage-analyzer/references/tools.md +204 -0
- package/skills/qa-cypress-writer/SKILL.md +134 -0
- package/skills/qa-cypress-writer/references/assertions.md +121 -0
- package/skills/qa-cypress-writer/references/best-practices.md +82 -0
- package/skills/qa-cypress-writer/references/config.md +121 -0
- package/skills/qa-cypress-writer/references/patterns.md +170 -0
- package/skills/qa-data-factory/SKILL.md +126 -0
- package/skills/qa-data-factory/references/factory-patterns.md +164 -0
- package/skills/qa-data-factory/references/faker-guide.md +131 -0
- package/skills/qa-diagram-generator/SKILL.md +125 -0
- package/skills/qa-diagram-generator/references/c4-model.md +53 -0
- package/skills/qa-diagram-generator/references/charts.md +58 -0
- package/skills/qa-diagram-generator/references/class-diagram.md +85 -0
- package/skills/qa-diagram-generator/references/er-diagram.md +69 -0
- package/skills/qa-diagram-generator/references/flowchart.md +92 -0
- package/skills/qa-diagram-generator/references/from-screenshot.md +45 -0
- package/skills/qa-diagram-generator/references/gantt.md +49 -0
- package/skills/qa-diagram-generator/references/journey.md +50 -0
- package/skills/qa-diagram-generator/references/mindmap.md +75 -0
- package/skills/qa-diagram-generator/references/sequence.md +69 -0
- package/skills/qa-diagram-generator/references/state-diagram.md +56 -0
- package/skills/qa-discovery-interview/SKILL.md +182 -0
- package/skills/qa-discovery-interview/references/completeness-checklist.md +53 -0
- package/skills/qa-discovery-interview/references/conflict-patterns.md +101 -0
- package/skills/qa-discovery-interview/references/qa-categories.md +147 -0
- package/skills/qa-discovery-interview/templates/qa-brief-template.md +168 -0
- package/skills/qa-environment-checker/SKILL.md +142 -0
- package/skills/qa-environment-checker/references/dependency-matrix.md +101 -0
- package/skills/qa-environment-checker/references/health-checks.md +209 -0
- package/skills/qa-environment-checker/templates/env-readiness-template.md +64 -0
- package/skills/qa-flaky-detector/SKILL.md +153 -0
- package/skills/qa-flaky-detector/references/ci-analysis.md +140 -0
- package/skills/qa-flaky-detector/references/flaky-patterns.md +247 -0
- package/skills/qa-github-issues-enhanced/SKILL.md +175 -0
- package/skills/qa-github-issues-enhanced/references/issue-templates.md +425 -0
- package/skills/qa-github-issues-enhanced/references/label-taxonomy.md +130 -0
- package/skills/qa-github-issues-enhanced/references/workflow-patterns.md +188 -0
- package/skills/qa-httpx-writer/SKILL.md +138 -0
- package/skills/qa-httpx-writer/references/assertions.md +195 -0
- package/skills/qa-httpx-writer/references/best-practices.md +140 -0
- package/skills/qa-httpx-writer/references/config.md +212 -0
- package/skills/qa-httpx-writer/references/patterns.md +262 -0
- package/skills/qa-jest-writer/SKILL.md +131 -0
- package/skills/qa-jest-writer/references/assertions.md +125 -0
- package/skills/qa-jest-writer/references/best-practices.md +136 -0
- package/skills/qa-jest-writer/references/config.md +134 -0
- package/skills/qa-jest-writer/references/patterns.md +172 -0
- package/skills/qa-jira-integration/SKILL.md +135 -0
- package/skills/qa-jira-integration/references/api-patterns.md +143 -0
- package/skills/qa-jira-integration/references/field-mapping.md +79 -0
- package/skills/qa-jira-integration/references/xray-integration.md +85 -0
- package/skills/qa-jmeter-writer/SKILL.md +171 -0
- package/skills/qa-jmeter-writer/references/best-practices.md +157 -0
- package/skills/qa-jmeter-writer/references/config.md +204 -0
- package/skills/qa-jmeter-writer/references/patterns.md +242 -0
- package/skills/qa-junit5-writer/SKILL.md +157 -0
- package/skills/qa-junit5-writer/references/assertions.md +118 -0
- package/skills/qa-junit5-writer/references/config.md +97 -0
- package/skills/qa-junit5-writer/references/patterns.md +162 -0
- package/skills/qa-k6-writer/SKILL.md +155 -0
- package/skills/qa-k6-writer/references/best-practices.md +236 -0
- package/skills/qa-k6-writer/references/config.md +219 -0
- package/skills/qa-k6-writer/references/patterns.md +304 -0
- package/skills/qa-linear-integration/SKILL.md +137 -0
- package/skills/qa-linear-integration/references/api-patterns.md +249 -0
- package/skills/qa-linear-integration/references/field-mapping.md +121 -0
- package/skills/qa-locust-writer/SKILL.md +151 -0
- package/skills/qa-locust-writer/references/best-practices.md +126 -0
- package/skills/qa-locust-writer/references/config.md +170 -0
- package/skills/qa-locust-writer/references/patterns.md +235 -0
- package/skills/qa-manual-test-designer/SKILL.md +145 -0
- package/skills/qa-manual-test-designer/references/exploratory-charters.md +138 -0
- package/skills/qa-manual-test-designer/references/personas.md +146 -0
- package/skills/qa-manual-test-designer/templates/exploratory-charter-template.md +47 -0
- package/skills/qa-manual-test-designer/templates/test-case-template.md +31 -0
- package/skills/qa-mobile-test-writer/SKILL.md +144 -0
- package/skills/qa-mobile-test-writer/references/best-practices.md +214 -0
- package/skills/qa-mobile-test-writer/references/config.md +309 -0
- package/skills/qa-mobile-test-writer/references/patterns.md +304 -0
- package/skills/qa-nfr-analyst/SKILL.md +177 -0
- package/skills/qa-nfr-analyst/references/iso-25010-model.md +159 -0
- package/skills/qa-nfr-analyst/references/owasp-wstg-baseline.md +202 -0
- package/skills/qa-nfr-analyst/references/wcag-checklist.md +184 -0
- package/skills/qa-nfr-analyst/templates/owasp-checklist-template.md +89 -0
- package/skills/qa-nfr-analyst/templates/wcag-checklist-template.md +48 -0
- package/skills/qa-orchestrator/SKILL.md +132 -0
- package/skills/qa-orchestrator/references/handoff-chains.md +105 -0
- package/skills/qa-orchestrator/references/pipeline-modes.md +115 -0
- package/skills/qa-orchestrator/references/scheduler-rules.md +84 -0
- package/skills/qa-pact-writer/SKILL.md +133 -0
- package/skills/qa-pact-writer/references/best-practices.md +100 -0
- package/skills/qa-pact-writer/references/config.md +135 -0
- package/skills/qa-pact-writer/references/patterns.md +161 -0
- package/skills/qa-plan-creator/SKILL.md +139 -0
- package/skills/qa-plan-creator/references/introduction-plan.md +43 -0
- package/skills/qa-plan-creator/references/migration-plan.md +44 -0
- package/skills/qa-plan-creator/references/onboarding-plan.md +46 -0
- package/skills/qa-plan-creator/references/performance-plan.md +44 -0
- package/skills/qa-plan-creator/references/regression-plan.md +45 -0
- package/skills/qa-plan-creator/references/release-plan.md +45 -0
- package/skills/qa-plan-creator/references/sprint-plan.md +44 -0
- package/skills/qa-plan-creator/references/test-plan.md +59 -0
- package/skills/qa-plan-creator/references/uat-plan.md +43 -0
- package/skills/qa-plan-creator/templates/checklist-template.md +36 -0
- package/skills/qa-plan-creator/templates/regression-checklist-template.md +49 -0
- package/skills/qa-plan-creator/templates/release-checklist-template.md +46 -0
- package/skills/qa-plan-creator/templates/test-plan-template.md +74 -0
- package/skills/qa-playwright-py-writer/SKILL.md +156 -0
- package/skills/qa-playwright-py-writer/references/best-practices.md +194 -0
- package/skills/qa-playwright-py-writer/references/config.md +195 -0
- package/skills/qa-playwright-py-writer/references/patterns.md +212 -0
- package/skills/qa-playwright-ts-writer/SKILL.md +151 -0
- package/skills/qa-playwright-ts-writer/references/assertions.md +109 -0
- package/skills/qa-playwright-ts-writer/references/best-practices.md +191 -0
- package/skills/qa-playwright-ts-writer/references/config.md +144 -0
- package/skills/qa-playwright-ts-writer/references/patterns.md +171 -0
- package/skills/qa-pytest-writer/SKILL.md +145 -0
- package/skills/qa-pytest-writer/references/assertions.md +149 -0
- package/skills/qa-pytest-writer/references/best-practices.md +97 -0
- package/skills/qa-pytest-writer/references/config.md +176 -0
- package/skills/qa-pytest-writer/references/patterns.md +251 -0
- package/skills/qa-qase-integration/SKILL.md +149 -0
- package/skills/qa-qase-integration/references/api-reference.md +354 -0
- package/skills/qa-qase-integration/references/ci-integration.md +196 -0
- package/skills/qa-qase-integration/references/field-mapping.md +157 -0
- package/skills/qa-requirements-generator/SKILL.md +152 -0
- package/skills/qa-requirements-generator/references/iso-29148-structure.md +153 -0
- package/skills/qa-requirements-generator/references/requirement-patterns.md +278 -0
- package/skills/qa-rest-assured-writer/SKILL.md +137 -0
- package/skills/qa-rest-assured-writer/references/best-practices.md +50 -0
- package/skills/qa-rest-assured-writer/references/config.md +124 -0
- package/skills/qa-rest-assured-writer/references/patterns.md +192 -0
- package/skills/qa-risk-analyzer/SKILL.md +158 -0
- package/skills/qa-risk-analyzer/references/impact-analysis.md +133 -0
- package/skills/qa-risk-analyzer/references/risk-factors.md +123 -0
- package/skills/qa-robot-framework-writer/SKILL.md +147 -0
- package/skills/qa-robot-framework-writer/references/best-practices.md +249 -0
- package/skills/qa-robot-framework-writer/references/config.md +204 -0
- package/skills/qa-robot-framework-writer/references/libraries.md +273 -0
- package/skills/qa-robot-framework-writer/references/patterns.md +216 -0
- package/skills/qa-security-test-writer/SKILL.md +123 -0
- package/skills/qa-security-test-writer/references/best-practices.md +155 -0
- package/skills/qa-security-test-writer/references/owasp-top10.md +331 -0
- package/skills/qa-security-test-writer/references/zap-config.md +258 -0
- package/skills/qa-selenium-java-writer/SKILL.md +143 -0
- package/skills/qa-selenium-java-writer/references/best-practices.md +59 -0
- package/skills/qa-selenium-java-writer/references/config.md +143 -0
- package/skills/qa-selenium-java-writer/references/patterns.md +170 -0
- package/skills/qa-selenium-py-writer/SKILL.md +150 -0
- package/skills/qa-selenium-py-writer/references/best-practices.md +175 -0
- package/skills/qa-selenium-py-writer/references/config.md +224 -0
- package/skills/qa-selenium-py-writer/references/patterns.md +255 -0
- package/skills/qa-shortcut-integration/SKILL.md +143 -0
- package/skills/qa-shortcut-integration/references/api-patterns.md +126 -0
- package/skills/qa-shortcut-integration/references/field-mapping.md +66 -0
- package/skills/qa-spec-auditor/SKILL.md +162 -0
- package/skills/qa-spec-auditor/references/audit-checklist.md +144 -0
- package/skills/qa-spec-auditor/references/drift-patterns.md +207 -0
- package/skills/qa-spec-writer/SKILL.md +143 -0
- package/skills/qa-spec-writer/references/gherkin-guide.md +253 -0
- package/skills/qa-spec-writer/references/specification-patterns.md +274 -0
- package/skills/qa-spring-test-writer/SKILL.md +170 -0
- package/skills/qa-spring-test-writer/references/best-practices.md +57 -0
- package/skills/qa-spring-test-writer/references/config.md +179 -0
- package/skills/qa-spring-test-writer/references/patterns.md +235 -0
- package/skills/qa-supertest-writer/SKILL.md +150 -0
- package/skills/qa-supertest-writer/references/assertions.md +192 -0
- package/skills/qa-supertest-writer/references/best-practices.md +102 -0
- package/skills/qa-supertest-writer/references/config.md +166 -0
- package/skills/qa-supertest-writer/references/patterns.md +242 -0
- package/skills/qa-task-creator/SKILL.md +142 -0
- package/skills/qa-task-creator/references/linking-patterns.md +127 -0
- package/skills/qa-task-creator/references/task-types.md +169 -0
- package/skills/qa-task-creator/templates/task-template.md +24 -0
- package/skills/qa-test-doc-compiler/SKILL.md +114 -0
- package/skills/qa-test-doc-compiler/references/agile-tailoring.md +220 -0
- package/skills/qa-test-doc-compiler/references/iso-29119-3-documents.md +302 -0
- package/skills/qa-test-healer/SKILL.md +101 -0
- package/skills/qa-test-healer/references/diagnosis-patterns.md +142 -0
- package/skills/qa-test-healer/references/fix-strategies.md +177 -0
- package/skills/qa-test-reporter/SKILL.md +130 -0
- package/skills/qa-test-reporter/references/best-practices.md +162 -0
- package/skills/qa-test-reporter/references/iso-29119-reports.md +236 -0
- package/skills/qa-test-reporter/references/report-formats.md +287 -0
- package/skills/qa-test-reviewer/SKILL.md +142 -0
- package/skills/qa-test-reviewer/references/anti-patterns.md +268 -0
- package/skills/qa-test-reviewer/references/review-checklist.md +93 -0
- package/skills/qa-test-strategy/SKILL.md +133 -0
- package/skills/qa-test-strategy/references/entry-exit-criteria.md +176 -0
- package/skills/qa-test-strategy/references/risk-matrix.md +102 -0
- package/skills/qa-test-strategy/references/testing-types.md +143 -0
- package/skills/qa-testcase-from-docs/SKILL.md +161 -0
- package/skills/qa-testcase-from-docs/references/test-case-format.md +196 -0
- package/skills/qa-testcase-from-docs/references/test-design-techniques.md +126 -0
- package/skills/qa-testcase-from-docs/templates/test-case-template.md +31 -0
- package/skills/qa-testcase-from-ui/SKILL.md +109 -0
- package/skills/qa-testcase-from-ui/references/ui-element-patterns.md +126 -0
- package/skills/qa-testcase-from-ui/references/visual-analysis-guide.md +146 -0
- package/skills/qa-testcase-from-ui/templates/test-case-template.md +31 -0
- package/skills/qa-visual-regression-writer/SKILL.md +175 -0
- package/skills/qa-visual-regression-writer/references/best-practices.md +154 -0
- package/skills/qa-visual-regression-writer/references/config.md +220 -0
- package/skills/qa-visual-regression-writer/references/patterns.md +213 -0
- package/skills/qa-vitest-writer/SKILL.md +141 -0
- package/skills/qa-vitest-writer/references/assertions.md +105 -0
- package/skills/qa-vitest-writer/references/best-practices.md +62 -0
- package/skills/qa-vitest-writer/references/config.md +127 -0
- package/skills/qa-vitest-writer/references/patterns.md +141 -0
- package/skills/qa-webdriverio-writer/SKILL.md +145 -0
- package/skills/qa-webdriverio-writer/references/best-practices.md +176 -0
- package/skills/qa-webdriverio-writer/references/config.md +240 -0
- package/skills/qa-webdriverio-writer/references/patterns.md +269 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Visual Regression Configuration
|
|
2
|
+
|
|
3
|
+
Configuration for Playwright screenshots, Percy, and BackstopJS.
|
|
4
|
+
|
|
5
|
+
## Playwright Screenshot Configuration
|
|
6
|
+
|
|
7
|
+
### playwright.config.ts
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { defineConfig } from '@playwright/test';
|
|
11
|
+
|
|
12
|
+
export default defineConfig({
|
|
13
|
+
testDir: './visual',
|
|
14
|
+
snapshotDir: './visual/snapshots',
|
|
15
|
+
snapshotPathTemplate: '{testDir}/{testFileDir}/__snapshots__/{arg}-{projectName}{ext}',
|
|
16
|
+
expect: {
|
|
17
|
+
toHaveScreenshot: {
|
|
18
|
+
maxDiffPixels: 100,
|
|
19
|
+
maxDiffPixelRatio: 0.01,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
use: {
|
|
23
|
+
baseURL: 'http://localhost:3000',
|
|
24
|
+
trace: 'retain-on-failure',
|
|
25
|
+
},
|
|
26
|
+
projects: [
|
|
27
|
+
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
|
|
28
|
+
{ name: 'mobile', use: { ...devices['iPhone 13'] } },
|
|
29
|
+
],
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Snapshot Path Template
|
|
34
|
+
|
|
35
|
+
| Variable | Description |
|
|
36
|
+
|----------|-------------|
|
|
37
|
+
| `{testDir}` | Test directory |
|
|
38
|
+
| `{testFileDir}` | Directory of test file |
|
|
39
|
+
| `{arg}` | Screenshot name |
|
|
40
|
+
| `{projectName}` | Project (browser/viewport) |
|
|
41
|
+
| `{ext}` | `.png` |
|
|
42
|
+
|
|
43
|
+
### Update Snapshots
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx playwright test --update-snapshots
|
|
47
|
+
npx playwright test visual/ --update-snapshots
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Per-Test Override
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
test('strict comparison', async ({ page }) => {
|
|
54
|
+
await expect(page).toHaveScreenshot('strict.png', {
|
|
55
|
+
maxDiffPixels: 0,
|
|
56
|
+
maxDiffPixelRatio: 0,
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Percy Configuration
|
|
62
|
+
|
|
63
|
+
### Installation
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm install @percy/cli @percy/playwright --save-dev
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### percy.config.js
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
72
|
+
module.exports = {
|
|
73
|
+
version: 2,
|
|
74
|
+
static: {
|
|
75
|
+
path: 'dist',
|
|
76
|
+
},
|
|
77
|
+
discovery: {
|
|
78
|
+
allowed-hostnames: ['localhost', '127.0.0.1'],
|
|
79
|
+
disallowed-hostnames: [],
|
|
80
|
+
network-idle-timeout: 750,
|
|
81
|
+
},
|
|
82
|
+
snapshot: {
|
|
83
|
+
widths: [1280, 375],
|
|
84
|
+
minHeight: 1024,
|
|
85
|
+
percyCSS: '',
|
|
86
|
+
enableJavaScript: true,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Playwright Integration
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
// playwright.config.ts
|
|
95
|
+
import { defineConfig } from '@playwright/test';
|
|
96
|
+
|
|
97
|
+
export default defineConfig({
|
|
98
|
+
testDir: './e2e',
|
|
99
|
+
reporter: [['list'], ['html']],
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
percy exec -- npx playwright test
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Snapshot in Test
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { test, expect } from '@playwright/test';
|
|
111
|
+
import percySnapshot from '@percy/playwright';
|
|
112
|
+
|
|
113
|
+
test('homepage', async ({ page }) => {
|
|
114
|
+
await page.goto('/');
|
|
115
|
+
await percySnapshot(page, 'Homepage');
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Environment Variables
|
|
120
|
+
|
|
121
|
+
| Variable | Description |
|
|
122
|
+
|----------|-------------|
|
|
123
|
+
| `PERCY_TOKEN` | Project token (required for upload) |
|
|
124
|
+
| `PERCY_BRANCH` | Branch name |
|
|
125
|
+
| `PERCY_PARTIAL_BUILD` | For parallelized runs |
|
|
126
|
+
|
|
127
|
+
## BackstopJS Configuration
|
|
128
|
+
|
|
129
|
+
### Installation
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npm install backstopjs --save-dev
|
|
133
|
+
npx backstop init
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### backstop.json
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"id": "visual_regression",
|
|
141
|
+
"viewports": [
|
|
142
|
+
{ "label": "desktop", "width": 1920, "height": 1080 },
|
|
143
|
+
{ "label": "tablet", "width": 768, "height": 1024 },
|
|
144
|
+
{ "label": "mobile", "width": 375, "height": 667 }
|
|
145
|
+
],
|
|
146
|
+
"scenarios": [
|
|
147
|
+
{
|
|
148
|
+
"label": "Homepage",
|
|
149
|
+
"url": "http://localhost:3000/",
|
|
150
|
+
"referenceUrl": "",
|
|
151
|
+
"readyEvent": "",
|
|
152
|
+
"readySelector": "",
|
|
153
|
+
"delay": 500,
|
|
154
|
+
"hideSelectors": [".timestamp", ".ad-banner"],
|
|
155
|
+
"removeSelectors": [],
|
|
156
|
+
"selectorExpansion": true,
|
|
157
|
+
"expect": 0,
|
|
158
|
+
"misMatchThreshold": 0.1
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"label": "Login",
|
|
162
|
+
"url": "http://localhost:3000/login",
|
|
163
|
+
"delay": 500,
|
|
164
|
+
"misMatchThreshold": 0.1
|
|
165
|
+
}
|
|
166
|
+
],
|
|
167
|
+
"paths": {
|
|
168
|
+
"bitmaps_reference": "backstop_data/bitmaps_reference",
|
|
169
|
+
"bitmaps_test": "backstop_data/bitmaps_test",
|
|
170
|
+
"engine_scripts": "backstop_data/engine_scripts",
|
|
171
|
+
"html_report": "backstop_data/html_report",
|
|
172
|
+
"ci_report": "backstop_data/ci_report"
|
|
173
|
+
},
|
|
174
|
+
"report": ["browser", "CI"],
|
|
175
|
+
"engine": "playwright",
|
|
176
|
+
"engineOptions": {
|
|
177
|
+
"args": ["--no-sandbox"]
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Scenario Options
|
|
183
|
+
|
|
184
|
+
| Option | Description |
|
|
185
|
+
|-------|-------------|
|
|
186
|
+
| `label` | Scenario name |
|
|
187
|
+
| `url` | Page URL |
|
|
188
|
+
| `delay` | Wait (ms) before capture |
|
|
189
|
+
| `hideSelectors` | Hide but keep layout |
|
|
190
|
+
| `removeSelectors` | Remove from DOM |
|
|
191
|
+
| `misMatchThreshold` | Tolerance (0–1) |
|
|
192
|
+
| `selector` | Capture specific element only |
|
|
193
|
+
|
|
194
|
+
### Commands
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
backstop test # Run comparison
|
|
198
|
+
backstop approve # Update reference images
|
|
199
|
+
backstop reference # Alias for approve
|
|
200
|
+
backstop openReport # Open HTML report
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Docker
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
docker run --rm -v $(pwd):/src backstopjs/backstopjs test
|
|
207
|
+
docker run --rm -v $(pwd):/src backstopjs/backstopjs approve
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Tool Comparison
|
|
211
|
+
|
|
212
|
+
| Feature | Playwright | Percy | BackstopJS |
|
|
213
|
+
|---------|------------|-------|------------|
|
|
214
|
+
| Setup | Built-in | npm + token | npm or Docker |
|
|
215
|
+
| Baselines | Local | Cloud | Local |
|
|
216
|
+
| Review UI | Diff artifacts | Web dashboard | HTML report |
|
|
217
|
+
| Viewports | Projects | Config | backstop.json |
|
|
218
|
+
| Masking | mask option | percyCSS | hideSelectors |
|
|
219
|
+
| CI | Native | percy exec | backstop test |
|
|
220
|
+
| Cost | Free | Paid (free tier) | Free |
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# Visual Regression Patterns
|
|
2
|
+
|
|
3
|
+
Screenshot strategies, masking, viewports, and threshold configuration for visual regression testing.
|
|
4
|
+
|
|
5
|
+
## Screenshot Strategies
|
|
6
|
+
|
|
7
|
+
### Full Page vs Element
|
|
8
|
+
|
|
9
|
+
| Strategy | Use Case | Example |
|
|
10
|
+
|----------|----------|---------|
|
|
11
|
+
| **Full page** | Layout, scroll behavior, long pages | `expect(page).toHaveScreenshot({ fullPage: true })` |
|
|
12
|
+
| **Viewport** | Above-the-fold, fixed viewport | `expect(page).toHaveScreenshot()` (default) |
|
|
13
|
+
| **Element** | Component, modal, header | `expect(locator).toHaveScreenshot()` |
|
|
14
|
+
| **Multiple elements** | Key sections | Capture each with unique names |
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
// Full page
|
|
18
|
+
await expect(page).toHaveScreenshot('homepage-full.png', { fullPage: true });
|
|
19
|
+
|
|
20
|
+
// Viewport only
|
|
21
|
+
await expect(page).toHaveScreenshot('homepage-viewport.png');
|
|
22
|
+
|
|
23
|
+
// Element
|
|
24
|
+
await expect(page.getByRole('banner')).toHaveScreenshot('header.png');
|
|
25
|
+
await expect(page.getByTestId('product-card')).toHaveScreenshot('product-card.png');
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### When to Use Each
|
|
29
|
+
|
|
30
|
+
- **Full page:** Marketing pages, documentation, long forms
|
|
31
|
+
- **Viewport:** Hero sections, dashboards, fixed layouts
|
|
32
|
+
- **Element:** Reusable components, modals, cards, headers
|
|
33
|
+
|
|
34
|
+
## Dynamic Content Masking
|
|
35
|
+
|
|
36
|
+
### Playwright Mask
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
await expect(page).toHaveScreenshot('dashboard.png', {
|
|
40
|
+
mask: [
|
|
41
|
+
page.getByTestId('user-avatar'),
|
|
42
|
+
page.getByTestId('timestamp'),
|
|
43
|
+
page.locator('.ad-banner'),
|
|
44
|
+
],
|
|
45
|
+
maskColor: '#000000', // Optional: color for masked regions
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Common Elements to Mask
|
|
50
|
+
|
|
51
|
+
| Element | Reason |
|
|
52
|
+
|---------|--------|
|
|
53
|
+
| Timestamps | Always changing |
|
|
54
|
+
| User avatars | User-specific |
|
|
55
|
+
| Ads | Third-party, variable |
|
|
56
|
+
| Charts/graphs | May use random data |
|
|
57
|
+
| "X minutes ago" | Relative time |
|
|
58
|
+
| Session IDs, tokens | Security, uniqueness |
|
|
59
|
+
|
|
60
|
+
### Percy Masking
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
await percySnapshot(page, 'Dashboard', {
|
|
64
|
+
percyCSS: `
|
|
65
|
+
[data-testid="timestamp"] { visibility: hidden; }
|
|
66
|
+
.ad-banner { display: none; }
|
|
67
|
+
`,
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### BackstopJS Selectors to Hide
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"scenarios": [{
|
|
76
|
+
"url": "https://example.com/dashboard",
|
|
77
|
+
"hideSelectors": [".timestamp", ".ad-banner", "[data-testid='avatar']"]
|
|
78
|
+
}]
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Viewport Variations
|
|
83
|
+
|
|
84
|
+
### Playwright Projects
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// playwright.config.ts
|
|
88
|
+
projects: [
|
|
89
|
+
{ name: 'desktop', use: { ...devices['Desktop Chrome'], viewport: { width: 1920, height: 1080 } } },
|
|
90
|
+
{ name: 'tablet', use: { ...devices['iPad Pro'] } },
|
|
91
|
+
{ name: 'mobile', use: { ...devices['iPhone 13'] } },
|
|
92
|
+
],
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Snapshot Naming with Viewport
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
test('homepage visual', async ({ page }, testInfo) => {
|
|
99
|
+
await page.goto('/');
|
|
100
|
+
const project = testInfo.project.name;
|
|
101
|
+
await expect(page).toHaveScreenshot(`homepage-${project}.png`);
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### BackstopJS Viewports
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"viewports": [
|
|
110
|
+
{ "label": "desktop", "width": 1920, "height": 1080 },
|
|
111
|
+
{ "label": "tablet", "width": 768, "height": 1024 },
|
|
112
|
+
{ "label": "mobile", "width": 375, "height": 667 }
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Recommended Breakpoints
|
|
118
|
+
|
|
119
|
+
| Label | Width | Height | Use |
|
|
120
|
+
|-------|-------|--------|-----|
|
|
121
|
+
| Desktop | 1920 | 1080 | Primary desktop |
|
|
122
|
+
| Tablet | 768 | 1024 | iPad portrait |
|
|
123
|
+
| Mobile | 375 | 667 | iPhone SE / small phone |
|
|
124
|
+
| Mobile large | 414 | 896 | iPhone 11+ |
|
|
125
|
+
|
|
126
|
+
## Threshold Configuration
|
|
127
|
+
|
|
128
|
+
### Playwright
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
await expect(page).toHaveScreenshot('page.png', {
|
|
132
|
+
maxDiffPixels: 100, // Absolute pixel count
|
|
133
|
+
maxDiffPixelRatio: 0.01, // 1% of pixels
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
| Option | Description | When to Use |
|
|
138
|
+
|--------|-------------|-------------|
|
|
139
|
+
| `maxDiffPixels` | Max differing pixels | Font/subpixel differences |
|
|
140
|
+
| `maxDiffPixelRatio` | Max ratio (0–1) | Proportional tolerance |
|
|
141
|
+
|
|
142
|
+
### BackstopJS
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"scenarios": [{
|
|
147
|
+
"misMatchThreshold": 0.1
|
|
148
|
+
}]
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
- `0` = strict (no tolerance)
|
|
153
|
+
- `0.1` = 0.1% tolerance
|
|
154
|
+
- `1` = 100% (accept all)
|
|
155
|
+
|
|
156
|
+
### Percy
|
|
157
|
+
|
|
158
|
+
Percy uses built-in diff engine; configure via dashboard or `percy.config.js` for ignore regions.
|
|
159
|
+
|
|
160
|
+
## Animation Disabling
|
|
161
|
+
|
|
162
|
+
### CSS Override (Playwright)
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
await page.addStyleTag({
|
|
166
|
+
content: `
|
|
167
|
+
*, *::before, *::after {
|
|
168
|
+
animation-duration: 0s !important;
|
|
169
|
+
animation-delay: 0s !important;
|
|
170
|
+
transition-duration: 0s !important;
|
|
171
|
+
}
|
|
172
|
+
`,
|
|
173
|
+
});
|
|
174
|
+
await expect(page).toHaveScreenshot('static.png');
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### prefers-reduced-motion
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
await page.emulateMedia({ reducedMotion: 'reduce' });
|
|
181
|
+
await expect(page).toHaveScreenshot('reduced-motion.png');
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Wait for Stability
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
await page.waitForLoadState('networkidle');
|
|
188
|
+
await page.waitForTimeout(500); // Allow animations to settle
|
|
189
|
+
await expect(page).toHaveScreenshot('stable.png');
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Element Screenshot Patterns
|
|
193
|
+
|
|
194
|
+
### Scroll Into View
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
await page.getByTestId('footer').scrollIntoViewIfNeeded();
|
|
198
|
+
await expect(page.getByTestId('footer')).toHaveScreenshot('footer.png');
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Modal / Overlay
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
await page.getByRole('button', { name: 'Open modal' }).click();
|
|
205
|
+
await expect(page.getByRole('dialog')).toHaveScreenshot('modal.png');
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Hover State
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
await page.getByTestId('card').hover();
|
|
212
|
+
await expect(page.getByTestId('card')).toHaveScreenshot('card-hover.png');
|
|
213
|
+
```
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qa-vitest-writer
|
|
3
|
+
description: Generate Vitest unit and integration tests for TypeScript projects with ESM-native support, Vite integration, and Jest-compatible API.
|
|
4
|
+
output_dir: tests/unit
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# QA Vitest Writer
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
Write Vitest unit and integration tests from test case specifications. Transform structured test cases (from qa-testcase-from-docs, qa-manual-test-designer, or specs) into executable Vitest code with proper mocking, fixtures, and assertions.
|
|
12
|
+
|
|
13
|
+
## Trigger Phrases
|
|
14
|
+
|
|
15
|
+
- "Write Vitest tests for [module/feature]"
|
|
16
|
+
- "Generate Vitest unit tests from test cases"
|
|
17
|
+
- "Create Vitest integration tests"
|
|
18
|
+
- "Add Vitest tests for [spec/requirements]"
|
|
19
|
+
- "Migrate Jest tests to Vitest"
|
|
20
|
+
- "Vitest tests with mocks and fixtures"
|
|
21
|
+
- "In-source Vitest tests for [component]"
|
|
22
|
+
- "Parameterized Vitest tests (test.each)"
|
|
23
|
+
|
|
24
|
+
## Key Advantages
|
|
25
|
+
|
|
26
|
+
| Advantage | Description |
|
|
27
|
+
| --------- | ----------- |
|
|
28
|
+
| **ESM-native** | No CommonJS transformation; native `import`/`export` |
|
|
29
|
+
| **Vite integration** | Uses Vite for fast transforms, HMR, and config |
|
|
30
|
+
| **Watch mode** | Instant re-runs on file changes |
|
|
31
|
+
| **Jest-compatible API** | `describe`/`it`/`test`, `expect`, `vi` (like `jest`) |
|
|
32
|
+
| **In-source testing** | Co-locate tests with source (`__tests__` or `*.test.ts`) |
|
|
33
|
+
| **Workspace support** | Monorepo config with project-level overrides |
|
|
34
|
+
|
|
35
|
+
## Workflow
|
|
36
|
+
|
|
37
|
+
1. **Read test cases** — From specs, requirements, or manual test designs
|
|
38
|
+
2. **Analyze code** — Inspect module under test: exports, dependencies, types
|
|
39
|
+
3. **Generate tests** — Produce `describe`/`it` blocks with assertions
|
|
40
|
+
4. **Add mocks/fixtures** — Use `vi.mock`, `vi.fn`, `vi.spyOn`, fixtures as needed
|
|
41
|
+
5. **Verify** — Ensure tests run and pass; fix any config or import issues
|
|
42
|
+
|
|
43
|
+
## Context7 MCP
|
|
44
|
+
|
|
45
|
+
Use **Context7 MCP** for current Vitest documentation when:
|
|
46
|
+
- API signatures or options are uncertain
|
|
47
|
+
- New Vitest features (e.g., `vi.hoisted`, workspace config) need verification
|
|
48
|
+
- Migration from Jest requires up-to-date compatibility notes
|
|
49
|
+
|
|
50
|
+
## Key Patterns
|
|
51
|
+
|
|
52
|
+
| Pattern | Usage |
|
|
53
|
+
| ------- | ----- |
|
|
54
|
+
| `describe` / `it` / `test` | Test structure (Jest-compatible) |
|
|
55
|
+
| `vi.mock()` | Module substitution; hoisted before imports |
|
|
56
|
+
| `vi.fn()` | Mock function with call tracking |
|
|
57
|
+
| `vi.spyOn()` | Spy on existing method; optionally replace |
|
|
58
|
+
| `vi.hoisted()` | Run code before imports (ESM mocking) |
|
|
59
|
+
| In-source testing | `__tests__/` or `{module}.test.ts` / `{module}.spec.ts` |
|
|
60
|
+
| Snapshot testing | `expect(obj).toMatchSnapshot()` |
|
|
61
|
+
| Parameterized | `test.each([...])` / `it.each([...])` |
|
|
62
|
+
| Concurrent | `it.concurrent` / `test.concurrent` |
|
|
63
|
+
|
|
64
|
+
See `references/patterns.md` for detailed patterns.
|
|
65
|
+
|
|
66
|
+
## Configuration
|
|
67
|
+
|
|
68
|
+
- **Config file:** `vitest.config.ts` or `vite.config.ts` with `test` block
|
|
69
|
+
- **Workspace:** `vitest.workspace.ts` for monorepos
|
|
70
|
+
- **Coverage:** `v8` or `istanbul` via `@vitest/coverage-v8` / `@vitest/coverage-istanbul`
|
|
71
|
+
|
|
72
|
+
See `references/config.md` for configuration patterns.
|
|
73
|
+
|
|
74
|
+
## Migration from Jest
|
|
75
|
+
|
|
76
|
+
| Jest | Vitest | Notes |
|
|
77
|
+
| ---- | ------ | ----- |
|
|
78
|
+
| `jest.mock()` | `vi.mock()` | Same semantics; hoisted |
|
|
79
|
+
| `jest.fn()` | `vi.fn()` | Same API |
|
|
80
|
+
| `jest.spyOn()` | `vi.spyOn()` | Same API |
|
|
81
|
+
| `jest.useFakeTimers()` | `vi.useFakeTimers()` | Same API |
|
|
82
|
+
| `beforeAll` / `afterAll` | Same | Unchanged |
|
|
83
|
+
| `beforeEach` / `afterEach` | Same | Unchanged |
|
|
84
|
+
|
|
85
|
+
ESM: Use `vi.hoisted()` when variables must be available in `vi.mock` factory. See `references/best-practices.md`.
|
|
86
|
+
|
|
87
|
+
## File Naming
|
|
88
|
+
|
|
89
|
+
- `{module}.test.ts` — Preferred for unit tests
|
|
90
|
+
- `{module}.spec.ts` — Alternative; common for integration tests
|
|
91
|
+
- `__tests__/{module}.test.ts` — Co-located in source directory
|
|
92
|
+
|
|
93
|
+
## Scope
|
|
94
|
+
|
|
95
|
+
**Can do (autonomous):**
|
|
96
|
+
- Generate Vitest unit and integration tests from test cases
|
|
97
|
+
- Add mocks (`vi.mock`, `vi.fn`, `vi.spyOn`), fixtures, and setup/teardown
|
|
98
|
+
- Use `test.each` for parameterized tests; `it.concurrent` for parallel runs
|
|
99
|
+
- Configure `vitest.config.ts` and coverage
|
|
100
|
+
- Migrate Jest tests to Vitest (syntax and API mapping)
|
|
101
|
+
- Call qa-diagram-generator for test flow diagrams if needed
|
|
102
|
+
|
|
103
|
+
**Cannot do (requires confirmation):**
|
|
104
|
+
- Change production code to satisfy tests
|
|
105
|
+
- Add tests for requirements not in source documents
|
|
106
|
+
- Override project-level Vitest/Vite config without approval
|
|
107
|
+
|
|
108
|
+
**Will not do (out of scope):**
|
|
109
|
+
- Execute tests (user runs `vitest` or `npm test`)
|
|
110
|
+
- Write Playwright/Cypress E2E tests (use qa-playwright-ts-writer)
|
|
111
|
+
- Modify CI/CD pipelines
|
|
112
|
+
|
|
113
|
+
## References
|
|
114
|
+
|
|
115
|
+
- `references/patterns.md` — ESM mocking, in-source testing, concurrent tests, workspace
|
|
116
|
+
- `references/assertions.md` — Vitest/Chai assertion reference
|
|
117
|
+
- `references/config.md` — vitest.config.ts, coverage, workspace, plugins
|
|
118
|
+
- `references/best-practices.md` — Best practices, Jest migration patterns
|
|
119
|
+
|
|
120
|
+
## Quality Checklist
|
|
121
|
+
|
|
122
|
+
- [ ] Tests match test case steps and expected results
|
|
123
|
+
- [ ] Mocks are properly scoped (per test or per describe)
|
|
124
|
+
- [ ] No hardcoded secrets or sensitive data
|
|
125
|
+
- [ ] Assertions are specific (avoid only `toBeTruthy` where value matters)
|
|
126
|
+
- [ ] `beforeEach`/`afterEach` restore state; mocks reset where needed
|
|
127
|
+
- [ ] File naming follows project convention (`*.test.ts` or `*.spec.ts`)
|
|
128
|
+
- [ ] Imports use ESM (`import`); no `require` unless required by dependency
|
|
129
|
+
- [ ] Coverage targets considered if specified in requirements
|
|
130
|
+
|
|
131
|
+
## Troubleshooting
|
|
132
|
+
|
|
133
|
+
| Symptom | Likely Cause | Fix |
|
|
134
|
+
| ------- | ------------ | --- |
|
|
135
|
+
| `vi.mock` not working | ESM hoisting; variable not in scope | Use `vi.hoisted()` to define variables before imports |
|
|
136
|
+
| Mock returns undefined | Factory not returning correct shape | Ensure factory returns object matching module exports |
|
|
137
|
+
| Tests pass individually, fail together | Shared mutable state | Reset mocks in `beforeEach`; use `vi.clearAllMocks()` |
|
|
138
|
+
| `import.meta.env` wrong in tests | Env not set for test | Use `vi.stubEnv()` with `unstubEnvs: true` in config |
|
|
139
|
+
| Coverage not collected | Reporter not configured | Add `@vitest/coverage-v8`, set `coverage.reporter` |
|
|
140
|
+
| Slow test runs | No workspace or wrong config | Use `vitest.workspace.ts`; exclude node_modules |
|
|
141
|
+
| Type errors in mocks | Mock shape doesn't match types | Use `vi.mocked()` or type assertions; match export shape |
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Vitest / Chai Assertion Reference
|
|
2
|
+
|
|
3
|
+
Vitest uses the same assertion API as Jest (which is built on Chai). All assertions are available via `expect()`.
|
|
4
|
+
|
|
5
|
+
## Equality
|
|
6
|
+
|
|
7
|
+
| Assertion | Description |
|
|
8
|
+
| --------- | ----------- |
|
|
9
|
+
| `expect(x).toBe(y)` | Strict equality (`Object.is`) |
|
|
10
|
+
| `expect(x).toEqual(y)` | Deep equality for objects/arrays |
|
|
11
|
+
| `expect(x).toStrictEqual(y)` | Deep equality + type checks (undefined, etc.) |
|
|
12
|
+
| `expect(x).not.toBe(y)` | Negation |
|
|
13
|
+
|
|
14
|
+
## Truthiness
|
|
15
|
+
|
|
16
|
+
| Assertion | Description |
|
|
17
|
+
| --------- | ----------- |
|
|
18
|
+
| `expect(x).toBeTruthy()` | Truthy value |
|
|
19
|
+
| `expect(x).toBeFalsy()` | Falsy value |
|
|
20
|
+
| `expect(x).toBeDefined()` | Not `undefined` |
|
|
21
|
+
| `expect(x).toBeUndefined()` | `undefined` |
|
|
22
|
+
| `expect(x).toBeNull()` | `null` |
|
|
23
|
+
|
|
24
|
+
## Numbers
|
|
25
|
+
|
|
26
|
+
| Assertion | Description |
|
|
27
|
+
| --------- | ----------- |
|
|
28
|
+
| `expect(n).toBeGreaterThan(m)` | `n > m` |
|
|
29
|
+
| `expect(n).toBeGreaterThanOrEqual(m)` | `n >= m` |
|
|
30
|
+
| `expect(n).toBeLessThan(m)` | `n < m` |
|
|
31
|
+
| `expect(n).toBeLessThanOrEqual(m)` | `n <= m` |
|
|
32
|
+
| `expect(n).toBeCloseTo(m, numDigits)` | Float comparison with precision |
|
|
33
|
+
| `expect(n).toBeNaN()` | `NaN` |
|
|
34
|
+
|
|
35
|
+
## Strings
|
|
36
|
+
|
|
37
|
+
| Assertion | Description |
|
|
38
|
+
| --------- | ----------- |
|
|
39
|
+
| `expect(s).toMatch(/regex/)` | Matches regex |
|
|
40
|
+
| `expect(s).toContain(substr)` | Includes substring |
|
|
41
|
+
| `expect(s).toHaveLength(n)` | Length equals n |
|
|
42
|
+
|
|
43
|
+
## Arrays and Iterables
|
|
44
|
+
|
|
45
|
+
| Assertion | Description |
|
|
46
|
+
| --------- | ----------- |
|
|
47
|
+
| `expect(arr).toContain(item)` | Array contains item |
|
|
48
|
+
| `expect(arr).toContainEqual(item)` | Array contains object matching shape |
|
|
49
|
+
| `expect(arr).toHaveLength(n)` | Array length |
|
|
50
|
+
| `expect(arr).toEqual(expect.arrayContaining([...]))` | Array contains subset |
|
|
51
|
+
|
|
52
|
+
## Objects
|
|
53
|
+
|
|
54
|
+
| Assertion | Description |
|
|
55
|
+
| --------- | ----------- |
|
|
56
|
+
| `expect(obj).toHaveProperty(key)` | Has property |
|
|
57
|
+
| `expect(obj).toHaveProperty(key, value)` | Property equals value |
|
|
58
|
+
| `expect(obj).toMatchObject(partial)` | Contains subset of properties |
|
|
59
|
+
| `expect(obj).toHaveLength(n)` | For array-like (length property) |
|
|
60
|
+
|
|
61
|
+
## Functions and Mocks
|
|
62
|
+
|
|
63
|
+
| Assertion | Description |
|
|
64
|
+
| --------- | ----------- |
|
|
65
|
+
| `expect(fn).toHaveBeenCalled()` | Called at least once |
|
|
66
|
+
| `expect(fn).toHaveBeenCalledTimes(n)` | Called exactly n times |
|
|
67
|
+
| `expect(fn).toHaveBeenCalledWith(arg1, arg2)` | Called with specific args |
|
|
68
|
+
| `expect(fn).toHaveBeenLastCalledWith(arg1, arg2)` | Last call args |
|
|
69
|
+
| `expect(fn).toHaveBeenNthCalledWith(n, arg1, arg2)` | Nth call args |
|
|
70
|
+
| `expect(fn).toHaveReturned()` | Returned (did not throw) |
|
|
71
|
+
| `expect(fn).toHaveReturnedWith(value)` | Returned specific value |
|
|
72
|
+
| `expect(fn).toThrow()` | Threw an error |
|
|
73
|
+
| `expect(fn).toThrow(error)` | Threw specific error type/message |
|
|
74
|
+
|
|
75
|
+
## Async
|
|
76
|
+
|
|
77
|
+
| Assertion | Description |
|
|
78
|
+
| --------- | ----------- |
|
|
79
|
+
| `await expect(promise).resolves.toBe(value)` | Resolved value |
|
|
80
|
+
| `await expect(promise).rejects.toThrow()` | Rejected with error |
|
|
81
|
+
|
|
82
|
+
## Snapshots
|
|
83
|
+
|
|
84
|
+
| Assertion | Description |
|
|
85
|
+
| --------- | ----------- |
|
|
86
|
+
| `expect(obj).toMatchSnapshot()` | File snapshot |
|
|
87
|
+
| `expect(obj).toMatchInlineSnapshot(\`...\`)` | Inline snapshot |
|
|
88
|
+
|
|
89
|
+
## Type Assertions (TypeScript)
|
|
90
|
+
|
|
91
|
+
Use `expect.any(constructor)` for flexible matching:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
expect(fn).toHaveBeenCalledWith(expect.any(String), expect.any(Number))
|
|
95
|
+
expect(obj).toEqual({ id: expect.any(Number), name: expect.any(String) })
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Negation
|
|
99
|
+
|
|
100
|
+
Prefix any assertion with `.not`:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
expect(x).not.toBeNull()
|
|
104
|
+
expect(arr).not.toContain(undefined)
|
|
105
|
+
```
|