@nerdev/skillset 0.2.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/LICENSE +21 -0
- package/README.md +351 -0
- package/bin/skillset.mjs +205 -0
- package/curations/README.md +53 -0
- package/curations/TEMPLATE/WHY.md +23 -0
- package/curations/TEMPLATE/overlay/SKILL.md +6 -0
- package/curations/impeccable/WHY.md +34 -0
- package/curations/impeccable/overlay/SKILL.md +116 -0
- package/package.json +43 -0
- package/scripts/ste-gate.mjs +39 -0
- package/scripts/ste-lint.py +201 -0
- package/scripts/sync.mjs +174 -0
- package/skills/ai-agent/agent-docs-writer/SKILL.md +105 -0
- package/skills/ai-agent/agent-docs-writer/references/principles.md +73 -0
- package/skills/ai-agent/agent-docs-writer/templates/AGENTS.template.md +44 -0
- package/skills/ai-agent/agent-docs-writer/templates/README.template.md +19 -0
- package/skills/ai-agent/ultra-context-engine/SKILL.md +941 -0
- package/skills/architecture/blueprint/SKILL.md +191 -0
- package/skills/architecture/code-tour/SKILL.md +204 -0
- package/skills/architecture/progress-guard/SKILL.md +148 -0
- package/skills/architecture/search-first/SKILL.md +97 -0
- package/skills/backend/api-design/SKILL.md +456 -0
- package/skills/backend/auth/SKILL.md +596 -0
- package/skills/backend/database/SKILL.md +431 -0
- package/skills/backend/realtime/SKILL.md +670 -0
- package/skills/backend/security/SKILL.md +590 -0
- package/skills/business/brag/SKILL.md +177 -0
- package/skills/business/brag/assets/music/README.md +20 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-1-by-ende-dot-app.music-cues.json +3846 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-1-by-ende-dot-app.music-cues.md +35 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-10-by-ende-dot-app.music-cues.json +1826 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-10-by-ende-dot-app.music-cues.md +35 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-11-by-ende-dot-app.music-cues.json +2266 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-11-by-ende-dot-app.music-cues.md +35 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-12-by-ende-dot-app.music-cues.json +2806 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-12-by-ende-dot-app.music-cues.md +35 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-9-by-ende-dot-app.music-cues.json +2796 -0
- package/skills/business/brag/assets/music/cues/happy-beats-business-moves-vol-9-by-ende-dot-app.music-cues.md +35 -0
- package/skills/business/brag/assets/music/happy-beats-business-moves-vol-1-by-ende-dot-app.mp3 +0 -0
- package/skills/business/brag/assets/music/happy-beats-business-moves-vol-10-by-ende-dot-app.mp3 +0 -0
- package/skills/business/brag/assets/music/happy-beats-business-moves-vol-11-by-ende-dot-app.mp3 +0 -0
- package/skills/business/brag/assets/music/happy-beats-business-moves-vol-12-by-ende-dot-app.mp3 +0 -0
- package/skills/business/brag/assets/music/happy-beats-business-moves-vol-9-by-ende-dot-app.mp3 +0 -0
- package/skills/business/brag/assets/sfx/casino/card-fan-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-fan-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-place-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-place-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-place-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-place-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-shove-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-shove-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-shove-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-shove-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-shuffle.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-5.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-6.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-7.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/card-slide-8.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/cards-pack-open-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/cards-pack-open-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chip-lay-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chip-lay-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chip-lay-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-collide-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-collide-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-collide-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-collide-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-handle-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-handle-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-handle-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-handle-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-handle-6.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-stack-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-stack-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-stack-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-stack-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-stack-5.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/chips-stack-6.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-grab-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-grab-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-shake-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-shake-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-shake-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-throw-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-throw-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/dice-throw-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/die-throw-1.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/die-throw-2.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/die-throw-3.ogg +0 -0
- package/skills/business/brag/assets/sfx/casino/die-throw-4.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_carpet_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_carpet_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_carpet_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_concrete_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_concrete_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_concrete_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_concrete_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_concrete_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_grass_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_grass_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_grass_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_grass_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_grass_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_snow_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_snow_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_snow_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_snow_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_snow_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_wood_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_wood_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_wood_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_wood_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/footstep_wood_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactBell_heavy_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactBell_heavy_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactBell_heavy_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGeneric_light_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGeneric_light_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGeneric_light_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGeneric_light_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGeneric_light_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_heavy_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_light_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_light_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_light_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactGlass_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_heavy_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_heavy_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_heavy_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_light_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_light_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMetal_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactMining_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlank_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlank_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlank_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlank_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlank_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_heavy_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_heavy_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_heavy_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_heavy_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_heavy_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_light_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_light_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_light_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_light_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_light_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPlate_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_heavy_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_heavy_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_heavy_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_heavy_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_heavy_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactPunch_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_heavy_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_heavy_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_heavy_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_heavy_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_heavy_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactSoft_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactTin_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactTin_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactTin_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactTin_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactTin_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_heavy_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_heavy_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_heavy_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_heavy_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_heavy_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_light_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_light_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_light_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_light_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_light_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_medium_000.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_medium_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_medium_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_medium_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/impact/impactWood_medium_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/bong_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/click_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/click_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/click_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/click_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/click_005.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/drop_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/drop_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/drop_003.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/error_005.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/error_006.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/glitch_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/glitch_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/select_008.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/switch_001.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/switch_002.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/switch_004.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/switch_005.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/switch_006.ogg +0 -0
- package/skills/business/brag/assets/sfx/interface/switch_007.ogg +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-001.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-002.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-003.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-004.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-005.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-006.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-007.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-008.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-009.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-010.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-011.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-012.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-013.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-014.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-015.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-016.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-017.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-018.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-019.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-020.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-021.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-022.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-023.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-024.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-025.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-026.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-027.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-028.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-029.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-030.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-031.wav +0 -0
- package/skills/business/brag/assets/sfx/keyboard/keypress-032.wav +0 -0
- package/skills/business/brag/assets/sfx/sfx-analysis.json +15584 -0
- package/skills/business/brag/assets/sfx/sfx-analysis.md +75 -0
- package/skills/business/brag/assets/sfx/ui/click1.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/click2.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/click3.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/click4.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/click5.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/mouseclick1.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/rollover1.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/rollover2.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/rollover4.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/rollover5.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch1.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch10.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch11.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch12.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch13.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch14.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch15.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch16.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch17.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch18.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch19.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch2.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch20.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch21.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch22.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch23.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch24.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch25.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch26.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch27.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch28.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch29.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch3.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch30.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch31.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch32.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch33.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch34.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch35.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch36.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch37.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch38.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch4.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch5.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch6.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch7.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch8.ogg +0 -0
- package/skills/business/brag/assets/sfx/ui/switch9.ogg +0 -0
- package/skills/business/brag/references/audio.md +307 -0
- package/skills/business/brag/references/step-1-inspect.md +133 -0
- package/skills/business/brag/references/step-2-plan.md +234 -0
- package/skills/business/brag/references/step-3-compose.md +210 -0
- package/skills/business/brag/references/step-4-deliver.md +168 -0
- package/skills/business/brag/references/tones.md +231 -0
- package/skills/business/brag/scripts/analyze_music_cues.py +309 -0
- package/skills/business/brag/scripts/pyproject.toml +14 -0
- package/skills/business/brag/scripts/uv.lock +819 -0
- package/skills/business/copywriting/SKILL.md +178 -0
- package/skills/business/customer-research/SKILL.md +259 -0
- package/skills/business/freelancing/SKILL.md +679 -0
- package/skills/business/launch/SKILL.md +273 -0
- package/skills/business/marketing-psychology/SKILL.md +364 -0
- package/skills/business/pricing/SKILL.md +233 -0
- package/skills/business/resume-revamp-jake-ats/SKILL.md +64 -0
- package/skills/business/startup-founder/SKILL.md +400 -0
- package/skills/business/startup-founder/references/funding.md +48 -0
- package/skills/business/startup-founder/references/further-reading.md +132 -0
- package/skills/business/startup-founder/references/gtm-tools.md +57 -0
- package/skills/business/startup-founder/references/legal-india.md +36 -0
- package/skills/business/startup-founder/references/marketing/README.md +16 -0
- package/skills/business/startup-founder/references/marketing/cold-email.md +172 -0
- package/skills/business/startup-founder/references/marketing/competitors.md +245 -0
- package/skills/business/startup-founder/references/marketing/customer-research.md +276 -0
- package/skills/business/startup-founder/references/marketing/free-tools.md +168 -0
- package/skills/business/startup-founder/references/marketing/launch.md +343 -0
- package/skills/business/startup-founder/references/marketing/marketing-plan.md +270 -0
- package/skills/business/startup-founder/references/marketing/pricing.md +237 -0
- package/skills/business/startup-founder/references/marketing/product-marketing.md +250 -0
- package/skills/business/startup-founder/references/validation.md +267 -0
- package/skills/devops/deployments/SKILL.md +339 -0
- package/skills/devops/git-ci/SKILL.md +372 -0
- package/skills/devops/performance/SKILL.md +523 -0
- package/skills/devops/testing/SKILL.md +558 -0
- package/skills/engineering/code-review/SKILL.md +149 -0
- package/skills/engineering/coding-standards/SKILL.md +229 -0
- package/skills/engineering/product-engineering/SKILL.md +219 -0
- package/skills/engineering/senior-engineer-prompts/SKILL.md +145 -0
- package/skills/engineering/tdd-workflow/SKILL.md +178 -0
- package/skills/engineering/verification-loop/SKILL.md +199 -0
- package/skills/nerdev/nerdev-abstraction/SKILL.md +412 -0
- package/skills/nerdev/nerdev-docs/SKILL.md +527 -0
- package/skills/nerdev/nerdev-docs/templates/adr-template.md +39 -0
- package/skills/nerdev/nerdev-docs/templates/contributing-template.md +140 -0
- package/skills/nerdev/nerdev-docs/templates/deploy-template.md +426 -0
- package/skills/nerdev/nerdev-docs/templates/design-template.md +105 -0
- package/skills/nerdev/nerdev-docs/templates/incident-template.md +66 -0
- package/skills/nerdev/nerdev-monorepo/SKILL.md +522 -0
- package/skills/quality/output-skill/SKILL.md +49 -0
- package/skills/quality/unslop/SKILL.md +67 -0
- package/skills/ui/animaxxing/SKILL.md +58 -0
- package/skills/ui/animaxxing/agents/openai.yaml +7 -0
- package/skills/ui/animaxxing/references/effect-restoration.md +26 -0
- package/skills/ui/animaxxing/references/motion-vocabulary.md +142 -0
- package/skills/ui/animaxxing/references/recipes/blast-off.md +119 -0
- package/skills/ui/animaxxing/references/recipes/particle-effects.md +718 -0
- package/skills/ui/animaxxing/references/recipes/particle-field.md +428 -0
- package/skills/ui/animaxxing/references/recipes/route-letters.md +205 -0
- package/skills/ui/animaxxing/references/recipes/speak-in.md +181 -0
- package/skills/ui/animaxxing/references/recipes/split-entrances.md +345 -0
- package/skills/ui/animaxxing/references/recipes/wave.md +144 -0
- package/skills/ui/animaxxing/references/text-stability.md +68 -0
- package/skills/ui/animaxxing/references/verification.md +44 -0
- package/skills/ui/ask-animation/SKILL.md +178 -0
- package/skills/ui/ask-base-ui/SKILL.md +400 -0
- package/skills/ui/ask-cmdk/SKILL.md +315 -0
- package/skills/ui/ask-command-menu/SKILL.md +262 -0
- package/skills/ui/ask-drawer/SKILL.md +235 -0
- package/skills/ui/ask-form/SKILL.md +229 -0
- package/skills/ui/ask-gsap/SKILL.md +435 -0
- package/skills/ui/ask-modal/SKILL.md +145 -0
- package/skills/ui/ask-motion/SKILL.md +339 -0
- package/skills/ui/ask-rhf/SKILL.md +388 -0
- package/skills/ui/ask-sonner/API.md +64 -0
- package/skills/ui/ask-sonner/SKILL.md +88 -0
- package/skills/ui/ask-table/SKILL.md +253 -0
- package/skills/ui/ask-tanstack-table/SKILL.md +490 -0
- package/skills/ui/ask-toast/SKILL.md +163 -0
- package/skills/ui/ask-vaul/SKILL.md +291 -0
- package/skills/ui/ask-virtual-list/SKILL.md +304 -0
- package/skills/ui/ask-virtuoso/SKILL.md +332 -0
- package/skills/ui/email-craft/SKILL.md +258 -0
- package/skills/ui/frontend-craftsmanship/SKILL.md +462 -0
- package/skills/ui/gsap-astro/SKILL.md +56 -0
- package/skills/ui/gsap-astro/agents/openai.yaml +7 -0
- package/skills/ui/gsap-astro/references/client-router-navigation.md +139 -0
- package/skills/ui/gsap-astro/references/initialization.md +87 -0
- package/skills/ui/gsap-astro/references/motion-system.md +152 -0
- package/skills/ui/gsap-astro/references/scripts-and-islands.md +65 -0
- package/skills/ui/gsap-astro/references/verification.md +44 -0
- package/skills/ui/gsap-core/SKILL.md +254 -0
- package/skills/ui/gsap-frameworks/SKILL.md +266 -0
- package/skills/ui/gsap-nextjs/SKILL.md +51 -0
- package/skills/ui/gsap-nextjs/agents/openai.yaml +7 -0
- package/skills/ui/gsap-nextjs/references/app-router-navigation.md +189 -0
- package/skills/ui/gsap-nextjs/references/initialization.md +87 -0
- package/skills/ui/gsap-nextjs/references/motion-system.md +158 -0
- package/skills/ui/gsap-nextjs/references/verification.md +40 -0
- package/skills/ui/gsap-nuxt/SKILL.md +56 -0
- package/skills/ui/gsap-nuxt/agents/openai.yaml +7 -0
- package/skills/ui/gsap-nuxt/references/initialization.md +87 -0
- package/skills/ui/gsap-nuxt/references/motion-system.md +161 -0
- package/skills/ui/gsap-nuxt/references/navigation.md +145 -0
- package/skills/ui/gsap-nuxt/references/page-transitions.md +107 -0
- package/skills/ui/gsap-nuxt/references/verification.md +42 -0
- package/skills/ui/gsap-performance/SKILL.md +79 -0
- package/skills/ui/gsap-plugins/SKILL.md +433 -0
- package/skills/ui/gsap-react/SKILL.md +136 -0
- package/skills/ui/gsap-react-router/SKILL.md +55 -0
- package/skills/ui/gsap-react-router/agents/openai.yaml +7 -0
- package/skills/ui/gsap-react-router/references/initialization.md +87 -0
- package/skills/ui/gsap-react-router/references/motion-system.md +158 -0
- package/skills/ui/gsap-react-router/references/react-router-navigation.md +165 -0
- package/skills/ui/gsap-react-router/references/route-lifetime.md +74 -0
- package/skills/ui/gsap-react-router/references/verification.md +42 -0
- package/skills/ui/gsap-scrolltrigger/SKILL.md +296 -0
- package/skills/ui/gsap-sveltekit/SKILL.md +54 -0
- package/skills/ui/gsap-sveltekit/agents/openai.yaml +7 -0
- package/skills/ui/gsap-sveltekit/references/initialization.md +87 -0
- package/skills/ui/gsap-sveltekit/references/motion-system.md +156 -0
- package/skills/ui/gsap-sveltekit/references/page-lifetime.md +63 -0
- package/skills/ui/gsap-sveltekit/references/sveltekit-navigation.md +160 -0
- package/skills/ui/gsap-sveltekit/references/verification.md +41 -0
- package/skills/ui/gsap-tanstack-router/SKILL.md +56 -0
- package/skills/ui/gsap-tanstack-router/agents/openai.yaml +7 -0
- package/skills/ui/gsap-tanstack-router/references/initialization.md +87 -0
- package/skills/ui/gsap-tanstack-router/references/motion-system.md +160 -0
- package/skills/ui/gsap-tanstack-router/references/route-lifetime.md +66 -0
- package/skills/ui/gsap-tanstack-router/references/tanstack-navigation.md +156 -0
- package/skills/ui/gsap-tanstack-router/references/verification.md +41 -0
- package/skills/ui/gsap-timeline/SKILL.md +107 -0
- package/skills/ui/gsap-utils/SKILL.md +284 -0
- package/skills/ui/gsap-vanilla/SKILL.md +63 -0
- package/skills/ui/gsap-vanilla/agents/openai.yaml +7 -0
- package/skills/ui/gsap-vanilla/references/cross-document-navigation.md +54 -0
- package/skills/ui/gsap-vanilla/references/initialization.md +87 -0
- package/skills/ui/gsap-vanilla/references/motion-system.md +150 -0
- package/skills/ui/gsap-vanilla/references/page-load.md +96 -0
- package/skills/ui/gsap-vanilla/references/spa-navigation.md +70 -0
- package/skills/ui/gsap-vanilla/references/verification.md +41 -0
- package/skills/ui/house-style/SKILL.md +366 -0
- package/skills/ui/imagegen/SKILL.md +49 -0
- package/skills/ui/imagegen/references/brandkit.md +48 -0
- package/skills/ui/imagegen/references/image-to-code.md +56 -0
- package/skills/ui/imagegen/references/mobile.md +58 -0
- package/skills/ui/imagegen/references/web.md +63 -0
- package/skills/ui/impeccable/SKILL.md +116 -0
- package/skills/ui/impeccable/reference/adapt.md +318 -0
- package/skills/ui/impeccable/reference/adapt.native.md +58 -0
- package/skills/ui/impeccable/reference/android.md +46 -0
- package/skills/ui/impeccable/reference/animate.md +89 -0
- package/skills/ui/impeccable/reference/audit.md +137 -0
- package/skills/ui/impeccable/reference/audit.native.md +139 -0
- package/skills/ui/impeccable/reference/bolder.md +33 -0
- package/skills/ui/impeccable/reference/clarify.md +94 -0
- package/skills/ui/impeccable/reference/colorize.md +86 -0
- package/skills/ui/impeccable/reference/craft-floor.md +44 -0
- package/skills/ui/impeccable/reference/craft.md +5 -0
- package/skills/ui/impeccable/reference/critique.md +806 -0
- package/skills/ui/impeccable/reference/degraded/asset-producer.md +37 -0
- package/skills/ui/impeccable/reference/degraded/documenter.md +24 -0
- package/skills/ui/impeccable/reference/degraded/finish-reviewer.md +38 -0
- package/skills/ui/impeccable/reference/degraded/manual-edit-applier.md +92 -0
- package/skills/ui/impeccable/reference/delight.md +70 -0
- package/skills/ui/impeccable/reference/distill.md +111 -0
- package/skills/ui/impeccable/reference/doctor.md +54 -0
- package/skills/ui/impeccable/reference/document.md +416 -0
- package/skills/ui/impeccable/reference/extract.md +69 -0
- package/skills/ui/impeccable/reference/generate.md +101 -0
- package/skills/ui/impeccable/reference/harden.md +345 -0
- package/skills/ui/impeccable/reference/hooks.md +111 -0
- package/skills/ui/impeccable/reference/init.md +131 -0
- package/skills/ui/impeccable/reference/ios.md +51 -0
- package/skills/ui/impeccable/reference/layout.md +84 -0
- package/skills/ui/impeccable/reference/live-setup.md +104 -0
- package/skills/ui/impeccable/reference/live.md +325 -0
- package/skills/ui/impeccable/reference/new-work.md +145 -0
- package/skills/ui/impeccable/reference/onboard.md +234 -0
- package/skills/ui/impeccable/reference/operate.md +61 -0
- package/skills/ui/impeccable/reference/optimize.md +258 -0
- package/skills/ui/impeccable/reference/overdrive.md +127 -0
- package/skills/ui/impeccable/reference/polish.md +105 -0
- package/skills/ui/impeccable/reference/quieter.md +99 -0
- package/skills/ui/impeccable/reference/routing.md +24 -0
- package/skills/ui/impeccable/reference/shape.md +59 -0
- package/skills/ui/impeccable/reference/typeset.md +80 -0
- package/skills/ui/impeccable/reference/visualize.md +46 -0
- package/skills/ui/impeccable/scripts/VERSION +1 -0
- package/skills/ui/impeccable/scripts/command-metadata.json +98 -0
- package/skills/ui/impeccable/scripts/data/font-index-failures.json +121 -0
- package/skills/ui/impeccable/scripts/data/font-index.json +1 -0
- package/skills/ui/impeccable/scripts/impeccable +206 -0
- package/skills/ui/impeccable/scripts/impeccable.cmd +214 -0
- package/skills/ui/impeccable/scripts/live-browser-dom.js +167 -0
- package/skills/ui/impeccable/scripts/live-browser-ignores.js +242 -0
- package/skills/ui/impeccable/scripts/live-browser-session.js +144 -0
- package/skills/ui/impeccable/scripts/live-browser.js +13510 -0
- package/skills/ui/impeccable/scripts/modern-screenshot.umd.js +14 -0
- package/skills/ui/motion/SKILL.md +207 -0
- package/skills/ui/pick-ui-library/SKILL.md +85 -0
- package/skills/ui/product-messaging/SKILL.md +163 -0
- package/skills/ui/product-site/SKILL.md +465 -0
- package/skills/ui/prototype/PICKER.md +197 -0
- package/skills/ui/prototype/SKILL.md +98 -0
- package/skills/ui/refero-design/SKILL.md +534 -0
- package/skills/ui/refero-design/agents/openai.yaml +4 -0
- package/skills/ui/refero-design/references/anti-ai-slop.md +292 -0
- package/skills/ui/refero-design/references/color.md +563 -0
- package/skills/ui/refero-design/references/copywriting.md +222 -0
- package/skills/ui/refero-design/references/craft-details.md +525 -0
- package/skills/ui/refero-design/references/example-workflow.md +264 -0
- package/skills/ui/refero-design/references/icons.md +166 -0
- package/skills/ui/refero-design/references/mcp-tools.md +258 -0
- package/skills/ui/refero-design/references/motion.md +504 -0
- package/skills/ui/refero-design/references/typography.md +737 -0
- package/skills/ui/refero-design/references/visual-workflow.md +105 -0
- package/skills/ui/style-animaxxing/SKILL.md +48 -0
- package/skills/ui/style-animaxxing/agents/openai.yaml +7 -0
- package/skills/ui/style-animaxxing/references/motion-vocabulary.md +51 -0
- package/skills/ui/style-animaxxing/references/tokens.md +288 -0
- package/skills/ui/style-animaxxing/references/typography-and-layout.md +149 -0
- package/skills/ui/style-animaxxing/references/verification.md +38 -0
- package/skills/ui/typography-picker/SKILL.md +305 -0
- package/skills/ui/ui-core/SKILL.md +345 -0
- package/skills/ui/ui-core/references/accessibility.md +85 -0
- package/skills/ui/ui-core/references/build.md +666 -0
- package/skills/ui/ui-core/references/copy.md +70 -0
- package/skills/ui/ui-core/references/dark-mode.md +76 -0
- package/skills/ui/ui-core/references/direction.md +99 -0
- package/skills/ui/ui-core/references/redesign.md +74 -0
- package/skills/ui/ui-core/references/responsive.md +77 -0
- package/skills/ui/ui-core/references/styles.md +42 -0
- package/skills/ui/ui-core/references/system.md +190 -0
- package/skills/ui/ui-core/references/verify.md +37 -0
- package/skills/ui/ui-engineering/SKILL.md +436 -0
- package/skills/ui/ui-engineering/references/avatars.md +74 -0
- package/skills/ui/ui-engineering/references/card-patterns.md +66 -0
- package/skills/ui/ui-engineering/references/floating-actions.md +65 -0
- package/skills/ui/ui-engineering/references/navigation.md +81 -0
- package/skills/ui/ui-engineering/references/overlays.md +74 -0
- package/skills/ui/ui-engineering/references/pagination.md +71 -0
- package/skills/ui/ui-engineering/references/progress-indicators.md +77 -0
- package/skills/ui/ui-engineering/references/quality-bar.md +293 -0
- package/skills/ui/ui-engineering/references/search.md +68 -0
- package/skills/ui/ui-engineering/references/tailwind-architecture.md +81 -0
- package/skills/ui/ui-theme-picker/SKILL.md +522 -0
- package/skills/ui/ui-theme-picker/references/component-sources.md +223 -0
- package/skills/ui/ui-theme-picker/references/styles.md +298 -0
- package/skills/ui/vitepress-docs/SKILL.md +439 -0
- package/skills/ui/vitepress-docs/references/components.md +333 -0
- package/skills/ui/vitepress-docs/references/layout.md +128 -0
- package/skills/ui/vitepress-docs/references/tokens.md +87 -0
- package/skills/ui/vitepress-docs/references/typography.md +76 -0
- package/skills/workflow/careful/SKILL.md +48 -0
- package/skills/workflow/context-restore/SKILL.md +69 -0
- package/skills/workflow/context-save/SKILL.md +96 -0
- package/skills/workflow/health/SKILL.md +99 -0
- package/skills/workflow/learn/SKILL.md +95 -0
- package/skills/workflow/office-hours/SKILL.md +136 -0
- package/skills/workflow/ship/SKILL.md +95 -0
- package/vendor.json +80 -0
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testing
|
|
3
|
+
description: Testing patterns, unit, integration, E2E, Vitest, Playwright, React Testing Library, MSW, test database, coverage, CI integration. Load when writing tests or setting up test infrastructure.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Testing
|
|
7
|
+
|
|
8
|
+
Load when writing tests, setting up test infrastructure, improving coverage, or debugging flaky tests.
|
|
9
|
+
|
|
10
|
+
## Test Pyramid
|
|
11
|
+
```
|
|
12
|
+
E2E (5-10%) Playwright - Critical user journeys
|
|
13
|
+
/ \
|
|
14
|
+
Integration (20-30%) Vitest + Testcontainers - API, DB, services
|
|
15
|
+
/ \
|
|
16
|
+
Unit (60-70%) Vitest + RTL - Pure functions, components, hooks
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Tooling
|
|
20
|
+
|
|
21
|
+
| Layer | Tool | Purpose |
|
|
22
|
+
|-------|------|---------|
|
|
23
|
+
| Unit | Vitest | Fast, TypeScript-native, Jest-compatible |
|
|
24
|
+
| Component | React Testing Library | Test behavior, not implementation |
|
|
25
|
+
| API | Vitest + MSW | Mock external services |
|
|
26
|
+
| Database | Testcontainers | Real Postgres in tests |
|
|
27
|
+
| E2E | Playwright | Cross-browser, real user flows |
|
|
28
|
+
| Visual | Playwright + pixelmatch | Screenshot regression |
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## Vitest Config
|
|
32
|
+
```typescript
|
|
33
|
+
// vitest.config.ts
|
|
34
|
+
import { defineConfig } from 'vitest/config'
|
|
35
|
+
import react from '@vitejs/plugin-react'
|
|
36
|
+
import path from 'path'
|
|
37
|
+
|
|
38
|
+
export default defineConfig({
|
|
39
|
+
plugins: [react()],
|
|
40
|
+
test: {
|
|
41
|
+
environment: 'jsdom',
|
|
42
|
+
setupFiles: ['./test/setup.ts'],
|
|
43
|
+
include: ['**/*.test.{ts,tsx}'],
|
|
44
|
+
coverage: {
|
|
45
|
+
provider: 'v8',
|
|
46
|
+
reporter: ['text', 'json', 'html', 'lcov'],
|
|
47
|
+
thresholds: {
|
|
48
|
+
lines: 80,
|
|
49
|
+
functions: 80,
|
|
50
|
+
branches: 70,
|
|
51
|
+
statements: 80,
|
|
52
|
+
},
|
|
53
|
+
exclude: ['**/*.d.ts', '**/*.config.*', 'test/**', '**/mock*'],
|
|
54
|
+
},
|
|
55
|
+
pool: 'threads',
|
|
56
|
+
poolOptions: { threads: { singleThread: true } },
|
|
57
|
+
},
|
|
58
|
+
resolve: {
|
|
59
|
+
alias: {
|
|
60
|
+
'@': path.resolve(__dirname, './src'),
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
// test/setup.ts
|
|
68
|
+
import { cleanup } from '@testing-library/react'
|
|
69
|
+
import { afterEach, vi } from 'vitest'
|
|
70
|
+
import '@testing-library/jest-dom'
|
|
71
|
+
|
|
72
|
+
afterEach(() => {
|
|
73
|
+
cleanup()
|
|
74
|
+
vi.clearAllMocks()
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
// Global mocks
|
|
78
|
+
vi.mock('next/navigation', () => ({
|
|
79
|
+
useRouter: () => ({ push: vi.fn(), replace: vi.fn(), back: vi.fn() }),
|
|
80
|
+
usePathname: () => '/',
|
|
81
|
+
useSearchParams: () => new URLSearchParams(),
|
|
82
|
+
}))
|
|
83
|
+
|
|
84
|
+
// MatchMedia mock
|
|
85
|
+
Object.defineProperty(window, 'matchMedia', {
|
|
86
|
+
writable: true,
|
|
87
|
+
value: vi.fn().mockImplementation(query => ({
|
|
88
|
+
matches: false,
|
|
89
|
+
media: query,
|
|
90
|
+
onchange: null,
|
|
91
|
+
addListener: vi.fn(),
|
|
92
|
+
removeListener: vi.fn(),
|
|
93
|
+
addEventListener: vi.fn(),
|
|
94
|
+
removeEventListener: vi.fn(),
|
|
95
|
+
dispatchEvent: vi.fn(),
|
|
96
|
+
})),
|
|
97
|
+
})
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Unit Tests (Pure Functions)
|
|
101
|
+
```typescript
|
|
102
|
+
// lib/utils/date.test.ts
|
|
103
|
+
import { describe, it, expect } from 'vitest'
|
|
104
|
+
import { formatRelativeTime, addDays, isWeekend } from './date'
|
|
105
|
+
|
|
106
|
+
describe('formatRelativeTime', () => {
|
|
107
|
+
it('formats seconds ago', () => {
|
|
108
|
+
const now = new Date()
|
|
109
|
+
const past = new Date(now.getTime() - 30 * 1000)
|
|
110
|
+
expect(formatRelativeTime(past, now)).toBe('30s ago')
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('formats minutes ago', () => {
|
|
114
|
+
const now = new Date()
|
|
115
|
+
const past = new Date(now.getTime() - 5 * 60 * 1000)
|
|
116
|
+
expect(formatRelativeTime(past, now)).toBe('5m ago')
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('handles future dates', () => {
|
|
120
|
+
const now = new Date()
|
|
121
|
+
const future = new Date(now.getTime() + 60 * 1000)
|
|
122
|
+
expect(formatRelativeTime(future, now)).toBe('in 1m')
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
describe('isWeekend', () => {
|
|
127
|
+
it('returns true for Saturday', () => {
|
|
128
|
+
expect(isWeekend(new Date('2024-01-06'))).toBe(true)
|
|
129
|
+
})
|
|
130
|
+
it('returns true for Sunday', () => {
|
|
131
|
+
expect(isWeekend(new Date('2024-01-07'))).toBe(true)
|
|
132
|
+
})
|
|
133
|
+
it('returns false for Monday', () => {
|
|
134
|
+
expect(isWeekend(new Date('2024-01-08'))).toBe(false)
|
|
135
|
+
})
|
|
136
|
+
})
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Component Tests (React Testing Library)
|
|
140
|
+
```typescript
|
|
141
|
+
// components/Button/Button.test.tsx
|
|
142
|
+
import { render, screen, fireEvent } from '@testing-library/react'
|
|
143
|
+
import { describe, it, expect, vi } from 'vitest'
|
|
144
|
+
import { Button } from './Button'
|
|
145
|
+
|
|
146
|
+
describe('Button', () => {
|
|
147
|
+
it('renders children', () => {
|
|
148
|
+
render(<Button>Click me</Button>)
|
|
149
|
+
expect(screen.getByRole('button', { name: 'Click me' })).toBeInTheDocument()
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
it('calls onClick when clicked', () => {
|
|
153
|
+
const handleClick = vi.fn()
|
|
154
|
+
render(<Button onClick={handleClick}>Click</Button>)
|
|
155
|
+
fireEvent.click(screen.getByRole('button'))
|
|
156
|
+
expect(handleClick).toHaveBeenCalledOnce()
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it('shows loading state', () => {
|
|
160
|
+
render(<Button isLoading>Submit</Button>)
|
|
161
|
+
expect(screen.getByRole('button', { name: 'Submit' })).toBeDisabled()
|
|
162
|
+
expect(screen.getByTestId('spinner')).toBeInTheDocument()
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
it('applies variant classes', () => {
|
|
166
|
+
render(<Button variant="destructive">Delete</Button>)
|
|
167
|
+
expect(screen.getByRole('button')).toHaveClass('bg-red-600')
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
it('forwards ref', () => {
|
|
171
|
+
const ref = vi.fn()
|
|
172
|
+
render(<Button ref={ref}>Test</Button>)
|
|
173
|
+
expect(ref).toHaveBeenCalledWith(expect.any(HTMLButtonElement))
|
|
174
|
+
})
|
|
175
|
+
})
|
|
176
|
+
```
|
|
177
|
+
### Testing Custom Hooks
|
|
178
|
+
```typescript
|
|
179
|
+
// hooks/useDebounce.test.ts
|
|
180
|
+
import { renderHook, act, waitFor } from '@testing-library/react'
|
|
181
|
+
import { describe, it, expect, vi } from 'vitest'
|
|
182
|
+
import { useDebounce } from './useDebounce'
|
|
183
|
+
|
|
184
|
+
describe('useDebounce', () => {
|
|
185
|
+
beforeEach(() => vi.useFakeTimers())
|
|
186
|
+
afterEach(() => vi.useRealTimers())
|
|
187
|
+
|
|
188
|
+
it('returns initial value immediately', () => {
|
|
189
|
+
const { result } = renderHook(() => useDebounce('initial', 300))
|
|
190
|
+
expect(result.current).toBe('initial')
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
it('updates after delay', () => {
|
|
194
|
+
const { result, rerender } = renderHook(({ value }) => useDebounce(value, 300), {
|
|
195
|
+
initialProps: { value: 'initial' },
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
rerender({ value: 'updated' })
|
|
199
|
+
expect(result.current).toBe('initial')
|
|
200
|
+
|
|
201
|
+
act(() => vi.advanceTimersByTime(300))
|
|
202
|
+
expect(result.current).toBe('updated')
|
|
203
|
+
})
|
|
204
|
+
})
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Integration Tests (API + Database)
|
|
208
|
+
|
|
209
|
+
### Test Database (Testcontainers)
|
|
210
|
+
```typescript
|
|
211
|
+
// test/db.ts
|
|
212
|
+
import { GenericContainer, StartedTestContainer } from 'testcontainers'
|
|
213
|
+
import { PrismaClient } from '@prisma/client'
|
|
214
|
+
|
|
215
|
+
let container: StartedTestContainer
|
|
216
|
+
let prisma: PrismaClient
|
|
217
|
+
|
|
218
|
+
export async function setupTestDb() {
|
|
219
|
+
container = await new GenericContainer('postgres:16-alpine')
|
|
220
|
+
.withEnvironment({
|
|
221
|
+
POSTGRES_USER: 'test',
|
|
222
|
+
POSTGRES_PASSWORD: 'test',
|
|
223
|
+
POSTGRES_DB: 'test',
|
|
224
|
+
})
|
|
225
|
+
.withExposedPorts(5432)
|
|
226
|
+
.start()
|
|
227
|
+
|
|
228
|
+
const url = `postgresql://test:test@localhost:${container.getMappedPort(5432)}/test`
|
|
229
|
+
process.env.DATABASE_URL = url
|
|
230
|
+
|
|
231
|
+
prisma = new PrismaClient({ datasources: { db: { url } } })
|
|
232
|
+
await prisma.$connect()
|
|
233
|
+
await prisma.$executeRawUnsafe(`CREATE SCHEMA IF NOT EXISTS test`)
|
|
234
|
+
await prisma.migrateDeploy()
|
|
235
|
+
|
|
236
|
+
return prisma
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export async function teardownTestDb() {
|
|
240
|
+
await prisma?.$disconnect()
|
|
241
|
+
await container?.stop()
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export async function cleanDatabase() {
|
|
245
|
+
const models = Reflect.ownKeys(prisma).filter(k => typeof prisma[k as string]?.deleteMany === 'function')
|
|
246
|
+
await Promise.all(models.map(m => prisma[m as string].deleteMany()))
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
### API Integration Test
|
|
250
|
+
```typescript
|
|
251
|
+
// apps/http-backend/src/routes/projects.test.ts
|
|
252
|
+
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest'
|
|
253
|
+
import { Elysia } from 'elysia'
|
|
254
|
+
import { setupTestDb, teardownTestDb, cleanDatabase, prisma } from '../../test/db'
|
|
255
|
+
import { projectsRoutes } from './projects'
|
|
256
|
+
|
|
257
|
+
describe('Projects API', () => {
|
|
258
|
+
let app: Elysia
|
|
259
|
+
|
|
260
|
+
beforeAll(async () => {
|
|
261
|
+
await setupTestDb()
|
|
262
|
+
app = new Elysia().use(projectsRoutes)
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
afterAll(async () => {
|
|
266
|
+
await teardownTestDb()
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
beforeEach(async () => {
|
|
270
|
+
await cleanDatabase()
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
it('creates a project', async () => {
|
|
274
|
+
const res = await app.handle(new Request('http://localhost/projects', {
|
|
275
|
+
method: 'POST',
|
|
276
|
+
headers: { 'Content-Type': 'application/json' },
|
|
277
|
+
body: JSON.stringify({ name: 'Test Project', visibility: 'private' }),
|
|
278
|
+
}))
|
|
279
|
+
|
|
280
|
+
expect(res.status).toBe(201)
|
|
281
|
+
const data = await res.json()
|
|
282
|
+
expect(data.name).toBe('Test Project')
|
|
283
|
+
expect(data.id).toBeDefined()
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
it('returns 400 for invalid input', async () => {
|
|
287
|
+
const res = await app.handle(new Request('http://localhost/projects', {
|
|
288
|
+
method: 'POST',
|
|
289
|
+
headers: { 'Content-Type': 'application/json' },
|
|
290
|
+
body: JSON.stringify({ name: '' }),
|
|
291
|
+
}))
|
|
292
|
+
|
|
293
|
+
expect(res.status).toBe(400)
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
it('lists projects with pagination', async () => {
|
|
297
|
+
await prisma.project.createMany({ data: Array(5).fill({ name: 'Test', visibility: 'private' }) })
|
|
298
|
+
|
|
299
|
+
const res = await app.handle(new Request('http://localhost/projects?page=1&limit=2'))
|
|
300
|
+
const data = await res.json()
|
|
301
|
+
|
|
302
|
+
expect(data.data).toHaveLength(2)
|
|
303
|
+
expect(data.meta.total).toBe(5)
|
|
304
|
+
})
|
|
305
|
+
})
|
|
306
|
+
```
|
|
307
|
+
### MSW for External Services
|
|
308
|
+
```typescript
|
|
309
|
+
// test/msw.ts
|
|
310
|
+
import { setupServer } from 'msw/node'
|
|
311
|
+
import { http, HttpResponse } from 'msw'
|
|
312
|
+
|
|
313
|
+
export const server = setupServer(
|
|
314
|
+
http.get('https://api.github.com/user', () => HttpResponse.json({
|
|
315
|
+
login: 'testuser',
|
|
316
|
+
id: 1,
|
|
317
|
+
avatar_url: 'https://github.com/testuser.png',
|
|
318
|
+
})),
|
|
319
|
+
http.post('https://api.stripe.com/v1/checkout/sessions', () => HttpResponse.json({
|
|
320
|
+
id: 'cs_test_123',
|
|
321
|
+
url: 'https://checkout.stripe.com/pay/cs_test_123',
|
|
322
|
+
})),
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
// test/setup.ts
|
|
326
|
+
import { beforeAll, afterAll, afterEach } from 'vitest'
|
|
327
|
+
import { server } from './msw'
|
|
328
|
+
|
|
329
|
+
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
|
|
330
|
+
afterAll(() => server.close())
|
|
331
|
+
afterEach(() => server.resetHandlers())
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## E2E Tests (Playwright)
|
|
335
|
+
```typescript
|
|
336
|
+
// playwright.config.ts
|
|
337
|
+
import { defineConfig, devices } from '@playwright/test'
|
|
338
|
+
|
|
339
|
+
export default defineConfig({
|
|
340
|
+
testDir: './e2e',
|
|
341
|
+
fullyParallel: true,
|
|
342
|
+
forbidOnly: !!process.env.CI,
|
|
343
|
+
retries: process.env.CI ? 2 : 0,
|
|
344
|
+
workers: process.env.CI ? 1 : undefined,
|
|
345
|
+
reporter: [['html', { open: 'never' }], ['json', { outputFile: 'test-results/results.json' }]],
|
|
346
|
+
use: {
|
|
347
|
+
baseURL: 'http://localhost:5173',
|
|
348
|
+
trace: 'on-first-retry',
|
|
349
|
+
screenshot: 'only-on-failure',
|
|
350
|
+
video: 'retain-on-failure',
|
|
351
|
+
},
|
|
352
|
+
projects: [
|
|
353
|
+
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
|
|
354
|
+
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
|
|
355
|
+
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
|
|
356
|
+
{ name: 'mobile-chrome', use: { ...devices['Pixel 5'] } },
|
|
357
|
+
{ name: 'mobile-safari', use: { ...devices['iPhone 12'] } },
|
|
358
|
+
],
|
|
359
|
+
webServer: {
|
|
360
|
+
command: 'bun run dev',
|
|
361
|
+
url: 'http://localhost:5173',
|
|
362
|
+
reuseExistingServer: !process.env.CI,
|
|
363
|
+
timeout: 120000,
|
|
364
|
+
},
|
|
365
|
+
})
|
|
366
|
+
```
|
|
367
|
+
### E2E Test Example
|
|
368
|
+
```typescript
|
|
369
|
+
// e2e/auth.spec.ts
|
|
370
|
+
import { test, expect } from '@playwright/test'
|
|
371
|
+
|
|
372
|
+
test.describe('Authentication', () => {
|
|
373
|
+
test('sign up flow', async ({ page }) => {
|
|
374
|
+
await page.goto('/signup')
|
|
375
|
+
|
|
376
|
+
await page.fill('[name="email"]', 'test@example.com')
|
|
377
|
+
await page.fill('[name="password"]', 'SecurePass123!')
|
|
378
|
+
await page.fill('[name="name"]', 'Test User')
|
|
379
|
+
await page.click('button[type="submit"]')
|
|
380
|
+
|
|
381
|
+
await expect(page).toHaveURL('/dashboard')
|
|
382
|
+
await expect(page.locator('text=Welcome, Test User')).toBeVisible()
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
test('sign in with invalid credentials shows error', async ({ page }) => {
|
|
386
|
+
await page.goto('/signin')
|
|
387
|
+
await page.fill('[name="email"]', 'wrong@example.com')
|
|
388
|
+
await page.fill('[name="password"]', 'wrong')
|
|
389
|
+
await page.click('button[type="submit"]')
|
|
390
|
+
|
|
391
|
+
await expect(page.locator('text=Invalid credentials')).toBeVisible()
|
|
392
|
+
})
|
|
393
|
+
|
|
394
|
+
test('protected route redirects to signin', async ({ page }) => {
|
|
395
|
+
await page.goto('/settings')
|
|
396
|
+
await expect(page).toHaveURL('/signin?redirect=/settings')
|
|
397
|
+
})
|
|
398
|
+
})
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
// e2e/projects.spec.ts
|
|
403
|
+
import { test, expect } from '@playwright/test'
|
|
404
|
+
|
|
405
|
+
test.describe('Projects', () => {
|
|
406
|
+
test.beforeEach(async ({ page }) => {
|
|
407
|
+
await page.goto('/signin')
|
|
408
|
+
await page.fill('[name="email"]', 'test@example.com')
|
|
409
|
+
await page.fill('[name="password"]', 'SecurePass123!')
|
|
410
|
+
await page.click('button[type="submit"]')
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
test('create project', async ({ page }) => {
|
|
414
|
+
await page.goto('/projects/new')
|
|
415
|
+
await page.fill('[name="name"]', 'My New Project')
|
|
416
|
+
await page.selectOption('[name="visibility"]', 'team')
|
|
417
|
+
await page.click('button[type="submit"]')
|
|
418
|
+
|
|
419
|
+
await expect(page.locator('text=Project created')).toBeVisible()
|
|
420
|
+
await expect(page).toHaveURL(/\/projects\/[a-z0-9]+/)
|
|
421
|
+
})
|
|
422
|
+
|
|
423
|
+
test('delete project with confirmation', async ({ page }) => {
|
|
424
|
+
await page.goto('/projects')
|
|
425
|
+
await page.click('[data-testid="project-menu"]:first-child')
|
|
426
|
+
await page.click('text=Delete')
|
|
427
|
+
await page.click('button:has-text("Delete")') // Confirmation dialog
|
|
428
|
+
|
|
429
|
+
await expect(page.locator('text=Deleted')).toBeVisible()
|
|
430
|
+
})
|
|
431
|
+
})
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
## Mocking Patterns
|
|
435
|
+
|
|
436
|
+
### Mock Prisma
|
|
437
|
+
```typescript
|
|
438
|
+
// test/mocks/prisma.ts
|
|
439
|
+
import { vi } from 'vitest'
|
|
440
|
+
|
|
441
|
+
export const mockPrisma = {
|
|
442
|
+
project: {
|
|
443
|
+
create: vi.fn(),
|
|
444
|
+
findMany: vi.fn(),
|
|
445
|
+
findUnique: vi.fn(),
|
|
446
|
+
update: vi.fn(),
|
|
447
|
+
delete: vi.fn(),
|
|
448
|
+
},
|
|
449
|
+
user: {
|
|
450
|
+
findUnique: vi.fn(),
|
|
451
|
+
findMany: vi.fn(),
|
|
452
|
+
},
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
vi.mock('@/lib/prisma', () => ({
|
|
456
|
+
prisma: mockPrisma,
|
|
457
|
+
}))
|
|
458
|
+
```
|
|
459
|
+
### Mock Next.js Router
|
|
460
|
+
```typescript
|
|
461
|
+
// test/mocks/next-navigation.ts
|
|
462
|
+
import { vi } from 'vitest'
|
|
463
|
+
|
|
464
|
+
export const mockRouter = {
|
|
465
|
+
push: vi.fn(),
|
|
466
|
+
replace: vi.fn(),
|
|
467
|
+
back: vi.fn(),
|
|
468
|
+
prefetch: vi.fn(),
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
vi.mock('next/navigation', () => ({
|
|
472
|
+
useRouter: () => mockRouter,
|
|
473
|
+
usePathname: () => '/',
|
|
474
|
+
useSearchParams: () => new URLSearchParams(),
|
|
475
|
+
}))
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## Coverage Goals
|
|
479
|
+
|
|
480
|
+
| Metric | Target | Enforcement |
|
|
481
|
+
|--------|--------|-------------|
|
|
482
|
+
| Lines | 80% | CI fails below |
|
|
483
|
+
| Functions | 80% | CI fails below |
|
|
484
|
+
| Branches | 70% | CI fails below |
|
|
485
|
+
| Statements | 80% | CI fails below |
|
|
486
|
+
|
|
487
|
+
### Coverage Exclusions
|
|
488
|
+
```typescript
|
|
489
|
+
// vitest.config.ts
|
|
490
|
+
coverage: {
|
|
491
|
+
exclude: [
|
|
492
|
+
'**/*.d.ts',
|
|
493
|
+
'**/*.config.*',
|
|
494
|
+
'test/**',
|
|
495
|
+
'**/mock*',
|
|
496
|
+
'**/*.stories.tsx',
|
|
497
|
+
'**/index.ts', // Barrel files
|
|
498
|
+
'apps/frontend/src/main.tsx', // Entry points
|
|
499
|
+
],
|
|
500
|
+
}
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
## CI Integration
|
|
504
|
+
```yaml
|
|
505
|
+
# .github/workflows/test.yml
|
|
506
|
+
jobs:
|
|
507
|
+
test:
|
|
508
|
+
runs-on: ubuntu-latest
|
|
509
|
+
steps:
|
|
510
|
+
- uses: actions/checkout@v4
|
|
511
|
+
- uses: oven-sh/setup-bun@v1
|
|
512
|
+
- run: bun install --frozen-lockfile
|
|
513
|
+
- run: bun run test --coverage
|
|
514
|
+
- uses: codecov/codecov-action@v4
|
|
515
|
+
if: github.event_name == 'pull_request'
|
|
516
|
+
with:
|
|
517
|
+
files: ./coverage/lcov.info
|
|
518
|
+
flags: unittests
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
## Debugging Flaky Tests
|
|
522
|
+
|
|
523
|
+
| Symptom | Fix |
|
|
524
|
+
|---------|-----|
|
|
525
|
+
| Random failures | Check async cleanup, use `waitFor` |
|
|
526
|
+
| Timeouts | Increase timeout, check hanging promises |
|
|
527
|
+
| Order-dependent | Clean state between tests (`beforeEach`) |
|
|
528
|
+
| Browser flaky | Add retries, check race conditions |
|
|
529
|
+
| DB state leaks | Use transactions + rollback, or clean DB |
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
## Quick Commands
|
|
533
|
+
```bash
|
|
534
|
+
# Run all tests
|
|
535
|
+
bun test
|
|
536
|
+
|
|
537
|
+
# Watch mode
|
|
538
|
+
bun test --watch
|
|
539
|
+
|
|
540
|
+
# Coverage
|
|
541
|
+
bun test --coverage
|
|
542
|
+
|
|
543
|
+
# Specific file
|
|
544
|
+
bun test Button.test.tsx
|
|
545
|
+
|
|
546
|
+
# E2E
|
|
547
|
+
bun playwright test
|
|
548
|
+
bun playwright test --headed
|
|
549
|
+
bun playwright show-report
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
## Related Skills
|
|
553
|
+
- `devops/git-ci` - CI pipeline integration
|
|
554
|
+
- `backend/database` - Testcontainers patterns
|
|
555
|
+
- `backend/auth` - Testing auth flows
|
|
556
|
+
- `backend/api-design` - Testing API contracts
|
|
557
|
+
- `engineering/tdd-workflow` - Test-first development
|
|
558
|
+
- `engineering/verification-loop` - Pre-PR quality gates
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-review
|
|
3
|
+
category: engineering
|
|
4
|
+
source: ECC (adapted)
|
|
5
|
+
description: "Confidence-weighted code review with false-positive suppression. Load when reviewing code or setting up review processes."
|
|
6
|
+
|
|
7
|
+
# Code Review
|
|
8
|
+
|
|
9
|
+
When to use: reviewing PRs, setting up review processes, establishing quality standards.
|
|
10
|
+
|
|
11
|
+
## Core Principle
|
|
12
|
+
|
|
13
|
+
**You own the code you commit.**
|
|
14
|
+
**You partially own the code you review and approve.**
|
|
15
|
+
**How the code is generated is irrelevant.**
|
|
16
|
+
|
|
17
|
+
This applies whether you wrote it, an AI wrote it, or a teammate wrote it. If you commit it, you own it. If you approve it, you share ownership.
|
|
18
|
+
|
|
19
|
+
## Review Checklist
|
|
20
|
+
|
|
21
|
+
### CRITICAL (Block merge)
|
|
22
|
+
|
|
23
|
+
| Check | What to Look For |
|
|
24
|
+
|-------|------------------|
|
|
25
|
+
| Security vulnerabilities | SQL injection, XSS, CSRF, secrets in code |
|
|
26
|
+
| Data loss risks | Missing error handling, unbounded operations |
|
|
27
|
+
| Race conditions | Shared state without synchronization |
|
|
28
|
+
| Authentication/Authorization bypass | Missing auth checks, broken access control |
|
|
29
|
+
|
|
30
|
+
### HIGH (Request changes)
|
|
31
|
+
|
|
32
|
+
| Check | What to Look For |
|
|
33
|
+
|-------|------------------|
|
|
34
|
+
| Breaking changes | API contract violations, schema changes |
|
|
35
|
+
| Performance regression | O(n²) loops, N+1 queries, missing indexes |
|
|
36
|
+
| Missing tests | New features without tests, bug fixes without regression tests |
|
|
37
|
+
| Error handling | Swallowed errors, unclear error messages |
|
|
38
|
+
|
|
39
|
+
### MEDIUM (Suggest improvements)
|
|
40
|
+
|
|
41
|
+
| Check | What to Look For |
|
|
42
|
+
|-------|------------------|
|
|
43
|
+
| Code duplication | Same logic in 3+ places |
|
|
44
|
+
| Long functions | > 50 lines, multiple responsibilities |
|
|
45
|
+
| Complex conditionals | Nested if/else, unclear logic |
|
|
46
|
+
| Missing documentation | Public APIs without JSDoc |
|
|
47
|
+
|
|
48
|
+
### LOW (Optional, don't block)
|
|
49
|
+
|
|
50
|
+
| Check | What to Look For |
|
|
51
|
+
|-------|------------------|
|
|
52
|
+
| Naming improvements | Unclear variable/function names |
|
|
53
|
+
| Minor refactoring | Small optimizations |
|
|
54
|
+
| Style consistency | Inconsistent patterns |
|
|
55
|
+
|
|
56
|
+
## Confidence Weighting
|
|
57
|
+
|
|
58
|
+
Each issue gets a confidence score (0.0 - 1.0):
|
|
59
|
+
|
|
60
|
+
| Score | Meaning | Action |
|
|
61
|
+
|-------|---------|--------|
|
|
62
|
+
| 0.9 - 1.0 | Definite bug or violation | Block merge |
|
|
63
|
+
| 0.7 - 0.8 | Likely problem | Request changes |
|
|
64
|
+
| 0.5 - 0.6 | Possible issue | Suggest improvement |
|
|
65
|
+
| 0.3 - 0.4 | Uncertain | Comment, don't block |
|
|
66
|
+
| 0.0 - 0.2 | Probably fine | Skip |
|
|
67
|
+
|
|
68
|
+
Confidence rules:
|
|
69
|
+
- Never report issues below 0.5 confidence unless you can cite exact line and failure mode.
|
|
70
|
+
- Suppress common LLM review noise: "consider adding error handling" on already-handled paths, "might be slow" without benchmarks, "could be more readable" without specific suggestions.
|
|
71
|
+
- Require concrete evidence: line numbers, error messages, test cases that would fail.
|
|
72
|
+
|
|
73
|
+
## Pre-Report Gate
|
|
74
|
+
|
|
75
|
+
Before reporting any issue, verify you can cite the exact line number, describe the concrete failure mode, explain why it would cause a problem in production, and confirm it is a real issue rather than a style preference. If any answer is "no", don't report it.
|
|
76
|
+
|
|
77
|
+
## Verdict System
|
|
78
|
+
|
|
79
|
+
| Verdict | Meaning | When to Use |
|
|
80
|
+
|---------|---------|-------------|
|
|
81
|
+
| APPROVE | Ready to merge | No critical/high issues, medium/low are optional |
|
|
82
|
+
| WARNING | Merge with caution | Medium issues exist but no blockers |
|
|
83
|
+
| BLOCK | Cannot merge | Critical or high issues present |
|
|
84
|
+
|
|
85
|
+
## Review Template
|
|
86
|
+
|
|
87
|
+
```markdown
|
|
88
|
+
## Code Review: [PR Title]
|
|
89
|
+
|
|
90
|
+
### Summary
|
|
91
|
+
[1-2 sentence overview of changes]
|
|
92
|
+
|
|
93
|
+
### Verdict: [APPROVE/WARNING/BLOCK]
|
|
94
|
+
|
|
95
|
+
### Issues Found
|
|
96
|
+
|
|
97
|
+
#### CRITICAL
|
|
98
|
+
[None or list with line citations]
|
|
99
|
+
|
|
100
|
+
#### HIGH
|
|
101
|
+
[None or list with line citations]
|
|
102
|
+
|
|
103
|
+
#### MEDIUM
|
|
104
|
+
[None or list with suggestions]
|
|
105
|
+
|
|
106
|
+
#### LOW
|
|
107
|
+
[None or list with optional improvements]
|
|
108
|
+
|
|
109
|
+
### Positives
|
|
110
|
+
[What was done well - always include at least one]
|
|
111
|
+
|
|
112
|
+
### Testing
|
|
113
|
+
- [ ] Tests pass
|
|
114
|
+
- [ ] Coverage maintained/improved
|
|
115
|
+
- [ ] Edge cases covered
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## False-Positive Suppression
|
|
119
|
+
|
|
120
|
+
Skip these common noise patterns:
|
|
121
|
+
- "Consider adding error handling" on already-handled paths
|
|
122
|
+
- "This might be slow" without benchmarks
|
|
123
|
+
- "Could be more readable" without specific suggestion
|
|
124
|
+
- "Consider using X library" when current solution works
|
|
125
|
+
- "This is a code smell" without concrete impact
|
|
126
|
+
- "Should use const" when let is intentional
|
|
127
|
+
|
|
128
|
+
Focus on: concrete bugs with reproduction steps, performance issues with measurements, security issues with attack vectors, maintainability issues with specific refactoring suggestions.
|
|
129
|
+
|
|
130
|
+
## Review Scope
|
|
131
|
+
|
|
132
|
+
Review: logic correctness, error handling, security implications, performance impact, test coverage, API contract changes, breaking changes.
|
|
133
|
+
|
|
134
|
+
Don't review: personal style preferences, trivial formatting (let the linter handle it), library choices (unless there's a security/performance concern), variable naming (unless truly confusing).
|
|
135
|
+
|
|
136
|
+
## Quick Commands
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
gh pr diff <pr-number>
|
|
140
|
+
gh pr checkout <pr-number>
|
|
141
|
+
bun test
|
|
142
|
+
grep -r "password\|secret\|token\|key" --include="*.ts" --include="*.js"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Related Skills
|
|
146
|
+
|
|
147
|
+
- `engineering/tdd-workflow` for test quality standards
|
|
148
|
+
- `engineering/verification-loop` for pre-PR quality gates
|
|
149
|
+
- `backend/security` for security review patterns
|