tribunal-kit 2.4.6 → 3.1.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 (250) hide show
  1. package/.agent/ARCHITECTURE.md +99 -99
  2. package/.agent/GEMINI.md +52 -52
  3. package/.agent/agents/accessibility-reviewer.md +139 -86
  4. package/.agent/agents/ai-code-reviewer.md +160 -90
  5. package/.agent/agents/backend-specialist.md +164 -127
  6. package/.agent/agents/code-archaeologist.md +115 -73
  7. package/.agent/agents/database-architect.md +130 -110
  8. package/.agent/agents/debugger.md +137 -97
  9. package/.agent/agents/dependency-reviewer.md +78 -30
  10. package/.agent/agents/devops-engineer.md +161 -118
  11. package/.agent/agents/documentation-writer.md +151 -87
  12. package/.agent/agents/explorer-agent.md +117 -99
  13. package/.agent/agents/frontend-reviewer.md +127 -47
  14. package/.agent/agents/frontend-specialist.md +169 -109
  15. package/.agent/agents/game-developer.md +28 -164
  16. package/.agent/agents/logic-reviewer.md +87 -49
  17. package/.agent/agents/mobile-developer.md +151 -103
  18. package/.agent/agents/mobile-reviewer.md +133 -50
  19. package/.agent/agents/orchestrator.md +121 -110
  20. package/.agent/agents/penetration-tester.md +103 -77
  21. package/.agent/agents/performance-optimizer.md +136 -92
  22. package/.agent/agents/performance-reviewer.md +139 -69
  23. package/.agent/agents/product-manager.md +104 -70
  24. package/.agent/agents/product-owner.md +6 -25
  25. package/.agent/agents/project-planner.md +95 -95
  26. package/.agent/agents/qa-automation-engineer.md +174 -87
  27. package/.agent/agents/security-auditor.md +133 -129
  28. package/.agent/agents/seo-specialist.md +160 -99
  29. package/.agent/agents/sql-reviewer.md +132 -44
  30. package/.agent/agents/supervisor-agent.md +137 -109
  31. package/.agent/agents/swarm-worker-contracts.md +17 -17
  32. package/.agent/agents/swarm-worker-registry.md +46 -46
  33. package/.agent/agents/test-coverage-reviewer.md +132 -53
  34. package/.agent/agents/test-engineer.md +0 -21
  35. package/.agent/agents/type-safety-reviewer.md +143 -33
  36. package/.agent/patterns/generator.md +9 -9
  37. package/.agent/patterns/inversion.md +12 -12
  38. package/.agent/patterns/pipeline.md +9 -9
  39. package/.agent/patterns/reviewer.md +13 -13
  40. package/.agent/patterns/tool-wrapper.md +9 -9
  41. package/.agent/rules/GEMINI.md +63 -63
  42. package/.agent/scripts/__pycache__/auto_preview.cpython-311.pyc +0 -0
  43. package/.agent/scripts/__pycache__/bundle_analyzer.cpython-311.pyc +0 -0
  44. package/.agent/scripts/__pycache__/checklist.cpython-311.pyc +0 -0
  45. package/.agent/scripts/__pycache__/dependency_analyzer.cpython-311.pyc +0 -0
  46. package/.agent/scripts/__pycache__/security_scan.cpython-311.pyc +0 -0
  47. package/.agent/scripts/__pycache__/session_manager.cpython-311.pyc +0 -0
  48. package/.agent/scripts/__pycache__/skill_integrator.cpython-311.pyc +0 -0
  49. package/.agent/scripts/__pycache__/swarm_dispatcher.cpython-311.pyc +0 -0
  50. package/.agent/scripts/__pycache__/test_runner.cpython-311.pyc +0 -0
  51. package/.agent/scripts/__pycache__/verify_all.cpython-311.pyc +0 -0
  52. package/.agent/scripts/compress_skills.py +167 -0
  53. package/.agent/scripts/consolidate_skills.py +173 -0
  54. package/.agent/scripts/deep_compress.py +202 -0
  55. package/.agent/scripts/minify_context.py +80 -0
  56. package/.agent/scripts/security_scan.py +1 -1
  57. package/.agent/scripts/strip_tribunal.py +41 -0
  58. package/.agent/skills/agent-organizer/SKILL.md +60 -100
  59. package/.agent/skills/agentic-patterns/SKILL.md +0 -70
  60. package/.agent/skills/ai-prompt-injection-defense/SKILL.md +108 -53
  61. package/.agent/skills/api-patterns/SKILL.md +197 -257
  62. package/.agent/skills/api-security-auditor/SKILL.md +125 -57
  63. package/.agent/skills/app-builder/SKILL.md +326 -50
  64. package/.agent/skills/app-builder/templates/SKILL.md +13 -15
  65. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +16 -16
  66. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +22 -22
  67. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +18 -18
  68. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +20 -20
  69. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +17 -17
  70. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +18 -18
  71. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +21 -21
  72. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +19 -19
  73. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +26 -26
  74. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +26 -26
  75. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +19 -19
  76. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +18 -18
  77. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +20 -20
  78. package/.agent/skills/appflow-wireframe/SKILL.md +71 -98
  79. package/.agent/skills/architecture/SKILL.md +161 -200
  80. package/.agent/skills/authentication-best-practices/SKILL.md +121 -54
  81. package/.agent/skills/bash-linux/SKILL.md +71 -166
  82. package/.agent/skills/behavioral-modes/SKILL.md +8 -69
  83. package/.agent/skills/brainstorming/SKILL.md +345 -127
  84. package/.agent/skills/building-native-ui/SKILL.md +125 -57
  85. package/.agent/skills/clean-code/SKILL.md +266 -149
  86. package/.agent/skills/code-review-checklist/SKILL.md +0 -62
  87. package/.agent/skills/config-validator/SKILL.md +73 -131
  88. package/.agent/skills/csharp-developer/SKILL.md +434 -73
  89. package/.agent/skills/database-design/SKILL.md +190 -275
  90. package/.agent/skills/deployment-procedures/SKILL.md +81 -158
  91. package/.agent/skills/devops-engineer/SKILL.md +255 -94
  92. package/.agent/skills/devops-incident-responder/SKILL.md +50 -69
  93. package/.agent/skills/doc.md +5 -5
  94. package/.agent/skills/documentation-templates/SKILL.md +19 -63
  95. package/.agent/skills/edge-computing/SKILL.md +75 -165
  96. package/.agent/skills/extract-design-system/SKILL.md +84 -58
  97. package/.agent/skills/framer-motion-expert/SKILL.md +195 -0
  98. package/.agent/skills/frontend-design/SKILL.md +151 -499
  99. package/.agent/skills/game-design-expert/SKILL.md +71 -0
  100. package/.agent/skills/game-engineering-expert/SKILL.md +88 -0
  101. package/.agent/skills/geo-fundamentals/SKILL.md +52 -178
  102. package/.agent/skills/github-operations/SKILL.md +197 -272
  103. package/.agent/skills/gsap-expert/SKILL.md +194 -0
  104. package/.agent/skills/i18n-localization/SKILL.md +60 -172
  105. package/.agent/skills/intelligent-routing/SKILL.md +123 -103
  106. package/.agent/skills/lint-and-validate/SKILL.md +8 -52
  107. package/.agent/skills/llm-engineering/SKILL.md +281 -195
  108. package/.agent/skills/local-first/SKILL.md +76 -159
  109. package/.agent/skills/mcp-builder/SKILL.md +48 -188
  110. package/.agent/skills/mobile-design/SKILL.md +213 -219
  111. package/.agent/skills/motion-engineering/SKILL.md +184 -0
  112. package/.agent/skills/nextjs-react-expert/SKILL.md +184 -203
  113. package/.agent/skills/nodejs-best-practices/SKILL.md +403 -185
  114. package/.agent/skills/observability/SKILL.md +211 -203
  115. package/.agent/skills/parallel-agents/SKILL.md +53 -146
  116. package/.agent/skills/performance-profiling/SKILL.md +171 -151
  117. package/.agent/skills/plan-writing/SKILL.md +49 -153
  118. package/.agent/skills/platform-engineer/SKILL.md +57 -103
  119. package/.agent/skills/playwright-best-practices/SKILL.md +110 -63
  120. package/.agent/skills/powershell-windows/SKILL.md +61 -179
  121. package/.agent/skills/python-patterns/SKILL.md +7 -35
  122. package/.agent/skills/python-pro/SKILL.md +273 -114
  123. package/.agent/skills/react-specialist/SKILL.md +227 -108
  124. package/.agent/skills/readme-builder/SKILL.md +15 -85
  125. package/.agent/skills/realtime-patterns/SKILL.md +216 -243
  126. package/.agent/skills/red-team-tactics/SKILL.md +10 -51
  127. package/.agent/skills/rust-pro/SKILL.md +525 -142
  128. package/.agent/skills/seo-fundamentals/SKILL.md +92 -153
  129. package/.agent/skills/server-management/SKILL.md +110 -166
  130. package/.agent/skills/shadcn-ui-expert/SKILL.md +154 -55
  131. package/.agent/skills/skill-creator/SKILL.md +18 -58
  132. package/.agent/skills/sql-pro/SKILL.md +543 -68
  133. package/.agent/skills/supabase-postgres-best-practices/SKILL.md +28 -68
  134. package/.agent/skills/swiftui-expert/SKILL.md +124 -57
  135. package/.agent/skills/systematic-debugging/SKILL.md +49 -151
  136. package/.agent/skills/tailwind-patterns/SKILL.md +433 -149
  137. package/.agent/skills/tdd-workflow/SKILL.md +63 -169
  138. package/.agent/skills/test-result-analyzer/SKILL.md +33 -73
  139. package/.agent/skills/testing-patterns/SKILL.md +437 -130
  140. package/.agent/skills/trend-researcher/SKILL.md +30 -71
  141. package/.agent/skills/ui-ux-pro-max/SKILL.md +0 -41
  142. package/.agent/skills/ui-ux-researcher/SKILL.md +51 -91
  143. package/.agent/skills/vue-expert/SKILL.md +225 -119
  144. package/.agent/skills/vulnerability-scanner/SKILL.md +264 -226
  145. package/.agent/skills/web-accessibility-auditor/SKILL.md +141 -58
  146. package/.agent/skills/web-design-guidelines/SKILL.md +17 -61
  147. package/.agent/skills/webapp-testing/SKILL.md +71 -196
  148. package/.agent/skills/whimsy-injector/SKILL.md +58 -132
  149. package/.agent/skills/workflow-optimizer/SKILL.md +28 -68
  150. package/.agent/workflows/api-tester.md +96 -224
  151. package/.agent/workflows/audit.md +81 -122
  152. package/.agent/workflows/brainstorm.md +69 -105
  153. package/.agent/workflows/changelog.md +65 -97
  154. package/.agent/workflows/create.md +73 -88
  155. package/.agent/workflows/debug.md +80 -111
  156. package/.agent/workflows/deploy.md +119 -92
  157. package/.agent/workflows/enhance.md +80 -91
  158. package/.agent/workflows/fix.md +68 -97
  159. package/.agent/workflows/generate.md +165 -164
  160. package/.agent/workflows/migrate.md +106 -109
  161. package/.agent/workflows/orchestrate.md +103 -86
  162. package/.agent/workflows/performance-benchmarker.md +77 -268
  163. package/.agent/workflows/plan.md +120 -98
  164. package/.agent/workflows/preview.md +39 -96
  165. package/.agent/workflows/refactor.md +105 -97
  166. package/.agent/workflows/review-ai.md +63 -102
  167. package/.agent/workflows/review.md +71 -110
  168. package/.agent/workflows/session.md +53 -113
  169. package/.agent/workflows/status.md +42 -88
  170. package/.agent/workflows/strengthen-skills.md +90 -51
  171. package/.agent/workflows/swarm.md +114 -129
  172. package/.agent/workflows/test.md +125 -102
  173. package/.agent/workflows/tribunal-backend.md +60 -78
  174. package/.agent/workflows/tribunal-database.md +62 -100
  175. package/.agent/workflows/tribunal-frontend.md +62 -82
  176. package/.agent/workflows/tribunal-full.md +56 -100
  177. package/.agent/workflows/tribunal-mobile.md +65 -94
  178. package/.agent/workflows/tribunal-performance.md +62 -105
  179. package/.agent/workflows/ui-ux-pro-max.md +72 -121
  180. package/README.md +11 -15
  181. package/package.json +1 -1
  182. package/.agent/skills/api-patterns/api-style.md +0 -42
  183. package/.agent/skills/api-patterns/auth.md +0 -24
  184. package/.agent/skills/api-patterns/documentation.md +0 -26
  185. package/.agent/skills/api-patterns/graphql.md +0 -41
  186. package/.agent/skills/api-patterns/rate-limiting.md +0 -31
  187. package/.agent/skills/api-patterns/response.md +0 -37
  188. package/.agent/skills/api-patterns/rest.md +0 -40
  189. package/.agent/skills/api-patterns/security-testing.md +0 -122
  190. package/.agent/skills/api-patterns/trpc.md +0 -41
  191. package/.agent/skills/api-patterns/versioning.md +0 -22
  192. package/.agent/skills/app-builder/agent-coordination.md +0 -71
  193. package/.agent/skills/app-builder/feature-building.md +0 -53
  194. package/.agent/skills/app-builder/project-detection.md +0 -34
  195. package/.agent/skills/app-builder/scaffolding.md +0 -118
  196. package/.agent/skills/app-builder/tech-stack.md +0 -40
  197. package/.agent/skills/architecture/context-discovery.md +0 -43
  198. package/.agent/skills/architecture/examples.md +0 -94
  199. package/.agent/skills/architecture/pattern-selection.md +0 -68
  200. package/.agent/skills/architecture/patterns-reference.md +0 -50
  201. package/.agent/skills/architecture/trade-off-analysis.md +0 -77
  202. package/.agent/skills/brainstorming/dynamic-questioning.md +0 -360
  203. package/.agent/skills/database-design/database-selection.md +0 -43
  204. package/.agent/skills/database-design/indexing.md +0 -39
  205. package/.agent/skills/database-design/migrations.md +0 -48
  206. package/.agent/skills/database-design/optimization.md +0 -36
  207. package/.agent/skills/database-design/orm-selection.md +0 -30
  208. package/.agent/skills/database-design/schema-design.md +0 -56
  209. package/.agent/skills/dotnet-core-expert/SKILL.md +0 -103
  210. package/.agent/skills/framer-motion-animations/SKILL.md +0 -74
  211. package/.agent/skills/frontend-design/animation-guide.md +0 -331
  212. package/.agent/skills/frontend-design/color-system.md +0 -329
  213. package/.agent/skills/frontend-design/decision-trees.md +0 -418
  214. package/.agent/skills/frontend-design/motion-graphics.md +0 -306
  215. package/.agent/skills/frontend-design/typography-system.md +0 -363
  216. package/.agent/skills/frontend-design/ux-psychology.md +0 -1116
  217. package/.agent/skills/frontend-design/visual-effects.md +0 -383
  218. package/.agent/skills/game-development/2d-games/SKILL.md +0 -119
  219. package/.agent/skills/game-development/3d-games/SKILL.md +0 -135
  220. package/.agent/skills/game-development/SKILL.md +0 -236
  221. package/.agent/skills/game-development/game-art/SKILL.md +0 -185
  222. package/.agent/skills/game-development/game-audio/SKILL.md +0 -190
  223. package/.agent/skills/game-development/game-design/SKILL.md +0 -129
  224. package/.agent/skills/game-development/mobile-games/SKILL.md +0 -108
  225. package/.agent/skills/game-development/multiplayer/SKILL.md +0 -132
  226. package/.agent/skills/game-development/pc-games/SKILL.md +0 -144
  227. package/.agent/skills/game-development/vr-ar/SKILL.md +0 -123
  228. package/.agent/skills/game-development/web-games/SKILL.md +0 -150
  229. package/.agent/skills/intelligent-routing/router-manifest.md +0 -65
  230. package/.agent/skills/mobile-design/decision-trees.md +0 -516
  231. package/.agent/skills/mobile-design/mobile-backend.md +0 -491
  232. package/.agent/skills/mobile-design/mobile-color-system.md +0 -420
  233. package/.agent/skills/mobile-design/mobile-debugging.md +0 -122
  234. package/.agent/skills/mobile-design/mobile-design-thinking.md +0 -357
  235. package/.agent/skills/mobile-design/mobile-navigation.md +0 -458
  236. package/.agent/skills/mobile-design/mobile-performance.md +0 -767
  237. package/.agent/skills/mobile-design/mobile-testing.md +0 -356
  238. package/.agent/skills/mobile-design/mobile-typography.md +0 -433
  239. package/.agent/skills/mobile-design/platform-android.md +0 -666
  240. package/.agent/skills/mobile-design/platform-ios.md +0 -561
  241. package/.agent/skills/mobile-design/touch-psychology.md +0 -537
  242. package/.agent/skills/nextjs-react-expert/1-async-eliminating-waterfalls.md +0 -312
  243. package/.agent/skills/nextjs-react-expert/2-bundle-bundle-size-optimization.md +0 -240
  244. package/.agent/skills/nextjs-react-expert/3-server-server-side-performance.md +0 -490
  245. package/.agent/skills/nextjs-react-expert/4-client-client-side-data-fetching.md +0 -264
  246. package/.agent/skills/nextjs-react-expert/5-rerender-re-render-optimization.md +0 -581
  247. package/.agent/skills/nextjs-react-expert/6-rendering-rendering-performance.md +0 -432
  248. package/.agent/skills/nextjs-react-expert/7-js-javascript-performance.md +0 -684
  249. package/.agent/skills/nextjs-react-expert/8-advanced-advanced-patterns.md +0 -150
  250. package/.agent/skills/vulnerability-scanner/checklists.md +0 -121
