bmad-method 6.0.5-next.9 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/package.json +1 -1
  2. package/src/bmm/agents/analyst.agent.yaml +1 -1
  3. package/src/bmm/module-help.csv +1 -1
  4. package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +1 -1
  5. package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +1 -1
  6. package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +1 -1
  7. package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +1 -1
  8. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md +1 -1
  9. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md +1 -1
  10. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md +1 -1
  11. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md +1 -1
  12. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md +1 -1
  13. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md +1 -1
  14. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md +1 -1
  15. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md +1 -1
  16. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md +1 -1
  17. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md +1 -1
  18. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md +1 -1
  19. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md +1 -1
  20. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md +1 -1
  21. package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +1 -1
  22. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +1 -1
  23. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +2 -2
  24. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +2 -2
  25. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +2 -2
  26. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +2 -2
  27. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +2 -2
  28. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +2 -2
  29. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +2 -2
  30. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +2 -2
  31. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +2 -2
  32. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +2 -2
  33. package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +2 -2
  34. package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +2 -2
  35. package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +2 -2
  36. package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +2 -2
  37. package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +2 -2
  38. package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +2 -2
  39. package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +2 -2
  40. package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md +31 -13
  41. package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +1 -1
  42. package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +6 -2
  43. package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +1 -1
  44. package/src/bmm/workflows/3-solutioning/create-epics-and-stories/templates/epics-template.md +4 -0
  45. package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/workflow.md +0 -4
  46. package/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +1 -1
  47. package/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +1 -1
  48. package/src/bmm/workflows/generate-project-context/steps/step-02-generate.md +1 -1
  49. package/src/core/module-help.csv +2 -2
  50. package/src/core/workflows/bmad-brainstorming/SKILL.md +6 -0
  51. package/src/core/workflows/bmad-brainstorming/bmad-skill-manifest.yaml +1 -0
  52. package/src/core/workflows/{brainstorming → bmad-brainstorming}/workflow.md +2 -5
  53. package/src/core/workflows/bmad-party-mode/SKILL.md +6 -0
  54. package/src/core/workflows/bmad-party-mode/bmad-skill-manifest.yaml +1 -0
  55. package/src/core/workflows/{party-mode → bmad-party-mode}/steps/step-03-graceful-exit.md +0 -1
  56. package/src/core/workflows/{party-mode → bmad-party-mode}/workflow.md +0 -4
  57. package/tools/cli/external-official-modules.yaml +18 -18
  58. package/tools/cli/installers/lib/core/installer.js +25 -8
  59. package/tools/cli/installers/lib/ide/_base-ide.js +0 -1
  60. package/tools/cli/installers/lib/ide/_config-driven.js +9 -4
  61. package/tools/cli/installers/lib/ide/manager.js +3 -3
  62. package/tools/cli/lib/agent/compiler.js +1 -1
  63. package/.augment/code_review_guidelines.yaml +0 -231
  64. package/.coderabbit.yaml +0 -85
  65. package/.github/CODE_OF_CONDUCT.md +0 -128
  66. package/.github/FUNDING.yaml +0 -15
  67. package/.github/ISSUE_TEMPLATE/bug-report.yaml +0 -124
  68. package/.github/ISSUE_TEMPLATE/config.yaml +0 -8
  69. package/.github/ISSUE_TEMPLATE/documentation.yaml +0 -55
  70. package/.github/ISSUE_TEMPLATE/feature-request.md +0 -22
  71. package/.github/ISSUE_TEMPLATE/issue.md +0 -32
  72. package/.github/PULL_REQUEST_TEMPLATE.md +0 -13
  73. package/.github/scripts/discord-helpers.sh +0 -34
  74. package/.github/workflows/coderabbit-review.yaml +0 -22
  75. package/.github/workflows/discord.yaml +0 -90
  76. package/.github/workflows/docs.yaml +0 -64
  77. package/.github/workflows/publish.yaml +0 -133
  78. package/.github/workflows/quality.yaml +0 -116
  79. package/.husky/pre-commit +0 -20
  80. package/.markdownlint-cli2.yaml +0 -41
  81. package/.nvmrc +0 -1
  82. package/.prettierignore +0 -12
  83. package/.vscode/settings.json +0 -96
  84. package/CHANGELOG.md +0 -1785
  85. package/CNAME +0 -1
  86. package/CONTRIBUTING.md +0 -176
  87. package/CONTRIBUTORS.md +0 -32
  88. package/SECURITY.md +0 -85
  89. package/TRADEMARK.md +0 -55
  90. package/Wordmark.png +0 -0
  91. package/banner-bmad-method.png +0 -0
  92. package/docs/404.md +0 -9
  93. package/docs/_STYLE_GUIDE.md +0 -370
  94. package/docs/explanation/advanced-elicitation.md +0 -49
  95. package/docs/explanation/adversarial-review.md +0 -59
  96. package/docs/explanation/brainstorming.md +0 -33
  97. package/docs/explanation/established-projects-faq.md +0 -50
  98. package/docs/explanation/party-mode.md +0 -59
  99. package/docs/explanation/preventing-agent-conflicts.md +0 -112
  100. package/docs/explanation/project-context.md +0 -157
  101. package/docs/explanation/quick-dev-new-preview.md +0 -73
  102. package/docs/explanation/quick-flow.md +0 -77
  103. package/docs/explanation/why-solutioning-matters.md +0 -77
  104. package/docs/how-to/customize-bmad.md +0 -172
  105. package/docs/how-to/established-projects.md +0 -117
  106. package/docs/how-to/get-answers-about-bmad.md +0 -138
  107. package/docs/how-to/install-bmad.md +0 -116
  108. package/docs/how-to/non-interactive-installation.md +0 -171
  109. package/docs/how-to/project-context.md +0 -136
  110. package/docs/how-to/quick-fixes.md +0 -123
  111. package/docs/how-to/shard-large-documents.md +0 -78
  112. package/docs/how-to/upgrade-to-v6.md +0 -100
  113. package/docs/index.md +0 -60
  114. package/docs/reference/agents.md +0 -28
  115. package/docs/reference/commands.md +0 -145
  116. package/docs/reference/modules.md +0 -76
  117. package/docs/reference/testing.md +0 -106
  118. package/docs/reference/workflow-map.md +0 -89
  119. package/docs/roadmap.mdx +0 -136
  120. package/docs/tutorials/getting-started.md +0 -275
  121. package/docs/zh-cn/404.md +0 -9
  122. package/docs/zh-cn/_STYLE_GUIDE.md +0 -370
  123. package/docs/zh-cn/explanation/advanced-elicitation.md +0 -62
  124. package/docs/zh-cn/explanation/adversarial-review.md +0 -71
  125. package/docs/zh-cn/explanation/brainstorming.md +0 -43
  126. package/docs/zh-cn/explanation/established-projects-faq.md +0 -60
  127. package/docs/zh-cn/explanation/party-mode.md +0 -79
  128. package/docs/zh-cn/explanation/preventing-agent-conflicts.md +0 -137
  129. package/docs/zh-cn/explanation/project-context.md +0 -176
  130. package/docs/zh-cn/explanation/quick-flow.md +0 -93
  131. package/docs/zh-cn/explanation/why-solutioning-matters.md +0 -90
  132. package/docs/zh-cn/how-to/customize-bmad.md +0 -182
  133. package/docs/zh-cn/how-to/established-projects.md +0 -134
  134. package/docs/zh-cn/how-to/get-answers-about-bmad.md +0 -144
  135. package/docs/zh-cn/how-to/install-bmad.md +0 -105
  136. package/docs/zh-cn/how-to/non-interactive-installation.md +0 -181
  137. package/docs/zh-cn/how-to/project-context.md +0 -152
  138. package/docs/zh-cn/how-to/quick-fixes.md +0 -140
  139. package/docs/zh-cn/how-to/shard-large-documents.md +0 -86
  140. package/docs/zh-cn/how-to/upgrade-to-v6.md +0 -120
  141. package/docs/zh-cn/index.md +0 -69
  142. package/docs/zh-cn/reference/agents.md +0 -41
  143. package/docs/zh-cn/reference/commands.md +0 -166
  144. package/docs/zh-cn/reference/modules.md +0 -94
  145. package/docs/zh-cn/reference/testing.md +0 -122
  146. package/docs/zh-cn/reference/workflow-map.md +0 -104
  147. package/docs/zh-cn/roadmap.mdx +0 -152
  148. package/docs/zh-cn/tutorials/getting-started.md +0 -300
  149. package/eslint.config.mjs +0 -141
  150. package/prettier.config.mjs +0 -32
  151. package/src/core/workflows/brainstorming/bmad-skill-manifest.yaml +0 -3
  152. package/src/core/workflows/party-mode/bmad-skill-manifest.yaml +0 -3
  153. package/test/README.md +0 -295
  154. package/test/adversarial-review-tests/README.md +0 -56
  155. package/test/adversarial-review-tests/sample-content.md +0 -46
  156. package/test/adversarial-review-tests/test-cases.yaml +0 -103
  157. package/test/fixtures/agent-schema/invalid/critical-actions/actions-as-string.agent.yaml +0 -27
  158. package/test/fixtures/agent-schema/invalid/critical-actions/empty-string-in-actions.agent.yaml +0 -30
  159. package/test/fixtures/agent-schema/invalid/menu/empty-menu.agent.yaml +0 -22
  160. package/test/fixtures/agent-schema/invalid/menu/missing-menu.agent.yaml +0 -20
  161. package/test/fixtures/agent-schema/invalid/menu-commands/empty-command-target.agent.yaml +0 -25
  162. package/test/fixtures/agent-schema/invalid/menu-commands/no-command-target.agent.yaml +0 -24
  163. package/test/fixtures/agent-schema/invalid/menu-triggers/camel-case.agent.yaml +0 -25
  164. package/test/fixtures/agent-schema/invalid/menu-triggers/compound-invalid-format.agent.yaml +0 -25
  165. package/test/fixtures/agent-schema/invalid/menu-triggers/compound-mismatched-kebab.agent.yaml +0 -25
  166. package/test/fixtures/agent-schema/invalid/menu-triggers/duplicate-triggers.agent.yaml +0 -31
  167. package/test/fixtures/agent-schema/invalid/menu-triggers/empty-trigger.agent.yaml +0 -25
  168. package/test/fixtures/agent-schema/invalid/menu-triggers/leading-asterisk.agent.yaml +0 -25
  169. package/test/fixtures/agent-schema/invalid/menu-triggers/snake-case.agent.yaml +0 -25
  170. package/test/fixtures/agent-schema/invalid/menu-triggers/trigger-with-spaces.agent.yaml +0 -25
  171. package/test/fixtures/agent-schema/invalid/metadata/empty-module-string.agent.yaml +0 -26
  172. package/test/fixtures/agent-schema/invalid/metadata/empty-name.agent.yaml +0 -24
  173. package/test/fixtures/agent-schema/invalid/metadata/extra-metadata-fields.agent.yaml +0 -27
  174. package/test/fixtures/agent-schema/invalid/metadata/missing-id.agent.yaml +0 -23
  175. package/test/fixtures/agent-schema/invalid/persona/empty-principles-array.agent.yaml +0 -24
  176. package/test/fixtures/agent-schema/invalid/persona/empty-string-in-principles.agent.yaml +0 -27
  177. package/test/fixtures/agent-schema/invalid/persona/extra-persona-fields.agent.yaml +0 -27
  178. package/test/fixtures/agent-schema/invalid/persona/missing-role.agent.yaml +0 -24
  179. package/test/fixtures/agent-schema/invalid/prompts/empty-content.agent.yaml +0 -29
  180. package/test/fixtures/agent-schema/invalid/prompts/extra-prompt-fields.agent.yaml +0 -31
  181. package/test/fixtures/agent-schema/invalid/prompts/missing-content.agent.yaml +0 -28
  182. package/test/fixtures/agent-schema/invalid/prompts/missing-id.agent.yaml +0 -28
  183. package/test/fixtures/agent-schema/invalid/top-level/empty-file.agent.yaml +0 -5
  184. package/test/fixtures/agent-schema/invalid/top-level/extra-top-level-keys.agent.yaml +0 -28
  185. package/test/fixtures/agent-schema/invalid/top-level/missing-agent-key.agent.yaml +0 -11
  186. package/test/fixtures/agent-schema/invalid/yaml-errors/invalid-indentation.agent.yaml +0 -19
  187. package/test/fixtures/agent-schema/invalid/yaml-errors/malformed-yaml.agent.yaml +0 -18
  188. package/test/fixtures/agent-schema/valid/critical-actions/empty-critical-actions.agent.yaml +0 -24
  189. package/test/fixtures/agent-schema/valid/critical-actions/no-critical-actions.agent.yaml +0 -22
  190. package/test/fixtures/agent-schema/valid/critical-actions/valid-critical-actions.agent.yaml +0 -27
  191. package/test/fixtures/agent-schema/valid/menu/multiple-menu-items.agent.yaml +0 -31
  192. package/test/fixtures/agent-schema/valid/menu/single-menu-item.agent.yaml +0 -22
  193. package/test/fixtures/agent-schema/valid/menu-commands/all-command-types.agent.yaml +0 -38
  194. package/test/fixtures/agent-schema/valid/menu-commands/multiple-commands.agent.yaml +0 -23
  195. package/test/fixtures/agent-schema/valid/menu-triggers/compound-triggers.agent.yaml +0 -31
  196. package/test/fixtures/agent-schema/valid/menu-triggers/kebab-case-triggers.agent.yaml +0 -34
  197. package/test/fixtures/agent-schema/valid/metadata/core-agent-with-module.agent.yaml +0 -24
  198. package/test/fixtures/agent-schema/valid/metadata/empty-module-name-in-path.agent.yaml +0 -24
  199. package/test/fixtures/agent-schema/valid/metadata/malformed-path-treated-as-core.agent.yaml +0 -24
  200. package/test/fixtures/agent-schema/valid/metadata/module-agent-correct.agent.yaml +0 -24
  201. package/test/fixtures/agent-schema/valid/metadata/module-agent-missing-module.agent.yaml +0 -23
  202. package/test/fixtures/agent-schema/valid/metadata/wrong-module-value.agent.yaml +0 -24
  203. package/test/fixtures/agent-schema/valid/persona/complete-persona.agent.yaml +0 -24
  204. package/test/fixtures/agent-schema/valid/prompts/empty-prompts.agent.yaml +0 -24
  205. package/test/fixtures/agent-schema/valid/prompts/no-prompts.agent.yaml +0 -22
  206. package/test/fixtures/agent-schema/valid/prompts/valid-prompts-minimal.agent.yaml +0 -28
  207. package/test/fixtures/agent-schema/valid/prompts/valid-prompts-with-description.agent.yaml +0 -30
  208. package/test/fixtures/agent-schema/valid/top-level/minimal-core-agent.agent.yaml +0 -24
  209. package/test/fixtures/file-refs-csv/invalid/all-empty-workflow.csv +0 -3
  210. package/test/fixtures/file-refs-csv/invalid/empty-data.csv +0 -1
  211. package/test/fixtures/file-refs-csv/invalid/no-workflow-column.csv +0 -3
  212. package/test/fixtures/file-refs-csv/invalid/unresolvable-vars.csv +0 -3
  213. package/test/fixtures/file-refs-csv/valid/bmm-style.csv +0 -3
  214. package/test/fixtures/file-refs-csv/valid/core-style.csv +0 -3
  215. package/test/fixtures/file-refs-csv/valid/minimal.csv +0 -2
  216. package/test/test-agent-schema.js +0 -387
  217. package/test/test-cli-integration.sh +0 -159
  218. package/test/test-file-refs-csv.js +0 -133
  219. package/test/test-install-to-bmad.js +0 -154
  220. package/test/test-installation-components.js +0 -1796
  221. package/test/test-rehype-plugins.mjs +0 -1050
  222. package/test/test-workflow-path-regex.js +0 -88
  223. package/test/unit-test-schema.js +0 -133
  224. package/tools/build-docs.mjs +0 -464
  225. package/tools/docs/_prompt-external-modules-page.md +0 -59
  226. package/tools/docs/fix-refs.md +0 -91
  227. package/tools/docs/native-skills-migration-checklist.md +0 -281
  228. package/tools/fix-doc-links.js +0 -285
  229. package/tools/validate-agent-schema.js +0 -110
  230. package/tools/validate-doc-links.js +0 -407
  231. package/tools/validate-file-refs.js +0 -556
  232. package/website/README.md +0 -75
  233. package/website/astro.config.mjs +0 -157
  234. package/website/public/diagrams/quick-dev-diagram.png +0 -0
  235. package/website/public/favicon.ico +0 -0
  236. package/website/public/img/bmad-dark.png +0 -0
  237. package/website/public/img/bmad-light.png +0 -0
  238. package/website/public/workflow-map-diagram.html +0 -361
  239. package/website/src/components/Banner.astro +0 -62
  240. package/website/src/components/Header.astro +0 -96
  241. package/website/src/components/MobileMenuFooter.astro +0 -33
  242. package/website/src/content/config.ts +0 -7
  243. package/website/src/content/i18n/zh-CN.json +0 -28
  244. package/website/src/lib/site-url.mjs +0 -25
  245. package/website/src/pages/404.astro +0 -11
  246. package/website/src/pages/robots.txt.ts +0 -48
  247. package/website/src/rehype-base-paths.js +0 -112
  248. package/website/src/rehype-markdown-links.js +0 -119
  249. package/website/src/styles/custom.css +0 -805
  250. /package/src/core/workflows/{brainstorming → bmad-brainstorming}/brain-methods.csv +0 -0
  251. /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-01-session-setup.md +0 -0
  252. /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-01b-continue.md +0 -0
  253. /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-02a-user-selected.md +0 -0
  254. /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-02b-ai-recommended.md +0 -0
  255. /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-02c-random-selection.md +0 -0
  256. /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-02d-progressive-flow.md +0 -0
  257. /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-03-technique-execution.md +0 -0
  258. /package/src/core/workflows/{brainstorming → bmad-brainstorming}/steps/step-04-idea-organization.md +0 -0
  259. /package/src/core/workflows/{brainstorming → bmad-brainstorming}/template.md +0 -0
  260. /package/src/core/workflows/{party-mode → bmad-party-mode}/steps/step-01-agent-loading.md +0 -0
  261. /package/src/core/workflows/{party-mode → bmad-party-mode}/steps/step-02-discussion-orchestration.md +0 -0
