@mclawnet/agent 0.5.8 → 0.6.1
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/cli.js +168 -61
- package/dist/__tests__/cli.test.d.ts +2 -0
- package/dist/__tests__/cli.test.d.ts.map +1 -0
- package/dist/__tests__/service-config.test.d.ts +2 -0
- package/dist/__tests__/service-config.test.d.ts.map +1 -0
- package/dist/__tests__/service-linux.test.d.ts +2 -0
- package/dist/__tests__/service-linux.test.d.ts.map +1 -0
- package/dist/__tests__/service-macos.test.d.ts +2 -0
- package/dist/__tests__/service-macos.test.d.ts.map +1 -0
- package/dist/__tests__/service-windows.test.d.ts +2 -0
- package/dist/__tests__/service-windows.test.d.ts.map +1 -0
- package/dist/backend-adapter.d.ts +2 -0
- package/dist/backend-adapter.d.ts.map +1 -1
- package/dist/{chunk-KHPEQTWF.js → chunk-KITKMSBE.js} +166 -90
- package/dist/chunk-KITKMSBE.js.map +1 -0
- package/dist/chunk-W3LSW4XY.js +95 -0
- package/dist/chunk-W3LSW4XY.js.map +1 -0
- package/dist/hub-connection.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/linux-5KQ4SCAA.js +175 -0
- package/dist/linux-5KQ4SCAA.js.map +1 -0
- package/dist/macos-FGY546NC.js +173 -0
- package/dist/macos-FGY546NC.js.map +1 -0
- package/dist/service/config.d.ts +19 -0
- package/dist/service/config.d.ts.map +1 -0
- package/dist/service/index.d.ts +6 -0
- package/dist/service/index.d.ts.map +1 -0
- package/dist/service/index.js +46 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/linux.d.ts +18 -0
- package/dist/service/linux.d.ts.map +1 -0
- package/dist/service/macos.d.ts +18 -0
- package/dist/service/macos.d.ts.map +1 -0
- package/dist/service/types.d.ts +19 -0
- package/dist/service/types.d.ts.map +1 -0
- package/dist/service/windows.d.ts +18 -0
- package/dist/service/windows.d.ts.map +1 -0
- package/dist/session-manager.d.ts +4 -7
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/skill-loader.d.ts +8 -0
- package/dist/skill-loader.d.ts.map +1 -0
- package/dist/start.d.ts.map +1 -1
- package/dist/start.js +1 -1
- package/dist/windows-PIJ4CMWX.js +164 -0
- package/dist/windows-PIJ4CMWX.js.map +1 -0
- package/package.json +18 -16
- package/skills/academic-search/SKILL.md +147 -0
- package/skills/architecture/SKILL.md +294 -0
- package/skills/changelog-generator/SKILL.md +112 -0
- package/skills/chart-visualization/SKILL.md +183 -0
- package/skills/code-review/SKILL.md +304 -0
- package/skills/codebase-health/SKILL.md +281 -0
- package/skills/consulting-analysis/SKILL.md +584 -0
- package/skills/content-research-writer/SKILL.md +546 -0
- package/skills/data-analysis/SKILL.md +194 -0
- package/skills/deep-research/SKILL.md +198 -0
- package/skills/docx/SKILL.md +211 -0
- package/skills/github-deep-research/SKILL.md +207 -0
- package/skills/image-generation/SKILL.md +209 -0
- package/skills/lead-research-assistant/SKILL.md +207 -0
- package/skills/mcp-builder/SKILL.md +304 -0
- package/skills/meeting-insights-analyzer/SKILL.md +335 -0
- package/skills/pair-programming/SKILL.md +196 -0
- package/skills/pdf/SKILL.md +309 -0
- package/skills/performance-analysis/SKILL.md +261 -0
- package/skills/podcast-generation/SKILL.md +224 -0
- package/skills/pptx/SKILL.md +497 -0
- package/skills/project-learnings/SKILL.md +280 -0
- package/skills/security-audit/SKILL.md +211 -0
- package/skills/skill-creator/SKILL.md +200 -0
- package/skills/technical-writing/SKILL.md +286 -0
- package/skills/testing/SKILL.md +363 -0
- package/skills/video-generation/SKILL.md +247 -0
- package/skills/web-design-guidelines/SKILL.md +203 -0
- package/skills/webapp-testing/SKILL.md +162 -0
- package/skills/workflow-automation/SKILL.md +299 -0
- package/skills/xlsx/SKILL.md +305 -0
- package/dist/chunk-KHPEQTWF.js.map +0 -1
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: technical-writing
|
|
3
|
+
description: Write clear, accurate technical documentation including API docs, architecture guides, runbooks, READMEs, and technical proposals. Use when creating or improving technical documents, writing specs, or documenting systems for developer audiences.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Technical Writing
|
|
7
|
+
|
|
8
|
+
Write clear, accurate, and useful technical documentation for developer audiences — API docs, architecture guides, runbooks, READMEs, RFCs, and technical proposals.
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
Good technical writing is invisible: readers find what they need, understand it on first read, and can act on it without asking someone. This skill provides a systematic approach to planning, structuring, writing, and reviewing technical documents.
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
- Writing API documentation or reference guides
|
|
17
|
+
- Creating architecture decision records (ADRs) or design docs
|
|
18
|
+
- Writing README files for projects or packages
|
|
19
|
+
- Authoring runbooks for operational procedures
|
|
20
|
+
- Drafting RFCs or technical proposals
|
|
21
|
+
- Documenting onboarding guides or setup instructions
|
|
22
|
+
- Improving existing documentation that is unclear or outdated
|
|
23
|
+
|
|
24
|
+
## When NOT to Use
|
|
25
|
+
|
|
26
|
+
- **Blog posts or marketing content** — use the `content-research-writer` skill
|
|
27
|
+
- **Meeting notes** — use the `meeting-insights-analyzer` skill
|
|
28
|
+
- **Code comments** — those belong in the code, not a separate document
|
|
29
|
+
- **User-facing help articles** — different audience, different style
|
|
30
|
+
|
|
31
|
+
## Writing Process
|
|
32
|
+
|
|
33
|
+
### Step 1: Define Audience and Purpose
|
|
34
|
+
|
|
35
|
+
Before writing a single word:
|
|
36
|
+
|
|
37
|
+
1. **Who reads this?** (Junior dev? SRE? External API consumer? Future you?)
|
|
38
|
+
2. **What do they need to do?** (Set up the project? Call an API? Debug an issue?)
|
|
39
|
+
3. **What do they already know?** (Don't explain Git to senior engineers)
|
|
40
|
+
4. **When do they read this?** (During onboarding? At 3am during an incident?)
|
|
41
|
+
|
|
42
|
+
### Step 2: Choose the Document Type
|
|
43
|
+
|
|
44
|
+
| Type | Purpose | Structure |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| README | First impression, quick start | Title → What → Quick start → Install → Usage → Contributing |
|
|
47
|
+
| API Reference | Endpoint/function documentation | Endpoint → Parameters → Request → Response → Errors → Example |
|
|
48
|
+
| Architecture Doc | System design explanation | Context → Goals → Design → Trade-offs → Alternatives |
|
|
49
|
+
| ADR | Record a specific decision | Status → Context → Decision → Consequences |
|
|
50
|
+
| Runbook | Step-by-step operational procedure | When to use → Prerequisites → Steps → Rollback → Contacts |
|
|
51
|
+
| RFC/Proposal | Propose a change for review | Problem → Proposal → Alternatives → Migration → Timeline |
|
|
52
|
+
| Onboarding Guide | Get someone productive | Prerequisites → Setup → First task → Resources → FAQ |
|
|
53
|
+
|
|
54
|
+
### Step 3: Write the First Draft
|
|
55
|
+
|
|
56
|
+
**Structure first, prose second.** Write all headings and bullet points before filling in paragraphs. This prevents rambling and ensures logical flow.
|
|
57
|
+
|
|
58
|
+
**Lead with the action.** For every section, the reader should know within the first sentence what to DO.
|
|
59
|
+
|
|
60
|
+
**One idea per paragraph.** If a paragraph covers two topics, split it.
|
|
61
|
+
|
|
62
|
+
### Step 4: Review and Refine
|
|
63
|
+
|
|
64
|
+
Run through the quality checklist (below) before publishing.
|
|
65
|
+
|
|
66
|
+
## Writing Principles
|
|
67
|
+
|
|
68
|
+
### Be Direct
|
|
69
|
+
|
|
70
|
+
- Bad: "It should be noted that the configuration file needs to be updated prior to deployment."
|
|
71
|
+
- Good: "Update `config.yaml` before deploying."
|
|
72
|
+
|
|
73
|
+
### Be Specific
|
|
74
|
+
|
|
75
|
+
- Bad: "The API may return an error in certain conditions."
|
|
76
|
+
- Good: "The API returns `403 Forbidden` when the API key lacks `write` scope."
|
|
77
|
+
|
|
78
|
+
### Be Complete
|
|
79
|
+
|
|
80
|
+
- Bad: "Install the dependencies and run the server."
|
|
81
|
+
- Good: "Run `npm install` to install dependencies, then `npm run dev` to start the server on port 3000."
|
|
82
|
+
|
|
83
|
+
### Show, Don't Just Tell
|
|
84
|
+
|
|
85
|
+
- Bad: "The function accepts various options."
|
|
86
|
+
- Good:
|
|
87
|
+
```typescript
|
|
88
|
+
createUser({
|
|
89
|
+
name: "Alice", // required
|
|
90
|
+
email: "alice@co.com", // required, must be valid email
|
|
91
|
+
role: "admin", // optional, defaults to "viewer"
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Use Consistent Terminology
|
|
96
|
+
|
|
97
|
+
Pick one term for each concept and use it everywhere. Don't alternate between "endpoint", "route", and "API path" for the same thing. Define terms in a glossary if needed.
|
|
98
|
+
|
|
99
|
+
## Document Templates
|
|
100
|
+
|
|
101
|
+
### README Template
|
|
102
|
+
|
|
103
|
+
```markdown
|
|
104
|
+
# Project Name
|
|
105
|
+
|
|
106
|
+
One-sentence description of what this project does.
|
|
107
|
+
|
|
108
|
+
## Quick Start
|
|
109
|
+
|
|
110
|
+
\`\`\`bash
|
|
111
|
+
npm install
|
|
112
|
+
npm run dev
|
|
113
|
+
# Open http://localhost:3000
|
|
114
|
+
\`\`\`
|
|
115
|
+
|
|
116
|
+
## What This Does
|
|
117
|
+
|
|
118
|
+
2-3 paragraphs explaining the project's purpose and key features.
|
|
119
|
+
|
|
120
|
+
## Installation
|
|
121
|
+
|
|
122
|
+
Step-by-step installation instructions.
|
|
123
|
+
|
|
124
|
+
## Usage
|
|
125
|
+
|
|
126
|
+
Most common usage examples with code.
|
|
127
|
+
|
|
128
|
+
## Configuration
|
|
129
|
+
|
|
130
|
+
Environment variables and config file options.
|
|
131
|
+
|
|
132
|
+
## API
|
|
133
|
+
|
|
134
|
+
Brief API reference or link to full docs.
|
|
135
|
+
|
|
136
|
+
## Development
|
|
137
|
+
|
|
138
|
+
How to set up the dev environment, run tests, and contribute.
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
[License type]
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### API Endpoint Template
|
|
146
|
+
|
|
147
|
+
```markdown
|
|
148
|
+
## POST /api/users
|
|
149
|
+
|
|
150
|
+
Create a new user account.
|
|
151
|
+
|
|
152
|
+
### Request
|
|
153
|
+
|
|
154
|
+
**Headers:**
|
|
155
|
+
| Header | Value | Required |
|
|
156
|
+
|--------|-------|----------|
|
|
157
|
+
| Authorization | Bearer {token} | Yes |
|
|
158
|
+
| Content-Type | application/json | Yes |
|
|
159
|
+
|
|
160
|
+
**Body:**
|
|
161
|
+
\`\`\`json
|
|
162
|
+
{
|
|
163
|
+
"name": "Alice Smith",
|
|
164
|
+
"email": "alice@example.com",
|
|
165
|
+
"role": "admin"
|
|
166
|
+
}
|
|
167
|
+
\`\`\`
|
|
168
|
+
|
|
169
|
+
| Field | Type | Required | Description |
|
|
170
|
+
|-------|------|----------|-------------|
|
|
171
|
+
| name | string | Yes | Full name, 1-100 characters |
|
|
172
|
+
| email | string | Yes | Valid email address |
|
|
173
|
+
| role | string | No | One of: admin, editor, viewer. Default: viewer |
|
|
174
|
+
|
|
175
|
+
### Response
|
|
176
|
+
|
|
177
|
+
**201 Created:**
|
|
178
|
+
\`\`\`json
|
|
179
|
+
{
|
|
180
|
+
"id": "usr_abc123",
|
|
181
|
+
"name": "Alice Smith",
|
|
182
|
+
"email": "alice@example.com",
|
|
183
|
+
"role": "admin",
|
|
184
|
+
"createdAt": "2024-01-15T10:30:00Z"
|
|
185
|
+
}
|
|
186
|
+
\`\`\`
|
|
187
|
+
|
|
188
|
+
### Errors
|
|
189
|
+
|
|
190
|
+
| Status | Code | Description |
|
|
191
|
+
|--------|------|-------------|
|
|
192
|
+
| 400 | INVALID_EMAIL | Email format is invalid |
|
|
193
|
+
| 409 | EMAIL_EXISTS | An account with this email already exists |
|
|
194
|
+
| 403 | INSUFFICIENT_PERMISSIONS | API key lacks user:create scope |
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Runbook Template
|
|
198
|
+
|
|
199
|
+
```markdown
|
|
200
|
+
# Runbook: [Procedure Name]
|
|
201
|
+
|
|
202
|
+
## When to Use
|
|
203
|
+
[Describe the situation that triggers this runbook]
|
|
204
|
+
|
|
205
|
+
## Prerequisites
|
|
206
|
+
- [ ] Access to [system/tool]
|
|
207
|
+
- [ ] Permissions: [specific permissions needed]
|
|
208
|
+
- [ ] Notify: [who to inform before starting]
|
|
209
|
+
|
|
210
|
+
## Steps
|
|
211
|
+
|
|
212
|
+
### 1. [First Step]
|
|
213
|
+
\`\`\`bash
|
|
214
|
+
[exact command]
|
|
215
|
+
\`\`\`
|
|
216
|
+
Expected output: [what you should see]
|
|
217
|
+
If this fails: [what to do]
|
|
218
|
+
|
|
219
|
+
### 2. [Second Step]
|
|
220
|
+
...
|
|
221
|
+
|
|
222
|
+
## Verification
|
|
223
|
+
How to confirm the procedure was successful:
|
|
224
|
+
\`\`\`bash
|
|
225
|
+
[verification command]
|
|
226
|
+
\`\`\`
|
|
227
|
+
|
|
228
|
+
## Rollback
|
|
229
|
+
If something goes wrong:
|
|
230
|
+
1. [Rollback step 1]
|
|
231
|
+
2. [Rollback step 2]
|
|
232
|
+
|
|
233
|
+
## Contacts
|
|
234
|
+
- Primary: [name, contact]
|
|
235
|
+
- Escalation: [name, contact]
|
|
236
|
+
|
|
237
|
+
## Revision History
|
|
238
|
+
| Date | Author | Change |
|
|
239
|
+
|------|--------|--------|
|
|
240
|
+
| YYYY-MM-DD | Name | Initial version |
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Quality Checklist
|
|
244
|
+
|
|
245
|
+
### Structure
|
|
246
|
+
- [ ] Title clearly states what the document is about
|
|
247
|
+
- [ ] Table of contents for documents > 3 sections
|
|
248
|
+
- [ ] Headings create a logical hierarchy (H1 → H2 → H3, no skipping)
|
|
249
|
+
- [ ] Sections are ordered by importance or workflow sequence
|
|
250
|
+
|
|
251
|
+
### Content
|
|
252
|
+
- [ ] Every claim is verifiable (commands, URLs, examples)
|
|
253
|
+
- [ ] Code examples are complete and runnable (not pseudocode)
|
|
254
|
+
- [ ] Error scenarios are documented, not just the happy path
|
|
255
|
+
- [ ] Prerequisites are listed before the steps that need them
|
|
256
|
+
- [ ] No assumptions about reader's environment (OS, tools, versions stated)
|
|
257
|
+
|
|
258
|
+
### Clarity
|
|
259
|
+
- [ ] No jargon without definition on first use
|
|
260
|
+
- [ ] Sentences average < 20 words
|
|
261
|
+
- [ ] Active voice used throughout ("Run the command" not "The command should be run")
|
|
262
|
+
- [ ] Each paragraph has one topic
|
|
263
|
+
|
|
264
|
+
### Maintenance
|
|
265
|
+
- [ ] Version/date visible (so readers know if it's current)
|
|
266
|
+
- [ ] No hardcoded values that change (use variables or "replace X with your value")
|
|
267
|
+
- [ ] Links are to specific versions/commits, not "latest" (which changes)
|
|
268
|
+
- [ ] Contact/owner information included
|
|
269
|
+
|
|
270
|
+
## Common Anti-Patterns
|
|
271
|
+
|
|
272
|
+
### Write Once, Never Update
|
|
273
|
+
**Problem**: Documentation written at launch, never updated as the system changes.
|
|
274
|
+
**Fix**: Treat docs as code — update them in the same PR that changes the feature.
|
|
275
|
+
|
|
276
|
+
### Wall of Text
|
|
277
|
+
**Problem**: 2000-word document with no headings, no code blocks, no structure.
|
|
278
|
+
**Fix**: Use headings every 3-5 paragraphs. Add code blocks for commands. Use tables for structured data.
|
|
279
|
+
|
|
280
|
+
### Assumed Knowledge
|
|
281
|
+
**Problem**: "Just SSH in and restart the service" — assumes reader knows which server, which service, and how to SSH.
|
|
282
|
+
**Fix**: Include every detail. Over-specify rather than under-specify.
|
|
283
|
+
|
|
284
|
+
### Tutorial Disguised as Reference
|
|
285
|
+
**Problem**: API docs that read like a tutorial ("First, you'll want to...").
|
|
286
|
+
**Fix**: Reference docs should be scannable. Use tables, consistent format, and direct language.
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testing
|
|
3
|
+
description: Design and implement comprehensive test suites using TDD methodology. Use when writing tests, improving test coverage, debugging test failures, or deciding what type of test to write for a given scenario.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Testing
|
|
7
|
+
|
|
8
|
+
Design and implement comprehensive, maintainable test suites following Test-Driven Development methodology and proven test design techniques.
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
This skill provides structured guidance for all testing activities: choosing the right test type for a given scenario, designing effective test cases using formal techniques, writing readable and maintainable tests, and achieving meaningful coverage targets.
|
|
13
|
+
|
|
14
|
+
Testing is not about achieving a coverage number. It is about building a safety net that catches real bugs, documents intended behavior, and gives developers confidence to refactor.
|
|
15
|
+
|
|
16
|
+
## When to Use
|
|
17
|
+
|
|
18
|
+
- Writing tests for new features or bug fixes
|
|
19
|
+
- Improving test coverage for existing code
|
|
20
|
+
- Debugging flaky or failing tests
|
|
21
|
+
- Deciding what type of test to write (unit vs integration vs E2E)
|
|
22
|
+
- Applying TDD workflow to drive implementation
|
|
23
|
+
- Reviewing test quality and identifying gaps
|
|
24
|
+
|
|
25
|
+
## When NOT to Use
|
|
26
|
+
|
|
27
|
+
- **Code review** — use the `code-review` skill instead
|
|
28
|
+
- **Browser-based E2E testing** with Playwright/Puppeteer — use the `webapp-testing` skill instead
|
|
29
|
+
- **Performance benchmarking** — use the `performance-analysis` skill
|
|
30
|
+
- **Security testing** — use the `security-audit` skill
|
|
31
|
+
|
|
32
|
+
## TDD Cycle
|
|
33
|
+
|
|
34
|
+
Follow the Red-Green-Refactor cycle strictly. Do not skip steps.
|
|
35
|
+
|
|
36
|
+
### Step 1: Red — Write a Failing Test
|
|
37
|
+
|
|
38
|
+
1. Identify the next smallest piece of behavior to implement
|
|
39
|
+
2. Write a test that describes that behavior in terms of inputs and expected outputs
|
|
40
|
+
3. Run the test suite and confirm the new test fails
|
|
41
|
+
4. The failure message should clearly indicate what is missing
|
|
42
|
+
|
|
43
|
+
Key rules:
|
|
44
|
+
- Write only ONE test at a time
|
|
45
|
+
- The test must fail for the RIGHT reason (missing implementation, not a syntax error)
|
|
46
|
+
- Do not write implementation code during this step
|
|
47
|
+
|
|
48
|
+
### Step 2: Green — Make It Pass
|
|
49
|
+
|
|
50
|
+
1. Write the MINIMAL code to make the failing test pass
|
|
51
|
+
2. It is acceptable to hardcode return values or use shortcuts at this stage
|
|
52
|
+
3. Run the full test suite to confirm the new test passes AND no existing tests broke
|
|
53
|
+
|
|
54
|
+
Key rules:
|
|
55
|
+
- Change only production code, not test code
|
|
56
|
+
- Do not add functionality beyond what the test requires
|
|
57
|
+
|
|
58
|
+
### Step 3: Refactor — Improve the Code
|
|
59
|
+
|
|
60
|
+
1. Look for duplication, unclear naming, or structural issues in BOTH test and production code
|
|
61
|
+
2. Apply refactoring patterns (extract method, rename, simplify conditionals)
|
|
62
|
+
3. Run the full test suite after each refactoring step
|
|
63
|
+
4. All tests must remain green throughout
|
|
64
|
+
|
|
65
|
+
Key rules:
|
|
66
|
+
- Do not change behavior during refactoring — only structure
|
|
67
|
+
- Refactor test code too: extract helpers, improve naming, reduce duplication
|
|
68
|
+
|
|
69
|
+
## Test Strategy Selection
|
|
70
|
+
|
|
71
|
+
Choose the test type based on what you are testing. Use the most focused test type that can verify the behavior.
|
|
72
|
+
|
|
73
|
+
### Decision Matrix
|
|
74
|
+
|
|
75
|
+
| What You Are Testing | Test Type | Why |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| Pure function (input → output) | Unit test | Fast, isolated, deterministic |
|
|
78
|
+
| Single class or module behavior | Unit test | Mock collaborators, test logic |
|
|
79
|
+
| Component interaction (2-3 modules) | Integration test | Verify contracts between components |
|
|
80
|
+
| Database queries or ORM behavior | Integration test | Need real or in-memory database |
|
|
81
|
+
| API endpoint request/response | Integration test | Test HTTP layer with real routing |
|
|
82
|
+
| Full user workflow (multi-step) | E2E test | Validate end-to-end behavior |
|
|
83
|
+
| Data transformation correctness | Property-based test | Generate many inputs automatically |
|
|
84
|
+
| Error handling and failure modes | Negative test | Verify graceful degradation |
|
|
85
|
+
| Performance-critical path | Benchmark test | Measure and assert timing/throughput |
|
|
86
|
+
| Backward compatibility | Contract test | Assert API shape has not changed |
|
|
87
|
+
|
|
88
|
+
### Rules of Thumb
|
|
89
|
+
|
|
90
|
+
- If you can test it with a unit test, do not write an integration test
|
|
91
|
+
- If the behavior depends on infrastructure (DB, network, filesystem), use an integration test
|
|
92
|
+
- Write E2E tests only for critical user paths — they are slow and brittle
|
|
93
|
+
- Aim for a test pyramid: many unit tests, fewer integration tests, fewest E2E tests
|
|
94
|
+
|
|
95
|
+
## Test Design Techniques
|
|
96
|
+
|
|
97
|
+
### Boundary Value Analysis
|
|
98
|
+
|
|
99
|
+
Bugs cluster at boundaries. For every input range, test:
|
|
100
|
+
|
|
101
|
+
- **Minimum value** — the lowest valid input
|
|
102
|
+
- **Just below minimum** — should be rejected or handled
|
|
103
|
+
- **Just above minimum** — should be accepted
|
|
104
|
+
- **Maximum value** — the highest valid input
|
|
105
|
+
- **Just above maximum** — should be rejected or handled
|
|
106
|
+
- **Zero / empty / null** — often a special case
|
|
107
|
+
- **Off-by-one** — array indices, loop counters, pagination offsets
|
|
108
|
+
|
|
109
|
+
Example boundaries: empty string, single character, max length string; empty array, single element, max size array; integer 0, -1, 1, MAX_SAFE_INTEGER.
|
|
110
|
+
|
|
111
|
+
### Equivalence Partitioning
|
|
112
|
+
|
|
113
|
+
Divide inputs into classes where all values in a class should produce the same behavior. Test ONE representative from each class.
|
|
114
|
+
|
|
115
|
+
**Valid partitions** — inputs the system should accept:
|
|
116
|
+
- Typical value from each valid range
|
|
117
|
+
- Each distinct valid format or type
|
|
118
|
+
|
|
119
|
+
**Invalid partitions** — inputs the system should reject:
|
|
120
|
+
- Wrong type (string instead of number, null instead of object)
|
|
121
|
+
- Out of range (negative age, future birthdate)
|
|
122
|
+
- Malformed format (invalid email, wrong date format)
|
|
123
|
+
- Missing required fields
|
|
124
|
+
|
|
125
|
+
### State Transition Testing
|
|
126
|
+
|
|
127
|
+
For components with lifecycle or state machines:
|
|
128
|
+
|
|
129
|
+
1. Identify all states the component can be in
|
|
130
|
+
2. Identify all events/inputs that trigger transitions
|
|
131
|
+
3. Map every valid transition (state + event → new state)
|
|
132
|
+
4. Test each valid transition at least once
|
|
133
|
+
5. Test invalid transitions (events that should not be possible in a given state)
|
|
134
|
+
|
|
135
|
+
### Decision Table Testing
|
|
136
|
+
|
|
137
|
+
For functions with complex conditional logic (multiple boolean conditions):
|
|
138
|
+
|
|
139
|
+
1. List all conditions (inputs that affect the decision)
|
|
140
|
+
2. List all actions (possible outcomes)
|
|
141
|
+
3. Create a truth table with every combination of conditions
|
|
142
|
+
4. For each combination, determine the expected action
|
|
143
|
+
5. Write one test for each row in the table
|
|
144
|
+
|
|
145
|
+
## Test Quality Dimensions
|
|
146
|
+
|
|
147
|
+
Use these dimensions to assess and improve test suite quality.
|
|
148
|
+
|
|
149
|
+
### 1. Coverage
|
|
150
|
+
|
|
151
|
+
Track three types:
|
|
152
|
+
- **Line coverage** — percentage of lines executed
|
|
153
|
+
- **Branch coverage** — percentage of conditional branches taken
|
|
154
|
+
- **Function coverage** — percentage of functions called
|
|
155
|
+
|
|
156
|
+
Important: High coverage does not mean good tests. A test that executes code without meaningful assertions provides false confidence.
|
|
157
|
+
|
|
158
|
+
### 2. Isolation
|
|
159
|
+
|
|
160
|
+
Each test must be independent:
|
|
161
|
+
- Tests must not depend on execution order
|
|
162
|
+
- Tests must not share mutable state
|
|
163
|
+
- Use fresh fixtures for each test (setup/teardown)
|
|
164
|
+
- Mock external systems (network, database, filesystem) in unit tests
|
|
165
|
+
|
|
166
|
+
### 3. Readability
|
|
167
|
+
|
|
168
|
+
Tests are documentation. Optimize for clarity:
|
|
169
|
+
- **Naming**: `should [expected behavior] when [condition]`
|
|
170
|
+
- **AAA pattern**: Clearly separate Arrange, Act, and Assert sections
|
|
171
|
+
- **One concept per test**: Each test verifies one logical assertion
|
|
172
|
+
- **No logic in tests**: Avoid conditionals, loops, or try/catch in test code
|
|
173
|
+
- **Literal values**: Use concrete values, not computed values, in assertions
|
|
174
|
+
|
|
175
|
+
### 4. Maintainability
|
|
176
|
+
|
|
177
|
+
Tests must be cheap to maintain:
|
|
178
|
+
- **DRY test helpers**: Extract repeated setup into helper functions
|
|
179
|
+
- **Builder pattern**: Use test data builders for complex objects
|
|
180
|
+
- **Avoid brittle selectors**: Test behavior, not implementation details
|
|
181
|
+
- **Keep tests close to source**: Co-locate `foo.test.ts` with `foo.ts`
|
|
182
|
+
|
|
183
|
+
### 5. Speed
|
|
184
|
+
|
|
185
|
+
Fast tests get run more often:
|
|
186
|
+
- Unit tests: target < 10ms each, entire suite < 10 seconds
|
|
187
|
+
- Integration tests: target < 500ms each, entire suite < 2 minutes
|
|
188
|
+
- Segregate slow tests with tags or directories
|
|
189
|
+
|
|
190
|
+
### 6. Determinism
|
|
191
|
+
|
|
192
|
+
A test that sometimes passes and sometimes fails is worse than no test:
|
|
193
|
+
- Do not depend on wall-clock time — use fake timers
|
|
194
|
+
- Do not depend on random values unless you seed the generator
|
|
195
|
+
- Do not depend on network availability — mock HTTP calls
|
|
196
|
+
- Do not depend on file system state — use temporary directories
|
|
197
|
+
- If a test is flaky, fix it immediately or delete it
|
|
198
|
+
|
|
199
|
+
## Test Organization
|
|
200
|
+
|
|
201
|
+
### File Structure
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
src/
|
|
205
|
+
services/
|
|
206
|
+
user-service.ts
|
|
207
|
+
user-service.test.ts # unit tests co-located
|
|
208
|
+
utils/
|
|
209
|
+
validator.ts
|
|
210
|
+
validator.test.ts
|
|
211
|
+
test/
|
|
212
|
+
integration/
|
|
213
|
+
user-api.integration.test.ts # integration tests separated
|
|
214
|
+
e2e/
|
|
215
|
+
user-workflow.e2e.test.ts # E2E tests separated
|
|
216
|
+
helpers/
|
|
217
|
+
test-factory.ts # shared test data builders
|
|
218
|
+
mock-database.ts # shared mocks
|
|
219
|
+
fixtures/
|
|
220
|
+
sample-user.json # static test data
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Describe/It Nesting
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
describe("UserService", () => {
|
|
227
|
+
describe("createUser", () => {
|
|
228
|
+
it("should create a user with valid input", () => {
|
|
229
|
+
// Arrange
|
|
230
|
+
const input = { name: "Alice", email: "alice@example.com" };
|
|
231
|
+
// Act
|
|
232
|
+
const result = userService.createUser(input);
|
|
233
|
+
// Assert
|
|
234
|
+
expect(result.id).toBeDefined();
|
|
235
|
+
expect(result.name).toBe("Alice");
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it("should throw ValidationError when email is missing", () => {
|
|
239
|
+
expect(() => userService.createUser({ name: "Alice" })).toThrow(ValidationError);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
describe("when user already exists", () => {
|
|
243
|
+
it("should throw DuplicateError", () => { /* ... */ });
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Setup and Teardown
|
|
250
|
+
|
|
251
|
+
- Use `beforeEach` for per-test setup (fresh state)
|
|
252
|
+
- Use `afterEach` for per-test cleanup (close connections, clear mocks)
|
|
253
|
+
- Use `beforeAll` / `afterAll` sparingly — only for expensive, read-only setup
|
|
254
|
+
- Always call `jest.restoreAllMocks()` or equivalent in `afterEach`
|
|
255
|
+
|
|
256
|
+
## Common Patterns
|
|
257
|
+
|
|
258
|
+
### Parameterized Tests
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
it.each([
|
|
262
|
+
{ input: "", expected: false },
|
|
263
|
+
{ input: "a", expected: false },
|
|
264
|
+
{ input: "valid@email.com", expected: true },
|
|
265
|
+
{ input: "no-at-sign.com", expected: false },
|
|
266
|
+
])("isValidEmail('$input') should return $expected", ({ input, expected }) => {
|
|
267
|
+
expect(isValidEmail(input)).toBe(expected);
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Snapshot Tests
|
|
272
|
+
|
|
273
|
+
- Review snapshot diffs carefully during code review
|
|
274
|
+
- Update snapshots intentionally, never blindly with `--update`
|
|
275
|
+
- Keep snapshots small — snapshot a component, not an entire page
|
|
276
|
+
- Prefer inline snapshots for small outputs
|
|
277
|
+
|
|
278
|
+
### Error Testing
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
// Synchronous
|
|
282
|
+
expect(() => divide(1, 0)).toThrow(DivisionByZeroError);
|
|
283
|
+
|
|
284
|
+
// Async
|
|
285
|
+
await expect(fetchUser("nonexistent")).rejects.toThrow(NotFoundError);
|
|
286
|
+
|
|
287
|
+
// Error properties
|
|
288
|
+
try {
|
|
289
|
+
await riskyOperation();
|
|
290
|
+
fail("Expected an error");
|
|
291
|
+
} catch (error) {
|
|
292
|
+
expect(error).toBeInstanceOf(AppError);
|
|
293
|
+
expect(error.code).toBe("RATE_LIMITED");
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Async Testing
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
// Awaiting promises
|
|
301
|
+
it("should fetch user data", async () => {
|
|
302
|
+
const user = await userService.getById("123");
|
|
303
|
+
expect(user.name).toBe("Alice");
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// Fake timers
|
|
307
|
+
it("should retry after delay", async () => {
|
|
308
|
+
jest.useFakeTimers();
|
|
309
|
+
const promise = retryableOperation();
|
|
310
|
+
jest.advanceTimersByTime(3000);
|
|
311
|
+
const result = await promise;
|
|
312
|
+
expect(result).toBe("success");
|
|
313
|
+
jest.useRealTimers();
|
|
314
|
+
});
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Coverage Goals
|
|
318
|
+
|
|
319
|
+
### Tiered Targets
|
|
320
|
+
|
|
321
|
+
| Code Category | Line Coverage | Branch Coverage | Rationale |
|
|
322
|
+
|---|---|---|---|
|
|
323
|
+
| Business logic, domain rules | 90%+ | 80%+ | Highest value, highest risk |
|
|
324
|
+
| API handlers, controllers | 80%+ | 70%+ | User-facing entry points |
|
|
325
|
+
| Utility functions, helpers | 70%+ | 60%+ | Reused widely, moderate risk |
|
|
326
|
+
| Glue code, configuration | 50%+ | — | Low logic density |
|
|
327
|
+
| Generated code, vendor wrappers | No target | — | Not worth testing |
|
|
328
|
+
|
|
329
|
+
### Coverage Rules
|
|
330
|
+
|
|
331
|
+
- Every bug fix MUST include a regression test that fails without the fix and passes with it
|
|
332
|
+
- New features must meet the coverage target for their category before merge
|
|
333
|
+
- Coverage should never decrease on a PR without explicit justification
|
|
334
|
+
|
|
335
|
+
## Anti-Patterns to Avoid
|
|
336
|
+
|
|
337
|
+
### Testing Implementation Details
|
|
338
|
+
BAD: Testing that a function calls another function internally.
|
|
339
|
+
GOOD: Testing that given input X, the output is Y. If you refactor internals and tests break without any behavior change, the tests are testing implementation.
|
|
340
|
+
|
|
341
|
+
### Over-Mocking
|
|
342
|
+
BAD: Mocking every dependency, including simple value objects and pure functions.
|
|
343
|
+
GOOD: Mock only external systems (network, database, clock) and expensive operations.
|
|
344
|
+
|
|
345
|
+
### Test Interdependence
|
|
346
|
+
BAD: Test B relies on state created by Test A.
|
|
347
|
+
GOOD: Each test creates its own state from scratch.
|
|
348
|
+
|
|
349
|
+
### Ignoring Test Failures
|
|
350
|
+
BAD: Marking failing tests as `skip` and moving on.
|
|
351
|
+
GOOD: Fix the test immediately. If it cannot be fixed now, create a tracked issue and delete the test.
|
|
352
|
+
|
|
353
|
+
### Testing the Framework
|
|
354
|
+
BAD: Testing that Express routes requests to handlers, or that React renders JSX.
|
|
355
|
+
GOOD: Testing your logic within those frameworks. Trust the framework.
|
|
356
|
+
|
|
357
|
+
### Tautological Tests
|
|
358
|
+
BAD: `expect(add(2, 3)).toBe(2 + 3)` — repeats the implementation logic.
|
|
359
|
+
GOOD: `expect(add(2, 3)).toBe(5)` — uses a hardcoded expected value.
|
|
360
|
+
|
|
361
|
+
### Assertion-Free Tests
|
|
362
|
+
BAD: A test that calls a function but never asserts anything.
|
|
363
|
+
GOOD: Every test has at least one meaningful assertion about the result or side effect.
|