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,62 @@
|
|
|
1
|
+
# Vitest Best Practices
|
|
2
|
+
|
|
3
|
+
## Test Structure
|
|
4
|
+
|
|
5
|
+
1. **One assertion focus per test** — Prefer narrow tests; use multiple `it` blocks instead of one test with many assertions when behaviors differ.
|
|
6
|
+
2. **Descriptive names** — Test names should read like specs: `it('returns 404 when user not found', ...)`.
|
|
7
|
+
3. **Arrange-Act-Assert** — Structure tests: setup → call code under test → assert.
|
|
8
|
+
|
|
9
|
+
## Mocking
|
|
10
|
+
|
|
11
|
+
1. **Prefer vi.spyOn when possible** — More type-safe and flexible than full module replacement.
|
|
12
|
+
2. **Use vi.hoisted for ESM** — When `vi.mock` factory needs variables, define them with `vi.hoisted()`.
|
|
13
|
+
3. **Reset mocks between tests** — Use `beforeEach(() => vi.clearAllMocks())` to avoid cross-test pollution.
|
|
14
|
+
4. **Mock at the boundary** — Mock external services (HTTP, DB), not internal implementation details.
|
|
15
|
+
|
|
16
|
+
## Isolation
|
|
17
|
+
|
|
18
|
+
1. **No shared mutable state** — Each test should be independent; use `beforeEach` for fresh state.
|
|
19
|
+
2. **Concurrent tests** — Use `it.concurrent` only when tests have no shared state.
|
|
20
|
+
3. **Clean up** — Restore spies, clear timers, reset env in `afterEach` when needed.
|
|
21
|
+
|
|
22
|
+
## Assertions
|
|
23
|
+
|
|
24
|
+
1. **Prefer specific assertions** — Use `toBe(5)` over `toBeTruthy()` when the value matters.
|
|
25
|
+
2. **Use toStrictEqual for objects** — Catches `undefined` vs missing key differences.
|
|
26
|
+
3. **Avoid snapshot overuse** — Use for stable, structured output; avoid for frequently changing UI.
|
|
27
|
+
|
|
28
|
+
## Performance
|
|
29
|
+
|
|
30
|
+
1. **Exclude unnecessary files** — Ensure `node_modules`, `dist`, and non-test paths are excluded.
|
|
31
|
+
2. **Use workspace for monorepos** — Split projects to parallelize and scope config.
|
|
32
|
+
3. **Mock heavy dependencies** — Don't load real DBs, external APIs, or large libs in unit tests.
|
|
33
|
+
|
|
34
|
+
## Migration from Jest
|
|
35
|
+
|
|
36
|
+
### API Mapping
|
|
37
|
+
|
|
38
|
+
| Jest | Vitest |
|
|
39
|
+
| ---- | ------ |
|
|
40
|
+
| `jest.mock()` | `vi.mock()` |
|
|
41
|
+
| `jest.fn()` | `vi.fn()` |
|
|
42
|
+
| `jest.spyOn()` | `vi.spyOn()` |
|
|
43
|
+
| `jest.useFakeTimers()` | `vi.useFakeTimers()` |
|
|
44
|
+
| `jest.runAllTimers()` | `vi.runAllTimers()` |
|
|
45
|
+
| `jest.setSystemTime()` | `vi.setSystemTime()` |
|
|
46
|
+
| `jest.resetModules()` | `vi.resetModules()` |
|
|
47
|
+
|
|
48
|
+
### Key Differences
|
|
49
|
+
|
|
50
|
+
1. **ESM by default** — Vitest is ESM-native; use `import`/`export`. For `vi.mock` factory variables, use `vi.hoisted()`.
|
|
51
|
+
2. **Config** — Vitest uses `vitest.config.ts` or `vite.config.ts` with a `test` block, not `jest.config.js`.
|
|
52
|
+
3. **Globals** — Enable `globals: true` for `describe`, `it`, `expect`, `vi` without imports.
|
|
53
|
+
4. **Coverage** — Use `@vitest/coverage-v8` or `@vitest/coverage-istanbul`; configure under `test.coverage`.
|
|
54
|
+
|
|
55
|
+
### Migration Steps
|
|
56
|
+
|
|
57
|
+
1. Install Vitest: `npm i -D vitest`
|
|
58
|
+
2. Add `vitest.config.ts` (or `test` block to `vite.config.ts`)
|
|
59
|
+
3. Replace `jest` with `vi` in test files
|
|
60
|
+
4. Update `package.json` scripts: `"test": "vitest"`
|
|
61
|
+
5. Fix ESM issues: add `vi.hoisted()` where `vi.mock` needs variables
|
|
62
|
+
6. Run tests and fix any environment or config differences
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Vitest Configuration
|
|
2
|
+
|
|
3
|
+
## Basic vitest.config.ts
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { defineConfig } from 'vitest/config'
|
|
7
|
+
import tsconfigPaths from 'vite-tsconfig-paths'
|
|
8
|
+
|
|
9
|
+
export default defineConfig({
|
|
10
|
+
plugins: [tsconfigPaths()],
|
|
11
|
+
test: {
|
|
12
|
+
globals: true,
|
|
13
|
+
environment: 'node',
|
|
14
|
+
include: ['src/**/*.{test,spec}.{ts,tsx}', 'tests/**/*.{test,spec}.{ts,tsx}'],
|
|
15
|
+
exclude: ['node_modules', 'dist'],
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Vite Config Integration
|
|
21
|
+
|
|
22
|
+
When using Vite for the app, add a `test` block to `vite.config.ts`:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { defineConfig } from 'vite'
|
|
26
|
+
import react from '@vitejs/plugin-react'
|
|
27
|
+
|
|
28
|
+
export default defineConfig({
|
|
29
|
+
plugins: [react()],
|
|
30
|
+
test: {
|
|
31
|
+
globals: true,
|
|
32
|
+
environment: 'jsdom',
|
|
33
|
+
setupFiles: ['./tests/setup.ts'],
|
|
34
|
+
include: ['src/**/*.{test,spec}.{ts,tsx}'],
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Environment
|
|
40
|
+
|
|
41
|
+
| Value | Use Case |
|
|
42
|
+
| ----- | -------- |
|
|
43
|
+
| `node` | Node.js APIs, backend, CLI |
|
|
44
|
+
| `jsdom` | DOM APIs, React, Vue (browser-like) |
|
|
45
|
+
| `happy-dom` | Lighter DOM alternative |
|
|
46
|
+
| `edge-runtime` | Edge workers |
|
|
47
|
+
| Custom | Path to custom env file |
|
|
48
|
+
|
|
49
|
+
## Coverage
|
|
50
|
+
|
|
51
|
+
### v8 (recommended)
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
// vitest.config.ts
|
|
55
|
+
export default defineConfig({
|
|
56
|
+
test: {
|
|
57
|
+
coverage: {
|
|
58
|
+
provider: 'v8',
|
|
59
|
+
reporter: ['text', 'json', 'html'],
|
|
60
|
+
include: ['src/**/*.ts'],
|
|
61
|
+
exclude: ['src/**/*.test.ts', 'src/**/*.spec.ts'],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
})
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Install: `npm i -D @vitest/coverage-v8`
|
|
68
|
+
|
|
69
|
+
### Istanbul
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
coverage: {
|
|
73
|
+
provider: 'istanbul',
|
|
74
|
+
reporter: ['text', 'lcov', 'html'],
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Install: `npm i -D @vitest/coverage-istanbul`
|
|
79
|
+
|
|
80
|
+
## Workspace (Monorepo)
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
// vitest.workspace.ts
|
|
84
|
+
import { defineWorkspace } from 'vitest/config'
|
|
85
|
+
|
|
86
|
+
export default defineWorkspace([
|
|
87
|
+
'packages/core',
|
|
88
|
+
'packages/utils',
|
|
89
|
+
'apps/web',
|
|
90
|
+
])
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Each workspace project can define its own `vitest.config.ts` or `vite.config.ts`.
|
|
94
|
+
|
|
95
|
+
## Setup Files
|
|
96
|
+
|
|
97
|
+
Run code before all tests:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
test: {
|
|
101
|
+
setupFiles: ['./tests/setup.ts'],
|
|
102
|
+
globalSetup: './tests/globalSetup.ts',
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
- `setupFiles`: Runs in each test environment (e.g., per worker)
|
|
107
|
+
- `globalSetup`: Runs once before all tests
|
|
108
|
+
|
|
109
|
+
## Plugins
|
|
110
|
+
|
|
111
|
+
Common plugins:
|
|
112
|
+
|
|
113
|
+
- `vite-tsconfig-paths` — Resolve `@/` and tsconfig paths
|
|
114
|
+
- `@vitest/coverage-v8` — Coverage
|
|
115
|
+
- `@vitest/ui` — Browser UI for test runs
|
|
116
|
+
|
|
117
|
+
## Common Options
|
|
118
|
+
|
|
119
|
+
| Option | Description |
|
|
120
|
+
| ------ | ----------- |
|
|
121
|
+
| `globals` | Expose `describe`, `it`, `expect`, `vi` globally |
|
|
122
|
+
| `unstubEnvs` | Reset `vi.stubEnv` between tests |
|
|
123
|
+
| `unstubGlobals` | Reset `vi.stubGlobal` between tests |
|
|
124
|
+
| `pool` | `threads` (default) or `forks` |
|
|
125
|
+
| `poolMatchGlobs` | Limit which files run in which pool |
|
|
126
|
+
| `testTimeout` | Default timeout per test (ms) |
|
|
127
|
+
| `hookTimeout` | Timeout for before/after hooks (ms) |
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Vitest Test Patterns
|
|
2
|
+
|
|
3
|
+
## ESM Mocking
|
|
4
|
+
|
|
5
|
+
### vi.mock() Hoisting
|
|
6
|
+
|
|
7
|
+
`vi.mock()` is **hoisted** to the top of the file and runs before all imports. Variables used in the factory must be defined via `vi.hoisted()`:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { vi } from 'vitest'
|
|
11
|
+
|
|
12
|
+
const mockFn = vi.hoisted(() => vi.fn())
|
|
13
|
+
|
|
14
|
+
vi.mock('./my-module', () => ({
|
|
15
|
+
myFunction: mockFn,
|
|
16
|
+
}))
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### vi.spyOn vs vi.mock
|
|
20
|
+
|
|
21
|
+
| Use Case | Prefer | Reason |
|
|
22
|
+
| -------- | ------ | ------ |
|
|
23
|
+
| Replace entire module | `vi.mock()` | Full substitution |
|
|
24
|
+
| Spy on single export | `vi.spyOn(exports, 'name')` | Type-safe, flexible |
|
|
25
|
+
| Partial mock (keep some exports) | `vi.mock` with `importOriginal` | Merge original + overrides |
|
|
26
|
+
| Browser mode | `vi.mock` (vi.spyOn has limitations) | See Vitest browser docs |
|
|
27
|
+
|
|
28
|
+
### Partial Module Mock
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
vi.mock('./some-path.js', async (importOriginal) => {
|
|
32
|
+
const mod = await importOriginal<typeof import('./some-path.js')>()
|
|
33
|
+
return {
|
|
34
|
+
...mod,
|
|
35
|
+
mockedExport: vi.fn(),
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## In-Source Testing
|
|
41
|
+
|
|
42
|
+
### Layout Options
|
|
43
|
+
|
|
44
|
+
| Layout | Path | Use Case |
|
|
45
|
+
| ------ | ---- | -------- |
|
|
46
|
+
| Colocated | `src/utils/__tests__/format.test.ts` | Unit tests next to source |
|
|
47
|
+
| Suffix | `src/utils/format.test.ts` | Same directory, suffix |
|
|
48
|
+
| Separate | `tests/unit/utils/format.test.ts` | Centralized test dir |
|
|
49
|
+
|
|
50
|
+
### Config for In-Source
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
// vitest.config.ts
|
|
54
|
+
export default defineConfig({
|
|
55
|
+
test: {
|
|
56
|
+
include: ['src/**/*.{test,spec}.{ts,tsx}', 'tests/**/*.{test,spec}.{ts,tsx}'],
|
|
57
|
+
exclude: ['node_modules', 'dist'],
|
|
58
|
+
},
|
|
59
|
+
})
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Concurrent Tests
|
|
63
|
+
|
|
64
|
+
Run tests in parallel within a file:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
it.concurrent('test 1', async () => { /* ... */ })
|
|
68
|
+
it.concurrent('test 2', async () => { /* ... */ })
|
|
69
|
+
|
|
70
|
+
// Or with test.each
|
|
71
|
+
it.concurrent.each([
|
|
72
|
+
[1, 2, 3],
|
|
73
|
+
[4, 5, 9],
|
|
74
|
+
])('adds %i + %i = %i', async (a, b, expected) => {
|
|
75
|
+
expect(a + b).toBe(expected)
|
|
76
|
+
})
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Caveats:** Avoid shared mutable state; each concurrent test should be independent.
|
|
80
|
+
|
|
81
|
+
## Workspace Testing (Monorepos)
|
|
82
|
+
|
|
83
|
+
Use `vitest.workspace.ts` to define multiple projects:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
// vitest.workspace.ts
|
|
87
|
+
import { defineWorkspace } from 'vitest/config'
|
|
88
|
+
|
|
89
|
+
export default defineWorkspace([
|
|
90
|
+
'packages/*',
|
|
91
|
+
'apps/*',
|
|
92
|
+
])
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Each workspace entry can have its own `vitest.config.ts` or `vite.config.ts` with a `test` block.
|
|
96
|
+
|
|
97
|
+
## Parameterized Tests (test.each)
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
test.each([
|
|
101
|
+
{ a: 1, b: 2, expected: 3 },
|
|
102
|
+
{ a: 0, b: 0, expected: 0 },
|
|
103
|
+
])('adds $a + $b = $expected', ({ a, b, expected }) => {
|
|
104
|
+
expect(a + b).toBe(expected)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
// Array of arrays
|
|
108
|
+
test.each([
|
|
109
|
+
[1, 2, 3],
|
|
110
|
+
[4, 5, 9],
|
|
111
|
+
])('adds %i + %i = %i', (a, b, expected) => {
|
|
112
|
+
expect(a + b).toBe(expected)
|
|
113
|
+
})
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Snapshot Testing
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
expect(obj).toMatchSnapshot()
|
|
120
|
+
expect(html).toMatchInlineSnapshot(`<div>...</div>`)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Use inline snapshots for small, stable outputs; file snapshots for larger structures.
|
|
124
|
+
|
|
125
|
+
## Setup and Teardown
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
beforeAll(() => { /* once per describe */ })
|
|
129
|
+
afterAll(() => { /* once per describe */ })
|
|
130
|
+
beforeEach(() => { /* before each it */ })
|
|
131
|
+
afterEach(() => { /* after each it */ })
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Reset mocks in `beforeEach` to avoid cross-test pollution:
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
beforeEach(() => {
|
|
138
|
+
vi.clearAllMocks()
|
|
139
|
+
// or vi.restoreAllMocks() to restore original implementations
|
|
140
|
+
})
|
|
141
|
+
```
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qa-webdriverio-writer
|
|
3
|
+
description: Generate WebdriverIO E2E and mobile web tests for TypeScript using W3C WebDriver protocol with multi-browser support, Appium integration, and Page Object pattern.
|
|
4
|
+
output_dir: tests/e2e
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# QA WebdriverIO Writer
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
Write WebdriverIO E2E and mobile web tests from test case specifications. Transform structured test cases into executable TypeScript test files using the W3C WebDriver protocol, multi-browser support, Appium for mobile web, and the Page Object pattern.
|
|
12
|
+
|
|
13
|
+
## Trigger Phrases
|
|
14
|
+
|
|
15
|
+
- "Write WebdriverIO tests for [feature/flow]"
|
|
16
|
+
- "Generate WebdriverIO E2E tests from test cases"
|
|
17
|
+
- "Create WebdriverIO tests with Page Objects"
|
|
18
|
+
- "Add WebdriverIO mobile web tests"
|
|
19
|
+
- "WebdriverIO tests for [URL/flow]"
|
|
20
|
+
- "Multi-browser WebdriverIO tests"
|
|
21
|
+
- "Appium + WebdriverIO tests for mobile web"
|
|
22
|
+
- "WDIO tests with custom commands"
|
|
23
|
+
|
|
24
|
+
## Workflow
|
|
25
|
+
|
|
26
|
+
1. **Read test cases** — From qa-testcase-from-docs, qa-manual-test-designer, qa-browser-data-collector
|
|
27
|
+
2. **Analyze target** — Page structure, selectors, mobile vs desktop
|
|
28
|
+
3. **Generate test files** — Create `*.spec.ts` in `test/specs/` or project convention
|
|
29
|
+
4. **Add Page Objects** — Encapsulate selectors and actions in `pageobjects/`
|
|
30
|
+
5. **Configure wdio.conf.ts** — Capabilities, services, reporters
|
|
31
|
+
|
|
32
|
+
## Key Features
|
|
33
|
+
|
|
34
|
+
- **W3C WebDriver protocol** — Standard browser automation
|
|
35
|
+
- **Multi-browser** — Chrome, Firefox, Safari, Edge via capabilities
|
|
36
|
+
- **Appium integration** — Mobile web testing (iOS Safari, Android Chrome)
|
|
37
|
+
- **Page Object pattern** — Encapsulate page logic, reusable selectors
|
|
38
|
+
- **Built-in wait strategies** — `waitForDisplayed`, `waitForClickable`, `waitForExist`
|
|
39
|
+
- **WDIO test runner** — Parallel execution, retries, reporters
|
|
40
|
+
|
|
41
|
+
## Test Types
|
|
42
|
+
|
|
43
|
+
| Type | Scope | Approach |
|
|
44
|
+
|------|-------|----------|
|
|
45
|
+
| **E2E** | Full user flows, page navigation | browser.url, $(), $$(), click, setValue, getText |
|
|
46
|
+
| **Mobile Web** | Mobile browser testing | Appium service, mobile capabilities, viewport |
|
|
47
|
+
|
|
48
|
+
## E2E Testing
|
|
49
|
+
|
|
50
|
+
- **Navigation:** `browser.url()`, `browser.back()`, `browser.refresh()`
|
|
51
|
+
- **Selectors:** `$('selector')` single element, `$$('selector')` element array
|
|
52
|
+
- **Actions:** `.click()`, `.setValue()`, `.addValue()`, `.clearValue()`, `.selectByVisibleText()`
|
|
53
|
+
- **Getters:** `.getText()`, `.getAttribute()`, `.getValue()`, `.isDisplayed()`
|
|
54
|
+
- **Waits:** `.waitForDisplayed()`, `.waitForClickable()`, `.waitForExist()`, `browser.waitUntil()`
|
|
55
|
+
|
|
56
|
+
See `references/patterns.md` for selectors, waits, Page Objects, custom commands, file upload, multiremote.
|
|
57
|
+
|
|
58
|
+
## Page Object Pattern
|
|
59
|
+
|
|
60
|
+
- **Base page:** Shared selectors, navigation helpers, common actions
|
|
61
|
+
- **Page-specific:** Extend base; encapsulate page-specific locators and methods
|
|
62
|
+
- **WDIO Page Object** — Use `get` getters for lazy element resolution
|
|
63
|
+
|
|
64
|
+
See `references/best-practices.md` for Page Object structure.
|
|
65
|
+
|
|
66
|
+
## Key Patterns
|
|
67
|
+
|
|
68
|
+
- **Structure:** `describe` / `it`, `before` / `after`, `beforeEach` / `afterEach`
|
|
69
|
+
- **Selectors:** CSS, XPath, accessibility (aria), data attributes
|
|
70
|
+
- **Assertions:** `expect()` (Chai/Expect), `browser.assert` (if using expect-webdriverio)
|
|
71
|
+
- **Custom commands:** `browser.addCommand()` for reusable actions
|
|
72
|
+
- **Multiremote:** Run same test across multiple browsers in parallel
|
|
73
|
+
|
|
74
|
+
## Services
|
|
75
|
+
|
|
76
|
+
| Service | Purpose |
|
|
77
|
+
|---------|---------|
|
|
78
|
+
| `@wdio/local-runner` | Local test execution |
|
|
79
|
+
| `@wdio/mocha-framework` | Mocha describe/it (or Jasmine, Cucumber) |
|
|
80
|
+
| `wdio-chromedriver-service` | ChromeDriver for Chrome |
|
|
81
|
+
| `@wdio/appium-service` | Appium for mobile web |
|
|
82
|
+
| `@wdio/selenium-standalone-service` | Selenium Grid / standalone |
|
|
83
|
+
|
|
84
|
+
## Configuration
|
|
85
|
+
|
|
86
|
+
- **wdio.conf.ts** — Capabilities, services, framework, reporters, specs
|
|
87
|
+
- **Multi-capability** — Run same tests on multiple browsers
|
|
88
|
+
- **Environment-specific** — baseUrl, timeouts via config
|
|
89
|
+
|
|
90
|
+
See `references/config.md` for full configuration guide.
|
|
91
|
+
|
|
92
|
+
## Context7 MCP
|
|
93
|
+
|
|
94
|
+
Uses Context7 MCP to fetch WebdriverIO documentation when needed. Query for WebdriverIO API, selectors, or configuration when patterns are unclear.
|
|
95
|
+
|
|
96
|
+
## Scope
|
|
97
|
+
|
|
98
|
+
**Can do (autonomous):**
|
|
99
|
+
- Generate WebdriverIO E2E and mobile web tests from test cases
|
|
100
|
+
- Apply Page Object pattern with getters and methods
|
|
101
|
+
- Add custom commands via `browser.addCommand()`
|
|
102
|
+
- Configure wdio.conf.ts (capabilities, services, reporters)
|
|
103
|
+
- Use multiremote for parallel browser testing
|
|
104
|
+
- Use Context7 MCP for WebdriverIO docs
|
|
105
|
+
|
|
106
|
+
**Cannot do (requires confirmation):**
|
|
107
|
+
- Change production code structure
|
|
108
|
+
- Add dependencies not in package.json
|
|
109
|
+
- Override project WDIO config without approval
|
|
110
|
+
- Modify Appium server configuration
|
|
111
|
+
|
|
112
|
+
**Will not do (out of scope):**
|
|
113
|
+
- Execute tests (user runs `npx wdio run wdio.conf.ts`)
|
|
114
|
+
- Write Jest/Vitest unit tests (use qa-jest-writer)
|
|
115
|
+
- Modify CI/CD pipelines
|
|
116
|
+
- Native mobile app testing (Appium native, not mobile web)
|
|
117
|
+
|
|
118
|
+
## References
|
|
119
|
+
|
|
120
|
+
- `references/patterns.md` — Selectors, waits, Page Objects, custom commands, file upload, multiremote
|
|
121
|
+
- `references/config.md` — wdio.conf.ts, capabilities, services, reporters
|
|
122
|
+
- `references/best-practices.md` — Stable selectors, wait strategies, Page Objects, parallel execution
|
|
123
|
+
|
|
124
|
+
## Quality Checklist
|
|
125
|
+
|
|
126
|
+
- [ ] Explicit waits used; avoid `browser.pause()` in committed code
|
|
127
|
+
- [ ] Page Object pattern applied for page-specific logic
|
|
128
|
+
- [ ] Stable selectors (data-testid, aria, semantic over brittle CSS)
|
|
129
|
+
- [ ] Tests independent (no shared state, order-independent)
|
|
130
|
+
- [ ] Proper teardown (afterEach, cleanup)
|
|
131
|
+
- [ ] Traceability to test case IDs where applicable
|
|
132
|
+
- [ ] No hardcoded secrets (use env vars)
|
|
133
|
+
- [ ] Capabilities match target browsers
|
|
134
|
+
|
|
135
|
+
## Troubleshooting
|
|
136
|
+
|
|
137
|
+
| Symptom | Likely Cause | Fix |
|
|
138
|
+
|---------|--------------|-----|
|
|
139
|
+
| Element not found | Selector too specific, timing | Use data-testid; add waitForDisplayed before action |
|
|
140
|
+
| Stale element | DOM changed after query | Re-query element; use getters in Page Objects |
|
|
141
|
+
| Timeout on wait | Element never meets condition | Verify selector; check overlays, iframes |
|
|
142
|
+
| Multiremote fails | Capability mismatch | Ensure all browsers support same commands |
|
|
143
|
+
| Appium not starting | Service/config issue | Check @wdio/appium-service; verify Appium installed |
|
|
144
|
+
| ChromeDriver version mismatch | Chrome updated | Update wdio-chromedriver-service or chromedriver |
|
|
145
|
+
| Flaky tests | Race conditions | Use waitForDisplayed/waitForClickable; avoid fixed delays |
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# WebdriverIO Best Practices
|
|
2
|
+
|
|
3
|
+
## Stable Selectors
|
|
4
|
+
|
|
5
|
+
### Prefer Data Attributes
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// Good — test-specific, stable
|
|
9
|
+
await $('[data-testid="submit-btn"]').click();
|
|
10
|
+
await $('[data-testid="email-input"]').setValue('user@example.com');
|
|
11
|
+
|
|
12
|
+
// Avoid — brittle
|
|
13
|
+
await $('.btn-primary').click();
|
|
14
|
+
await $('#email').setValue('user@example.com');
|
|
15
|
+
await $('div > form > div:nth-child(2) > input').setValue('user@example.com');
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Add `data-testid` to production markup or recommend adding to the app. Avoid relying on CSS classes, IDs, or DOM structure that may change with refactors.
|
|
19
|
+
|
|
20
|
+
### Selector Priority
|
|
21
|
+
|
|
22
|
+
1. **data-testid** — Explicit, stable, test-specific
|
|
23
|
+
2. **Semantic attributes** — name, aria-label, role
|
|
24
|
+
3. **Stable IDs** — IDs that won't change
|
|
25
|
+
4. **CSS** — Simple, meaningful classes
|
|
26
|
+
5. **XPath** — Last resort; use for text when necessary
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Wait Strategies
|
|
31
|
+
|
|
32
|
+
### Use Explicit Waits
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// Good — wait for condition
|
|
36
|
+
await $('#results').waitForDisplayed({ timeout: 5000 });
|
|
37
|
+
await $('#loading').waitForExist({ reverse: true });
|
|
38
|
+
await $('button').waitForClickable();
|
|
39
|
+
|
|
40
|
+
// Bad — arbitrary delay
|
|
41
|
+
await browser.pause(3000);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### waitUntil for Custom Conditions
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
await browser.waitUntil(
|
|
48
|
+
async () => (await $('#status').getText()) === 'Complete',
|
|
49
|
+
{ timeout: 10000, interval: 500, timeoutMsg: 'Status never became Complete' }
|
|
50
|
+
);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Assertions Include Implicit Waits
|
|
54
|
+
|
|
55
|
+
WebdriverIO assertions retry until timeout:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
await expect($('#results')).toBeDisplayed();
|
|
59
|
+
await expect($('h1')).toHaveText('Welcome');
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Page Object Pattern
|
|
65
|
+
|
|
66
|
+
### Structure
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
test/
|
|
70
|
+
specs/
|
|
71
|
+
login.spec.ts
|
|
72
|
+
pages/
|
|
73
|
+
BasePage.ts
|
|
74
|
+
LoginPage.ts
|
|
75
|
+
DashboardPage.ts
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Encapsulation
|
|
79
|
+
|
|
80
|
+
- **One page object per page/screen** — Encapsulate selectors and actions
|
|
81
|
+
- **Base page for shared logic** — Navigation, common helpers
|
|
82
|
+
- **Getters for elements** — Lazy evaluation; elements resolved when used
|
|
83
|
+
- **Methods for actions** — Reusable flows (login, fillForm, etc.)
|
|
84
|
+
|
|
85
|
+
### Avoid Logic in Tests
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
// Bad — implementation details in test
|
|
89
|
+
it('logs in', async () => {
|
|
90
|
+
await $('input[name="email"]').setValue('user@test.com');
|
|
91
|
+
await $('input[name="password"]').setValue('secret');
|
|
92
|
+
await $('button').click();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Good — page object encapsulates
|
|
96
|
+
it('logs in', async () => {
|
|
97
|
+
await loginPage.login('user@test.com', 'secret');
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Parallel Execution
|
|
104
|
+
|
|
105
|
+
### maxInstances
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// wdio.conf.ts
|
|
109
|
+
maxInstances: 5, // Run up to 5 specs in parallel
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Test Independence
|
|
113
|
+
|
|
114
|
+
- Each test must run in isolation
|
|
115
|
+
- No shared mutable state between tests
|
|
116
|
+
- Use `beforeEach` for setup; avoid order-dependent tests
|
|
117
|
+
- Prefer API or fixture data over UI-created state
|
|
118
|
+
|
|
119
|
+
### Sharding for CI
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
wdio run wdio.conf.ts --shard=1/4
|
|
123
|
+
wdio run wdio.conf.ts --shard=2/4
|
|
124
|
+
wdio run wdio.conf.ts --shard=3/4
|
|
125
|
+
wdio run wdio.conf.ts --shard=4/4
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Error Handling and Debugging
|
|
131
|
+
|
|
132
|
+
### Screenshots on Failure
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
afterTest: async function (test, context, result) {
|
|
136
|
+
if (result.error) {
|
|
137
|
+
await browser.takeScreenshot();
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Logs
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
browser.debug(); // Pause and open REPL
|
|
146
|
+
browser.pause(5000); // Pause (avoid in production tests)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Traceability
|
|
150
|
+
|
|
151
|
+
Include test case IDs in describe/it names:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
describe('Login [TC-001]', () => {
|
|
155
|
+
it('displays error on invalid credentials [TC-001-01]', async () => {
|
|
156
|
+
// ...
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Security and Secrets
|
|
164
|
+
|
|
165
|
+
- Never hardcode credentials — use `process.env` or config
|
|
166
|
+
- Store API keys in `.env` (gitignored)
|
|
167
|
+
- Use `browser.addCommand` for login flows that need credentials from env
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Mobile Web (Appium)
|
|
172
|
+
|
|
173
|
+
- Use `browser.isMobile` to branch mobile vs desktop logic when needed
|
|
174
|
+
- Prefer touch actions for mobile: `element.touchAction('tap')` or `element.click()`
|
|
175
|
+
- Set viewport/capabilities for target device sizes
|
|
176
|
+
- Use Appium inspector to discover selectors on real devices/emulators
|