@@ -1,205 +1,512 @@
1
1
  ---
2
2
  name: testing-patterns
3
- description: Testing patterns and principles. Unit, integration, mocking strategies.
3
+ description: Testing mastery across stacks. Unit testing with Jest/Vitest/pytest, integration testing, E2E with Playwright, mocking strategies, test architecture (AAA, Given-When-Then), code coverage, snapshot testing, API testing, component testing with Testing Library, and TDD workflow. Use when writing tests, designing test architecture, or improving test coverage.
4
4
  allowed-tools: Read, Write, Edit, Glob, Grep
5
- version: 1.0.0
6
- last-updated: 2026-03-12
5
+ version: 2.0.0
6
+ last-updated: 2026-04-01
7
7
  applies-to-model: gemini-2.5-pro, claude-3-7-sonnet
8
8
  ---
9
9
 
10
- # Testing Patterns
11
-
12
- > Tests don't prove code works. They make it safe to change.
13
- > A codebase without tests is a codebase you're afraid to touch.
10
+ # Testing Patterns — Cross-Stack Testing Mastery
14
11
 
15
12
  ---
16
13
 
17
- ## Test Pyramid
14
+ ## Test Architecture
18
15
 
19
- Write tests at the right level. Most tests should be unit tests. Fewer integration tests. Fewest E2E tests.
16
+ ### The Testing Pyramid
20
17
 
