claude-code-kit 0.7.0__py3-none-any.whl
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.
- claude_code_kit-0.7.0.dist-info/METADATA +384 -0
- claude_code_kit-0.7.0.dist-info/RECORD +209 -0
- claude_code_kit-0.7.0.dist-info/WHEEL +4 -0
- claude_code_kit-0.7.0.dist-info/entry_points.txt +4 -0
- claude_code_kit-0.7.0.dist-info/licenses/LICENSE +21 -0
- claude_kit/__init__.py +10 -0
- claude_kit/__main__.py +8 -0
- claude_kit/_payload/agents/acceptance-reviewer.md +60 -0
- claude_kit/_payload/agents/auditor.md +76 -0
- claude_kit/_payload/agents/dependency-scanner.md +84 -0
- claude_kit/_payload/agents/developer.md +187 -0
- claude_kit/_payload/agents/devils-advocate.md +62 -0
- claude_kit/_payload/agents/devops-engineer.md +134 -0
- claude_kit/_payload/agents/e2e-tester.md +152 -0
- claude_kit/_payload/agents/em-reviewer.md +105 -0
- claude_kit/_payload/agents/incident-responder.md +64 -0
- claude_kit/_payload/agents/merge-reviewer.md +194 -0
- claude_kit/_payload/agents/observability-engineer.md +94 -0
- claude_kit/_payload/agents/orchestrator.md +551 -0
- claude_kit/_payload/agents/owasp-reviewer.md +76 -0
- claude_kit/_payload/agents/policy-validator.md +63 -0
- claude_kit/_payload/agents/pr-raiser.md +138 -0
- claude_kit/_payload/agents/risk-classifier.md +50 -0
- claude_kit/_payload/agents/sdlc-code-reviewer.md +196 -0
- claude_kit/_payload/agents/secret-scanner.md +70 -0
- claude_kit/_payload/agents/security-reviewer.md +80 -0
- claude_kit/_payload/agents/senior-backend-dev.md +199 -0
- claude_kit/_payload/agents/senior-frontend-dev.md +181 -0
- claude_kit/_payload/agents/senior-tester.md +206 -0
- claude_kit/_payload/agents/spec-doc-writer.md +331 -0
- claude_kit/_payload/agents/story-planner.md +56 -0
- claude_kit/_payload/agents/technical-architect.md +139 -0
- claude_kit/_payload/agents/tester.md +193 -0
- claude_kit/_payload/agents/ui-designer.md +73 -0
- claude_kit/_payload/agents/unit-tester.md +119 -0
- claude_kit/_payload/catalog/mcp.yaml +54 -0
- claude_kit/_payload/catalog/org.yaml +145 -0
- claude_kit/_payload/catalog/profiles.yaml +96 -0
- claude_kit/_payload/catalog/stacks.yaml +96 -0
- claude_kit/_payload/commands/init.md +36 -0
- claude_kit/_payload/commands/sdlc.md +18 -0
- claude_kit/_payload/commands/status.md +20 -0
- claude_kit/_payload/hooks/hooks.json +58 -0
- claude_kit/_payload/hooks/scripts/audit-log.sh +18 -0
- claude_kit/_payload/hooks/scripts/guard-secrets.sh +26 -0
- claude_kit/_payload/hooks/scripts/lint-fix.sh +38 -0
- claude_kit/_payload/hooks/scripts/load-continuity.sh +32 -0
- claude_kit/_payload/hooks/scripts/load-learnings.sh +40 -0
- claude_kit/_payload/hooks/scripts/type-check.sh +23 -0
- claude_kit/_payload/hooks/scripts/validate-frontmatter.sh +34 -0
- claude_kit/_payload/hooks/scripts/validate-settings.sh +21 -0
- claude_kit/_payload/hooks/scripts/warn-large-edits.sh +24 -0
- claude_kit/_payload/hooks/scripts/warn-missing-tests.sh +24 -0
- claude_kit/_payload/hooks/scripts/warn-sensitive-files.sh +30 -0
- claude_kit/_payload/hooks/scripts/warn-shared-modules.sh +33 -0
- claude_kit/_payload/rules/agent-guardrails.md +83 -0
- claude_kit/_payload/rules/agent-memory.md +106 -0
- claude_kit/_payload/rules/agent-resilience.md +61 -0
- claude_kit/_payload/rules/autonomy-levels.md +30 -0
- claude_kit/_payload/rules/code-organization.md +312 -0
- claude_kit/_payload/rules/continuity.md +84 -0
- claude_kit/_payload/rules/design-patterns.md +422 -0
- claude_kit/_payload/rules/devops-observability.md +57 -0
- claude_kit/_payload/rules/documentation.md +326 -0
- claude_kit/_payload/rules/evals.md +62 -0
- claude_kit/_payload/rules/frontend-best-practices.md +157 -0
- claude_kit/_payload/rules/goal-setting-and-monitoring.md +72 -0
- claude_kit/_payload/rules/human-in-the-loop.md +64 -0
- claude_kit/_payload/rules/linting-and-formatting.md +220 -0
- claude_kit/_payload/rules/mandatory-workflow.md +309 -0
- claude_kit/_payload/rules/model-tiers.md +34 -0
- claude_kit/_payload/rules/quality-gates.md +107 -0
- claude_kit/_payload/rules/rarv-cycle.md +31 -0
- claude_kit/_payload/rules/reasoning-techniques.md +62 -0
- claude_kit/_payload/rules/responsive-and-accessibility.md +353 -0
- claude_kit/_payload/rules/risk-classification.md +36 -0
- claude_kit/_payload/rules/testing.md +417 -0
- claude_kit/_payload/rules/tool-design.md +66 -0
- claude_kit/_payload/skills/_references/accessibility-checklist.md +160 -0
- claude_kit/_payload/skills/_references/orchestration-patterns.md +405 -0
- claude_kit/_payload/skills/_references/performance-checklist.md +153 -0
- claude_kit/_payload/skills/_references/security-checklist.md +134 -0
- claude_kit/_payload/skills/_references/testing-patterns.md +236 -0
- claude_kit/_payload/skills/accessibility-review/SKILL.md +56 -0
- claude_kit/_payload/skills/api-and-interface-design/SKILL.md +294 -0
- claude_kit/_payload/skills/api-integration/SKILL.md +348 -0
- claude_kit/_payload/skills/archive-sprint/SKILL.md +31 -0
- claude_kit/_payload/skills/backlog/SKILL.md +41 -0
- claude_kit/_payload/skills/backlog/item-template.md +20 -0
- claude_kit/_payload/skills/browser-testing-with-devtools/SKILL.md +302 -0
- claude_kit/_payload/skills/ci-cd-and-automation/SKILL.md +402 -0
- claude_kit/_payload/skills/code-review-and-quality/SKILL.md +347 -0
- claude_kit/_payload/skills/code-simplification/SKILL.md +331 -0
- claude_kit/_payload/skills/component-design/SKILL.md +171 -0
- claude_kit/_payload/skills/consolidate-learnings/SKILL.md +55 -0
- claude_kit/_payload/skills/context-engineering/SKILL.md +321 -0
- claude_kit/_payload/skills/debugging-and-error-recovery/SKILL.md +300 -0
- claude_kit/_payload/skills/decision/SKILL.md +46 -0
- claude_kit/_payload/skills/decision/adr-template.md +36 -0
- claude_kit/_payload/skills/deprecation-and-migration/SKILL.md +207 -0
- claude_kit/_payload/skills/documentation-and-adrs/SKILL.md +299 -0
- claude_kit/_payload/skills/doubt-driven-development/SKILL.md +243 -0
- claude_kit/_payload/skills/execute/SKILL.md +27 -0
- claude_kit/_payload/skills/frontend-ui-engineering/SKILL.md +328 -0
- claude_kit/_payload/skills/git-workflow-and-versioning/SKILL.md +300 -0
- claude_kit/_payload/skills/idea-refine/SKILL.md +178 -0
- claude_kit/_payload/skills/idea-refine/examples.md +238 -0
- claude_kit/_payload/skills/idea-refine/frameworks.md +99 -0
- claude_kit/_payload/skills/idea-refine/refinement-criteria.md +113 -0
- claude_kit/_payload/skills/idea-refine/scripts/idea-refine.sh +15 -0
- claude_kit/_payload/skills/incident-postmortem/SKILL.md +74 -0
- claude_kit/_payload/skills/incremental-implementation/SKILL.md +245 -0
- claude_kit/_payload/skills/interview-me/SKILL.md +221 -0
- claude_kit/_payload/skills/load-testing/SKILL.md +83 -0
- claude_kit/_payload/skills/manual-test/SKILL.md +516 -0
- claude_kit/_payload/skills/performance-optimization/SKILL.md +277 -0
- claude_kit/_payload/skills/planning-and-task-breakdown/SKILL.md +223 -0
- claude_kit/_payload/skills/playwright-verification/SKILL.md +205 -0
- claude_kit/_payload/skills/refresh-docs/SKILL.md +63 -0
- claude_kit/_payload/skills/remember/SKILL.md +96 -0
- claude_kit/_payload/skills/scope/SKILL.md +52 -0
- claude_kit/_payload/skills/scope/scope-template.md +82 -0
- claude_kit/_payload/skills/sdlc/SKILL.md +83 -0
- claude_kit/_payload/skills/security-and-hardening/SKILL.md +368 -0
- claude_kit/_payload/skills/security-verification/SKILL.md +209 -0
- claude_kit/_payload/skills/shipping-and-launch/SKILL.md +309 -0
- claude_kit/_payload/skills/smoke-test/SKILL.md +78 -0
- claude_kit/_payload/skills/source-driven-development/SKILL.md +195 -0
- claude_kit/_payload/skills/spec-driven-development/SKILL.md +200 -0
- claude_kit/_payload/skills/sprint/SKILL.md +67 -0
- claude_kit/_payload/skills/sprint/sprint-template.md +90 -0
- claude_kit/_payload/skills/test-driven-development/SKILL.md +383 -0
- claude_kit/_payload/skills/threat-model/SKILL.md +60 -0
- claude_kit/_payload/skills/triage/SKILL.md +87 -0
- claude_kit/_payload/skills/ui-ux-design/SKILL.md +71 -0
- claude_kit/_payload/skills/unit-test/SKILL.md +237 -0
- claude_kit/_payload/skills/using-agent-skills/SKILL.md +180 -0
- claude_kit/_payload/templates/CLAUDE.md +238 -0
- claude_kit/_payload/templates/CLAUDE.stack.md.tmpl +53 -0
- claude_kit/_payload/templates/CONTINUITY.template.md +35 -0
- claude_kit/_payload/templates/README.claude-sdlc.md.tmpl +219 -0
- claude_kit/_payload/templates/agent-memory/MEMORY.md +30 -0
- claude_kit/_payload/templates/agent-memory/api/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/architecture/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/debugging/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/gotchas/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/patterns/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/performance/.gitkeep +0 -0
- claude_kit/_payload/templates/artifacts/adr.md +18 -0
- claude_kit/_payload/templates/artifacts/feature-spec.md +29 -0
- claude_kit/_payload/templates/artifacts/release-plan.md +23 -0
- claude_kit/_payload/templates/artifacts/runbook.md +24 -0
- claude_kit/_payload/templates/artifacts/security-review.md +23 -0
- claude_kit/_payload/templates/artifacts/test-plan.md +22 -0
- claude_kit/_payload/templates/org/README.md +53 -0
- claude_kit/_payload/templates/org/agents/data-workflow-agent.md +59 -0
- claude_kit/_payload/templates/org/agents/founder-prototype-agent.md +61 -0
- claude_kit/_payload/templates/org/agents/internal-tools-builder.md +63 -0
- claude_kit/_payload/templates/org/agents/pm-copilot.md +60 -0
- claude_kit/_payload/templates/org/agents/support-ticket-engineer.md +63 -0
- claude_kit/_payload/templates/org/packs/devops-and-release/README.md +46 -0
- claude_kit/_payload/templates/org/packs/devops-and-release/pack.yaml +32 -0
- claude_kit/_payload/templates/org/packs/engineering-core/README.md +46 -0
- claude_kit/_payload/templates/org/packs/engineering-core/pack.yaml +44 -0
- claude_kit/_payload/templates/org/packs/non-engineer-builder/README.md +53 -0
- claude_kit/_payload/templates/org/packs/non-engineer-builder/pack.yaml +39 -0
- claude_kit/_payload/templates/org/packs/onboarding-and-docs/README.md +49 -0
- claude_kit/_payload/templates/org/packs/onboarding-and-docs/pack.yaml +26 -0
- claude_kit/_payload/templates/org/packs/product-to-code/README.md +50 -0
- claude_kit/_payload/templates/org/packs/product-to-code/pack.yaml +34 -0
- claude_kit/_payload/templates/org/packs/quality-and-review/README.md +53 -0
- claude_kit/_payload/templates/org/packs/quality-and-review/pack.yaml +40 -0
- claude_kit/_payload/templates/org/packs/security-and-compliance/README.md +50 -0
- claude_kit/_payload/templates/org/packs/security-and-compliance/pack.yaml +36 -0
- claude_kit/_payload/templates/org/rules/ai-working-agreement.md +45 -0
- claude_kit/_payload/templates/org/rules/ambiguity-resolution.md +36 -0
- claude_kit/_payload/templates/org/rules/branch-and-pr-policy.md +41 -0
- claude_kit/_payload/templates/org/rules/compliance-policy.md +50 -0
- claude_kit/_payload/templates/org/rules/non-engineer-safe-coding.md +37 -0
- claude_kit/_payload/templates/org/rules/pii-policy.md +46 -0
- claude_kit/_payload/templates/org/rules/production-data-policy.md +35 -0
- claude_kit/_payload/templates/org/rules/prompt-to-task-conversion.md +30 -0
- claude_kit/_payload/templates/org/rules/prototype-boundaries.md +40 -0
- claude_kit/_payload/templates/org/rules/secrets-policy.md +34 -0
- claude_kit/_payload/templates/org/skills/customer-issue-to-fix/SKILL.md +61 -0
- claude_kit/_payload/templates/org/skills/feature-from-idea/SKILL.md +56 -0
- claude_kit/_payload/templates/org/skills/prompt-to-safe-task/SKILL.md +59 -0
- claude_kit/_payload/templates/org/skills/prototype-to-production/SKILL.md +61 -0
- claude_kit/_payload/templates/org/skills/repo-onboarding/SKILL.md +60 -0
- claude_kit/_payload/templates/settings.json +53 -0
- claude_kit/_payload/templates/stacks/backend/python/fastapi/rules/fastapi-patterns.md +64 -0
- claude_kit/_payload/templates/stacks/db/mongodb/agents/migration-specialist.md +61 -0
- claude_kit/_payload/templates/stacks/db/mongodb/agents/mongodb-specialist.md +59 -0
- claude_kit/_payload/templates/stacks/db/mongodb/rules/mongodb-patterns.md +39 -0
- claude_kit/_payload/templates/stacks/db/postgres/agents/db-performance-reviewer.md +66 -0
- claude_kit/_payload/templates/stacks/db/postgres/agents/migration-specialist.md +56 -0
- claude_kit/_payload/templates/stacks/db/postgres/agents/postgres-specialist.md +58 -0
- claude_kit/_payload/templates/stacks/db/postgres/rules/database-performance.md +64 -0
- claude_kit/_payload/templates/stacks/db/postgres/rules/postgres-patterns.md +43 -0
- claude_kit/_payload/templates/stacks/frontend/react/rules/react-patterns.md +63 -0
- claude_kit/catalog.py +476 -0
- claude_kit/cli.py +327 -0
- claude_kit/hooks.py +246 -0
- claude_kit/models.py +205 -0
- claude_kit/prompts.py +209 -0
- claude_kit/render.py +146 -0
- claude_kit/scaffold.py +492 -0
- claude_kit/upgrader.py +294 -0
- claude_kit/validator.py +197 -0
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
# Testing Standards
|
|
2
|
+
|
|
3
|
+
All new code and modified code MUST have accompanying unit tests with a minimum **90% coverage** threshold across all metrics (or as defined by the project's coverage policy).
|
|
4
|
+
|
|
5
|
+
## Coverage Thresholds (Enforced)
|
|
6
|
+
|
|
7
|
+
| Metric | Minimum |
|
|
8
|
+
|--------|---------|
|
|
9
|
+
| Statements | 90% |
|
|
10
|
+
| Branches | 90% |
|
|
11
|
+
| Functions | 90% |
|
|
12
|
+
| Lines | 90% |
|
|
13
|
+
|
|
14
|
+
These thresholds should be configured in the project's test runner configuration and enforced via the test coverage command. **Do not lower them without justification.**
|
|
15
|
+
|
|
16
|
+
## Stack-Specific Setup
|
|
17
|
+
|
|
18
|
+
The project uses:
|
|
19
|
+
- The project's test runner (check package.json/pyproject.toml/build config for the test framework)
|
|
20
|
+
- The project's coverage provider
|
|
21
|
+
- Testing libraries appropriate to the stack (component testing libraries for UI, mocking libraries, assertion libraries)
|
|
22
|
+
|
|
23
|
+
Refer to the project's test configuration files for exact setup and command reference.
|
|
24
|
+
|
|
25
|
+
## Commands
|
|
26
|
+
|
|
27
|
+
Run the project's test commands:
|
|
28
|
+
- Run all tests once
|
|
29
|
+
- Run in watch mode during development
|
|
30
|
+
- Run with coverage report (enforces coverage threshold)
|
|
31
|
+
|
|
32
|
+
Check the project's package manager scripts or test runner documentation for exact commands.
|
|
33
|
+
|
|
34
|
+
## File Organization
|
|
35
|
+
|
|
36
|
+
Tests should mirror the source structure. Common patterns:
|
|
37
|
+
|
|
38
|
+
**Option 1: Co-located tests**
|
|
39
|
+
```
|
|
40
|
+
src/
|
|
41
|
+
├── module/
|
|
42
|
+
│ ├── feature.ts
|
|
43
|
+
│ └── feature.test.ts
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Option 2: Separate test directory**
|
|
47
|
+
```
|
|
48
|
+
src/
|
|
49
|
+
├── module/
|
|
50
|
+
│ └── feature.ts
|
|
51
|
+
└── test/
|
|
52
|
+
└── module/
|
|
53
|
+
└── feature.test.ts
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Backend projects often use:**
|
|
57
|
+
```
|
|
58
|
+
backend/
|
|
59
|
+
├── app/
|
|
60
|
+
│ └── module/
|
|
61
|
+
│ └── service.py
|
|
62
|
+
└── tests/
|
|
63
|
+
└── module/
|
|
64
|
+
└── test_service.py
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- Test file naming: `<source-file-name>.test.<ext>` or `test_<source-file-name>.<ext>`
|
|
68
|
+
- Mirror the source directory structure
|
|
69
|
+
- Test setup/fixtures in a dedicated setup file or conftest
|
|
70
|
+
|
|
71
|
+
## What to Test
|
|
72
|
+
|
|
73
|
+
### Always Test
|
|
74
|
+
|
|
75
|
+
| Category | Examples |
|
|
76
|
+
|----------|---------|
|
|
77
|
+
| **Pure functions** | Formatters, validators, transformers, utility helpers |
|
|
78
|
+
| **State management** | Store actions, state mutations, derived state, edge cases |
|
|
79
|
+
| **Custom abstractions** | Custom hooks, decorators, middleware, utilities |
|
|
80
|
+
| **Component/view rendering** | Renders without crashing, displays correct content based on inputs |
|
|
81
|
+
| **User interactions** | Click handlers, form submissions, input changes |
|
|
82
|
+
| **Conditional logic** | Loading, empty, error, and success states |
|
|
83
|
+
| **Edge cases** | Null/undefined inputs, empty collections, boundary values |
|
|
84
|
+
| **Accessibility** | Correct ARIA attributes, roles, labels (for UI components) |
|
|
85
|
+
| **API contracts** | Request/response shapes, error handling, validation |
|
|
86
|
+
| **Business logic** | Service layer functions, domain rules, calculations |
|
|
87
|
+
|
|
88
|
+
### Never Test
|
|
89
|
+
|
|
90
|
+
| Category | Why |
|
|
91
|
+
|----------|-----|
|
|
92
|
+
| Implementation details | Internal state values, private methods — test behavior, not internals |
|
|
93
|
+
| Third-party libraries | Trust the library; test your usage, not the library itself |
|
|
94
|
+
| Exact styling/CSS classes | Brittle, changes don't affect behavior |
|
|
95
|
+
| Snapshot tests | Fragile, noisy diffs, false positives (use sparingly if at all) |
|
|
96
|
+
| Type definitions | The type checker handles this at compile/build time |
|
|
97
|
+
| Console output | Not user-visible behavior unless it's logging/monitoring specific |
|
|
98
|
+
|
|
99
|
+
## Writing Tests
|
|
100
|
+
|
|
101
|
+
### Test Structure
|
|
102
|
+
|
|
103
|
+
**General pattern (language-agnostic concept):**
|
|
104
|
+
```
|
|
105
|
+
describe/group tests by module or feature
|
|
106
|
+
describe/group by function/class/component
|
|
107
|
+
setup/teardown hooks to reset state between tests
|
|
108
|
+
|
|
109
|
+
test case: valid input produces expected output
|
|
110
|
+
test case: edge case handling
|
|
111
|
+
test case: error handling
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Example (JavaScript/TypeScript style):**
|
|
115
|
+
```typescript
|
|
116
|
+
import { describe, it, expect, beforeEach } from '<test-framework>';
|
|
117
|
+
|
|
118
|
+
describe('ModuleName', () => {
|
|
119
|
+
describe('functionName', () => {
|
|
120
|
+
beforeEach(() => {
|
|
121
|
+
// Reset state between tests
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('returns expected value for valid input', () => {
|
|
125
|
+
expect(functionName('input')).toBe('expected');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('handles edge case', () => {
|
|
129
|
+
expect(functionName('')).toBe('default');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('throws for invalid input', () => {
|
|
133
|
+
expect(() => functionName(null)).toThrow();
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Example (Python style):**
|
|
140
|
+
```python
|
|
141
|
+
import pytest
|
|
142
|
+
|
|
143
|
+
class TestModuleName:
|
|
144
|
+
def setup_method(self):
|
|
145
|
+
# Reset state before each test
|
|
146
|
+
pass
|
|
147
|
+
|
|
148
|
+
def test_returns_expected_value_for_valid_input(self):
|
|
149
|
+
assert function_name('input') == 'expected'
|
|
150
|
+
|
|
151
|
+
def test_handles_edge_case(self):
|
|
152
|
+
assert function_name('') == 'default'
|
|
153
|
+
|
|
154
|
+
def test_raises_for_invalid_input(self):
|
|
155
|
+
with pytest.raises(ValueError):
|
|
156
|
+
function_name(None)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Testing Pure Functions
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
// Example: Utility functions
|
|
163
|
+
describe('formatCurrency', () => {
|
|
164
|
+
it('formats positive numbers with currency symbol', () => {
|
|
165
|
+
expect(formatCurrency(1234.5)).toBe('$1,234.50');
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('handles zero', () => {
|
|
169
|
+
expect(formatCurrency(0)).toBe('$0.00');
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('handles negative numbers', () => {
|
|
173
|
+
expect(formatCurrency(-500)).toBe('-$500.00');
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Testing State Management
|
|
179
|
+
|
|
180
|
+
Test stores/state containers by:
|
|
181
|
+
1. Verifying initial state
|
|
182
|
+
2. Testing actions/mutations
|
|
183
|
+
3. Testing derived/computed state
|
|
184
|
+
4. Resetting state between tests
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
// Example: Client-side state store
|
|
188
|
+
describe('AppStore', () => {
|
|
189
|
+
beforeEach(() => {
|
|
190
|
+
// Reset store to initial state
|
|
191
|
+
store.reset();
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('has correct initial state', () => {
|
|
195
|
+
const state = store.getState();
|
|
196
|
+
expect(state.currentUser).toBeNull();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('updates user via setUser action', () => {
|
|
200
|
+
store.setUser({ id: 1, name: 'Test' });
|
|
201
|
+
expect(store.getState().currentUser).toEqual({ id: 1, name: 'Test' });
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Testing Components/Views
|
|
207
|
+
|
|
208
|
+
For UI frameworks, test:
|
|
209
|
+
1. Rendering with required props/inputs
|
|
210
|
+
2. User interactions (clicks, form submissions)
|
|
211
|
+
3. Conditional rendering (loading, empty, error states)
|
|
212
|
+
4. Accessibility attributes
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
// Example: UI component testing
|
|
216
|
+
describe('ComponentName', () => {
|
|
217
|
+
it('renders with required props', () => {
|
|
218
|
+
render(<ComponentName title="Test" value={42} />);
|
|
219
|
+
expect(screen.getByText('Test')).toBeInTheDocument();
|
|
220
|
+
expect(screen.getByText('42')).toBeInTheDocument();
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('calls onClick when button is clicked', async () => {
|
|
224
|
+
const handleClick = mockFunction();
|
|
225
|
+
render(<ComponentName onClick={handleClick} />);
|
|
226
|
+
|
|
227
|
+
await userInteraction.click(screen.getByRole('button'));
|
|
228
|
+
expect(handleClick).toHaveBeenCalledOnce();
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('shows empty state when no data', () => {
|
|
232
|
+
render(<ComponentName data={[]} />);
|
|
233
|
+
expect(screen.getByText(/no.*found/i)).toBeInTheDocument();
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Testing API/Service Layer
|
|
239
|
+
|
|
240
|
+
For backend services and API clients:
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
# Example: Backend service testing
|
|
244
|
+
class TestUserService:
|
|
245
|
+
async def test_create_user_with_valid_data(self, db_session):
|
|
246
|
+
payload = {"email": "test@example.com", "password": "secure123"}
|
|
247
|
+
user = await user_service.create_user(db_session, payload)
|
|
248
|
+
|
|
249
|
+
assert user.id is not None
|
|
250
|
+
assert user.email == "test@example.com"
|
|
251
|
+
# Never leak sensitive fields in responses
|
|
252
|
+
assert not hasattr(user, 'password')
|
|
253
|
+
|
|
254
|
+
async def test_create_user_duplicate_email_raises_conflict(self, db_session):
|
|
255
|
+
payload = {"email": "test@example.com", "password": "secure123"}
|
|
256
|
+
await user_service.create_user(db_session, payload)
|
|
257
|
+
|
|
258
|
+
with pytest.raises(ConflictError):
|
|
259
|
+
await user_service.create_user(db_session, payload)
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Query/Selection Priority (UI Testing)
|
|
263
|
+
|
|
264
|
+
When testing UI components, use the most accessible/semantic selector first:
|
|
265
|
+
|
|
266
|
+
| Priority | Method | When |
|
|
267
|
+
|----------|--------|------|
|
|
268
|
+
| 1 | By role | Buttons, headings, links, form elements (semantic HTML) |
|
|
269
|
+
| 2 | By label | Form inputs with labels |
|
|
270
|
+
| 3 | By text content | Non-interactive text |
|
|
271
|
+
| 4 | By current value | Form input values |
|
|
272
|
+
| 5 | By test ID | Last resort — add `data-testid` or similar attribute |
|
|
273
|
+
|
|
274
|
+
**Never query by CSS class, tag name, or DOM structure.** These are implementation details.
|
|
275
|
+
|
|
276
|
+
## Mocking
|
|
277
|
+
|
|
278
|
+
### Module/Import Mocks
|
|
279
|
+
|
|
280
|
+
Mock external dependencies at module boundaries:
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
// Mock an entire module
|
|
284
|
+
mock('@/external/service');
|
|
285
|
+
|
|
286
|
+
// Mock with custom implementation
|
|
287
|
+
mock('@/lib/utils', () => ({
|
|
288
|
+
formatCurrency: mockFn((v: number) => `$${v}`),
|
|
289
|
+
}));
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
```python
|
|
293
|
+
# Mock with pytest/unittest
|
|
294
|
+
from unittest.mock import patch, MagicMock
|
|
295
|
+
|
|
296
|
+
@patch('app.external.service.make_api_call')
|
|
297
|
+
def test_service_with_mocked_api(mock_api_call):
|
|
298
|
+
mock_api_call.return_value = {'status': 'ok'}
|
|
299
|
+
# test code
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### State Store Mocks
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
// Mock state container/store
|
|
306
|
+
mock('@/stores/appStore');
|
|
307
|
+
|
|
308
|
+
beforeEach(() => {
|
|
309
|
+
mockedStore.mockImplementation((selector) =>
|
|
310
|
+
selector({
|
|
311
|
+
currentUser: { id: 1, name: 'Test' },
|
|
312
|
+
logout: mockFn(),
|
|
313
|
+
})
|
|
314
|
+
);
|
|
315
|
+
});
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Time/Timer Mocks
|
|
319
|
+
|
|
320
|
+
For testing debouncing, throttling, or time-dependent behavior:
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
beforeEach(() => {
|
|
324
|
+
useFakeTimers();
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
afterEach(() => {
|
|
328
|
+
useRealTimers();
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('debounces input', () => {
|
|
332
|
+
// trigger input
|
|
333
|
+
advanceTimersByTime(300);
|
|
334
|
+
// assert debounced result
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## Rules
|
|
339
|
+
|
|
340
|
+
1. **Write tests for every new function, module, and component** — no exceptions
|
|
341
|
+
2. **Run coverage checks before finishing work** — all metrics must meet the threshold
|
|
342
|
+
3. **Test behavior, not implementation** — assert what the user/caller sees, not internal state
|
|
343
|
+
4. **One assertion concept per test** — multiple assertions are fine if they test the same concept
|
|
344
|
+
5. **Use descriptive test names** — `it('shows error message when form is invalid')` not `it('test 3')`
|
|
345
|
+
6. **Mock at boundaries** — mock external APIs, stores, and I/O; not internal functions
|
|
346
|
+
7. **Reset state between tests** — use setup/teardown hooks to clear mocks and reset state
|
|
347
|
+
8. **No test interdependence** — each test must pass in isolation and in any order
|
|
348
|
+
9. **Cover edge cases** — empty collections, null values, boundary numbers, long strings
|
|
349
|
+
10. **Cover all branches** — if there's an `if/else`, test both paths; if there's a switch, test all cases
|
|
350
|
+
11. **For multi-tenant systems** — test tenant/authorization scoping on every query/operation that should be scoped
|
|
351
|
+
|
|
352
|
+
## Adding Tests for Bug Fixes
|
|
353
|
+
|
|
354
|
+
When fixing a bug:
|
|
355
|
+
|
|
356
|
+
1. **Write the failing test first** — reproduce the bug in a test
|
|
357
|
+
2. **Verify it fails** — confirm the test catches the actual bug
|
|
358
|
+
3. **Fix the bug** — make the test pass
|
|
359
|
+
4. **Keep the test** — it prevents regression
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// Example: Bug #123 — formatCurrency returns NaN for undefined
|
|
363
|
+
it('handles undefined input without NaN (bug #123)', () => {
|
|
364
|
+
expect(formatCurrency(undefined as unknown as number)).toBe('$0.00');
|
|
365
|
+
});
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## Coverage Report
|
|
369
|
+
|
|
370
|
+
After running the coverage command:
|
|
371
|
+
|
|
372
|
+
- Check terminal output for summary of all metrics
|
|
373
|
+
- Check the coverage report directory (often `coverage/` or `htmlcov/`) for detailed line-by-line coverage
|
|
374
|
+
- Uncovered lines are usually highlighted in the terminal or HTML report
|
|
375
|
+
|
|
376
|
+
If coverage drops below the threshold on any metric, the test run **fails**. Add tests to cover the gap before committing.
|
|
377
|
+
|
|
378
|
+
## Stack-Specific Guidance
|
|
379
|
+
|
|
380
|
+
### Async/Event-Loop Systems
|
|
381
|
+
|
|
382
|
+
For systems with async I/O or event loops (Node.js, Python asyncio, Go goroutines):
|
|
383
|
+
- Mock all I/O operations (database, HTTP, file system)
|
|
384
|
+
- Use the test framework's async support (`async/await` in tests)
|
|
385
|
+
- Never use blocking I/O in tests for async systems — mock it or use async equivalents
|
|
386
|
+
|
|
387
|
+
### Multi-Tenant/Authorization Systems
|
|
388
|
+
|
|
389
|
+
For systems with tenant isolation or fine-grained authorization:
|
|
390
|
+
- Every test for a scoped query/operation must verify scoping is correct
|
|
391
|
+
- Test cross-tenant access attempts (should fail with 404 or 403)
|
|
392
|
+
- Test missing authorization (should fail with 401 or 403)
|
|
393
|
+
|
|
394
|
+
### API/HTTP Testing
|
|
395
|
+
|
|
396
|
+
For REST/GraphQL/RPC APIs:
|
|
397
|
+
- Test all response status codes (200, 201, 400, 401, 403, 404, 409, 422, 429, 500)
|
|
398
|
+
- Test request validation (missing fields, wrong types, out-of-range values)
|
|
399
|
+
- Test authentication and authorization
|
|
400
|
+
- Test rate limiting if applicable
|
|
401
|
+
|
|
402
|
+
### Frontend/UI Testing
|
|
403
|
+
|
|
404
|
+
For component-based UI frameworks:
|
|
405
|
+
- Test all UI states: loading, empty, error, success
|
|
406
|
+
- Test user interactions with proper event simulation
|
|
407
|
+
- Test accessibility (ARIA attributes, keyboard navigation, screen reader support)
|
|
408
|
+
- Test responsive behavior if applicable (different viewport sizes)
|
|
409
|
+
|
|
410
|
+
See `.claude/rules/responsive-and-accessibility.md` for UI-specific accessibility requirements.
|
|
411
|
+
|
|
412
|
+
## Integration with Workflow
|
|
413
|
+
|
|
414
|
+
This file defines unit testing standards. Integration and end-to-end testing are covered separately:
|
|
415
|
+
- Unit tests run in the development pipeline (lint → type-check → unit tests → build)
|
|
416
|
+
- Integration/E2E tests run in the testing phase of the SDLC pipeline (see `.claude/rules/mandatory-workflow.md`)
|
|
417
|
+
- Coverage requirements apply to unit tests; integration tests have separate success criteria
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Tool Design (tools & MCP for agents)
|
|
2
|
+
|
|
3
|
+
When you build a tool, MCP server, script, or slash command for an agent to use, design it for an
|
|
4
|
+
**agent consumer**, not a human one. The agent pays tokens for every tool definition it carries and
|
|
5
|
+
every byte a tool prints, can't see a GUI, and reasons purely from text. A well-designed tool is as
|
|
6
|
+
high-leverage as a well-written prompt — and a badly-designed one quietly burns the context budget and
|
|
7
|
+
derails the agent.
|
|
8
|
+
|
|
9
|
+
> Source: Mario Zechner, "What if you don't need MCP at all?"; Anthropic Engineering, "Building a C
|
|
10
|
+
> compiler with a team of parallel Claudes"; "The Anatomy of an Agent Harness." Paraphrased for this kit.
|
|
11
|
+
|
|
12
|
+
## 1. Prefer small composable tools over heavyweight always-loaded servers
|
|
13
|
+
|
|
14
|
+
Every persistently-registered MCP server front-loads its whole tool schema into context **every turn**
|
|
15
|
+
(often thousands of tokens) whether or not it's used. A small CLI/script the agent calls on demand
|
|
16
|
+
costs ~nothing until invoked, and composes — its output can pipe into the next command. Reach for a
|
|
17
|
+
persistent MCP server when you genuinely need stateful sessions, pushed events, or auth the agent
|
|
18
|
+
can't hold; otherwise prefer a script the agent runs.
|
|
19
|
+
|
|
20
|
+
## 2. Progressive disclosure
|
|
21
|
+
|
|
22
|
+
Don't dump every capability up front. Expose a **name + one-line description**; load full usage only
|
|
23
|
+
when the tool is actually used (the model behind `.claude/skills/`). This keeps the attention budget on
|
|
24
|
+
the task — see `.claude/skills/context-engineering`.
|
|
25
|
+
|
|
26
|
+
## 3. Name and scope for the model
|
|
27
|
+
|
|
28
|
+
- **Action-oriented names** that say what the tool does.
|
|
29
|
+
- **One clear job per tool** (tight granularity) — a few well-named tools beat many overlapping ones.
|
|
30
|
+
- **Self-describing inputs/outputs** in the description, so the agent doesn't guess the contract.
|
|
31
|
+
|
|
32
|
+
## 4. Design output for a context window
|
|
33
|
+
|
|
34
|
+
- **Print sparsely.** A few lines of signal inline; write full detail to a file the agent can open if
|
|
35
|
+
it needs to. Dumping a 500-line log into context is how agents lose the thread.
|
|
36
|
+
- **Single grep-friendly errors.** Emit failures as one line (`ERROR <reason>`) the agent can scan for.
|
|
37
|
+
- **Pre-compute summaries** so the agent reasons from a compact signal, not raw output.
|
|
38
|
+
- **Offer a fast/sampled mode** for tight iteration loops where full output isn't needed.
|
|
39
|
+
|
|
40
|
+
## 5. Structured output for machine consumption
|
|
41
|
+
|
|
42
|
+
When a result is consumed by code or another agent (not read by a human), return a **typed/validated
|
|
43
|
+
structure**, not prose to be re-parsed. Schema-validated output removes a whole class of brittle
|
|
44
|
+
string-parsing failures and makes fan-out/verification flows reliable
|
|
45
|
+
(`.claude/skills/_references/orchestration-patterns.md`).
|
|
46
|
+
|
|
47
|
+
## 6. Safe and idempotent
|
|
48
|
+
|
|
49
|
+
A tool is a **privilege boundary** (`.claude/rules/agent-guardrails.md`): grant least privilege,
|
|
50
|
+
validate inputs, make repeated calls safe to retry (idempotent), and gate destructive or
|
|
51
|
+
outward-facing actions behind `.claude/rules/human-in-the-loop.md`.
|
|
52
|
+
|
|
53
|
+
## Rules
|
|
54
|
+
|
|
55
|
+
1. **Design for the agent, not a human dashboard** — text-first, token-aware, self-describing.
|
|
56
|
+
2. **Composable-over-heavy** — a script the agent runs beats an always-loaded server unless you need
|
|
57
|
+
state/events/auth.
|
|
58
|
+
3. **Sparse output + single-line errors + structured results** are the default, not a nicety.
|
|
59
|
+
4. **Eval your tools too** — a tool's effect on agent success is measurable; see `.claude/rules/evals.md`.
|
|
60
|
+
|
|
61
|
+
## Relationship to other rules
|
|
62
|
+
|
|
63
|
+
- **`.claude/rules/agent-guardrails.md`** — tools as privilege boundary; least privilege; gating.
|
|
64
|
+
- **`.claude/rules/reasoning-techniques.md`** / **`model-tiers.md`** — tool use is part of how an agent reasons.
|
|
65
|
+
- **`.claude/rules/evals.md`** — measure whether a tool change actually helps.
|
|
66
|
+
- **`catalog/mcp.yaml`** (kit authors) — where MCP servers are declared and wired into a project.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Accessibility Checklist
|
|
2
|
+
|
|
3
|
+
Quick reference for WCAG 2.1 AA compliance. Use alongside the `frontend-ui-engineering` skill.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Essential Checks](#essential-checks)
|
|
8
|
+
- [Common HTML Patterns](#common-html-patterns)
|
|
9
|
+
- [Testing Tools](#testing-tools)
|
|
10
|
+
- [Quick Reference: ARIA Live Regions](#quick-reference-aria-live-regions)
|
|
11
|
+
- [Common Anti-Patterns](#common-anti-patterns)
|
|
12
|
+
|
|
13
|
+
## Essential Checks
|
|
14
|
+
|
|
15
|
+
### Keyboard Navigation
|
|
16
|
+
- [ ] All interactive elements focusable via Tab key
|
|
17
|
+
- [ ] Focus order follows visual/logical order
|
|
18
|
+
- [ ] Focus is visible (outline/ring on focused elements)
|
|
19
|
+
- [ ] Custom widgets have keyboard support (Enter to activate, Escape to close)
|
|
20
|
+
- [ ] No keyboard traps (user can always Tab away from a component)
|
|
21
|
+
- [ ] Skip-to-content link at top of page - visible (at least) on keyboard focus
|
|
22
|
+
- [ ] Modals trap focus while open, return focus on close
|
|
23
|
+
|
|
24
|
+
### Screen Readers
|
|
25
|
+
- [ ] All images have `alt` text (or `alt=""` for decorative images)
|
|
26
|
+
- [ ] All form inputs have associated labels (`<label>` or `aria-label`)
|
|
27
|
+
- [ ] Buttons and links have descriptive text (not "Click here")
|
|
28
|
+
- [ ] Icon-only buttons have `aria-label`
|
|
29
|
+
- [ ] Page has one `<h1>` and headings don't skip levels
|
|
30
|
+
- [ ] Dynamic content changes announced (`aria-live` regions)
|
|
31
|
+
- [ ] Tables have `<th>` headers with scope
|
|
32
|
+
|
|
33
|
+
### Visual
|
|
34
|
+
- [ ] Text contrast ≥ 4.5:1 (normal text) or ≥ 3:1 (large text, 18px+)
|
|
35
|
+
- [ ] UI components contrast ≥ 3:1 against background
|
|
36
|
+
- [ ] Color is not the only way to convey information
|
|
37
|
+
- [ ] Text resizable to 200% without breaking layout
|
|
38
|
+
- [ ] No content that flashes more than 3 times per second
|
|
39
|
+
|
|
40
|
+
### Forms
|
|
41
|
+
- [ ] Every input has a visible label
|
|
42
|
+
- [ ] Required fields indicated (not by color alone)
|
|
43
|
+
- [ ] Error messages specific and associated with the field
|
|
44
|
+
- [ ] Error state visible by more than color (icon, text, border)
|
|
45
|
+
- [ ] Form submission errors summarized and focusable
|
|
46
|
+
- [ ] Known fields use autocomplete (for example `type="email" autocomplete="email"`)
|
|
47
|
+
|
|
48
|
+
### Content
|
|
49
|
+
- [ ] Language declared (`<html lang="en">`)
|
|
50
|
+
- [ ] Page has a descriptive `<title>`
|
|
51
|
+
- [ ] Links distinguish from surrounding text (not by color alone)
|
|
52
|
+
- [ ] Touch targets ≥ 44x44px on mobile
|
|
53
|
+
- [ ] Meaningful empty states (not blank screens)
|
|
54
|
+
|
|
55
|
+
## Common HTML Patterns
|
|
56
|
+
|
|
57
|
+
### Buttons vs. Links
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<!-- Use <button> for actions -->
|
|
61
|
+
<button onClick={handleDelete}>Delete Task</button>
|
|
62
|
+
|
|
63
|
+
<!-- Use <a> for navigation -->
|
|
64
|
+
<a href="/tasks/123">View Task</a>
|
|
65
|
+
|
|
66
|
+
<!-- NEVER use div/span as buttons -->
|
|
67
|
+
<div onClick={handleDelete}>Delete</div> <!-- BAD -->
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Form Labels
|
|
71
|
+
|
|
72
|
+
```html
|
|
73
|
+
<!-- Explicit label association -->
|
|
74
|
+
<label htmlFor="email">Email address</label>
|
|
75
|
+
<input id="email" type="email" required />
|
|
76
|
+
|
|
77
|
+
<!-- Implicit wrapping -->
|
|
78
|
+
<label>
|
|
79
|
+
Email address
|
|
80
|
+
<input type="email" required />
|
|
81
|
+
</label>
|
|
82
|
+
|
|
83
|
+
<!-- Hidden label (visible label preferred) -->
|
|
84
|
+
<input type="search" aria-label="Search tasks" />
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### ARIA Roles
|
|
88
|
+
|
|
89
|
+
```html
|
|
90
|
+
<!-- Navigation -->
|
|
91
|
+
<nav aria-label="Main navigation">...</nav>
|
|
92
|
+
<nav aria-label="Footer links">...</nav>
|
|
93
|
+
|
|
94
|
+
<!-- Status messages -->
|
|
95
|
+
<div role="status" aria-live="polite">Task saved</div>
|
|
96
|
+
|
|
97
|
+
<!-- Alert messages -->
|
|
98
|
+
<div role="alert">Error: Title is required</div>
|
|
99
|
+
|
|
100
|
+
<!-- Modal dialogs -->
|
|
101
|
+
<dialog aria-modal="true" aria-labelledby="dialog-title">
|
|
102
|
+
<h2 id="dialog-title">Confirm Delete</h2>
|
|
103
|
+
...
|
|
104
|
+
</dialog>
|
|
105
|
+
|
|
106
|
+
<!-- Loading states -->
|
|
107
|
+
<div aria-busy="true" aria-label="Loading tasks">
|
|
108
|
+
<Spinner />
|
|
109
|
+
</div>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Accessible Lists
|
|
113
|
+
|
|
114
|
+
```html
|
|
115
|
+
<ul role="list" aria-label="Tasks">
|
|
116
|
+
<li>
|
|
117
|
+
<input type="checkbox" id="task-1" aria-label="Complete: Buy groceries" />
|
|
118
|
+
<label htmlFor="task-1">Buy groceries</label>
|
|
119
|
+
</li>
|
|
120
|
+
</ul>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Testing Tools
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Automated audit
|
|
127
|
+
npx axe-core # Programmatic accessibility testing
|
|
128
|
+
npx pa11y # CLI accessibility checker
|
|
129
|
+
|
|
130
|
+
# In browser
|
|
131
|
+
# Chrome DevTools → Lighthouse → Accessibility
|
|
132
|
+
# Chrome DevTools → Elements → Accessibility tree
|
|
133
|
+
|
|
134
|
+
# Screen reader testing
|
|
135
|
+
# macOS: VoiceOver (Cmd + F5)
|
|
136
|
+
# Windows: NVDA (free) or JAWS
|
|
137
|
+
# Linux: Orca
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Quick Reference: ARIA Live Regions
|
|
141
|
+
|
|
142
|
+
| Value | Behavior | Use For |
|
|
143
|
+
|-------|----------|---------|
|
|
144
|
+
| `aria-live="polite"` | Announced at next pause | Status updates, saved confirmations |
|
|
145
|
+
| `aria-live="assertive"` | Announced immediately | Errors, time-sensitive alerts |
|
|
146
|
+
| `role="status"` | Same as `polite` | Status messages |
|
|
147
|
+
| `role="alert"` | Same as `assertive` | Error messages |
|
|
148
|
+
|
|
149
|
+
## Common Anti-Patterns
|
|
150
|
+
|
|
151
|
+
| Anti-Pattern | Problem | Fix |
|
|
152
|
+
|---|---|---|
|
|
153
|
+
| `div` as button | Not focusable, no keyboard support | Use `<button>` |
|
|
154
|
+
| Missing `alt` text | Images invisible to screen readers | Add descriptive `alt` |
|
|
155
|
+
| Color-only states | Invisible to color-blind users | Add icons, text, or patterns |
|
|
156
|
+
| Autoplaying media | Disorienting, can't be stopped | Add controls, don't autoplay |
|
|
157
|
+
| Custom dropdown with no ARIA | Unusable by keyboard/screen reader | Use native `<select>` or proper ARIA listbox |
|
|
158
|
+
| Removing focus outlines | Users can't see where they are | Style outlines, don't remove them |
|
|
159
|
+
| Empty links/buttons | "Link" announced with no description | Add text or `aria-label` |
|
|
160
|
+
| `tabindex > 0` | Breaks natural tab order | Use `tabindex="0"` or `-1` only |
|