trinity-method-sdk 2.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.
Files changed (191) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/LICENSE +21 -0
  3. package/README.md +555 -0
  4. package/dist/cli/commands/deploy/agents.d.ts +14 -0
  5. package/dist/cli/commands/deploy/agents.js +59 -0
  6. package/dist/cli/commands/deploy/ci-cd.d.ts +13 -0
  7. package/dist/cli/commands/deploy/ci-cd.js +50 -0
  8. package/dist/cli/commands/deploy/claude-setup.d.ts +17 -0
  9. package/dist/cli/commands/deploy/claude-setup.js +91 -0
  10. package/dist/cli/commands/deploy/configuration.d.ts +13 -0
  11. package/dist/cli/commands/deploy/configuration.js +215 -0
  12. package/dist/cli/commands/deploy/directories.d.ts +12 -0
  13. package/dist/cli/commands/deploy/directories.js +38 -0
  14. package/dist/cli/commands/deploy/gitignore.d.ts +12 -0
  15. package/dist/cli/commands/deploy/gitignore.js +53 -0
  16. package/dist/cli/commands/deploy/index.d.ts +38 -0
  17. package/dist/cli/commands/deploy/index.js +156 -0
  18. package/dist/cli/commands/deploy/knowledge-base.d.ts +16 -0
  19. package/dist/cli/commands/deploy/knowledge-base.js +75 -0
  20. package/dist/cli/commands/deploy/linting.d.ts +18 -0
  21. package/dist/cli/commands/deploy/linting.js +51 -0
  22. package/dist/cli/commands/deploy/metrics.d.ts +13 -0
  23. package/dist/cli/commands/deploy/metrics.js +34 -0
  24. package/dist/cli/commands/deploy/pre-flight.d.ts +13 -0
  25. package/dist/cli/commands/deploy/pre-flight.js +29 -0
  26. package/dist/cli/commands/deploy/root-files.d.ts +16 -0
  27. package/dist/cli/commands/deploy/root-files.js +178 -0
  28. package/dist/cli/commands/deploy/sdk-install.d.ts +12 -0
  29. package/dist/cli/commands/deploy/sdk-install.js +57 -0
  30. package/dist/cli/commands/deploy/summary.d.ts +14 -0
  31. package/dist/cli/commands/deploy/summary.js +130 -0
  32. package/dist/cli/commands/deploy/templates.d.ts +14 -0
  33. package/dist/cli/commands/deploy/templates.js +84 -0
  34. package/dist/cli/commands/deploy/types.d.ts +39 -0
  35. package/dist/cli/commands/deploy/types.js +5 -0
  36. package/dist/cli/commands/update/agents.d.ts +14 -0
  37. package/dist/cli/commands/update/agents.js +31 -0
  38. package/dist/cli/commands/update/backup.d.ts +31 -0
  39. package/dist/cli/commands/update/backup.js +97 -0
  40. package/dist/cli/commands/update/commands.d.ts +14 -0
  41. package/dist/cli/commands/update/commands.js +75 -0
  42. package/dist/cli/commands/update/index.d.ts +15 -0
  43. package/dist/cli/commands/update/index.js +118 -0
  44. package/dist/cli/commands/update/knowledge-base.d.ts +14 -0
  45. package/dist/cli/commands/update/knowledge-base.js +38 -0
  46. package/dist/cli/commands/update/pre-flight.d.ts +13 -0
  47. package/dist/cli/commands/update/pre-flight.js +37 -0
  48. package/dist/cli/commands/update/summary.d.ts +20 -0
  49. package/dist/cli/commands/update/summary.js +47 -0
  50. package/dist/cli/commands/update/templates.d.ts +14 -0
  51. package/dist/cli/commands/update/templates.js +25 -0
  52. package/dist/cli/commands/update/types.d.ts +13 -0
  53. package/dist/cli/commands/update/types.js +7 -0
  54. package/dist/cli/commands/update/utils.d.ts +11 -0
  55. package/dist/cli/commands/update/utils.js +19 -0
  56. package/dist/cli/commands/update/verification.d.ts +20 -0
  57. package/dist/cli/commands/update/verification.js +54 -0
  58. package/dist/cli/commands/update/version.d.ts +18 -0
  59. package/dist/cli/commands/update/version.js +36 -0
  60. package/dist/cli/commands/update.d.ts +7 -0
  61. package/dist/cli/commands/update.js +7 -0
  62. package/dist/cli/index.d.ts +3 -0
  63. package/dist/cli/index.js +36 -0
  64. package/dist/cli/types.d.ts +77 -0
  65. package/dist/cli/types.js +5 -0
  66. package/dist/cli/utils/deploy-ci.d.ts +22 -0
  67. package/dist/cli/utils/deploy-ci.js +138 -0
  68. package/dist/cli/utils/deploy-linting.d.ts +3 -0
  69. package/dist/cli/utils/deploy-linting.js +136 -0
  70. package/dist/cli/utils/detect-stack.d.ts +3 -0
  71. package/dist/cli/utils/detect-stack.js +270 -0
  72. package/dist/cli/utils/error-classes.d.ts +63 -0
  73. package/dist/cli/utils/error-classes.js +84 -0
  74. package/dist/cli/utils/error-handler.d.ts +59 -0
  75. package/dist/cli/utils/error-handler.js +127 -0
  76. package/dist/cli/utils/errors.d.ts +52 -0
  77. package/dist/cli/utils/errors.js +102 -0
  78. package/dist/cli/utils/get-sdk-path.d.ts +18 -0
  79. package/dist/cli/utils/get-sdk-path.js +31 -0
  80. package/dist/cli/utils/inject-dependencies.d.ts +2 -0
  81. package/dist/cli/utils/inject-dependencies.js +55 -0
  82. package/dist/cli/utils/linting-tools.d.ts +8 -0
  83. package/dist/cli/utils/linting-tools.js +206 -0
  84. package/dist/cli/utils/metrics/code-quality.d.ts +32 -0
  85. package/dist/cli/utils/metrics/code-quality.js +122 -0
  86. package/dist/cli/utils/metrics/dependency-parser.d.ts +21 -0
  87. package/dist/cli/utils/metrics/dependency-parser.js +153 -0
  88. package/dist/cli/utils/metrics/file-complexity.d.ts +26 -0
  89. package/dist/cli/utils/metrics/file-complexity.js +77 -0
  90. package/dist/cli/utils/metrics/framework-detector.d.ts +17 -0
  91. package/dist/cli/utils/metrics/framework-detector.js +120 -0
  92. package/dist/cli/utils/metrics/git-metrics.d.ts +30 -0
  93. package/dist/cli/utils/metrics/git-metrics.js +83 -0
  94. package/dist/cli/utils/metrics/index.d.ts +28 -0
  95. package/dist/cli/utils/metrics/index.js +100 -0
  96. package/dist/cli/utils/template-processor.d.ts +10 -0
  97. package/dist/cli/utils/template-processor.js +188 -0
  98. package/dist/cli/utils/validate-path.d.ts +80 -0
  99. package/dist/cli/utils/validate-path.js +180 -0
  100. package/dist/index.d.ts +6 -0
  101. package/dist/index.js +8 -0
  102. package/dist/templates/agents/aj-team/apo-documentation-specialist.md.template +572 -0
  103. package/dist/templates/agents/aj-team/bas-quality-gate.md.template +906 -0
  104. package/dist/templates/agents/aj-team/bon-dependency-manager.md.template +636 -0
  105. package/dist/templates/agents/aj-team/cap-configuration-specialist.md.template +670 -0
  106. package/dist/templates/agents/aj-team/dra-code-reviewer.md.template +768 -0
  107. package/dist/templates/agents/aj-team/kil-task-executor.md.template +764 -0
  108. package/dist/templates/agents/aj-team/uro-refactoring-specialist.md.template +759 -0
  109. package/dist/templates/agents/audit/juno-auditor.md.template +447 -0
  110. package/dist/templates/agents/deployment/ein-cicd.md.template +694 -0
  111. package/dist/templates/agents/deployment/ino-context.md.template +733 -0
  112. package/dist/templates/agents/deployment/tan-structure.md.template +661 -0
  113. package/dist/templates/agents/deployment/zen-knowledge.md.template +451 -0
  114. package/dist/templates/agents/leadership/aj-cc.md.template +462 -0
  115. package/dist/templates/agents/leadership/aj-maestro.md.template +943 -0
  116. package/dist/templates/agents/leadership/aly-cto.md.template +407 -0
  117. package/dist/templates/agents/planning/eus-decomposer.md.template +496 -0
  118. package/dist/templates/agents/planning/mon-requirements.md.template +323 -0
  119. package/dist/templates/agents/planning/ror-design.md.template +465 -0
  120. package/dist/templates/agents/planning/tra-planner.md.template +432 -0
  121. package/dist/templates/ci/cd.yml.template +175 -0
  122. package/dist/templates/ci/ci.yml.template +196 -0
  123. package/dist/templates/ci/generic-ci.yml +115 -0
  124. package/dist/templates/ci/github-actions.yml +86 -0
  125. package/dist/templates/ci/gitlab-ci.yml +103 -0
  126. package/dist/templates/claude/EMPLOYEE-DIRECTORY.md.template +545 -0
  127. package/dist/templates/documentation/ROOT-README.md.template +307 -0
  128. package/dist/templates/documentation/SUBDIRECTORY-README.md.template +261 -0
  129. package/dist/templates/investigations/bug.md.template +484 -0
  130. package/dist/templates/investigations/feature.md.template +564 -0
  131. package/dist/templates/investigations/performance.md.template +625 -0
  132. package/dist/templates/investigations/security.md.template +714 -0
  133. package/dist/templates/investigations/technical.md.template +433 -0
  134. package/dist/templates/knowledge-base/AI-DEVELOPMENT-GUIDE.md.template +957 -0
  135. package/dist/templates/knowledge-base/ARCHITECTURE.md.template +452 -0
  136. package/dist/templates/knowledge-base/CODING-PRINCIPLES.md.template +750 -0
  137. package/dist/templates/knowledge-base/DOCUMENTATION-CRITERIA.md.template +1118 -0
  138. package/dist/templates/knowledge-base/ISSUES.md.template +539 -0
  139. package/dist/templates/knowledge-base/TESTING-PRINCIPLES.md.template +894 -0
  140. package/dist/templates/knowledge-base/Technical-Debt.md.template +640 -0
  141. package/dist/templates/knowledge-base/To-do.md.template +407 -0
  142. package/dist/templates/knowledge-base/Trinity.md.template +464 -0
  143. package/dist/templates/linting/flutter/.pre-commit-config.yaml.template +27 -0
  144. package/dist/templates/linting/flutter/analysis_options.yaml.template +26 -0
  145. package/dist/templates/linting/nodejs/.eslintrc-commonjs.json.template +19 -0
  146. package/dist/templates/linting/nodejs/.eslintrc-esm.json.template +19 -0
  147. package/dist/templates/linting/nodejs/.eslintrc-typescript.json.template +22 -0
  148. package/dist/templates/linting/nodejs/.pre-commit-config.yaml.template +51 -0
  149. package/dist/templates/linting/nodejs/.prettierrc.json.template +10 -0
  150. package/dist/templates/linting/python/.flake8.template +16 -0
  151. package/dist/templates/linting/python/.pre-commit-config.yaml.template +30 -0
  152. package/dist/templates/linting/python/pyproject.toml.template +38 -0
  153. package/dist/templates/linting/rust/.pre-commit-config.yaml.template +28 -0
  154. package/dist/templates/linting/rust/clippy.toml.template +14 -0
  155. package/dist/templates/linting/rust/rustfmt.toml.template +12 -0
  156. package/dist/templates/root/CLAUDE.md.template +65 -0
  157. package/dist/templates/root/TRINITY.md.template +52 -0
  158. package/dist/templates/shared/claude-commands/trinity-agents.md.template +168 -0
  159. package/dist/templates/shared/claude-commands/trinity-audit.md.template +646 -0
  160. package/dist/templates/shared/claude-commands/trinity-changelog.md.template +624 -0
  161. package/dist/templates/shared/claude-commands/trinity-continue.md.template +549 -0
  162. package/dist/templates/shared/claude-commands/trinity-create-investigation.md.template +232 -0
  163. package/dist/templates/shared/claude-commands/trinity-decompose.md.template +181 -0
  164. package/dist/templates/shared/claude-commands/trinity-design.md.template +347 -0
  165. package/dist/templates/shared/claude-commands/trinity-docs.md.template +2093 -0
  166. package/dist/templates/shared/claude-commands/trinity-end.md.template +397 -0
  167. package/dist/templates/shared/claude-commands/trinity-init.md.template +606 -0
  168. package/dist/templates/shared/claude-commands/trinity-investigate-templates.md.template +725 -0
  169. package/dist/templates/shared/claude-commands/trinity-orchestrate.md.template +1061 -0
  170. package/dist/templates/shared/claude-commands/trinity-plan-investigation.md.template +135 -0
  171. package/dist/templates/shared/claude-commands/trinity-plan.md.template +201 -0
  172. package/dist/templates/shared/claude-commands/trinity-readme.md.template +1971 -0
  173. package/dist/templates/shared/claude-commands/trinity-requirements.md.template +148 -0
  174. package/dist/templates/shared/claude-commands/trinity-start.md.template +268 -0
  175. package/dist/templates/shared/claude-commands/trinity-verify.md.template +453 -0
  176. package/dist/templates/shared/claude-commands/trinity-workorder.md.template +249 -0
  177. package/dist/templates/source/base-CLAUDE.md.template +310 -0
  178. package/dist/templates/source/flutter-CLAUDE.md.template +593 -0
  179. package/dist/templates/source/nodejs-CLAUDE.md.template +531 -0
  180. package/dist/templates/source/python-CLAUDE.md.template +510 -0
  181. package/dist/templates/source/react-CLAUDE.md.template +513 -0
  182. package/dist/templates/source/rust-CLAUDE.md.template +653 -0
  183. package/dist/templates/source/tests-CLAUDE.md.template +432 -0
  184. package/dist/templates/trinity/CLAUDE.md.template +372 -0
  185. package/dist/templates/work-orders/ANALYSIS-TEMPLATE.md.template +276 -0
  186. package/dist/templates/work-orders/AUDIT-TEMPLATE.md.template +262 -0
  187. package/dist/templates/work-orders/IMPLEMENTATION-TEMPLATE.md.template +260 -0
  188. package/dist/templates/work-orders/INVESTIGATION-TEMPLATE.md.template +206 -0
  189. package/dist/templates/work-orders/PATTERN-TEMPLATE.md.template +320 -0
  190. package/dist/templates/work-orders/VERIFICATION-TEMPLATE.md.template +273 -0
  191. package/package.json +94 -0