21
18
  ```
22
- /\
23
- /E2E\ Fewest — expensive to write and run
24
- /------\
25
- /Integr. \ Some — verify component interactions
26
- /----------\
27
- / Unit Tests \ Most — fast, isolated, focused
28
- /--------------\
19
+ / E2E \ ← Few: critical user flows (Playwright/Cypress)
20
+ /──────────\
21
+ / Integration \ ← Moderate: API routes, DB queries, component integration
22
+ /──────────────\
23
+ / Unit Tests \ ← Many: pure functions, hooks, utilities, business logic
24
+ /──────────────────\
25
+
26
+ Rules:
27
+ - 70% unit, 20% integration, 10% E2E
28
+ - Unit tests: < 50ms each
29
+ - Integration tests: < 2s each
30
+ - E2E tests: < 30s each
31
+ - If a test takes > 5s, it's a design problem
29
32
  ```
30
33
 
31
- **Why this shape:**
32
- - Unit tests run in milliseconds — you can have thousands
33
- - E2E tests take seconds — you want dozens, not hundreds
34
- - Inverting the pyramid = slow CI, fragile test suite, low confidence
34
+ ### AAA Pattern (Arrange-Act-Assert)
35
35
 
36
- ---
36
+ ```typescript
37
+ // Every test follows the same structure
38
+ it("calculates total with tax", () => {
39
+ // Arrange — set up the scenario
40
+ const cart = new Cart();
41
+ cart.addItem({ name: "Widget", price: 100 });
42
+ cart.setTaxRate(0.08);
37
43
 
38
- ## AAA Pattern
44
+ // Act — perform the action being tested
45
+ const total = cart.calculateTotal();
39
46
 
40
- Every test follows this structure:
47
+ // Assert verify the result
48
+ expect(total).toBe(108);
49
+ });
41
50
 
42
- ```ts
43
- it('should return 401 when token is expired', async () => {
44
- // Arrange set up the scenario
45
- const expiredToken = generateToken({ expiresIn: '-1s' });
46
- const request = buildRequest({ authorization: `Bearer ${expiredToken}` });
51
+ // ❌ BAD: Multiple acts in one test
52
+ it("does too many things", () => {
53
+ cart.addItem({ name: "A", price: 10 });
54
+ expect(cart.total).toBe(10); // assert
55
+ cart.addItem({ name: "B", price: 20 });
56
+ expect(cart.total).toBe(30); // another assert after another act
57
+ cart.removeItem("A");
58
+ expect(cart.total).toBe(20); // yet another — split into 3 tests
59
+ });
60
+ ```
47
61
 
48
- // Act do the thing being tested
49
- const response = await authMiddleware(request);
62
+ ### Test Naming Convention
50
63
 
51
- // Assert — verify the outcome
52
- expect(response.status).toBe(401);
53
- expect(response.body.error).toBe('Token expired');
64
+ ```typescript
65
+ // Format: [unit] + [scenario] + [expected result]
66
+
67
+ // ✅ GOOD: Descriptive, reads like a specification
68
+ describe("calculateDiscount", () => {
69
+ it("returns 0% when cart total is under $50", () => {});
70
+ it("returns 10% when cart total is $50-$99", () => {});
71
+ it("returns 20% when cart total is $100+", () => {});
72
+ it("throws when cart is empty", () => {});
54
73
  });
55
- ```
56
74
 
57
- Never combine Arrange and Assert. Never skip Arrange by relying on test state from a previous test.
75
+ // BAD: Vague, implementation-focused
76
+ describe("calculateDiscount", () => {
77
+ it("works", () => {});
78
+ it("test1", () => {});
79
+ it("should return correct value", () => {});
80
+ });
81
+ ```
58
82
 
59
83
  ---
60
84
 
61
- ## Unit Tests
85
+ ## Unit Testing (Vitest / Jest)
86
+
87
+ ### Pure Function Testing
88
+
89
+ ```typescript
90
+ // utils/math.ts
91
+ export function clamp(value: number, min: number, max: number): number {
92
+ return Math.min(Math.max(value, min), max);
93
+ }
94
+
95
+ // utils/math.test.ts
96
+ import { describe, it, expect } from "vitest";
97
+ import { clamp } from "./math";
62
98
 
63
- Unit tests test one unit of logic in isolation. Everything external is replaced with a controlled substitute.
99
+ describe("clamp", () => {
100
+ it("returns the value when within range", () => {
101
+ expect(clamp(5, 0, 10)).toBe(5);
102
+ });
64
103
 
65
- ```ts
66
- // Test the function's logic — not the database, not the network
67
- it('should hash the password before saving', async () => {
68
- const mockSave = vi.fn().mockResolvedValue({ id: '1' });
69
- const userRepo = { save: mockSave };
104
+ it("clamps to min when value is below range", () => {
105
+ expect(clamp(-5, 0, 10)).toBe(0);
106
+ });
70
107
 
71
- await createUser({ email: 'a@b.com', password: 'secret' }, userRepo);
108
+ it("clamps to max when value is above range", () => {
109
+ expect(clamp(15, 0, 10)).toBe(10);
110
+ });
72
111
 
73
- const savedUser = mockSave.mock.calls[0][0];
74
- expect(savedUser.password).not.toBe('secret'); // was hashed
75
- expect(savedUser.password).toMatch(/^\$2b\$/); // bcrypt format
112
+ it("handles equal min and max", () => {
113
+ expect(clamp(5, 3, 3)).toBe(3);
114
+ });
115
+
116
+ it("handles floating point values", () => {
117
+ expect(clamp(0.5, 0, 1)).toBeCloseTo(0.5);
118
+ });
76
119
  });
77
120
  ```
78
121
 
79
- **Rules for unit tests:**
80
- - One assertion per concept (multiple `expect` calls are fine if they verify the same behavior)
81
- - No network calls, no file system, no real database
82
- - Tests are order-independent — they don't rely on state from other tests
83
- - Test names describe behavior: `should X when Y` or `returns X given Y`
122
+ ### Async Testing
84
123
 
85
- ---
124
+ ```typescript
125
+ import { describe, it, expect, vi } from "vitest";
86
126
 
87
- ## Integration Tests
127
+ // Async function under test
128
+ async function fetchUser(id: string): Promise<User> {
129
+ const response = await fetch(`/api/users/${id}`);
130
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
131
+ return response.json();
132
+ }
88
133
 
89
- Integration tests verify that two or more components work together correctly.
134
+ describe("fetchUser", () => {
135
+ it("returns user data on success", async () => {
136
+ const mockUser = { id: "1", name: "Alice" };
137
+ global.fetch = vi.fn().mockResolvedValue({
138
+ ok: true,
139
+ json: () => Promise.resolve(mockUser),
140
+ });
90
141
 
91
- ```ts
92
- // Tests the real database interaction
93
- it('should save and retrieve a user', async () => {
94
- const user = await UserService.create({ email: 'test@test.com', name: 'Test' });
95
- const found = await UserService.findById(user.id);
142
+ const user = await fetchUser("1");
143
+ expect(user).toEqual(mockUser);
144
+ expect(fetch).toHaveBeenCalledWith("/api/users/1");
145
+ });
96
146
 
97
- expect(found.email).toBe('test@test.com');
147
+ it("throws on HTTP error", async () => {
148
+ global.fetch = vi.fn().mockResolvedValue({ ok: false, status: 404 });
149
+
150
+ await expect(fetchUser("999")).rejects.toThrow("HTTP 404");
151
+ });
98
152
  });
99
153
  ```
100
154
 
101
- **Integration test rules:**
102
- - Use a real test database — not a mock
103
- - Clean up data before or after each test (use transactions that rollback, or seed scripts)
104
- - Slower than unit tests — run on CI but not on every file save
155
+ ### Timer & Date Mocking
156
+
157
+ ```typescript
158
+ describe("debounce", () => {
159
+ beforeEach(() => {
160
+ vi.useFakeTimers();
161
+ });
162
+
163
+ afterEach(() => {
164
+ vi.useRealTimers();
165
+ });
166
+
167
+ it("delays execution by specified ms", () => {
168
+ const fn = vi.fn();
169
+ const debounced = debounce(fn, 300);
170
+
171
+ debounced();
172
+ expect(fn).not.toHaveBeenCalled(); // not yet
173
+
174
+ vi.advanceTimersByTime(200);
175
+ expect(fn).not.toHaveBeenCalled(); // still not
176
+
177
+ vi.advanceTimersByTime(100);
178
+ expect(fn).toHaveBeenCalledOnce(); // now
179
+ });
180
+
181
+ it("resets timer on subsequent calls", () => {
182
+ const fn = vi.fn();
183
+ const debounced = debounce(fn, 300);
184
+
185
+ debounced();
186
+ vi.advanceTimersByTime(200);
187
+ debounced(); // reset timer
188
+ vi.advanceTimersByTime(200);
189
+ expect(fn).not.toHaveBeenCalled(); // timer was reset
190
+
191
+ vi.advanceTimersByTime(100);
192
+ expect(fn).toHaveBeenCalledOnce();
193
+ });
194
+ });
195
+
196
+ // Date mocking
197
+ it("formats today's date", () => {
198
+ vi.setSystemTime(new Date("2024-06-15T12:00:00Z"));
199
+ expect(getFormattedDate()).toBe("June 15, 2024");
200
+ vi.useRealTimers();
201
+ });
202
+ ```
105
203
 
106
204
  ---
107
205
 
108
- ## Mocking Principles
206
+ ## Mocking Strategies
109
207
 
110
- Mocks replace external dependencies. Use them accurately.
208
+ ### Module Mocks
111
209
 
112
- ```ts
113
- // Mock that returns nothing useful
114
- vi.mock('./mailer', () => ({ send: vi.fn() }));
210
+ ```typescript
211
+ import { vi, describe, it, expect, beforeEach } from "vitest";
212
+ import { sendEmail } from "./email-service";
213
+ import { createUser } from "./user-service";
115
214
 
116
- // Mock that reflects real behavior
117
- vi.mock('./mailer', () => ({
118
- send: vi.fn().mockResolvedValue({ messageId: 'mock-id-123' }),
215
+ // Mock an entire module
216
+ vi.mock("./email-service", () => ({
217
+ sendEmail: vi.fn().mockResolvedValue({ sent: true }),
119
218
  }));
219
+
220
+ describe("createUser", () => {
221
+ beforeEach(() => {
222
+ vi.clearAllMocks(); // reset call counts between tests
223
+ });
224
+
225
+ it("sends welcome email after creating user", async () => {
226
+ await createUser({ name: "Alice", email: "alice@test.com" });
227
+
228
+ expect(sendEmail).toHaveBeenCalledWith({
229
+ to: "alice@test.com",
230
+ subject: "Welcome!",
231
+ body: expect.stringContaining("Alice"),
232
+ });
233
+ });
234
+
235
+ it("does not send email on validation failure", async () => {
236
+ await expect(createUser({ name: "", email: "" })).rejects.toThrow();
237
+ expect(sendEmail).not.toHaveBeenCalled();
238
+ });
239
+ });
120
240
  ```
121
241
 
122
- **What to mock:**
123
- - External HTTP calls (payment gateways, third-party APIs)
124
- - Time (`Date.now()`, `new Date()`) when time-dependent
125
- - File system in unit tests
126
- - Email/SMS sending
242
+ ### Spy Pattern
243
+
244
+ ```typescript
245
+ // Spy on an existing method (don't replace it — observe it)
246
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
247
+
248
+ await riskyOperation();
249
+
250
+ expect(consoleSpy).toHaveBeenCalledWith(
251
+ expect.stringContaining("failed"),
252
+ expect.any(Error)
253
+ );
127
254
 
128
- **What not to mock:**
129
- - Your own business logic
130
- - The function being tested
131
- - Simple pure utility functions
255
+ consoleSpy.mockRestore(); // restore original
256
+ ```
257
+
258
+ ### Dependency Injection Pattern (Testable by Design)
259
+
260
+ ```typescript
261
+ // ❌ BAD: Hard-coded dependency — untestable without module mocking
262
+ class UserService {
263
+ async getUser(id: string) {
264
+ return await fetch(`/api/users/${id}`).then((r) => r.json());
265
+ }
266
+ }
267
+
268
+ // ✅ GOOD: Injected dependency — naturally testable
269
+ interface HttpClient {
270
+ get<T>(url: string): Promise<T>;
271
+ }
272
+
273
+ class UserService {
274
+ constructor(private http: HttpClient) {}
275
+
276
+ async getUser(id: string): Promise<User> {
277
+ return this.http.get<User>(`/api/users/${id}`);
278
+ }
279
+ }
280
+
281
+ // In test:
282
+ const mockHttp: HttpClient = {
283
+ get: vi.fn().mockResolvedValue({ id: "1", name: "Alice" }),
284
+ };
285
+ const service = new UserService(mockHttp);
286
+
287
+ // ❌ HALLUCINATION TRAP: Prefer dependency injection over vi.mock()
288
+ // vi.mock() is global and can leak between tests
289
+ // DI makes tests isolated and explicit
290
+ ```
132
291
 
133
292
  ---
134
293
 
135
- ## Test Coverage
294
+ ## React Component Testing (Testing Library)
136
295
 
137
- Coverage measures which lines are executed during tests. 100% coverage does not mean the code is correct.
296
+ ```tsx
297
+ import { render, screen, waitFor } from "@testing-library/react";
298
+ import userEvent from "@testing-library/user-event";
299
+ import { describe, it, expect, vi } from "vitest";
300
+ import { LoginForm } from "./LoginForm";
138
301
 
139
- **Useful coverage:**
140
- - `> 80%` for business logic modules
141
- - Focus on statement + branch coverage (not just line coverage)
142
- - Low coverage on infrastructure/config files is acceptable
302
+ describe("LoginForm", () => {
303
+ it("renders email and password fields", () => {
304
+ render(<LoginForm onSubmit={vi.fn()} />);
143
305
 
144
- **Coverage anti-patterns:**
145
- - Tests written solely to increase coverage numbers
146
- - Asserting that mocks were called instead of asserting real outcomes
147
- - Tautology tests: `expect(result).toBe(result)`
306
+ expect(screen.getByLabelText(/email/i)).toBeInTheDocument();
307
+ expect(screen.getByLabelText(/password/i)).toBeInTheDocument();
308
+ expect(screen.getByRole("button", { name: /sign in/i })).toBeInTheDocument();
309
+ });
148
310
 
149
- ---
311
+ it("calls onSubmit with credentials", async () => {
312
+ const user = userEvent.setup();
313
+ const onSubmit = vi.fn();
314
+ render(<LoginForm onSubmit={onSubmit} />);
150
315
 
151
- ## Scripts
316
+ await user.type(screen.getByLabelText(/email/i), "alice@test.com");
317
+ await user.type(screen.getByLabelText(/password/i), "secret123");
318
+ await user.click(screen.getByRole("button", { name: /sign in/i }));
152
319
 
153
- | Script | Purpose | Run With |
154
- |---|---|---|
155
- | `scripts/test_runner.py` | Runs test suite and reports results | `python scripts/test_runner.py <project_path>` |
320
+ expect(onSubmit).toHaveBeenCalledWith({
321
+ email: "alice@test.com",
322
+ password: "secret123",
323
+ });
324
+ });
156
325
 
157
- ---
326
+ it("shows validation error for invalid email", async () => {
327
+ const user = userEvent.setup();
328
+ render(<LoginForm onSubmit={vi.fn()} />);
158
329
 
159
- ## Output Format
330
+ await user.type(screen.getByLabelText(/email/i), "not-an-email");
331
+ await user.click(screen.getByRole("button", { name: /sign in/i }));
160
332
 
161
- When this skill produces or reviews code, structure your output as follows:
333
+ expect(screen.getByText(/invalid email/i)).toBeInTheDocument();
334
+ });
162
335
 
163
- ```
164
- ━━━ Testing Patterns Report ━━━━━━━━━━━━━━━━━━━━━━━━
165
- Skill: Testing Patterns
166
- Language: [detected language / framework]
167
- Scope: [N files · N functions]
168
- ─────────────────────────────────────────────────
169
- ✅ Passed: [checks that passed, or "All clean"]
170
- ⚠️ Warnings: [non-blocking issues, or "None"]
171
- ❌ Blocked: [blocking issues requiring fix, or "None"]
172
- ─────────────────────────────────────────────────
173
- VBC status: PENDING → VERIFIED
174
- Evidence: [test output / lint pass / compile success]
175
- ```
336
+ it("disables submit button while loading", async () => {
337
+ render(<LoginForm onSubmit={vi.fn()} isLoading={true} />);
176
338
 
177
- **VBC (Verification-Before-Completion) is mandatory.**
178
- Do not mark status as VERIFIED until concrete terminal evidence is provided.
339
+ expect(screen.getByRole("button", { name: /sign in/i })).toBeDisabled();
340
+ });
341
+ });
179
342
 
343
+ // ❌ HALLUCINATION TRAP: Query priorities (use in this order):
344
+ // 1. getByRole — accessible role ("button", "textbox", etc.)
345
+ // 2. getByLabelText — form inputs with labels
346
+ // 3. getByPlaceholderText — when no label exists
347
+ // 4. getByText — non-interactive elements
348
+ // 5. getByTestId — LAST RESORT only
349
+ // ❌ Never default to getByTestId — it tests implementation, not behavior
350
+ ```
180
351
 
181
352
  ---
182
353
 
183
- ## 🏛️ Tribunal Integration (Anti-Hallucination)
354
+ ## E2E Testing (Playwright)
184
355
 
185
- **Slash command: `/test`**
186
- **Active reviewers: `logic` · `test-coverage-reviewer`**
356
+ ```typescript
357
+ import { test, expect } from "@playwright/test";
187
358
 
188
- ### Forbidden AI Tropes in Testing
359
+ test.describe("Login Flow", () => {
360
+ test("successful login redirects to dashboard", async ({ page }) => {
361
+ await page.goto("/login");
189
362
 
190
- 1. **Tautological Tests** — writing `expect(x).toBe(x)` or testing that a mock returns what it was mocked to return, ignoring actual behavior.
191
- 2. **Missing the "Arrange" Step** — relying on test state leftover from a previous `it()` block.
192
- 3. **Over-mocking** mocking the system under test or mocking out so much that the test is completely useless.
193
- 4. **Assertions in loops** — writing loops with dynamic assertions instead of explicit, readable test cases.
194
- 5. **Ignoring Async Failures** — forgetting to `await` the assertions or the function under test, leading to false positives.
363
+ await page.getByLabel("Email").fill("admin@test.com");
364
+ await page.getByLabel("Password").fill("password123");
365
+ await page.getByRole("button", { name: "Sign In" }).click();
195
366
 
196
- ### Pre-Flight Self-Audit
367
+ // Wait for navigation
368
+ await expect(page).toHaveURL("/dashboard");
369
+ await expect(page.getByRole("heading", { name: "Dashboard" })).toBeVisible();
370
+ });
197
371
 
198
- Review these questions before generating test code:
372
+ test("shows error for invalid credentials", async ({ page }) => {
373
+ await page.goto("/login");
374
+
375
+ await page.getByLabel("Email").fill("wrong@test.com");
376
+ await page.getByLabel("Password").fill("wrongpassword");
377
+ await page.getByRole("button", { name: "Sign In" }).click();
378
+
379
+ await expect(page.getByText("Invalid credentials")).toBeVisible();
380
+ await expect(page).toHaveURL("/login"); // no redirect
381
+ });
382
+
383
+ test("responsive: mobile menu toggles", async ({ page, isMobile }) => {
384
+ test.skip(!isMobile, "Mobile only");
385
+
386
+ await page.goto("/");
387
+ await page.getByRole("button", { name: "Menu" }).click();
388
+ await expect(page.getByRole("navigation")).toBeVisible();
389
+ });
390
+ });
391
+
392
+ // API testing with Playwright
393
+ test("API: create user returns 201", async ({ request }) => {
394
+ const response = await request.post("/api/users", {
395
+ data: { name: "Alice", email: "alice@test.com" },
396
+ });
397
+
398
+ expect(response.status()).toBe(201);
399
+ const body = await response.json();
400
+ expect(body).toMatchObject({ name: "Alice", email: "alice@test.com" });
401
+ });
199
402
  ```
200
- ✅ Does each test explicitly follow the Arrange-Act-Assert (AAA) pattern?
201
- Are external dependencies (DBs, Networks) isolated efficiently using proper mocks?
202
- ✅ Is the test asserting verifying behavioral OUTCOMES rather than internal implementation details?
203
- ✅ Did I properly `await` asynchronous operations to prevent false positives?
204
- Are test names readable and descriptive of the tested behavior?
403
+
404
+ ### Playwright Config
405
+
406
+ ```typescript
407
+ // playwright.config.ts
408
+ import { defineConfig } from "@playwright/test";
409
+
410
+ export default defineConfig({
411
+ testDir: "./e2e",
412
+ timeout: 30000,
413
+ retries: process.env.CI ? 2 : 0, // retry in CI only
414
+ use: {
415
+ baseURL: "http://localhost:3000",
416
+ trace: "on-first-retry", // save trace on failures
417
+ screenshot: "only-on-failure",
418
+ },
419
+ webServer: {
420
+ command: "npm run dev",
421
+ port: 3000,
422
+ reuseExistingServer: !process.env.CI,
423
+ },
424
+ projects: [
425
+ { name: "chrome", use: { browserName: "chromium" } },
426
+ { name: "firefox", use: { browserName: "firefox" } },
427
+ { name: "mobile", use: { ...devices["iPhone 14"] } },
428
+ ],
429
+ });
205
430
  ```
431
+
432
+ ---
433
+
434
+ ## API Testing
435
+
436
+ ```typescript
437
+ // Testing REST APIs with supertest (Express/Fastify)
438
+ import request from "supertest";
439
+ import { app } from "./app";
440
+
441
+ describe("POST /api/users", () => {
442
+ it("creates a user and returns 201", async () => {
443
+ const response = await request(app)
444
+ .post("/api/users")
445
+ .send({ name: "Alice", email: "alice@test.com" })
446
+ .expect(201)
447
+ .expect("Content-Type", /json/);
448
+
449
+ expect(response.body).toMatchObject({
450
+ id: expect.any(Number),
451
+ name: "Alice",
452
+ email: "alice@test.com",
453
+ });
454
+ });
455
+
456
+ it("returns 400 for missing required fields", async () => {
457
+ await request(app)
458
+ .post("/api/users")
459
+ .send({ name: "" })
460
+ .expect(400);
461
+ });
462
+
463
+ it("returns 409 for duplicate email", async () => {
464
+ await request(app)
465
+ .post("/api/users")
466
+ .send({ name: "Alice", email: "existing@test.com" })
467
+ .expect(409);
468
+ });
469
+ });
470
+ ```
471
+
472
+ ---
473
+
474
+ ## Code Coverage
475
+
476
+ ```jsonc
477
+ // vitest.config.ts
478
+ export default defineConfig({
479
+ test: {
480
+ coverage: {
481
+ provider: "v8",
482
+ reporter: ["text", "lcov", "html"],
483
+ thresholds: {
484
+ lines: 80,
485
+ functions: 80,
486
+ branches: 75,
487
+ statements: 80,
488
+ },
489
+ exclude: [
490
+ "**/*.test.ts",
491
+ "**/*.spec.ts",
492
+ "**/types/**",
493
+ "**/mocks/**",
494
+ ],
495
+ },
496
+ },
497
+ });
498
+
499
+ // Run: npx vitest --coverage
500
+ ```
501
+
502
+ ```
503
+ Coverage rules:
504
+ - 80% is the practical threshold (not 100%)
505
+ - 100% coverage ≠ 100% confidence
506
+ - Cover edge cases and error paths, not just happy paths
507
+ - Avoid testing implementation details (private methods, internal state)
508
+ - Focus coverage on: business logic, data transformations, auth/security
509
+ - Skip coverage on: config files, types-only files, generated code
510
+ ```
511
+
512
+ ---