@@ -1,387 +0,0 @@
1
- /**
2
- * Agent Schema Validation Test Runner
3
- *
4
- * Runs all test fixtures and verifies expected outcomes.
5
- * Reports pass/fail for each test and overall coverage statistics.
6
- *
7
- * Usage: node test/test-agent-schema.js
8
- * Exit codes: 0 = all tests pass, 1 = test failures
9
- */
10
-
11
- const fs = require('node:fs');
12
- const path = require('node:path');
13
- const yaml = require('yaml');
14
- const { validateAgentFile } = require('../tools/schema/agent.js');
15
- const { glob } = require('glob');
16
-
17
- // ANSI color codes
18
- const colors = {
19
- reset: '\u001B[0m',
20
- green: '\u001B[32m',
21
- red: '\u001B[31m',
22
- yellow: '\u001B[33m',
23
- blue: '\u001B[34m',
24
- cyan: '\u001B[36m',
25
- dim: '\u001B[2m',
26
- };
27
-
28
- /**
29
- * Parse test metadata from YAML comments
30
- * @param {string} filePath
31
- * @returns {{shouldPass: boolean, errorExpectation?: object, pathContext?: string}}
32
- */
33
- function parseTestMetadata(filePath) {
34
- const content = fs.readFileSync(filePath, 'utf8');
35
- const lines = content.split('\n');
36
-
37
- let shouldPass = true;
38
- let pathContext = null;
39
- const errorExpectation = {};
40
-
41
- for (const line of lines) {
42
- if (line.includes('Expected: PASS')) {
43
- shouldPass = true;
44
- } else if (line.includes('Expected: FAIL')) {
45
- shouldPass = false;
46
- }
47
-
48
- // Parse error metadata
49
- const codeMatch = line.match(/^# Error code: (.+)$/);
50
- if (codeMatch) {
51
- errorExpectation.code = codeMatch[1].trim();
52
- }
53
-
54
- const pathMatch = line.match(/^# Error path: (.+)$/);
55
- if (pathMatch) {
56
- errorExpectation.path = pathMatch[1].trim();
57
- }
58
-
59
- const messageMatch = line.match(/^# Error message: (.+)$/);
60
- if (messageMatch) {
61
- errorExpectation.message = messageMatch[1].trim();
62
- }
63
-
64
- const minimumMatch = line.match(/^# Error minimum: (\d+)$/);
65
- if (minimumMatch) {
66
- errorExpectation.minimum = parseInt(minimumMatch[1], 10);
67
- }
68
-
69
- const expectedMatch = line.match(/^# Error expected: (.+)$/);
70
- if (expectedMatch) {
71
- errorExpectation.expected = expectedMatch[1].trim();
72
- }
73
-
74
- const receivedMatch = line.match(/^# Error received: (.+)$/);
75
- if (receivedMatch) {
76
- errorExpectation.received = receivedMatch[1].trim();
77
- }
78
-
79
- const keysMatch = line.match(/^# Error keys: \[(.+)\]$/);
80
- if (keysMatch) {
81
- errorExpectation.keys = keysMatch[1].split(',').map((k) => k.trim().replaceAll(/['"]/g, ''));
82
- }
83
-
84
- const contextMatch = line.match(/^# Path context: (.+)$/);
85
- if (contextMatch) {
86
- pathContext = contextMatch[1].trim();
87
- }
88
- }
89
-
90
- return {
91
- shouldPass,
92
- errorExpectation: Object.keys(errorExpectation).length > 0 ? errorExpectation : null,
93
- pathContext,
94
- };
95
- }
96
-
97
- /**
98
- * Convert dot-notation path string to array (handles array indices)
99
- * e.g., "agent.menu[0].trigger" => ["agent", "menu", 0, "trigger"]
100
- */
101
- function parsePathString(pathString) {
102
- return pathString
103
- .replaceAll(/\[(\d+)\]/g, '.$1') // Convert [0] to .0
104
- .split('.')
105
- .map((part) => {
106
- const num = parseInt(part, 10);
107
- return isNaN(num) ? part : num;
108
- });
109
- }
110
-
111
- /**
112
- * Validate error against expectations
113
- * @param {object} error - Zod error issue
114
- * @param {object} expectation - Expected error structure
115
- * @returns {{valid: boolean, reason?: string}}
116
- */
117
- function validateError(error, expectation) {
118
- // Check error code
119
- if (expectation.code && error.code !== expectation.code) {
120
- return { valid: false, reason: `Expected code "${expectation.code}", got "${error.code}"` };
121
- }
122
-
123
- // Check error path
124
- if (expectation.path) {
125
- const expectedPath = parsePathString(expectation.path);
126
- const actualPath = error.path;
127
-
128
- if (JSON.stringify(expectedPath) !== JSON.stringify(actualPath)) {
129
- return {
130
- valid: false,
131
- reason: `Expected path ${JSON.stringify(expectedPath)}, got ${JSON.stringify(actualPath)}`,
132
- };
133
- }
134
- }
135
-
136
- // For custom errors, strictly check message
137
- if (expectation.code === 'custom' && expectation.message && error.message !== expectation.message) {
138
- return {
139
- valid: false,
140
- reason: `Expected message "${expectation.message}", got "${error.message}"`,
141
- };
142
- }
143
-
144
- // For Zod errors, check type-specific fields
145
- if (expectation.minimum !== undefined && error.minimum !== expectation.minimum) {
146
- return { valid: false, reason: `Expected minimum ${expectation.minimum}, got ${error.minimum}` };
147
- }
148
-
149
- if (expectation.expected && error.expected !== expectation.expected) {
150
- return { valid: false, reason: `Expected type "${expectation.expected}", got "${error.expected}"` };
151
- }
152
-
153
- if (expectation.received && error.received !== expectation.received) {
154
- return { valid: false, reason: `Expected received "${expectation.received}", got "${error.received}"` };
155
- }
156
-
157
- if (expectation.keys) {
158
- const expectedKeys = expectation.keys.sort();
159
- const actualKeys = (error.keys || []).sort();
160
- if (JSON.stringify(expectedKeys) !== JSON.stringify(actualKeys)) {
161
- return {
162
- valid: false,
163
- reason: `Expected keys ${JSON.stringify(expectedKeys)}, got ${JSON.stringify(actualKeys)}`,
164
- };
165
- }
166
- }
167
-
168
- return { valid: true };
169
- }
170
-
171
- /**
172
- * Run a single test case
173
- * @param {string} filePath
174
- * @returns {{passed: boolean, message: string}}
175
- */
176
- function runTest(filePath) {
177
- const metadata = parseTestMetadata(filePath);
178
- const { shouldPass, errorExpectation, pathContext } = metadata;
179
-
180
- try {
181
- const fileContent = fs.readFileSync(filePath, 'utf8');
182
- let agentData;
183
-
184
- try {
185
- agentData = yaml.parse(fileContent);
186
- } catch (parseError) {
187
- // YAML parse error
188
- if (shouldPass) {
189
- return {
190
- passed: false,
191
- message: `Expected PASS but got YAML parse error: ${parseError.message}`,
192
- };
193
- }
194
- return {
195
- passed: true,
196
- message: 'Got expected YAML parse error',
197
- };
198
- }
199
-
200
- // Determine validation path
201
- // If pathContext is specified in comments, use it; otherwise derive from fixture location
202
- let validationPath = pathContext;
203
- if (!validationPath) {
204
- // Map fixture location to simulated src/ path
205
- const relativePath = path.relative(path.join(__dirname, 'fixtures/agent-schema'), filePath);
206
- const parts = relativePath.split(path.sep);
207
-
208
- if (parts.includes('metadata') && parts[0] === 'valid') {
209
- // Valid metadata tests: check if filename suggests module or core
210
- const filename = path.basename(filePath);
211
- if (filename.includes('module')) {
212
- validationPath = 'src/bmm/agents/test.agent.yaml';
213
- } else {
214
- validationPath = 'src/core/agents/test.agent.yaml';
215
- }
216
- } else if (parts.includes('metadata') && parts[0] === 'invalid') {
217
- // Invalid metadata tests: derive from filename
218
- const filename = path.basename(filePath);
219
- if (filename.includes('module') || filename.includes('wrong-module')) {
220
- validationPath = 'src/bmm/agents/test.agent.yaml';
221
- } else if (filename.includes('core')) {
222
- validationPath = 'src/core/agents/test.agent.yaml';
223
- } else {
224
- validationPath = 'src/core/agents/test.agent.yaml';
225
- }
226
- } else {
227
- // Default to core agent path
228
- validationPath = 'src/core/agents/test.agent.yaml';
229
- }
230
- }
231
-
232
- const result = validateAgentFile(validationPath, agentData);
233
-
234
- if (result.success && shouldPass) {
235
- return {
236
- passed: true,
237
- message: 'Validation passed as expected',
238
- };
239
- }
240
-
241
- if (!result.success && !shouldPass) {
242
- const actualError = result.error.issues[0];
243
-
244
- // If we have error expectations, validate strictly
245
- if (errorExpectation) {
246
- const validation = validateError(actualError, errorExpectation);
247
-
248
- if (!validation.valid) {
249
- return {
250
- passed: false,
251
- message: `Error validation failed: ${validation.reason}`,
252
- };
253
- }
254
-
255
- return {
256
- passed: true,
257
- message: `Got expected error (${errorExpectation.code}): ${actualError.message}`,
258
- };
259
- }
260
-
261
- // No specific expectations - just check that it failed
262
- return {
263
- passed: true,
264
- message: `Got expected validation error: ${actualError?.message}`,
265
- };
266
- }
267
-
268
- if (result.success && !shouldPass) {
269
- return {
270
- passed: false,
271
- message: 'Expected validation to FAIL but it PASSED',
272
- };
273
- }
274
-
275
- if (!result.success && shouldPass) {
276
- return {
277
- passed: false,
278
- message: `Expected validation to PASS but it FAILED: ${result.error.issues[0]?.message}`,
279
- };
280
- }
281
-
282
- return {
283
- passed: false,
284
- message: 'Unexpected test state',
285
- };
286
- } catch (error) {
287
- return {
288
- passed: false,
289
- message: `Test execution error: ${error.message}`,
290
- };
291
- }
292
- }
293
-
294
- /**
295
- * Main test runner
296
- */
297
- async function main() {
298
- console.log(`${colors.cyan}╔═══════════════════════════════════════════════════════════╗${colors.reset}`);
299
- console.log(`${colors.cyan}║ Agent Schema Validation Test Suite ║${colors.reset}`);
300
- console.log(`${colors.cyan}╚═══════════════════════════════════════════════════════════╝${colors.reset}\n`);
301
-
302
- // Find all test fixtures
303
- const testFiles = await glob('test/fixtures/agent-schema/**/*.agent.yaml', {
304
- cwd: path.join(__dirname, '..'),
305
- absolute: true,
306
- });
307
-
308
- if (testFiles.length === 0) {
309
- console.log(`${colors.yellow}⚠️ No test fixtures found${colors.reset}`);
310
- process.exit(0);
311
- }
312
-
313
- console.log(`Found ${colors.cyan}${testFiles.length}${colors.reset} test fixture(s)\n`);
314
-
315
- // Group tests by category
316
- const categories = {};
317
- for (const testFile of testFiles) {
318
- const relativePath = path.relative(path.join(__dirname, 'fixtures/agent-schema'), testFile);
319
- const parts = relativePath.split(path.sep);
320
- const validInvalid = parts[0]; // 'valid' or 'invalid'
321
- const category = parts[1]; // 'top-level', 'metadata', etc.
322
-
323
- const categoryKey = `${validInvalid}/${category}`;
324
- if (!categories[categoryKey]) {
325
- categories[categoryKey] = [];
326
- }
327
- categories[categoryKey].push(testFile);
328
- }
329
-
330
- // Run tests by category
331
- let totalTests = 0;
332
- let passedTests = 0;
333
- const failures = [];
334
-
335
- for (const [categoryKey, files] of Object.entries(categories).sort()) {
336
- const [validInvalid, category] = categoryKey.split('/');
337
- const categoryLabel = category.replaceAll('-', ' ').toUpperCase();
338
- const validLabel = validInvalid === 'valid' ? '✅' : '❌';
339
-
340
- console.log(`${colors.blue}${validLabel} ${categoryLabel} (${validInvalid})${colors.reset}`);
341
-
342
- for (const testFile of files) {
343
- totalTests++;
344
- const testName = path.basename(testFile, '.agent.yaml');
345
- const result = runTest(testFile);
346
-
347
- if (result.passed) {
348
- passedTests++;
349
- console.log(` ${colors.green}✓${colors.reset} ${testName} ${colors.dim}${result.message}${colors.reset}`);
350
- } else {
351
- console.log(` ${colors.red}✗${colors.reset} ${testName} ${colors.red}${result.message}${colors.reset}`);
352
- failures.push({
353
- file: path.relative(process.cwd(), testFile),
354
- message: result.message,
355
- });
356
- }
357
- }
358
- console.log('');
359
- }
360
-
361
- // Summary
362
- console.log(`${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}`);
363
- console.log(`${colors.cyan}Test Results:${colors.reset}`);
364
- console.log(` Total: ${totalTests}`);
365
- console.log(` Passed: ${colors.green}${passedTests}${colors.reset}`);
366
- console.log(` Failed: ${passedTests === totalTests ? colors.green : colors.red}${totalTests - passedTests}${colors.reset}`);
367
- console.log(`${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}\n`);
368
-
369
- // Report failures
370
- if (failures.length > 0) {
371
- console.log(`${colors.red}❌ FAILED TESTS:${colors.reset}\n`);
372
- for (const failure of failures) {
373
- console.log(`${colors.red}✗${colors.reset} ${failure.file}`);
374
- console.log(` ${failure.message}\n`);
375
- }
376
- process.exit(1);
377
- }
378
-
379
- console.log(`${colors.green}✨ All tests passed!${colors.reset}\n`);
380
- process.exit(0);
381
- }
382
-
383
- // Run
384
- main().catch((error) => {
385
- console.error(`${colors.red}Fatal error:${colors.reset}`, error);
386
- process.exit(1);
387
- });
@@ -1,159 +0,0 @@
1
- #!/bin/bash
2
- # CLI Integration Tests for Agent Schema Validator
3
- # Tests the CLI wrapper (tools/validate-agent-schema.js) behavior and error handling
4
- # NOTE: Tests CLI functionality using temporary test fixtures
5
-
6
- echo "========================================"
7
- echo "CLI Integration Tests"
8
- echo "========================================"
9
- echo ""
10
-
11
- # Colors
12
- GREEN='\033[0;32m'
13
- RED='\033[0;31m'
14
- YELLOW='\033[1;33m'
15
- NC='\033[0m' # No Color
16
-
17
- PASSED=0
18
- FAILED=0
19
-
20
- # Get the repo root (assuming script is in test/ directory)
21
- REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
22
-
23
- # Create temp directory for test fixtures
24
- TEMP_DIR=$(mktemp -d)
25
- cleanup() {
26
- rm -rf "$TEMP_DIR"
27
- }
28
- trap cleanup EXIT
29
-
30
- # Test 1: CLI fails when no files found (exit 1)
31
- echo "Test 1: CLI fails when no agent files found (should exit 1)"
32
- mkdir -p "$TEMP_DIR/empty/src/core/agents"
33
- OUTPUT=$(node "$REPO_ROOT/tools/validate-agent-schema.js" "$TEMP_DIR/empty" 2>&1)
34
- EXIT_CODE=$?
35
- if [ $EXIT_CODE -eq 1 ] && echo "$OUTPUT" | grep -q "No agent files found"; then
36
- echo -e "${GREEN}✓${NC} CLI fails correctly when no files found (exit 1)"
37
- PASSED=$((PASSED + 1))
38
- else
39
- echo -e "${RED}✗${NC} CLI failed to handle no files properly (exit code: $EXIT_CODE)"
40
- FAILED=$((FAILED + 1))
41
- fi
42
- echo ""
43
-
44
- # Test 2: CLI reports validation errors with exit code 1
45
- echo "Test 2: CLI reports validation errors (should exit 1)"
46
- mkdir -p "$TEMP_DIR/invalid/src/core/agents"
47
- cat > "$TEMP_DIR/invalid/src/core/agents/bad.agent.yaml" << 'EOF'
48
- agent:
49
- metadata:
50
- id: bad
51
- name: Bad
52
- title: Bad
53
- icon: 🧪
54
- persona:
55
- role: Test
56
- identity: Test
57
- communication_style: Test
58
- principles: []
59
- menu: []
60
- EOF
61
- OUTPUT=$(node "$REPO_ROOT/tools/validate-agent-schema.js" "$TEMP_DIR/invalid" 2>&1)
62
- EXIT_CODE=$?
63
- if [ $EXIT_CODE -eq 1 ] && echo "$OUTPUT" | grep -q "failed validation"; then
64
- echo -e "${GREEN}✓${NC} CLI reports errors correctly (exit 1)"
65
- PASSED=$((PASSED + 1))
66
- else
67
- echo -e "${RED}✗${NC} CLI failed to report errors (exit code: $EXIT_CODE)"
68
- FAILED=$((FAILED + 1))
69
- fi
70
- echo ""
71
-
72
- # Test 3: CLI discovers and counts agent files correctly
73
- echo "Test 3: CLI discovers and counts agent files"
74
- mkdir -p "$TEMP_DIR/valid/src/core/agents"
75
- cat > "$TEMP_DIR/valid/src/core/agents/test1.agent.yaml" << 'EOF'
76
- agent:
77
- metadata:
78
- id: test1
79
- name: Test1
80
- title: Test1
81
- icon: 🧪
82
- persona:
83
- role: Test
84
- identity: Test
85
- communication_style: Test
86
- principles: [Test]
87
- menu:
88
- - trigger: help
89
- description: Help
90
- action: help
91
- EOF
92
- cat > "$TEMP_DIR/valid/src/core/agents/test2.agent.yaml" << 'EOF'
93
- agent:
94
- metadata:
95
- id: test2
96
- name: Test2
97
- title: Test2
98
- icon: 🧪
99
- persona:
100
- role: Test
101
- identity: Test
102
- communication_style: Test
103
- principles: [Test]
104
- menu:
105
- - trigger: help
106
- description: Help
107
- action: help
108
- EOF
109
- OUTPUT=$(node "$REPO_ROOT/tools/validate-agent-schema.js" "$TEMP_DIR/valid" 2>&1)
110
- EXIT_CODE=$?
111
- if [ $EXIT_CODE -eq 0 ] && echo "$OUTPUT" | grep -q "Found 2 agent file"; then
112
- echo -e "${GREEN}✓${NC} CLI discovers and counts files correctly"
113
- PASSED=$((PASSED + 1))
114
- else
115
- echo -e "${RED}✗${NC} CLI file discovery failed"
116
- echo "Output: $OUTPUT"
117
- FAILED=$((FAILED + 1))
118
- fi
119
- echo ""
120
-
121
- # Test 4: CLI provides detailed error messages
122
- echo "Test 4: CLI provides detailed error messages"
123
- OUTPUT=$(node "$REPO_ROOT/tools/validate-agent-schema.js" "$TEMP_DIR/invalid" 2>&1)
124
- if echo "$OUTPUT" | grep -q "Path:" && echo "$OUTPUT" | grep -q "Error:"; then
125
- echo -e "${GREEN}✓${NC} CLI provides error details (Path and Error)"
126
- PASSED=$((PASSED + 1))
127
- else
128
- echo -e "${RED}✗${NC} CLI error details missing"
129
- FAILED=$((FAILED + 1))
130
- fi
131
- echo ""
132
-
133
- # Test 5: CLI validates real BMAD agents (smoke test)
134
- echo "Test 5: CLI validates actual BMAD agents (smoke test)"
135
- OUTPUT=$(node "$REPO_ROOT/tools/validate-agent-schema.js" 2>&1)
136
- EXIT_CODE=$?
137
- if [ $EXIT_CODE -eq 0 ] && echo "$OUTPUT" | grep -qE "Found [0-9]+ agent file"; then
138
- echo -e "${GREEN}✓${NC} CLI validates real BMAD agents successfully"
139
- PASSED=$((PASSED + 1))
140
- else
141
- echo -e "${RED}✗${NC} CLI failed on real BMAD agents (exit code: $EXIT_CODE)"
142
- FAILED=$((FAILED + 1))
143
- fi
144
- echo ""
145
-
146
- # Summary
147
- echo "========================================"
148
- echo "Test Results:"
149
- echo " Passed: ${GREEN}$PASSED${NC}"
150
- echo " Failed: ${RED}$FAILED${NC}"
151
- echo "========================================"
152
-
153
- if [ $FAILED -eq 0 ]; then
154
- echo -e "\n${GREEN}✨ All CLI integration tests passed!${NC}\n"
155
- exit 0
156
- else
157
- echo -e "\n${RED}❌ Some CLI integration tests failed${NC}\n"
158
- exit 1
159
- fi
@@ -1,133 +0,0 @@
1
- /**
2
- * CSV File Reference Extraction Test Runner
3
- *
4
- * Tests extractCsvRefs() from validate-file-refs.js against fixtures.
5
- * Verifies correct extraction of workflow-file references from CSV files.
6
- *
7
- * Usage: node test/test-file-refs-csv.js
8
- * Exit codes: 0 = all tests pass, 1 = test failures
9
- */
10
-
11
- const fs = require('node:fs');
12
- const path = require('node:path');
13
- const { extractCsvRefs } = require('../tools/validate-file-refs.js');
14
-
15
- // ANSI color codes
16
- const colors = {
17
- reset: '\u001B[0m',
18
- green: '\u001B[32m',
19
- red: '\u001B[31m',
20
- cyan: '\u001B[36m',
21
- dim: '\u001B[2m',
22
- };
23
-
24
- const FIXTURES = path.join(__dirname, 'fixtures/file-refs-csv');
25
-
26
- let totalTests = 0;
27
- let passedTests = 0;
28
- const failures = [];
29
-
30
- function test(name, fn) {
31
- totalTests++;
32
- try {
33
- fn();
34
- passedTests++;
35
- console.log(` ${colors.green}\u2713${colors.reset} ${name}`);
36
- } catch (error) {
37
- console.log(` ${colors.red}\u2717${colors.reset} ${name} ${colors.red}${error.message}${colors.reset}`);
38
- failures.push({ name, message: error.message });
39
- }
40
- }
41
-
42
- function assert(condition, message) {
43
- if (!condition) throw new Error(message);
44
- }
45
-
46
- function loadFixture(relativePath) {
47
- const fullPath = path.join(FIXTURES, relativePath);
48
- const content = fs.readFileSync(fullPath, 'utf-8');
49
- return { fullPath, content };
50
- }
51
-
52
- // --- Valid fixtures ---
53
-
54
- console.log(`\n${colors.cyan}CSV File Reference Extraction Tests${colors.reset}\n`);
55
- console.log(`${colors.cyan}Valid fixtures${colors.reset}`);
56
-
57
- test('bmm-style.csv: extracts workflow-file refs with trailing commas', () => {
58
- const { fullPath, content } = loadFixture('valid/bmm-style.csv');
59
- const refs = extractCsvRefs(fullPath, content);
60
- assert(refs.length === 2, `Expected 2 refs, got ${refs.length}`);
61
- assert(refs[0].raw === '_bmad/bmm/workflows/document-project/workflow.md', `Wrong raw[0]: ${refs[0].raw}`);
62
- assert(refs[1].raw === '_bmad/core/workflows/brainstorming/workflow.md', `Wrong raw[1]: ${refs[1].raw}`);
63
- assert(refs[0].type === 'project-root', `Wrong type: ${refs[0].type}`);
64
- assert(refs[0].line === 2, `Wrong line for row 0: ${refs[0].line}`);
65
- assert(refs[1].line === 3, `Wrong line for row 1: ${refs[1].line}`);
66
- assert(refs[0].file === fullPath, 'Wrong file path');
67
- });
68
-
69
- test('core-style.csv: extracts refs from core module-help format', () => {
70
- const { fullPath, content } = loadFixture('valid/core-style.csv');
71
- const refs = extractCsvRefs(fullPath, content);
72
- assert(refs.length === 2, `Expected 2 refs, got ${refs.length}`);
73
- assert(refs[0].raw === '_bmad/core/workflows/brainstorming/workflow.md', `Wrong raw[0]: ${refs[0].raw}`);
74
- assert(refs[1].raw === '_bmad/core/workflows/party-mode/workflow.md', `Wrong raw[1]: ${refs[1].raw}`);
75
- });
76
-
77
- test('minimal.csv: extracts refs from minimal 3-column CSV', () => {
78
- const { fullPath, content } = loadFixture('valid/minimal.csv');
79
- const refs = extractCsvRefs(fullPath, content);
80
- assert(refs.length === 1, `Expected 1 ref, got ${refs.length}`);
81
- assert(refs[0].raw === '_bmad/core/tasks/help.md', `Wrong raw: ${refs[0].raw}`);
82
- assert(refs[0].line === 2, `Wrong line: ${refs[0].line}`);
83
- });
84
-
85
- // --- Invalid fixtures ---
86
-
87
- console.log(`\n${colors.cyan}Invalid fixtures (expect 0 refs)${colors.reset}`);
88
-
89
- test('no-workflow-column.csv: returns 0 refs when workflow-file column missing', () => {
90
- const { fullPath, content } = loadFixture('invalid/no-workflow-column.csv');
91
- const refs = extractCsvRefs(fullPath, content);
92
- assert(refs.length === 0, `Expected 0 refs, got ${refs.length}`);
93
- });
94
-
95
- test('empty-data.csv: returns 0 refs when CSV has header only', () => {
96
- const { fullPath, content } = loadFixture('invalid/empty-data.csv');
97
- const refs = extractCsvRefs(fullPath, content);
98
- assert(refs.length === 0, `Expected 0 refs, got ${refs.length}`);
99
- });
100
-
101
- test('all-empty-workflow.csv: returns 0 refs when all workflow-file cells empty', () => {
102
- const { fullPath, content } = loadFixture('invalid/all-empty-workflow.csv');
103
- const refs = extractCsvRefs(fullPath, content);
104
- assert(refs.length === 0, `Expected 0 refs, got ${refs.length}`);
105
- });
106
-
107
- test('unresolvable-vars.csv: filters out template variables, keeps normal refs', () => {
108
- const { fullPath, content } = loadFixture('invalid/unresolvable-vars.csv');
109
- const refs = extractCsvRefs(fullPath, content);
110
- assert(refs.length === 1, `Expected 1 ref, got ${refs.length}`);
111
- assert(refs[0].raw === '_bmad/core/tasks/help.md', `Wrong raw: ${refs[0].raw}`);
112
- });
113
-
114
- // --- Summary ---
115
-
116
- console.log(`\n${colors.cyan}${'═'.repeat(55)}${colors.reset}`);
117
- console.log(`${colors.cyan}Test Results:${colors.reset}`);
118
- console.log(` Total: ${totalTests}`);
119
- console.log(` Passed: ${colors.green}${passedTests}${colors.reset}`);
120
- console.log(` Failed: ${passedTests === totalTests ? colors.green : colors.red}${totalTests - passedTests}${colors.reset}`);
121
- console.log(`${colors.cyan}${'═'.repeat(55)}${colors.reset}\n`);
122
-
123
- if (failures.length > 0) {
124
- console.log(`${colors.red}FAILED TESTS:${colors.reset}\n`);
125
- for (const failure of failures) {
126
- console.log(`${colors.red}\u2717${colors.reset} ${failure.name}`);
127
- console.log(` ${failure.message}\n`);
128
- }
129
- process.exit(1);
130
- }
131
-
132
- console.log(`${colors.green}All tests passed!${colors.reset}\n`);
133
- process.exit(0);