@@ -0,0 +1,894 @@
1
+ # Testing Principles
2
+
3
+ **Version**: 2.0.0
4
+ **Last Updated**: {{date}}
5
+ **Project**: {{projectName}}
6
+
7
+ ---
8
+
9
+ ## Purpose
10
+
11
+ This document establishes testing standards and best practices for {{projectName}}. All code must meet these testing requirements to ensure reliability, maintainability, and confidence in changes.
12
+
13
+ ## 1. Test-Driven Development (TDD)
14
+
15
+ ### 1.1 RED-GREEN-REFACTOR Cycle
16
+
17
+ **Rule**: All new features must follow the TDD cycle.
18
+
19
+ **The TDD Cycle**:
20
+
21
+ ```
22
+ 🔴 RED: Write a failing test first
23
+
24
+ 🟢 GREEN: Write minimal code to make it pass
25
+
26
+ 🔵 REFACTOR: Improve code while keeping tests green
27
+
28
+ [Repeat]
29
+ ```
30
+
31
+ **✅ Good Example**:
32
+
33
+ ```javascript
34
+ // STEP 1: RED - Write failing test
35
+ describe('calculateTax', () => {
36
+ test('should calculate 10% tax on $100', () => {
37
+ expect(calculateTax(100, 0.10)).toBe(10);
38
+ });
39
+ });
40
+
41
+ // Run test → FAILS (calculateTax doesn't exist yet)
42
+
43
+ // STEP 2: GREEN - Minimal implementation
44
+ function calculateTax(amount, rate) {
45
+ return amount * rate;
46
+ }
47
+
48
+ // Run test → PASSES
49
+
50
+ // STEP 3: REFACTOR - Improve (add validation)
51
+ function calculateTax(amount, rate) {
52
+ if (typeof amount !== 'number' || amount < 0) {
53
+ throw new Error('Amount must be a positive number');
54
+ }
55
+ if (typeof rate !== 'number' || rate < 0 || rate > 1) {
56
+ throw new Error('Rate must be between 0 and 1');
57
+ }
58
+ return amount * rate;
59
+ }
60
+
61
+ // Add test for validation
62
+ test('should throw error for negative amount', () => {
63
+ expect(() => calculateTax(-100, 0.10)).toThrow('Amount must be');
64
+ });
65
+
66
+ // Run tests → STILL PASSES
67
+ ```
68
+
69
+ **❌ Bad Example (No TDD)**:
70
+
71
+ ```javascript
72
+ // Write implementation first
73
+ function calculateTax(amount, rate) {
74
+ // 50 lines of complex logic
75
+ // No tests, no confidence
76
+ }
77
+
78
+ // Write tests later (or never)
79
+ ```
80
+
81
+ ### 1.2 When to Use TDD
82
+
83
+ **Always TDD**:
84
+ - ✅ New features
85
+ - ✅ Bug fixes (write test that reproduces bug, then fix)
86
+ - ✅ Refactoring (tests ensure behavior unchanged)
87
+
88
+ **TDD Optional** (but still test):
89
+ - ⚠️ Exploratory prototypes (test after proving concept)
90
+ - ⚠️ UI components (harder to TDD, but test after)
91
+ - ⚠️ Glue code (thin integration layers)
92
+
93
+ ---
94
+
95
+ ## 2. Test Coverage
96
+
97
+ ### 2.1 Coverage Requirements
98
+
99
+ **Rule**: Minimum 80% code coverage required.
100
+
101
+ **Coverage Metrics**:
102
+ - **Line Coverage**: ≥80% of lines executed
103
+ - **Branch Coverage**: ≥80% of branches (if/else) tested
104
+ - **Function Coverage**: ≥80% of functions called
105
+ - **Statement Coverage**: ≥80% of statements executed
106
+
107
+ **✅ Good Coverage Example**:
108
+
109
+ ```javascript
110
+ // Function with good coverage
111
+ function validateUser(user) {
112
+ if (!user) {
113
+ throw new Error('User required');
114
+ }
115
+
116
+ if (!user.email) {
117
+ throw new Error('Email required');
118
+ }
119
+
120
+ if (!isValidEmail(user.email)) {
121
+ throw new Error('Invalid email');
122
+ }
123
+
124
+ return true;
125
+ }
126
+
127
+ // Tests covering all branches
128
+ describe('validateUser', () => {
129
+ test('throws error when user is null', () => {
130
+ expect(() => validateUser(null)).toThrow('User required');
131
+ });
132
+
133
+ test('throws error when email is missing', () => {
134
+ expect(() => validateUser({})).toThrow('Email required');
135
+ });
136
+
137
+ test('throws error when email is invalid', () => {
138
+ expect(() => validateUser({ email: 'invalid' })).toThrow('Invalid email');
139
+ });
140
+
141
+ test('returns true for valid user', () => {
142
+ expect(validateUser({ email: 'test@example.com' })).toBe(true);
143
+ });
144
+ });
145
+
146
+ // Coverage: 100% lines, 100% branches ✅
147
+ ```
148
+
149
+ **❌ Poor Coverage Example**:
150
+
151
+ ```javascript
152
+ // Same function, inadequate tests
153
+ describe('validateUser', () => {
154
+ test('works with valid user', () => {
155
+ expect(validateUser({ email: 'test@example.com' })).toBe(true);
156
+ });
157
+ });
158
+
159
+ // Coverage: 40% lines, 25% branches ❌
160
+ // Error paths not tested!
161
+ ```
162
+
163
+ ### 2.2 Coverage Exceptions
164
+
165
+ **When <80% is Acceptable**:
166
+ - Configuration files
167
+ - Type definitions
168
+ - Simple getters/setters
169
+ - Deprecated code marked for removal
170
+
171
+ **Mark exceptions explicitly**:
172
+
173
+ ```javascript
174
+ /* istanbul ignore next */
175
+ function legacyFunction() {
176
+ // Deprecated, will be removed in v3.0
177
+ }
178
+ ```
179
+
180
+ ### 2.3 Coverage Enforcement
181
+
182
+ **BAS Quality Gate Phase 5** enforces 80% coverage:
183
+
184
+ ```bash
185
+ # Coverage check
186
+ npm run test:coverage
187
+
188
+ # Must meet threshold to pass quality gate
189
+ {
190
+ "jest": {
191
+ "coverageThreshold": {
192
+ "global": {
193
+ "lines": 80,
194
+ "branches": 80,
195
+ "functions": 80,
196
+ "statements": 80
197
+ }
198
+ }
199
+ }
200
+ }
201
+ ```
202
+
203
+ ---
204
+
205
+ ## 3. Test Structure
206
+
207
+ ### 3.1 AAA Pattern (Arrange-Act-Assert)
208
+
209
+ **Rule**: Structure tests using the AAA pattern for clarity.
210
+
211
+ **The Pattern**:
212
+ 1. **Arrange**: Set up test data and preconditions
213
+ 2. **Act**: Execute the code under test
214
+ 3. **Assert**: Verify the expected outcome
215
+
216
+ **✅ Good Example**:
217
+
218
+ ```javascript
219
+ test('should calculate order total correctly', () => {
220
+ // ARRANGE: Set up test data
221
+ const order = {
222
+ items: [
223
+ { price: 10, quantity: 2 }, // $20
224
+ { price: 15, quantity: 1 } // $15
225
+ ],
226
+ taxRate: 0.10,
227
+ shippingCost: 5
228
+ };
229
+
230
+ // ACT: Execute function
231
+ const total = calculateOrderTotal(order);
232
+
233
+ // ASSERT: Verify result
234
+ expect(total).toBe(42.5); // (20 + 15) * 1.10 + 5 = 42.5
235
+ });
236
+ ```
237
+
238
+ **❌ Bad Example**:
239
+
240
+ ```javascript
241
+ test('calculates total', () => {
242
+ // Everything mixed together - hard to understand
243
+ expect(calculateOrderTotal({
244
+ items: [{ price: 10, quantity: 2 }, { price: 15, quantity: 1 }],
245
+ taxRate: 0.10,
246
+ shippingCost: 5
247
+ })).toBe(42.5);
248
+ });
249
+ ```
250
+
251
+ ### 3.2 One Assertion Per Test (Guideline)
252
+
253
+ **Rule**: Prefer one logical assertion per test (but multiple expects are OK if testing same concept).
254
+
255
+ **✅ Good Examples**:
256
+
257
+ ```javascript
258
+ // Single assertion - clear
259
+ test('should return user with correct ID', () => {
260
+ const user = findUserById('123');
261
+ expect(user.id).toBe('123');
262
+ });
263
+
264
+ test('should return user with correct name', () => {
265
+ const user = findUserById('123');
266
+ expect(user.name).toBe('John Doe');
267
+ });
268
+
269
+ // Multiple asserts OK when testing same concept
270
+ test('should return complete user object', () => {
271
+ const user = findUserById('123');
272
+ expect(user).toEqual({
273
+ id: '123',
274
+ name: 'John Doe',
275
+ email: 'john@example.com'
276
+ });
277
+ });
278
+ ```
279
+
280
+ **⚠️ Acceptable (Multiple related assertions)**:
281
+
282
+ ```javascript
283
+ test('should validate user object structure', () => {
284
+ const user = createUser('John', 'john@example.com');
285
+ expect(user).toHaveProperty('id');
286
+ expect(user).toHaveProperty('name');
287
+ expect(user).toHaveProperty('email');
288
+ expect(user).toHaveProperty('createdAt');
289
+ });
290
+ ```
291
+
292
+ **❌ Bad Example (Unrelated assertions)**:
293
+
294
+ ```javascript
295
+ test('user functions', () => {
296
+ expect(createUser('John')).toBeDefined(); // Test 1
297
+ expect(deleteUser('123')).toBe(true); // Test 2 - unrelated!
298
+ expect(findUsers()).toHaveLength(5); // Test 3 - unrelated!
299
+ });
300
+ // Split into 3 separate tests
301
+ ```
302
+
303
+ ### 3.3 Descriptive Test Names
304
+
305
+ **Rule**: Test names should describe what they test and expected outcome.
306
+
307
+ **✅ Good Names**:
308
+
309
+ ```javascript
310
+ describe('UserService', () => {
311
+ describe('createUser', () => {
312
+ test('should create user with valid data', () => { /* ... */ });
313
+
314
+ test('should throw error when email is missing', () => { /* ... */ });
315
+
316
+ test('should throw error when email format is invalid', () => { /* ... */ });
317
+
318
+ test('should hash password before saving', () => { /* ... */ });
319
+
320
+ test('should set createdAt timestamp', () => { /* ... */ });
321
+ });
322
+ });
323
+ ```
324
+
325
+ **❌ Bad Names**:
326
+
327
+ ```javascript
328
+ describe('UserService', () => {
329
+ test('test1', () => { /* ... */ }); // What does this test?
330
+ test('works', () => { /* ... */ }); // What works?
331
+ test('user', () => { /* ... */ }); // Tests what about user?
332
+ test('should pass', () => { /* ... */ }); // Useless
333
+ });
334
+ ```
335
+
336
+ ---
337
+
338
+ ## 4. Mocking & Stubbing
339
+
340
+ ### 4.1 When to Mock
341
+
342
+ **Mock External Dependencies**:
343
+ - ✅ Database calls
344
+ - ✅ API requests
345
+ - ✅ File system operations
346
+ - ✅ Third-party services
347
+ - ✅ Time-dependent operations (Date.now, setTimeout)
348
+
349
+ **Don't Mock**:
350
+ - ❌ Internal business logic (test the real thing)
351
+ - ❌ Simple utilities (they're fast, test real)
352
+ - ❌ Everything (over-mocking = brittle tests)
353
+
354
+ **✅ Good Mocking Example**:
355
+
356
+ ```javascript
357
+ // Mock external API
358
+ jest.mock('../services/api');
359
+ const api = require('../services/api');
360
+
361
+ test('should fetch and return user data', async () => {
362
+ // ARRANGE: Mock API response
363
+ api.get.mockResolvedValue({
364
+ data: { id: '123', name: 'John' }
365
+ });
366
+
367
+ // ACT: Call function that uses API
368
+ const user = await getUserData('123');
369
+
370
+ // ASSERT: Verify behavior
371
+ expect(api.get).toHaveBeenCalledWith('/users/123');
372
+ expect(user).toEqual({ id: '123', name: 'John' });
373
+ });
374
+ ```
375
+
376
+ ### 4.2 Mock Implementation Strategies
377
+
378
+ **Strategy 1: Jest Mock Functions**:
379
+
380
+ ```javascript
381
+ const mockFn = jest.fn();
382
+ mockFn.mockReturnValue(42);
383
+ mockFn.mockResolvedValue('async result');
384
+ mockFn.mockRejectedValue(new Error('failure'));
385
+ ```
386
+
387
+ **Strategy 2: Manual Mocks**:
388
+
389
+ ```javascript
390
+ // __mocks__/database.js
391
+ module.exports = {
392
+ users: {
393
+ findOne: jest.fn(),
394
+ insert: jest.fn(),
395
+ delete: jest.fn()
396
+ }
397
+ };
398
+ ```
399
+
400
+ **Strategy 3: Dependency Injection** (Recommended):
401
+
402
+ ```javascript
403
+ // Production code
404
+ function createUserService(database) {
405
+ return {
406
+ async getUser(id) {
407
+ return await database.users.findOne({ id });
408
+ }
409
+ };
410
+ }
411
+
412
+ // Test code
413
+ test('should get user from database', async () => {
414
+ const mockDb = {
415
+ users: {
416
+ findOne: jest.fn().mockResolvedValue({ id: '123', name: 'John' })
417
+ }
418
+ };
419
+
420
+ const service = createUserService(mockDb);
421
+ const user = await service.getUser('123');
422
+
423
+ expect(user).toEqual({ id: '123', name: 'John' });
424
+ });
425
+ ```
426
+
427
+ ### 4.3 Verify Mock Interactions
428
+
429
+ **✅ Good Verification**:
430
+
431
+ ```javascript
432
+ test('should call emailService.send with correct params', async () => {
433
+ const mockEmailService = { send: jest.fn() };
434
+
435
+ await sendWelcomeEmail('user@example.com', mockEmailService);
436
+
437
+ expect(mockEmailService.send).toHaveBeenCalledWith({
438
+ to: 'user@example.com',
439
+ subject: 'Welcome!',
440
+ body: expect.stringContaining('Welcome to our platform')
441
+ });
442
+
443
+ expect(mockEmailService.send).toHaveBeenCalledTimes(1);
444
+ });
445
+ ```
446
+
447
+ ---
448
+
449
+ ## 5. Test Types
450
+
451
+ ### 5.1 Unit Tests (60% of test suite)
452
+
453
+ **Purpose**: Test individual functions/modules in isolation.
454
+
455
+ **Characteristics**:
456
+ - Fast (milliseconds)
457
+ - Isolated (no external dependencies)
458
+ - Focused (one function/module)
459
+
460
+ **✅ Good Unit Test**:
461
+
462
+ ```javascript
463
+ describe('formatCurrency', () => {
464
+ test('should format USD correctly', () => {
465
+ expect(formatCurrency(1234.56, 'USD')).toBe('$1,234.56');
466
+ });
467
+
468
+ test('should format EUR correctly', () => {
469
+ expect(formatCurrency(1234.56, 'EUR')).toBe('€1,234.56');
470
+ });
471
+
472
+ test('should round to 2 decimal places', () => {
473
+ expect(formatCurrency(1234.567, 'USD')).toBe('$1,234.57');
474
+ });
475
+ });
476
+ ```
477
+
478
+ ### 5.2 Integration Tests (30% of test suite)
479
+
480
+ **Purpose**: Test how multiple modules work together.
481
+
482
+ **Characteristics**:
483
+ - Slower (seconds)
484
+ - Tests interactions between modules
485
+ - May use real database (test DB) or API
486
+
487
+ **✅ Good Integration Test**:
488
+
489
+ ```javascript
490
+ describe('User Registration Flow', () => {
491
+ test('should create user and send welcome email', async () => {
492
+ // Uses real userService + emailService (mocked SMTP)
493
+ const result = await registerUser({
494
+ email: 'test@example.com',
495
+ password: 'secure123'
496
+ });
497
+
498
+ // Verify user created
499
+ const user = await db.users.findOne({ email: 'test@example.com' });
500
+ expect(user).toBeDefined();
501
+ expect(user.email).toBe('test@example.com');
502
+
503
+ // Verify email sent
504
+ expect(emailService.lastSentEmail).toMatchObject({
505
+ to: 'test@example.com',
506
+ subject: 'Welcome!'
507
+ });
508
+ });
509
+ });
510
+ ```
511
+
512
+ ### 5.3 End-to-End Tests (10% of test suite)
513
+
514
+ **Purpose**: Test complete user flows through the entire system.
515
+
516
+ **Characteristics**:
517
+ - Slowest (minutes)
518
+ - Tests real scenarios
519
+ - May use real browser (Puppeteer, Playwright)
520
+
521
+ **✅ Good E2E Test**:
522
+
523
+ ```javascript
524
+ describe('E2E: User Login', () => {
525
+ test('user can log in and see dashboard', async () => {
526
+ // Open browser
527
+ await page.goto('http://localhost:3000');
528
+
529
+ // Fill login form
530
+ await page.fill('input[name="email"]', 'test@example.com');
531
+ await page.fill('input[name="password"]', 'password123');
532
+ await page.click('button[type="submit"]');
533
+
534
+ // Verify redirected to dashboard
535
+ await page.waitForURL('http://localhost:3000/dashboard');
536
+
537
+ // Verify user name displayed
538
+ const userName = await page.textContent('.user-name');
539
+ expect(userName).toBe('Test User');
540
+ });
541
+ });
542
+ ```
543
+
544
+ ### 5.4 Test Pyramid
545
+
546
+ ```
547
+ /\
548
+ /E2E\ 10% - End-to-End (slow, comprehensive)
549
+ /______\
550
+ / \
551
+ /Integration\ 30% - Integration (medium speed)
552
+ /____________\
553
+ / \
554
+ / Unit Tests \ 60% - Unit (fast, focused)
555
+ /__________________\
556
+ ```
557
+
558
+ **Balance** (Total: 100%):
559
+ - **60% Unit Tests**: Fast feedback, test individual functions
560
+ - **30% Integration Tests**: Test module interactions
561
+ - **10% E2E Tests**: Test critical user flows
562
+
563
+ ---
564
+
565
+ ## 6. Test Organization
566
+
567
+ ### 6.1 File Structure
568
+
569
+ **Rule**: Mirror source directory structure in test directory.
570
+
571
+ **✅ Good Structure**:
572
+
573
+ ```
574
+ src/
575
+ services/
576
+ userService.js
577
+ emailService.js
578
+ utils/
579
+ validation.js
580
+
581
+ tests/
582
+ services/
583
+ userService.test.js
584
+ emailService.test.js
585
+ utils/
586
+ validation.test.js
587
+ ```
588
+
589
+ **Alternative** (Co-located):
590
+
591
+ ```
592
+ src/
593
+ services/
594
+ userService.js
595
+ userService.test.js
596
+ emailService.js
597
+ emailService.test.js
598
+ ```
599
+
600
+ ### 6.2 Test Naming Convention
601
+
602
+ **Rule**: Test files end with `.test.js` or `.spec.js`.
603
+
604
+ ```
605
+ ✅ userService.test.js
606
+ ✅ userService.spec.js
607
+ ❌ userService-test.js
608
+ ❌ test_userService.js
609
+ ```
610
+
611
+ ### 6.3 Setup and Teardown
612
+
613
+ **Use beforeEach/afterEach for common setup**:
614
+
615
+ ```javascript
616
+ describe('UserService', () => {
617
+ let db;
618
+ let userService;
619
+
620
+ beforeEach(() => {
621
+ // Setup: Create fresh test database
622
+ db = createTestDatabase();
623
+ userService = createUserService(db);
624
+ });
625
+
626
+ afterEach(() => {
627
+ // Teardown: Clean up
628
+ db.close();
629
+ });
630
+
631
+ test('should create user', async () => {
632
+ const user = await userService.createUser({ email: 'test@example.com' });
633
+ expect(user).toBeDefined();
634
+ });
635
+
636
+ test('should delete user', async () => {
637
+ const user = await userService.createUser({ email: 'test@example.com' });
638
+ const result = await userService.deleteUser(user.id);
639
+ expect(result).toBe(true);
640
+ });
641
+ });
642
+ ```
643
+
644
+ ---
645
+
646
+ ## 7. Test Quality
647
+
648
+ ### 7.1 Avoid Flaky Tests
649
+
650
+ **Flaky Test**: Test that sometimes passes, sometimes fails (unreliable).
651
+
652
+ **Common Causes**:
653
+ - ❌ Timing issues (async operations, timeouts)
654
+ - ❌ Shared state between tests
655
+ - ❌ Dependency on external services
656
+ - ❌ Test order dependencies
657
+
658
+ **✅ Fixes**:
659
+
660
+ ```javascript
661
+ // BAD: Flaky due to timing
662
+ test('should update after 100ms', async () => {
663
+ updateAfterDelay();
664
+ await sleep(100);
665
+ expect(value).toBe('updated'); // Might fail if delay varies
666
+ });
667
+
668
+ // GOOD: Wait for actual condition
669
+ test('should update after delay', async () => {
670
+ updateAfterDelay();
671
+ await waitFor(() => expect(value).toBe('updated'), { timeout: 1000 });
672
+ });
673
+
674
+ // BAD: Shared state (tests affect each other)
675
+ let counter = 0;
676
+ test('increments counter', () => {
677
+ counter++;
678
+ expect(counter).toBe(1); // Fails if run after other tests
679
+ });
680
+
681
+ // GOOD: Isolated state
682
+ test('increments counter', () => {
683
+ let counter = 0;
684
+ counter++;
685
+ expect(counter).toBe(1);
686
+ });
687
+ ```
688
+
689
+ ### 7.2 Test Independence
690
+
691
+ **Rule**: Tests must not depend on each other. Each test should pass in isolation.
692
+
693
+ ```javascript
694
+ // ❌ BAD: Tests depend on order
695
+ let user;
696
+
697
+ test('creates user', () => {
698
+ user = createUser('John');
699
+ expect(user).toBeDefined();
700
+ });
701
+
702
+ test('deletes user', () => {
703
+ deleteUser(user.id); // Fails if run alone!
704
+ expect(findUser(user.id)).toBeUndefined();
705
+ });
706
+
707
+ // ✅ GOOD: Each test independent
708
+ test('creates user', () => {
709
+ const user = createUser('John');
710
+ expect(user).toBeDefined();
711
+ });
712
+
713
+ test('deletes user', () => {
714
+ const user = createUser('John'); // Create own test data
715
+ deleteUser(user.id);
716
+ expect(findUser(user.id)).toBeUndefined();
717
+ });
718
+ ```
719
+
720
+ ### 7.3 Avoid Test Logic
721
+
722
+ **Rule**: Tests should not contain complex logic (loops, conditionals).
723
+
724
+ ```javascript
725
+ // ❌ BAD: Logic in test (hard to debug)
726
+ test('validates all users', () => {
727
+ const users = getUsers();
728
+ for (const user of users) {
729
+ if (user.email) {
730
+ expect(isValidEmail(user.email)).toBe(true);
731
+ }
732
+ }
733
+ });
734
+
735
+ // ✅ GOOD: Explicit tests
736
+ test('validates user with email', () => {
737
+ const user = { email: 'test@example.com' };
738
+ expect(isValidEmail(user.email)).toBe(true);
739
+ });
740
+
741
+ test('handles user without email', () => {
742
+ const user = {};
743
+ expect(user.email).toBeUndefined();
744
+ });
745
+ ```
746
+
747
+ ---
748
+
749
+ ## 8. Testing Best Practices
750
+
751
+ ### 8.1 Fast Tests
752
+
753
+ **Rule**: Unit tests should run in <1 second each.
754
+
755
+ **Tips**:
756
+ - Mock slow operations (DB, API, file I/O)
757
+ - Use in-memory databases for integration tests
758
+ - Parallelize test execution
759
+ - Limit E2E tests to critical paths
760
+
761
+ ### 8.2 Readable Tests
762
+
763
+ **Rule**: Tests are documentation. Write them for humans.
764
+
765
+ ```javascript
766
+ // ✅ GOOD: Readable
767
+ test('should reject password shorter than 8 characters', () => {
768
+ expect(() => validatePassword('short')).toThrow('at least 8 characters');
769
+ });
770
+
771
+ // ❌ BAD: Cryptic
772
+ test('pwd val', () => {
773
+ expect(() => v('x')).toThrow();
774
+ });
775
+ ```
776
+
777
+ ### 8.3 Don't Test Implementation Details
778
+
779
+ **Rule**: Test behavior, not implementation.
780
+
781
+ ```javascript
782
+ // ❌ BAD: Testing implementation (brittle)
783
+ test('should call _internalHelper', () => {
784
+ const spy = jest.spyOn(service, '_internalHelper');
785
+ service.publicMethod();
786
+ expect(spy).toHaveBeenCalled();
787
+ });
788
+
789
+ // ✅ GOOD: Testing behavior (stable)
790
+ test('should return formatted user data', () => {
791
+ const result = service.publicMethod();
792
+ expect(result).toEqual({ id: '123', name: 'John Doe' });
793
+ });
794
+ ```
795
+
796
+ ---
797
+
798
+ ## 9. Continuous Testing
799
+
800
+ ### 9.1 Watch Mode
801
+
802
+ **Rule**: Run tests automatically on file changes during development.
803
+
804
+ ```bash
805
+ npm run test:watch
806
+ ```
807
+
808
+ ### 9.2 Pre-Commit Hook
809
+
810
+ **Rule**: All tests must pass before committing.
811
+
812
+ ```bash
813
+ # .husky/pre-commit
814
+ npm test || exit 1
815
+ ```
816
+
817
+ ### 9.3 CI/CD Integration
818
+
819
+ **Rule**: All tests must pass in CI before merging.
820
+
821
+ ```yaml
822
+ # .github/workflows/test.yml
823
+ - name: Run Tests
824
+ run: npm test
825
+
826
+ - name: Check Coverage
827
+ run: npm run test:coverage
828
+ ```
829
+
830
+ ---
831
+
832
+ ## 10. Enforcement
833
+
834
+ ### BAS Quality Gate (Phase 4 & 5)
835
+
836
+ **Phase 4: Testing**
837
+ - All tests must pass
838
+ - Failing tests block commit
839
+
840
+ **Phase 5: Coverage**
841
+ - Coverage must be ≥80%
842
+ - Blocks commit if below threshold
843
+
844
+ ### Code Review Checklist
845
+
846
+ - [ ] New code has tests (TDD followed)
847
+ - [ ] Tests follow AAA pattern
848
+ - [ ] Test names are descriptive
849
+ - [ ] Coverage ≥80%
850
+ - [ ] No flaky tests
851
+ - [ ] Tests are fast (<1s unit, <10s integration)
852
+ - [ ] Mocks used appropriately
853
+ - [ ] Tests are independent
854
+
855
+ ---
856
+
857
+ ## References
858
+
859
+ - Test Driven Development by Kent Beck
860
+ - Growing Object-Oriented Software, Guided by Tests by Steve Freeman
861
+ - xUnit Test Patterns by Gerard Meszaros
862
+
863
+ ---
864
+
865
+ ## 📝 WHEN TO UPDATE THIS DOCUMENT
866
+
867
+ This **standards document** updates infrequently - only when testing standards evolve.
868
+
869
+ ### When to Update ⚠️
870
+
871
+ Update **only when standards change**:
872
+
873
+ - ✅ **New Test Pattern**: Team discovers better testing approach (mocking, stubbing, etc.)
874
+ - ✅ **Coverage Target Changed**: Team adjusts coverage thresholds based on project needs
875
+ - ✅ **Framework Upgrade**: Test framework version changes testing best practices
876
+ - ✅ **Test Strategy Gap**: Issue missed by tests reveals gap in testing principles
877
+
878
+ ### How to Update
879
+
880
+ 1. Add new test pattern example to relevant section
881
+ 2. Update coverage targets if team consensus changed
882
+ 3. Add testing strategy for new component types
883
+ 4. Cross-reference to ISSUES.md if pattern prevents test gaps
884
+ 5. Update timestamp: `Last reviewed: {{date}}`
885
+
886
+ **Cross-References**: When updating, check [ISSUES.md](./ISSUES.md) - does new standard prevent bugs that tests missed?
887
+
888
+ **Update Frequency**: Rare (quarterly or less) - testing standards are stable
889
+
890
+ ---
891
+
892
+ **Document maintained by**: ZEN (Documentation Specialist)
893
+ **Enforced by**: KIL (Task Executor - TDD), BAS (Quality Fixer - Coverage), APO (Acceptance Test Generator)
894
+ **Last reviewed**: {{date}}