cfsa-antigravity 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/bin/cli.mjs +324 -0
  2. package/package.json +34 -0
  3. package/template/.agent/instructions/commands.md +48 -0
  4. package/template/.agent/instructions/patterns.md +61 -0
  5. package/template/.agent/instructions/structure.md +29 -0
  6. package/template/.agent/instructions/tech-stack.md +43 -0
  7. package/template/.agent/instructions/workflow.md +41 -0
  8. package/template/.agent/kit-sync.md +15 -0
  9. package/template/.agent/rules/boundary-not-placeholder.md +146 -0
  10. package/template/.agent/rules/completion-checklist.md +48 -0
  11. package/template/.agent/rules/decision-classification.md +103 -0
  12. package/template/.agent/rules/extensibility.md +47 -0
  13. package/template/.agent/rules/question-vs-command.md +81 -0
  14. package/template/.agent/rules/security-first.md +43 -0
  15. package/template/.agent/rules/specificity-standards.md +54 -0
  16. package/template/.agent/rules/tdd-contract-first.md +57 -0
  17. package/template/.agent/rules/vertical-slices.md +42 -0
  18. package/template/.agent/skill-library/MANIFEST.md +480 -0
  19. package/template/.agent/skill-library/README.md +38 -0
  20. package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
  21. package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
  22. package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
  23. package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
  24. package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
  25. package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
  26. package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
  27. package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
  28. package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
  29. package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
  30. package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
  31. package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
  32. package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
  33. package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
  34. package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
  35. package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
  36. package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
  37. package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
  38. package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
  39. package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
  40. package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
  41. package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
  42. package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
  43. package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
  44. package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
  45. package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
  46. package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
  47. package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
  48. package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
  49. package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
  50. package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
  51. package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
  52. package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
  53. package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
  54. package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
  55. package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
  56. package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
  57. package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
  58. package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
  59. package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
  60. package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
  61. package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
  62. package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
  63. package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
  64. package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
  65. package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
  66. package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
  67. package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
  68. package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
  69. package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
  70. package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
  71. package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
  72. package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
  73. package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
  74. package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
  75. package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
  76. package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
  77. package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
  78. package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
  79. package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
  80. package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
  81. package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
  82. package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
  83. package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
  84. package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
  85. package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
  86. package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
  87. package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
  88. package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
  89. package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
  90. package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
  91. package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
  92. package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
  93. package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
  94. package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
  95. package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
  96. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
  97. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
  98. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
  99. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
  100. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
  101. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
  102. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
  103. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
  104. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
  105. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
  106. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
  107. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
  108. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
  109. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
  110. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
  111. package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
  112. package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
  113. package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
  114. package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
  115. package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
  116. package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
  117. package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
  118. package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
  119. package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
  120. package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
  121. package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
  122. package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
  123. package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
  124. package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
  125. package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
  126. package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
  127. package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
  128. package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
  129. package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
  130. package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
  131. package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
  132. package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
  133. package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
  134. package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
  135. package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
  136. package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
  137. package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
  138. package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
  139. package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
  140. package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
  141. package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
  142. package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
  143. package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
  144. package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
  145. package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
  146. package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
  147. package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
  148. package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
  149. package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
  150. package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
  151. package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
  152. package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
  153. package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
  154. package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
  155. package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
  156. package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
  157. package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
  158. package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
  159. package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
  160. package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
  161. package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
  162. package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
  163. package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
  164. package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
  165. package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
  166. package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
  167. package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
  168. package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
  169. package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
  170. package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
  171. package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
  172. package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
  173. package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
  174. package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
  175. package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
  176. package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
  177. package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
  178. package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
  179. package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
  180. package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
  181. package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
  182. package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
  183. package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
  184. package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
  185. package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
  186. package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
  187. package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
  188. package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
  189. package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
  190. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
  191. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
  192. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
  193. package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
  194. package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
  195. package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
  196. package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
  197. package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
  198. package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
  199. package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
  200. package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
  201. package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
  202. package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
  203. package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
  204. package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
  205. package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
  206. package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
  207. package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
  208. package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
  209. package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
  210. package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
  211. package/template/.agent/skills/accessibility/SKILL.md +522 -0
  212. package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
  213. package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
  214. package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
  215. package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
  216. package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
  217. package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
  218. package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
  219. package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
  220. package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
  221. package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
  222. package/template/.agent/skills/api-versioning/SKILL.md +420 -0
  223. package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
  224. package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
  225. package/template/.agent/skills/brainstorming/SKILL.md +236 -0
  226. package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
  227. package/template/.agent/skills/clean-code/SKILL.md +94 -0
  228. package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
  229. package/template/.agent/skills/concise-planning/SKILL.md +68 -0
  230. package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
  231. package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
  232. package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
  233. package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
  234. package/template/.agent/skills/design-direction/SKILL.md +45 -0
  235. package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
  236. package/template/.agent/skills/find-skills/SKILL.md +145 -0
  237. package/template/.agent/skills/git-advanced/SKILL.md +972 -0
  238. package/template/.agent/skills/git-workflow/SKILL.md +420 -0
  239. package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
  240. package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
  241. package/template/.agent/skills/migration-management/SKILL.md +384 -0
  242. package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
  243. package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
  244. package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
  245. package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
  246. package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
  247. package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
  248. package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
  249. package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
  250. package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
  251. package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
  252. package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
  253. package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
  254. package/template/.agent/skills/prd-templates/SKILL.md +88 -0
  255. package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
  256. package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
  257. package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
  258. package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
  259. package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
  260. package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
  261. package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
  262. package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
  263. package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
  264. package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
  265. package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
  266. package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
  267. package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
  268. package/template/.agent/skills/prompt-engineer/README.md +659 -0
  269. package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
  270. package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
  271. package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
  272. package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
  273. package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
  274. package/template/.agent/skills/session-continuity/SKILL.md +730 -0
  275. package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
  276. package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
  277. package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
  278. package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
  279. package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
  280. package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
  281. package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
  282. package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
  283. package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
  284. package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
  285. package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
  286. package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
  287. package/template/.agent/skills/skill-creator/README.md +270 -0
  288. package/template/.agent/skills/skill-creator/SKILL.md +590 -0
  289. package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
  290. package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
  291. package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
  292. package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
  293. package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
  294. package/template/.agent/skills/spec-writing/SKILL.md +110 -0
  295. package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
  296. package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
  297. package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  298. package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
  299. package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
  300. package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
  301. package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
  302. package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
  303. package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
  304. package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
  305. package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
  306. package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
  307. package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
  308. package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
  309. package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
  310. package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
  311. package/template/.agent/skills/technical-writer/SKILL.md +242 -0
  312. package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
  313. package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
  314. package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
  315. package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
  316. package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
  317. package/template/.agent/workflows/audit-ambiguity.md +64 -0
  318. package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
  319. package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
  320. package/template/.agent/workflows/bootstrap-agents.md +66 -0
  321. package/template/.agent/workflows/create-prd-architecture.md +119 -0
  322. package/template/.agent/workflows/create-prd-compile.md +138 -0
  323. package/template/.agent/workflows/create-prd-design-system.md +135 -0
  324. package/template/.agent/workflows/create-prd-security.md +113 -0
  325. package/template/.agent/workflows/create-prd-stack.md +91 -0
  326. package/template/.agent/workflows/create-prd.md +168 -0
  327. package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
  328. package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
  329. package/template/.agent/workflows/decompose-architecture.md +111 -0
  330. package/template/.agent/workflows/evolve-contract.md +98 -0
  331. package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
  332. package/template/.agent/workflows/evolve-feature-classify.md +116 -0
  333. package/template/.agent/workflows/evolve-feature.md +56 -0
  334. package/template/.agent/workflows/ideate-discover.md +144 -0
  335. package/template/.agent/workflows/ideate-extract.md +129 -0
  336. package/template/.agent/workflows/ideate-validate.md +117 -0
  337. package/template/.agent/workflows/ideate.md +113 -0
  338. package/template/.agent/workflows/implement-slice-setup.md +113 -0
  339. package/template/.agent/workflows/implement-slice-tdd.md +198 -0
  340. package/template/.agent/workflows/implement-slice.md +50 -0
  341. package/template/.agent/workflows/plan-phase.md +202 -0
  342. package/template/.agent/workflows/propagate-decision-apply.md +135 -0
  343. package/template/.agent/workflows/propagate-decision-scan.md +147 -0
  344. package/template/.agent/workflows/propagate-decision.md +56 -0
  345. package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
  346. package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
  347. package/template/.agent/workflows/remediate-pipeline.md +55 -0
  348. package/template/.agent/workflows/resolve-ambiguity.md +82 -0
  349. package/template/.agent/workflows/sync-kit.md +209 -0
  350. package/template/.agent/workflows/update-architecture-map.md +74 -0
  351. package/template/.agent/workflows/validate-phase.md +219 -0
  352. package/template/.agent/workflows/verify-infrastructure.md +207 -0
  353. package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
  354. package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
  355. package/template/.agent/workflows/write-architecture-spec.md +63 -0
  356. package/template/.agent/workflows/write-be-spec-classify.md +165 -0
  357. package/template/.agent/workflows/write-be-spec-write.md +98 -0
  358. package/template/.agent/workflows/write-be-spec.md +76 -0
  359. package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
  360. package/template/.agent/workflows/write-fe-spec-write.md +94 -0
  361. package/template/.agent/workflows/write-fe-spec.md +71 -0
  362. package/template/AGENTS.md +176 -0
  363. package/template/GEMINI.md +177 -0
  364. package/template/docs/README.md +187 -0
  365. package/template/docs/audits/.gitkeep +0 -0
  366. package/template/docs/audits/README.md +10 -0
  367. package/template/docs/plans/.gitkeep +0 -0
  368. package/template/docs/plans/README.md +21 -0
  369. package/template/docs/plans/be/.gitkeep +0 -0
  370. package/template/docs/plans/be/README.md +11 -0
  371. package/template/docs/plans/fe/.gitkeep +0 -0
  372. package/template/docs/plans/fe/README.md +11 -0
  373. package/template/docs/plans/ia/.gitkeep +0 -0
  374. package/template/docs/plans/ia/README.md +17 -0
  375. package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
  376. package/template/docs/plans/ia/deep-dives/README.md +5 -0
  377. package/template/docs/plans/phases/.gitkeep +0 -0
  378. package/template/docs/plans/phases/README.md +11 -0
@@ -0,0 +1,872 @@
1
+ ---
2
+ name: testing-library
3
+ description: "Comprehensive Testing Library guide for React, Vue, and Angular covering the user-centric testing philosophy, query priority (getByRole, getByLabelText, getByText), user events (userEvent over fireEvent), async utilities (waitFor, findBy), rendering patterns, testing forms and modals, accessibility-driven queries, MSW for API mocking, custom render with providers, testing hooks, and common mistakes. Use when writing component and integration tests."
4
+ version: 1.0.0
5
+ ---
6
+
7
+ # Testing Library (React / Vue / Angular)
8
+
9
+ ## 1. Philosophy
10
+
11
+ Testing Library enforces one principle: **test the way users interact with your software, not implementation details.**
12
+
13
+ Users do not know about component state, hooks, or context providers. They see text, labels, buttons, and roles. Tests should reflect that.
14
+
15
+ ```
16
+ Good: "Click the Submit button, then verify the success message appears."
17
+ Bad: "Assert that setState was called with { submitted: true }."
18
+ ```
19
+
20
+ ---
21
+
22
+ ## 2. Query Priority
23
+
24
+ Queries are ordered by how accessible they are. Use the highest-priority query that works.
25
+
26
+ ### Priority 1: Accessible to Everyone
27
+
28
+ ```typescript
29
+ // getByRole -- the BEST query. Uses ARIA roles.
30
+ screen.getByRole('button', { name: 'Submit' });
31
+ screen.getByRole('heading', { level: 2 });
32
+ screen.getByRole('textbox', { name: 'Email' });
33
+ screen.getByRole('checkbox', { name: 'Remember me' });
34
+ screen.getByRole('link', { name: 'Learn more' });
35
+ screen.getByRole('dialog', { name: 'Confirm deletion' });
36
+ screen.getByRole('tab', { selected: true });
37
+ screen.getByRole('alert');
38
+ screen.getByRole('navigation');
39
+
40
+ // getByLabelText -- form fields with proper labels
41
+ screen.getByLabelText('Email address');
42
+ screen.getByLabelText('Password');
43
+ screen.getByLabelText(/first name/i);
44
+
45
+ // getByPlaceholderText -- only if there is no label
46
+ screen.getByPlaceholderText('Search...');
47
+
48
+ // getByText -- non-interactive text content
49
+ screen.getByText('No results found');
50
+ screen.getByText(/welcome/i);
51
+
52
+ // getByDisplayValue -- current value of form elements
53
+ screen.getByDisplayValue('john@example.com');
54
+ ```
55
+
56
+ ### Priority 2: Semantic Queries
57
+
58
+ ```typescript
59
+ // getByAltText -- images
60
+ screen.getByAltText('User avatar');
61
+
62
+ // getByTitle -- title attribute (less common)
63
+ screen.getByTitle('Close');
64
+ ```
65
+
66
+ ### Priority 3: Last Resort
67
+
68
+ ```typescript
69
+ // getByTestId -- ONLY when no accessible query works
70
+ screen.getByTestId('custom-chart-widget');
71
+
72
+ // Configure the test ID attribute:
73
+ // configure({ testIdAttribute: 'data-testid' });
74
+ ```
75
+
76
+ ### Query Variants
77
+
78
+ ```typescript
79
+ // getBy -- throws if not found (synchronous, for elements that exist now)
80
+ screen.getByRole('button', { name: 'Save' });
81
+
82
+ // queryBy -- returns null if not found (for asserting absence)
83
+ expect(screen.queryByText('Error message')).not.toBeInTheDocument();
84
+
85
+ // findBy -- returns a Promise, waits for element to appear (async)
86
+ await screen.findByText('Data loaded');
87
+
88
+ // getAllBy -- returns array, throws if empty
89
+ screen.getAllByRole('listitem');
90
+
91
+ // queryAllBy -- returns array, empty if none found
92
+ screen.queryAllByRole('listitem');
93
+
94
+ // findAllBy -- returns Promise of array, waits
95
+ await screen.findAllByRole('row');
96
+ ```
97
+
98
+ ---
99
+
100
+ ## 3. User Events
101
+
102
+ ### userEvent over fireEvent
103
+
104
+ `userEvent` simulates real user behavior (focus, keyboard, mouse). `fireEvent` dispatches a single DOM event. Always prefer `userEvent`.
105
+
106
+ ```typescript
107
+ import userEvent from '@testing-library/user-event';
108
+
109
+ // ALWAYS create a user instance per test
110
+ const user = userEvent.setup();
111
+
112
+ // Click
113
+ await user.click(screen.getByRole('button', { name: 'Submit' }));
114
+
115
+ // Double click
116
+ await user.dblClick(screen.getByRole('button', { name: 'Select' }));
117
+
118
+ // Type text (includes focus, keydown, keypress, keyup per character)
119
+ await user.type(screen.getByLabelText('Email'), 'test@example.com');
120
+
121
+ // Clear then type
122
+ await user.clear(screen.getByLabelText('Search'));
123
+ await user.type(screen.getByLabelText('Search'), 'new query');
124
+
125
+ // Tab navigation
126
+ await user.tab();
127
+ expect(screen.getByLabelText('Password')).toHaveFocus();
128
+
129
+ // Keyboard shortcuts
130
+ await user.keyboard('{Enter}');
131
+ await user.keyboard('{Shift>}{A}{/Shift}'); // Shift+A
132
+ await user.keyboard('{Control>}{a}{/Control}'); // Ctrl+A
133
+
134
+ // Select dropdown option
135
+ await user.selectOptions(screen.getByRole('combobox'), 'option-value');
136
+
137
+ // Upload file
138
+ const file = new File(['content'], 'test.png', { type: 'image/png' });
139
+ await user.upload(screen.getByLabelText('Upload'), file);
140
+
141
+ // Hover
142
+ await user.hover(screen.getByText('Tooltip trigger'));
143
+ expect(screen.getByRole('tooltip')).toBeInTheDocument();
144
+ await user.unhover(screen.getByText('Tooltip trigger'));
145
+
146
+ // Clipboard
147
+ await user.copy();
148
+ await user.paste();
149
+
150
+ // Pointer (advanced)
151
+ await user.pointer({ target: element, offset: 5, keys: '[MouseLeft]' });
152
+ ```
153
+
154
+ ---
155
+
156
+ ## 4. Async Utilities
157
+
158
+ ### waitFor
159
+
160
+ ```typescript
161
+ import { waitFor } from '@testing-library/react';
162
+
163
+ // Wait for an assertion to pass (polls until timeout)
164
+ await waitFor(() => {
165
+ expect(screen.getByText('Success')).toBeInTheDocument();
166
+ });
167
+
168
+ // With options
169
+ await waitFor(
170
+ () => {
171
+ expect(mockFn).toHaveBeenCalledTimes(1);
172
+ },
173
+ {
174
+ timeout: 3000, // Max wait time (default: 1000ms)
175
+ interval: 100, // Polling interval (default: 50ms)
176
+ }
177
+ );
178
+
179
+ // waitForElementToBeRemoved
180
+ await waitForElementToBeRemoved(() => screen.queryByText('Loading...'));
181
+ ```
182
+
183
+ ### findBy (Built-in Async Queries)
184
+
185
+ ```typescript
186
+ // findBy = getBy + waitFor (returns a Promise)
187
+ const successMessage = await screen.findByText('Operation complete');
188
+ expect(successMessage).toBeInTheDocument();
189
+
190
+ // findAllBy
191
+ const rows = await screen.findAllByRole('row');
192
+ expect(rows).toHaveLength(5);
193
+ ```
194
+
195
+ ### Debugging
196
+
197
+ ```typescript
198
+ // Print the current DOM tree
199
+ screen.debug();
200
+
201
+ // Print a specific element
202
+ screen.debug(screen.getByRole('form'));
203
+
204
+ // Log testing playground URL (paste into browser to visualize)
205
+ screen.logTestingPlaygroundURL();
206
+
207
+ // Increase debug output length
208
+ screen.debug(undefined, 30000);
209
+ ```
210
+
211
+ ---
212
+
213
+ ## 5. Rendering Patterns
214
+
215
+ ### React
216
+
217
+ ```typescript
218
+ import { render, screen } from '@testing-library/react';
219
+ import userEvent from '@testing-library/user-event';
220
+ import { describe, it, expect, vi } from 'vitest';
221
+ import { Button } from './Button';
222
+
223
+ describe('Button', () => {
224
+ it('calls onClick when clicked', async () => {
225
+ const user = userEvent.setup();
226
+ const handleClick = vi.fn();
227
+ render(<Button onClick={handleClick}>Save</Button>);
228
+
229
+ await user.click(screen.getByRole('button', { name: 'Save' }));
230
+
231
+ expect(handleClick).toHaveBeenCalledTimes(1);
232
+ });
233
+
234
+ it('renders as disabled when disabled prop is true', () => {
235
+ render(<Button disabled>Save</Button>);
236
+
237
+ expect(screen.getByRole('button', { name: 'Save' })).toBeDisabled();
238
+ });
239
+ });
240
+ ```
241
+
242
+ ### Vue
243
+
244
+ ```typescript
245
+ import { render, screen } from '@testing-library/vue';
246
+ import userEvent from '@testing-library/user-event';
247
+ import Counter from './Counter.vue';
248
+
249
+ test('increments counter on click', async () => {
250
+ const user = userEvent.setup();
251
+ render(Counter, {
252
+ props: { initialCount: 0 },
253
+ });
254
+
255
+ await user.click(screen.getByRole('button', { name: 'Increment' }));
256
+
257
+ expect(screen.getByText('Count: 1')).toBeInTheDocument();
258
+ });
259
+ ```
260
+
261
+ ### Angular
262
+
263
+ ```typescript
264
+ import { render, screen } from '@testing-library/angular';
265
+ import userEvent from '@testing-library/user-event';
266
+ import { CounterComponent } from './counter.component';
267
+
268
+ test('increments counter on click', async () => {
269
+ const user = userEvent.setup();
270
+ await render(CounterComponent, {
271
+ componentProperties: { initialCount: 0 },
272
+ });
273
+
274
+ await user.click(screen.getByRole('button', { name: 'Increment' }));
275
+
276
+ expect(screen.getByText('Count: 1')).toBeInTheDocument();
277
+ });
278
+ ```
279
+
280
+ ---
281
+
282
+ ## 6. Custom Render with Providers
283
+
284
+ ```typescript
285
+ // test-utils.tsx
286
+ import { render, RenderOptions } from '@testing-library/react';
287
+ import { ReactElement } from 'react';
288
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
289
+ import { BrowserRouter } from 'react-router-dom';
290
+ import { ThemeProvider } from './theme';
291
+
292
+ function createTestQueryClient(): QueryClient {
293
+ return new QueryClient({
294
+ defaultOptions: {
295
+ queries: {
296
+ retry: false,
297
+ gcTime: 0,
298
+ },
299
+ },
300
+ });
301
+ }
302
+
303
+ interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> {
304
+ queryClient?: QueryClient;
305
+ route?: string;
306
+ }
307
+
308
+ function customRender(
309
+ ui: ReactElement,
310
+ options: CustomRenderOptions = {}
311
+ ): ReturnType<typeof render> {
312
+ const {
313
+ queryClient = createTestQueryClient(),
314
+ route = '/',
315
+ ...renderOptions
316
+ } = options;
317
+
318
+ window.history.pushState({}, 'Test', route);
319
+
320
+ function AllProviders({ children }: { children: React.ReactNode }) {
321
+ return (
322
+ <QueryClientProvider client={queryClient}>
323
+ <BrowserRouter>
324
+ <ThemeProvider>
325
+ {children}
326
+ </ThemeProvider>
327
+ </BrowserRouter>
328
+ </QueryClientProvider>
329
+ );
330
+ }
331
+
332
+ return render(ui, { wrapper: AllProviders, ...renderOptions });
333
+ }
334
+
335
+ // Re-export everything from testing-library
336
+ export * from '@testing-library/react';
337
+ export { customRender as render };
338
+ ```
339
+
340
+ Usage:
341
+
342
+ ```typescript
343
+ // Import from your test-utils instead of @testing-library/react
344
+ import { render, screen } from '../test-utils';
345
+ import { UserProfile } from './UserProfile';
346
+
347
+ test('renders user profile', async () => {
348
+ render(<UserProfile userId="123" />, { route: '/profile/123' });
349
+
350
+ expect(await screen.findByRole('heading', { name: 'User Profile' }))
351
+ .toBeInTheDocument();
352
+ });
353
+ ```
354
+
355
+ ---
356
+
357
+ ## 7. Testing Forms
358
+
359
+ ```typescript
360
+ import { render, screen, waitFor } from '../test-utils';
361
+ import userEvent from '@testing-library/user-event';
362
+ import { RegistrationForm } from './RegistrationForm';
363
+
364
+ describe('RegistrationForm', () => {
365
+ it('submits valid form data', async () => {
366
+ const user = userEvent.setup();
367
+ const onSubmit = vi.fn();
368
+ render(<RegistrationForm onSubmit={onSubmit} />);
369
+
370
+ await user.type(screen.getByLabelText('Full Name'), 'Jane Doe');
371
+ await user.type(screen.getByLabelText('Email'), 'jane@example.com');
372
+ await user.type(screen.getByLabelText('Password'), 'SecurePass123!');
373
+ await user.type(screen.getByLabelText('Confirm Password'), 'SecurePass123!');
374
+ await user.click(screen.getByRole('checkbox', { name: /terms/i }));
375
+ await user.click(screen.getByRole('button', { name: 'Register' }));
376
+
377
+ await waitFor(() => {
378
+ expect(onSubmit).toHaveBeenCalledWith({
379
+ name: 'Jane Doe',
380
+ email: 'jane@example.com',
381
+ password: 'SecurePass123!',
382
+ confirmPassword: 'SecurePass123!',
383
+ termsAccepted: true,
384
+ });
385
+ });
386
+ });
387
+
388
+ it('shows validation errors for empty required fields', async () => {
389
+ const user = userEvent.setup();
390
+ render(<RegistrationForm onSubmit={vi.fn()} />);
391
+
392
+ await user.click(screen.getByRole('button', { name: 'Register' }));
393
+
394
+ expect(await screen.findByText('Name is required')).toBeInTheDocument();
395
+ expect(screen.getByText('Email is required')).toBeInTheDocument();
396
+ });
397
+
398
+ it('shows error when passwords do not match', async () => {
399
+ const user = userEvent.setup();
400
+ render(<RegistrationForm onSubmit={vi.fn()} />);
401
+
402
+ await user.type(screen.getByLabelText('Password'), 'Password1');
403
+ await user.type(screen.getByLabelText('Confirm Password'), 'Password2');
404
+ await user.click(screen.getByRole('button', { name: 'Register' }));
405
+
406
+ expect(await screen.findByText('Passwords must match')).toBeInTheDocument();
407
+ });
408
+
409
+ it('disables submit button while submitting', async () => {
410
+ const user = userEvent.setup();
411
+ const onSubmit = vi.fn(
412
+ () => new Promise((resolve) => setTimeout(resolve, 1000))
413
+ );
414
+ render(<RegistrationForm onSubmit={onSubmit} />);
415
+
416
+ await user.type(screen.getByLabelText('Full Name'), 'Jane');
417
+ await user.type(screen.getByLabelText('Email'), 'jane@test.com');
418
+ await user.type(screen.getByLabelText('Password'), 'Pass123!');
419
+ await user.type(screen.getByLabelText('Confirm Password'), 'Pass123!');
420
+ await user.click(screen.getByRole('checkbox', { name: /terms/i }));
421
+ await user.click(screen.getByRole('button', { name: 'Register' }));
422
+
423
+ expect(screen.getByRole('button', { name: /registering/i })).toBeDisabled();
424
+ });
425
+ });
426
+ ```
427
+
428
+ ---
429
+
430
+ ## 8. Testing Modals and Dialogs
431
+
432
+ ```typescript
433
+ import { render, screen, waitForElementToBeRemoved } from '../test-utils';
434
+ import userEvent from '@testing-library/user-event';
435
+ import { ConfirmDialog } from './ConfirmDialog';
436
+
437
+ describe('ConfirmDialog', () => {
438
+ it('opens when trigger is clicked', async () => {
439
+ const user = userEvent.setup();
440
+ render(<ConfirmDialog trigger="Delete Item" onConfirm={vi.fn()} />);
441
+
442
+ // Dialog should not be in DOM initially
443
+ expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
444
+
445
+ await user.click(screen.getByRole('button', { name: 'Delete Item' }));
446
+
447
+ // Dialog should appear
448
+ expect(screen.getByRole('dialog', { name: 'Confirm Deletion' }))
449
+ .toBeInTheDocument();
450
+ });
451
+
452
+ it('calls onConfirm and closes when confirmed', async () => {
453
+ const user = userEvent.setup();
454
+ const onConfirm = vi.fn();
455
+ render(<ConfirmDialog trigger="Delete" onConfirm={onConfirm} />);
456
+
457
+ await user.click(screen.getByRole('button', { name: 'Delete' }));
458
+ await user.click(screen.getByRole('button', { name: 'Confirm' }));
459
+
460
+ expect(onConfirm).toHaveBeenCalledTimes(1);
461
+ await waitForElementToBeRemoved(() => screen.queryByRole('dialog'));
462
+ });
463
+
464
+ it('closes without calling onConfirm when cancelled', async () => {
465
+ const user = userEvent.setup();
466
+ const onConfirm = vi.fn();
467
+ render(<ConfirmDialog trigger="Delete" onConfirm={onConfirm} />);
468
+
469
+ await user.click(screen.getByRole('button', { name: 'Delete' }));
470
+ await user.click(screen.getByRole('button', { name: 'Cancel' }));
471
+
472
+ expect(onConfirm).not.toHaveBeenCalled();
473
+ await waitForElementToBeRemoved(() => screen.queryByRole('dialog'));
474
+ });
475
+
476
+ it('closes when Escape key is pressed', async () => {
477
+ const user = userEvent.setup();
478
+ render(<ConfirmDialog trigger="Delete" onConfirm={vi.fn()} />);
479
+
480
+ await user.click(screen.getByRole('button', { name: 'Delete' }));
481
+ expect(screen.getByRole('dialog')).toBeInTheDocument();
482
+
483
+ await user.keyboard('{Escape}');
484
+ await waitForElementToBeRemoved(() => screen.queryByRole('dialog'));
485
+ });
486
+
487
+ it('traps focus within the dialog', async () => {
488
+ const user = userEvent.setup();
489
+ render(<ConfirmDialog trigger="Delete" onConfirm={vi.fn()} />);
490
+
491
+ await user.click(screen.getByRole('button', { name: 'Delete' }));
492
+
493
+ // First focusable element should receive focus
494
+ expect(screen.getByRole('button', { name: 'Cancel' })).toHaveFocus();
495
+
496
+ // Tab should cycle within the dialog
497
+ await user.tab();
498
+ expect(screen.getByRole('button', { name: 'Confirm' })).toHaveFocus();
499
+
500
+ await user.tab();
501
+ expect(screen.getByRole('button', { name: 'Cancel' })).toHaveFocus();
502
+ });
503
+ });
504
+ ```
505
+
506
+ ---
507
+
508
+ ## 9. Testing Navigation and Routing
509
+
510
+ ```typescript
511
+ import { render, screen } from '../test-utils';
512
+ import userEvent from '@testing-library/user-event';
513
+ import { App } from './App';
514
+
515
+ describe('Navigation', () => {
516
+ it('navigates to profile page when link is clicked', async () => {
517
+ const user = userEvent.setup();
518
+ render(<App />, { route: '/' });
519
+
520
+ await user.click(screen.getByRole('link', { name: 'Profile' }));
521
+
522
+ expect(await screen.findByRole('heading', { name: 'Your Profile' }))
523
+ .toBeInTheDocument();
524
+ });
525
+
526
+ it('shows 404 page for unknown routes', () => {
527
+ render(<App />, { route: '/unknown-page' });
528
+
529
+ expect(screen.getByText('Page not found')).toBeInTheDocument();
530
+ });
531
+
532
+ it('redirects unauthenticated users to login', async () => {
533
+ render(<App />, { route: '/dashboard' });
534
+
535
+ // Should redirect to login
536
+ expect(await screen.findByRole('heading', { name: 'Sign In' }))
537
+ .toBeInTheDocument();
538
+ });
539
+ });
540
+ ```
541
+
542
+ ---
543
+
544
+ ## 10. MSW for API Mocking
545
+
546
+ ```typescript
547
+ // mocks/handlers.ts
548
+ import { http, HttpResponse } from 'msw';
549
+
550
+ export const handlers = [
551
+ http.get('/api/users', () => {
552
+ return HttpResponse.json([
553
+ { id: '1', name: 'Alice', email: 'alice@example.com' },
554
+ { id: '2', name: 'Bob', email: 'bob@example.com' },
555
+ ]);
556
+ }),
557
+
558
+ http.post('/api/users', async ({ request }) => {
559
+ const body = await request.json();
560
+ return HttpResponse.json(
561
+ { id: '3', ...body },
562
+ { status: 201 }
563
+ );
564
+ }),
565
+
566
+ http.delete('/api/users/:id', ({ params }) => {
567
+ return new HttpResponse(null, { status: 204 });
568
+ }),
569
+ ];
570
+
571
+ // mocks/server.ts
572
+ import { setupServer } from 'msw/node';
573
+ import { handlers } from './handlers';
574
+
575
+ export const server = setupServer(...handlers);
576
+ ```
577
+
578
+ ### Test Setup
579
+
580
+ ```typescript
581
+ // test/setup.ts
582
+ import { server } from '../mocks/server';
583
+ import { afterAll, afterEach, beforeAll } from 'vitest';
584
+
585
+ beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
586
+ afterEach(() => server.resetHandlers());
587
+ afterAll(() => server.close());
588
+ ```
589
+
590
+ ### Per-Test Overrides
591
+
592
+ ```typescript
593
+ import { http, HttpResponse } from 'msw';
594
+ import { server } from '../mocks/server';
595
+
596
+ test('shows error message when API fails', async () => {
597
+ // Override for this specific test
598
+ server.use(
599
+ http.get('/api/users', () => {
600
+ return HttpResponse.json(
601
+ { error: 'Internal Server Error' },
602
+ { status: 500 }
603
+ );
604
+ })
605
+ );
606
+
607
+ render(<UserList />);
608
+
609
+ expect(await screen.findByRole('alert'))
610
+ .toHaveTextContent('Failed to load users');
611
+ });
612
+
613
+ test('shows empty state when no users exist', async () => {
614
+ server.use(
615
+ http.get('/api/users', () => {
616
+ return HttpResponse.json([]);
617
+ })
618
+ );
619
+
620
+ render(<UserList />);
621
+
622
+ expect(await screen.findByText('No users found')).toBeInTheDocument();
623
+ });
624
+ ```
625
+
626
+ ---
627
+
628
+ ## 11. Testing Hooks
629
+
630
+ ```typescript
631
+ import { renderHook, act, waitFor } from '@testing-library/react';
632
+ import { useCounter } from './useCounter';
633
+ import { useDebounce } from './useDebounce';
634
+
635
+ describe('useCounter', () => {
636
+ it('initializes with the given value', () => {
637
+ const { result } = renderHook(() => useCounter(5));
638
+
639
+ expect(result.current.count).toBe(5);
640
+ });
641
+
642
+ it('increments the counter', () => {
643
+ const { result } = renderHook(() => useCounter(0));
644
+
645
+ act(() => {
646
+ result.current.increment();
647
+ });
648
+
649
+ expect(result.current.count).toBe(1);
650
+ });
651
+
652
+ it('resets to initial value', () => {
653
+ const { result } = renderHook(() => useCounter(0));
654
+
655
+ act(() => {
656
+ result.current.increment();
657
+ result.current.increment();
658
+ result.current.reset();
659
+ });
660
+
661
+ expect(result.current.count).toBe(0);
662
+ });
663
+ });
664
+
665
+ // Testing hooks with props that change
666
+ describe('useDebounce', () => {
667
+ it('returns debounced value after delay', async () => {
668
+ const { result, rerender } = renderHook(
669
+ ({ value, delay }) => useDebounce(value, delay),
670
+ { initialProps: { value: 'initial', delay: 300 } }
671
+ );
672
+
673
+ expect(result.current).toBe('initial');
674
+
675
+ rerender({ value: 'updated', delay: 300 });
676
+
677
+ // Value should not change immediately
678
+ expect(result.current).toBe('initial');
679
+
680
+ // Wait for debounce
681
+ await waitFor(() => {
682
+ expect(result.current).toBe('updated');
683
+ });
684
+ });
685
+ });
686
+
687
+ // Testing hooks that need providers
688
+ describe('useAuth', () => {
689
+ it('returns current user', () => {
690
+ const wrapper = ({ children }: { children: React.ReactNode }) => (
691
+ <AuthProvider user={{ id: '1', name: 'Test' }}>
692
+ {children}
693
+ </AuthProvider>
694
+ );
695
+
696
+ const { result } = renderHook(() => useAuth(), { wrapper });
697
+
698
+ expect(result.current.user).toEqual({ id: '1', name: 'Test' });
699
+ });
700
+ });
701
+ ```
702
+
703
+ ---
704
+
705
+ ## 12. Accessibility-Driven Testing
706
+
707
+ ```typescript
708
+ // Testing Library queries naturally enforce accessibility
709
+ describe('Accessible Form', () => {
710
+ it('has properly labeled inputs', () => {
711
+ render(<LoginForm />);
712
+
713
+ // These queries FAIL if labels are not properly associated
714
+ expect(screen.getByLabelText('Email')).toBeInTheDocument();
715
+ expect(screen.getByLabelText('Password')).toBeInTheDocument();
716
+ });
717
+
718
+ it('has proper ARIA roles', () => {
719
+ render(<LoginForm />);
720
+
721
+ expect(screen.getByRole('form', { name: 'Login' })).toBeInTheDocument();
722
+ expect(screen.getByRole('button', { name: 'Sign in' })).toBeInTheDocument();
723
+ });
724
+
725
+ it('announces errors to screen readers', async () => {
726
+ const user = userEvent.setup();
727
+ render(<LoginForm />);
728
+
729
+ await user.click(screen.getByRole('button', { name: 'Sign in' }));
730
+
731
+ // Error messages should have role="alert"
732
+ expect(screen.getByRole('alert')).toHaveTextContent('Email is required');
733
+ });
734
+
735
+ it('manages focus after submission error', async () => {
736
+ const user = userEvent.setup();
737
+ render(<LoginForm />);
738
+
739
+ await user.click(screen.getByRole('button', { name: 'Sign in' }));
740
+
741
+ // Focus should move to the first error field
742
+ await waitFor(() => {
743
+ expect(screen.getByLabelText('Email')).toHaveFocus();
744
+ });
745
+ });
746
+ });
747
+ ```
748
+
749
+ ---
750
+
751
+ ## 13. Common Mistakes
752
+
753
+ ### Testing Implementation Details
754
+
755
+ ```typescript
756
+ // BAD: Testing internal state
757
+ test('sets isLoading to true', () => {
758
+ const { result } = renderHook(() => useData());
759
+ expect(result.current.isLoading).toBe(true); // Implementation detail
760
+ });
761
+
762
+ // GOOD: Testing user-visible behavior
763
+ test('shows loading spinner while fetching', () => {
764
+ render(<DataList />);
765
+ expect(screen.getByRole('progressbar')).toBeInTheDocument();
766
+ });
767
+
768
+ // BAD: Testing component internals
769
+ test('calls handleSubmit', () => {
770
+ const wrapper = shallow(<Form />);
771
+ wrapper.instance().handleSubmit(); // Never do this
772
+ });
773
+
774
+ // GOOD: Testing as user would
775
+ test('submits form data', async () => {
776
+ const user = userEvent.setup();
777
+ render(<Form />);
778
+ await user.type(screen.getByLabelText('Name'), 'Test');
779
+ await user.click(screen.getByRole('button', { name: 'Submit' }));
780
+ expect(await screen.findByText('Submitted!')).toBeInTheDocument();
781
+ });
782
+ ```
783
+
784
+ ### Wrong Query Choice
785
+
786
+ ```typescript
787
+ // BAD: Using test IDs when accessible queries exist
788
+ screen.getByTestId('submit-button'); // Users do not see test IDs
789
+
790
+ // GOOD: Using role-based queries
791
+ screen.getByRole('button', { name: 'Submit' });
792
+
793
+ // BAD: Using container.querySelector
794
+ const { container } = render(<Component />);
795
+ container.querySelector('.my-class'); // CSS class is an implementation detail
796
+
797
+ // GOOD: Using semantic queries
798
+ screen.getByRole('heading', { level: 1 });
799
+ ```
800
+
801
+ ### Incorrect Async Handling
802
+
803
+ ```typescript
804
+ // BAD: No await on async operations
805
+ test('loads data', () => {
806
+ render(<DataList />);
807
+ expect(screen.getByText('Data loaded')).toBeInTheDocument(); // Race condition
808
+ });
809
+
810
+ // GOOD: Await async results
811
+ test('loads data', async () => {
812
+ render(<DataList />);
813
+ expect(await screen.findByText('Data loaded')).toBeInTheDocument();
814
+ });
815
+
816
+ // BAD: Using setTimeout to wait
817
+ test('shows toast', async () => {
818
+ render(<App />);
819
+ await new Promise((r) => setTimeout(r, 1000)); // Fragile timing
820
+ expect(screen.getByText('Saved')).toBeInTheDocument();
821
+ });
822
+
823
+ // GOOD: Using waitFor
824
+ test('shows toast', async () => {
825
+ render(<App />);
826
+ await waitFor(() => {
827
+ expect(screen.getByText('Saved')).toBeInTheDocument();
828
+ });
829
+ });
830
+ ```
831
+
832
+ ### Excessive Mocking
833
+
834
+ ```typescript
835
+ // BAD: Mocking your own components
836
+ vi.mock('./ChildComponent', () => ({
837
+ ChildComponent: () => <div>mocked</div>, // Defeats the purpose
838
+ }));
839
+
840
+ // GOOD: Render real component tree, mock external dependencies
841
+ server.use(
842
+ http.get('/api/data', () => HttpResponse.json({ items: [] }))
843
+ );
844
+ render(<ParentComponent />);
845
+ ```
846
+
847
+ ---
848
+
849
+ ## 14. Critical Reminders
850
+
851
+ ### ALWAYS
852
+
853
+ - Use `userEvent.setup()` at the start of each test (not the global import)
854
+ - Use `getByRole` as the first choice for all queries
855
+ - Use `findBy` for elements that appear asynchronously
856
+ - Use `queryBy` only when asserting something is NOT in the DOM
857
+ - Use `waitFor` for async state changes (not `setTimeout`)
858
+ - Use `screen` instead of destructuring from `render()`
859
+ - Clean up mocks and server handlers after each test
860
+ - Test loading, error, and empty states -- not just happy path
861
+ - Create a custom `render` that wraps providers once
862
+
863
+ ### NEVER
864
+
865
+ - Use `fireEvent` when `userEvent` works (userEvent simulates real behavior)
866
+ - Use `container.querySelector` or `container.innerHTML` (breaks the abstraction)
867
+ - Test CSS classes, state variables, or internal methods (implementation details)
868
+ - Use `act()` warnings as an excuse to wrap everything in `act` (find root cause)
869
+ - Use snapshot tests as a substitute for behavioral assertions
870
+ - Use `getByTestId` when a role or label query exists
871
+ - Leave `screen.debug()` in committed test code
872
+ - Use `waitFor` with side effects inside the callback (only assertions)