eslint-plugin-traceability 1.23.0 → 1.24.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 (247) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/lib/{src/rules → rules}/require-traceability.js +49 -4
  3. package/package.json +8 -8
  4. package/user-docs/api-reference.md +25 -0
  5. package/lib/tests/cli-error-handling.test.d.ts +0 -1
  6. package/lib/tests/cli-error-handling.test.js +0 -54
  7. package/lib/tests/config/eslint-config-validation.test.d.ts +0 -9
  8. package/lib/tests/config/eslint-config-validation.test.js +0 -101
  9. package/lib/tests/config/flat-config-presets-integration.test.d.ts +0 -1
  10. package/lib/tests/config/flat-config-presets-integration.test.js +0 -76
  11. package/lib/tests/config/require-story-annotation-config.test.d.ts +0 -10
  12. package/lib/tests/config/require-story-annotation-config.test.js +0 -26
  13. package/lib/tests/fixtures/stale/example.d.ts +0 -0
  14. package/lib/tests/fixtures/stale/example.js +0 -4
  15. package/lib/tests/fixtures/update/example.d.ts +0 -0
  16. package/lib/tests/fixtures/update/example.js +0 -4
  17. package/lib/tests/fixtures/valid-annotations/example.d.ts +0 -0
  18. package/lib/tests/fixtures/valid-annotations/example.js +0 -3
  19. package/lib/tests/integration/annotation-placement-inside-prettier.integration.test.d.ts +0 -1
  20. package/lib/tests/integration/annotation-placement-inside-prettier.integration.test.js +0 -133
  21. package/lib/tests/integration/catch-annotation-prettier.integration.test.d.ts +0 -1
  22. package/lib/tests/integration/catch-annotation-prettier.integration.test.js +0 -121
  23. package/lib/tests/integration/cli-integration.test.d.ts +0 -1
  24. package/lib/tests/integration/cli-integration.test.js +0 -96
  25. package/lib/tests/integration/else-if-annotation-prettier.integration.test.d.ts +0 -1
  26. package/lib/tests/integration/else-if-annotation-prettier.integration.test.js +0 -100
  27. package/lib/tests/integration/no-redundant-annotation.integration.test.d.ts +0 -1
  28. package/lib/tests/integration/no-redundant-annotation.integration.test.js +0 -129
  29. package/lib/tests/integration/prettier-test-helpers.d.ts +0 -9
  30. package/lib/tests/integration/prettier-test-helpers.js +0 -35
  31. package/lib/tests/integration/require-traceability-aliases.integration.test.d.ts +0 -1
  32. package/lib/tests/integration/require-traceability-aliases.integration.test.js +0 -152
  33. package/lib/tests/integration/require-traceability-test-callbacks.integration.test.d.ts +0 -1
  34. package/lib/tests/integration/require-traceability-test-callbacks.integration.test.js +0 -149
  35. package/lib/tests/maintenance/batch.test.d.ts +0 -1
  36. package/lib/tests/maintenance/batch.test.js +0 -80
  37. package/lib/tests/maintenance/cli.test.d.ts +0 -1
  38. package/lib/tests/maintenance/cli.test.js +0 -306
  39. package/lib/tests/maintenance/detect-isolated.test.d.ts +0 -1
  40. package/lib/tests/maintenance/detect-isolated.test.js +0 -187
  41. package/lib/tests/maintenance/detect.test.d.ts +0 -1
  42. package/lib/tests/maintenance/detect.test.js +0 -46
  43. package/lib/tests/maintenance/index.test.d.ts +0 -1
  44. package/lib/tests/maintenance/index.test.js +0 -26
  45. package/lib/tests/maintenance/report.test.d.ts +0 -1
  46. package/lib/tests/maintenance/report.test.js +0 -68
  47. package/lib/tests/maintenance/storyParser.test.d.ts +0 -8
  48. package/lib/tests/maintenance/storyParser.test.js +0 -505
  49. package/lib/tests/maintenance/update-isolated.test.d.ts +0 -1
  50. package/lib/tests/maintenance/update-isolated.test.js +0 -71
  51. package/lib/tests/maintenance/update.test.d.ts +0 -1
  52. package/lib/tests/maintenance/update.test.js +0 -27
  53. package/lib/tests/perf/maintenance-cli-large-workspace.test.d.ts +0 -1
  54. package/lib/tests/perf/maintenance-cli-large-workspace.test.js +0 -229
  55. package/lib/tests/perf/maintenance-large-workspace.test.d.ts +0 -1
  56. package/lib/tests/perf/maintenance-large-workspace.test.js +0 -169
  57. package/lib/tests/perf/require-branch-annotation-large-file.test.d.ts +0 -1
  58. package/lib/tests/perf/require-branch-annotation-large-file.test.js +0 -67
  59. package/lib/tests/perf/valid-annotation-format-large-file.test.d.ts +0 -1
  60. package/lib/tests/perf/valid-annotation-format-large-file.test.js +0 -75
  61. package/lib/tests/plugin-default-export-and-configs.test.d.ts +0 -1
  62. package/lib/tests/plugin-default-export-and-configs.test.js +0 -121
  63. package/lib/tests/plugin-setup-error.test.d.ts +0 -6
  64. package/lib/tests/plugin-setup-error.test.js +0 -38
  65. package/lib/tests/plugin-setup.test.d.ts +0 -1
  66. package/lib/tests/plugin-setup.test.js +0 -63
  67. package/lib/tests/rules/auto-fix-behavior-008.test.d.ts +0 -1
  68. package/lib/tests/rules/auto-fix-behavior-008.test.js +0 -285
  69. package/lib/tests/rules/error-reporting.test.d.ts +0 -1
  70. package/lib/tests/rules/error-reporting.test.js +0 -99
  71. package/lib/tests/rules/no-redundant-annotation.test.d.ts +0 -1
  72. package/lib/tests/rules/no-redundant-annotation.test.js +0 -163
  73. package/lib/tests/rules/prefer-implements-annotation.test.d.ts +0 -1
  74. package/lib/tests/rules/prefer-implements-annotation.test.js +0 -162
  75. package/lib/tests/rules/require-branch-annotation.test.d.ts +0 -1
  76. package/lib/tests/rules/require-branch-annotation.test.js +0 -593
  77. package/lib/tests/rules/require-req-annotation.test.d.ts +0 -1
  78. package/lib/tests/rules/require-req-annotation.test.js +0 -264
  79. package/lib/tests/rules/require-story-annotation.test.d.ts +0 -1
  80. package/lib/tests/rules/require-story-annotation.test.js +0 -376
  81. package/lib/tests/rules/require-story-core-edgecases.test.d.ts +0 -1
  82. package/lib/tests/rules/require-story-core-edgecases.test.js +0 -15
  83. package/lib/tests/rules/require-story-core.autofix.test.d.ts +0 -1
  84. package/lib/tests/rules/require-story-core.autofix.test.js +0 -66
  85. package/lib/tests/rules/require-story-core.test.d.ts +0 -1
  86. package/lib/tests/rules/require-story-core.test.js +0 -65
  87. package/lib/tests/rules/require-story-helpers-edgecases.test.d.ts +0 -7
  88. package/lib/tests/rules/require-story-helpers-edgecases.test.js +0 -80
  89. package/lib/tests/rules/require-story-helpers.test.d.ts +0 -1
  90. package/lib/tests/rules/require-story-helpers.test.js +0 -474
  91. package/lib/tests/rules/require-story-io-behavior.test.d.ts +0 -7
  92. package/lib/tests/rules/require-story-io-behavior.test.js +0 -46
  93. package/lib/tests/rules/require-story-io.edgecases.test.d.ts +0 -7
  94. package/lib/tests/rules/require-story-io.edgecases.test.js +0 -46
  95. package/lib/tests/rules/require-story-utils.test.d.ts +0 -7
  96. package/lib/tests/rules/require-story-utils.test.js +0 -158
  97. package/lib/tests/rules/require-story-visitors-edgecases.test.d.ts +0 -7
  98. package/lib/tests/rules/require-story-visitors-edgecases.test.js +0 -27
  99. package/lib/tests/rules/require-test-traceability.test.d.ts +0 -1
  100. package/lib/tests/rules/require-test-traceability.test.js +0 -95
  101. package/lib/tests/rules/valid-annotation-format-internal.test.d.ts +0 -8
  102. package/lib/tests/rules/valid-annotation-format-internal.test.js +0 -47
  103. package/lib/tests/rules/valid-annotation-format.test.d.ts +0 -1
  104. package/lib/tests/rules/valid-annotation-format.test.js +0 -634
  105. package/lib/tests/rules/valid-req-reference.test.d.ts +0 -1
  106. package/lib/tests/rules/valid-req-reference.test.js +0 -129
  107. package/lib/tests/rules/valid-story-reference.test.d.ts +0 -1
  108. package/lib/tests/rules/valid-story-reference.test.js +0 -413
  109. package/lib/tests/utils/annotation-checker-autofix-behavior.test.d.ts +0 -5
  110. package/lib/tests/utils/annotation-checker-autofix-behavior.test.js +0 -103
  111. package/lib/tests/utils/annotation-checker.test.d.ts +0 -24
  112. package/lib/tests/utils/annotation-checker.test.js +0 -84
  113. package/lib/tests/utils/annotation-scope-analyzer.test.d.ts +0 -1
  114. package/lib/tests/utils/annotation-scope-analyzer.test.js +0 -211
  115. package/lib/tests/utils/branch-annotation-catch-insert-position.test.d.ts +0 -1
  116. package/lib/tests/utils/branch-annotation-catch-insert-position.test.js +0 -69
  117. package/lib/tests/utils/branch-annotation-catch-position.test.d.ts +0 -1
  118. package/lib/tests/utils/branch-annotation-catch-position.test.js +0 -115
  119. package/lib/tests/utils/branch-annotation-else-if-insert-position.test.d.ts +0 -1
  120. package/lib/tests/utils/branch-annotation-else-if-insert-position.test.js +0 -82
  121. package/lib/tests/utils/branch-annotation-else-if-position.test.d.ts +0 -1
  122. package/lib/tests/utils/branch-annotation-else-if-position.test.js +0 -145
  123. package/lib/tests/utils/branch-annotation-helpers.test.d.ts +0 -1
  124. package/lib/tests/utils/branch-annotation-helpers.test.js +0 -462
  125. package/lib/tests/utils/fsTestHelpers.d.ts +0 -7
  126. package/lib/tests/utils/fsTestHelpers.js +0 -26
  127. package/lib/tests/utils/ioTestHelpers.d.ts +0 -7
  128. package/lib/tests/utils/ioTestHelpers.js +0 -24
  129. package/lib/tests/utils/req-annotation-detection.test.d.ts +0 -1
  130. package/lib/tests/utils/req-annotation-detection.test.js +0 -358
  131. package/lib/tests/utils/require-story-core-test-helpers.d.ts +0 -10
  132. package/lib/tests/utils/require-story-core-test-helpers.js +0 -75
  133. package/lib/tests/utils/temp-dir-helpers.d.ts +0 -19
  134. package/lib/tests/utils/temp-dir-helpers.js +0 -62
  135. package/lib/tests/utils/ts-language-options.d.ts +0 -16
  136. package/lib/tests/utils/ts-language-options.js +0 -30
  137. /package/lib/{src/index.d.ts → index.d.ts} +0 -0
  138. /package/lib/{src/index.js → index.js} +0 -0
  139. /package/lib/{src/maintenance → maintenance}/batch.d.ts +0 -0
  140. /package/lib/{src/maintenance → maintenance}/batch.js +0 -0
  141. /package/lib/{src/maintenance → maintenance}/cli.d.ts +0 -0
  142. /package/lib/{src/maintenance → maintenance}/cli.js +0 -0
  143. /package/lib/{src/maintenance → maintenance}/commands.d.ts +0 -0
  144. /package/lib/{src/maintenance → maintenance}/commands.js +0 -0
  145. /package/lib/{src/maintenance → maintenance}/detect.d.ts +0 -0
  146. /package/lib/{src/maintenance → maintenance}/detect.js +0 -0
  147. /package/lib/{src/maintenance → maintenance}/flags.d.ts +0 -0
  148. /package/lib/{src/maintenance → maintenance}/flags.js +0 -0
  149. /package/lib/{src/maintenance → maintenance}/index.d.ts +0 -0
  150. /package/lib/{src/maintenance → maintenance}/index.js +0 -0
  151. /package/lib/{src/maintenance → maintenance}/report.d.ts +0 -0
  152. /package/lib/{src/maintenance → maintenance}/report.js +0 -0
  153. /package/lib/{src/maintenance → maintenance}/storyParser.d.ts +0 -0
  154. /package/lib/{src/maintenance → maintenance}/storyParser.js +0 -0
  155. /package/lib/{src/maintenance → maintenance}/update.d.ts +0 -0
  156. /package/lib/{src/maintenance → maintenance}/update.js +0 -0
  157. /package/lib/{src/maintenance → maintenance}/utils.d.ts +0 -0
  158. /package/lib/{src/maintenance → maintenance}/utils.js +0 -0
  159. /package/lib/{src/rules → rules}/helpers/pattern-validators.d.ts +0 -0
  160. /package/lib/{src/rules → rules}/helpers/pattern-validators.js +0 -0
  161. /package/lib/{src/rules → rules}/helpers/prefer-implements-inline.d.ts +0 -0
  162. /package/lib/{src/rules → rules}/helpers/prefer-implements-inline.js +0 -0
  163. /package/lib/{src/rules → rules}/helpers/require-story-comment-detection.d.ts +0 -0
  164. /package/lib/{src/rules → rules}/helpers/require-story-comment-detection.js +0 -0
  165. /package/lib/{src/rules → rules}/helpers/require-story-core.d.ts +0 -0
  166. /package/lib/{src/rules → rules}/helpers/require-story-core.js +0 -0
  167. /package/lib/{src/rules → rules}/helpers/require-story-helpers.d.ts +0 -0
  168. /package/lib/{src/rules → rules}/helpers/require-story-helpers.js +0 -0
  169. /package/lib/{src/rules → rules}/helpers/require-story-io.d.ts +0 -0
  170. /package/lib/{src/rules → rules}/helpers/require-story-io.js +0 -0
  171. /package/lib/{src/rules → rules}/helpers/require-story-name-extraction.d.ts +0 -0
  172. /package/lib/{src/rules → rules}/helpers/require-story-name-extraction.js +0 -0
  173. /package/lib/{src/rules → rules}/helpers/require-story-node-utils.d.ts +0 -0
  174. /package/lib/{src/rules → rules}/helpers/require-story-node-utils.js +0 -0
  175. /package/lib/{src/rules → rules}/helpers/require-story-utils.d.ts +0 -0
  176. /package/lib/{src/rules → rules}/helpers/require-story-utils.js +0 -0
  177. /package/lib/{src/rules → rules}/helpers/require-story-visitors.d.ts +0 -0
  178. /package/lib/{src/rules → rules}/helpers/require-story-visitors.js +0 -0
  179. /package/lib/{src/rules → rules}/helpers/require-test-traceability-helpers.d.ts +0 -0
  180. /package/lib/{src/rules → rules}/helpers/require-test-traceability-helpers.js +0 -0
  181. /package/lib/{src/rules → rules}/helpers/test-callback-exclusion.d.ts +0 -0
  182. /package/lib/{src/rules → rules}/helpers/test-callback-exclusion.js +0 -0
  183. /package/lib/{src/rules → rules}/helpers/valid-annotation-format-internal.d.ts +0 -0
  184. /package/lib/{src/rules → rules}/helpers/valid-annotation-format-internal.js +0 -0
  185. /package/lib/{src/rules → rules}/helpers/valid-annotation-format-validators.d.ts +0 -0
  186. /package/lib/{src/rules → rules}/helpers/valid-annotation-format-validators.js +0 -0
  187. /package/lib/{src/rules → rules}/helpers/valid-annotation-options.d.ts +0 -0
  188. /package/lib/{src/rules → rules}/helpers/valid-annotation-options.js +0 -0
  189. /package/lib/{src/rules → rules}/helpers/valid-annotation-utils.d.ts +0 -0
  190. /package/lib/{src/rules → rules}/helpers/valid-annotation-utils.js +0 -0
  191. /package/lib/{src/rules → rules}/helpers/valid-implements-utils.d.ts +0 -0
  192. /package/lib/{src/rules → rules}/helpers/valid-implements-utils.js +0 -0
  193. /package/lib/{src/rules → rules}/helpers/valid-req-reference-helpers.d.ts +0 -0
  194. /package/lib/{src/rules → rules}/helpers/valid-req-reference-helpers.js +0 -0
  195. /package/lib/{src/rules → rules}/helpers/valid-story-reference-helpers.d.ts +0 -0
  196. /package/lib/{src/rules → rules}/helpers/valid-story-reference-helpers.js +0 -0
  197. /package/lib/{src/rules → rules}/no-redundant-annotation.d.ts +0 -0
  198. /package/lib/{src/rules → rules}/no-redundant-annotation.js +0 -0
  199. /package/lib/{src/rules → rules}/prefer-implements-annotation.d.ts +0 -0
  200. /package/lib/{src/rules → rules}/prefer-implements-annotation.js +0 -0
  201. /package/lib/{src/rules → rules}/require-branch-annotation.d.ts +0 -0
  202. /package/lib/{src/rules → rules}/require-branch-annotation.js +0 -0
  203. /package/lib/{src/rules → rules}/require-req-annotation.d.ts +0 -0
  204. /package/lib/{src/rules → rules}/require-req-annotation.js +0 -0
  205. /package/lib/{src/rules → rules}/require-story-annotation.d.ts +0 -0
  206. /package/lib/{src/rules → rules}/require-story-annotation.js +0 -0
  207. /package/lib/{src/rules → rules}/require-test-traceability.d.ts +0 -0
  208. /package/lib/{src/rules → rules}/require-test-traceability.js +0 -0
  209. /package/lib/{src/rules → rules}/require-traceability.d.ts +0 -0
  210. /package/lib/{src/rules → rules}/valid-annotation-format.d.ts +0 -0
  211. /package/lib/{src/rules → rules}/valid-annotation-format.js +0 -0
  212. /package/lib/{src/rules → rules}/valid-req-reference.d.ts +0 -0
  213. /package/lib/{src/rules → rules}/valid-req-reference.js +0 -0
  214. /package/lib/{src/rules → rules}/valid-story-reference.d.ts +0 -0
  215. /package/lib/{src/rules → rules}/valid-story-reference.js +0 -0
  216. /package/lib/{src/utils → utils}/annotation-checker.d.ts +0 -0
  217. /package/lib/{src/utils → utils}/annotation-checker.js +0 -0
  218. /package/lib/{src/utils → utils}/annotation-scope-analyzer.d.ts +0 -0
  219. /package/lib/{src/utils → utils}/annotation-scope-analyzer.js +0 -0
  220. /package/lib/{src/utils → utils}/branch-annotation-catch-helpers.d.ts +0 -0
  221. /package/lib/{src/utils → utils}/branch-annotation-catch-helpers.js +0 -0
  222. /package/lib/{src/utils → utils}/branch-annotation-helpers.d.ts +0 -0
  223. /package/lib/{src/utils → utils}/branch-annotation-helpers.js +0 -0
  224. /package/lib/{src/utils → utils}/branch-annotation-if-helpers.d.ts +0 -0
  225. /package/lib/{src/utils → utils}/branch-annotation-if-helpers.js +0 -0
  226. /package/lib/{src/utils → utils}/branch-annotation-indent-helpers.d.ts +0 -0
  227. /package/lib/{src/utils → utils}/branch-annotation-indent-helpers.js +0 -0
  228. /package/lib/{src/utils → utils}/branch-annotation-loop-helpers.d.ts +0 -0
  229. /package/lib/{src/utils → utils}/branch-annotation-loop-helpers.js +0 -0
  230. /package/lib/{src/utils → utils}/branch-annotation-report-helpers.d.ts +0 -0
  231. /package/lib/{src/utils → utils}/branch-annotation-report-helpers.js +0 -0
  232. /package/lib/{src/utils → utils}/branch-annotation-story-fix-helpers.d.ts +0 -0
  233. /package/lib/{src/utils → utils}/branch-annotation-story-fix-helpers.js +0 -0
  234. /package/lib/{src/utils → utils}/branch-annotation-switch-helpers.d.ts +0 -0
  235. /package/lib/{src/utils → utils}/branch-annotation-switch-helpers.js +0 -0
  236. /package/lib/{src/utils → utils}/branch-validation.d.ts +0 -0
  237. /package/lib/{src/utils → utils}/branch-validation.js +0 -0
  238. /package/lib/{src/utils → utils}/comment-text-helpers.d.ts +0 -0
  239. /package/lib/{src/utils → utils}/comment-text-helpers.js +0 -0
  240. /package/lib/{src/utils → utils}/function-annotation-helpers.d.ts +0 -0
  241. /package/lib/{src/utils → utils}/function-annotation-helpers.js +0 -0
  242. /package/lib/{src/utils → utils}/redundancy-detector.d.ts +0 -0
  243. /package/lib/{src/utils → utils}/redundancy-detector.js +0 -0
  244. /package/lib/{src/utils → utils}/reqAnnotationDetection.d.ts +0 -0
  245. /package/lib/{src/utils → utils}/reqAnnotationDetection.js +0 -0
  246. /package/lib/{src/utils → utils}/storyReferenceUtils.d.ts +0 -0
  247. /package/lib/{src/utils → utils}/storyReferenceUtils.js +0 -0
package/CHANGELOG.md CHANGED
@@ -1,9 +1,9 @@
1
- # [1.23.0](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.22.0...v1.23.0) (2026-01-10)
1
+ # [1.24.0](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.23.1...v1.24.0) (2026-01-10)
2
2
 
3
3
 
4
4
  ### Features
5
5
 
6
- * **rules:** add ArrowFunctionExpression support to require-req-annotation ([92d2e60](https://github.com/voder-ai/eslint-plugin-traceability/commit/92d2e60686c661faa58c41fd533e7d9e6acbae18))
6
+ * add auto-fix support to require-traceability rule ([ee35349](https://github.com/voder-ai/eslint-plugin-traceability/commit/ee353492bfbebbc18dba7ae8e4d32b8ec386bdf1))
7
7
 
8
8
  # Changelog
9
9
 
@@ -39,7 +39,7 @@ const rule = {
39
39
  recommended: "error",
40
40
  },
41
41
  hasSuggestions: true,
42
- fixable: undefined,
42
+ fixable: "code",
43
43
  messages: {
44
44
  // Unified messageId for potential future direct use by this rule.
45
45
  missingTraceability: "Function '{{name}}' must declare both story and requirement traceability annotations.",
@@ -48,11 +48,56 @@ const rule = {
48
48
  ...(storyRule.meta?.messages ?? {}),
49
49
  ...(reqRule.meta?.messages ?? {}),
50
50
  },
51
- schema: [],
51
+ schema: [
52
+ {
53
+ type: "object",
54
+ properties: {
55
+ scope: {
56
+ type: "array",
57
+ items: {
58
+ type: "string",
59
+ },
60
+ },
61
+ exportPriority: {
62
+ type: "string",
63
+ enum: ["all", "exported", "non-exported"],
64
+ },
65
+ annotationTemplate: {
66
+ type: "string",
67
+ },
68
+ methodAnnotationTemplate: {
69
+ type: "string",
70
+ },
71
+ autoFix: {
72
+ type: "boolean",
73
+ description: "When false, disables automatic fix behavior while retaining diagnostics. When true (default), the rule inserts placeholder annotations in --fix mode.",
74
+ },
75
+ excludeTestCallbacks: {
76
+ type: "boolean",
77
+ },
78
+ annotationPlacement: {
79
+ type: "string",
80
+ enum: ["before", "inside"],
81
+ },
82
+ },
83
+ additionalProperties: false,
84
+ },
85
+ ],
52
86
  },
53
87
  create(context) {
54
- const storyListeners = storyRule.create(context) || {};
55
- const reqListeners = reqRule.create(context) || {};
88
+ // Create a modified context that passes through options to composed rules
89
+ // We need to preserve all context methods while modifying the options array
90
+ const options = context.options[0] || {};
91
+ const modifiedContext = Object.create(context, {
92
+ options: {
93
+ value: [options],
94
+ writable: false,
95
+ enumerable: true,
96
+ configurable: false,
97
+ },
98
+ });
99
+ const storyListeners = storyRule.create(modifiedContext) || {};
100
+ const reqListeners = reqRule.create(modifiedContext) || {};
56
101
  const mergedListener = {};
57
102
  const allEventNames = new Set([
58
103
  ...Object.keys(storyListeners),
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "eslint-plugin-traceability",
3
- "version": "1.23.0",
3
+ "version": "1.24.0",
4
4
  "description": "A customizable ESLint plugin that enforces traceability annotations in your code, ensuring each implementation is linked to its requirement or test case.",
5
- "main": "lib/src/index.js",
6
- "types": "lib/src/index.d.ts",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
7
  "files": [
8
8
  "lib",
9
9
  "README.md",
@@ -16,11 +16,11 @@
16
16
  "doc": "docs"
17
17
  },
18
18
  "bin": {
19
- "traceability-maint": "lib/src/maintenance/cli.js"
19
+ "traceability-maint": "lib/maintenance/cli.js"
20
20
  },
21
21
  "scripts": {
22
- "build": "tsc -p tsconfig.json",
23
- "prepare": "husky",
22
+ "build": "tsc -p tsconfig.build.json",
23
+ "prepare": "node scripts/prepare.js",
24
24
  "type-check": "tsc --noEmit -p tsconfig.json",
25
25
  "check:traceability": "node scripts/traceability-check.js",
26
26
  "lint-plugin-check": "node scripts/lint-plugin-check.js",
@@ -31,7 +31,7 @@
31
31
  "test:unit": "jest --ci --bail --testPathPatterns='tests/(rules|maintenance|utils|unit)' --testPathIgnorePatterns='integration'",
32
32
  "test:integration": "jest --ci --bail --testPathPatterns='tests/integration'",
33
33
  "ci-verify": "npm run type-check && npm run lint && npm run format:check && npm run duplication && npm run check:traceability && npm test && npm run audit:ci && npm run safety:deps",
34
- "ci-verify:full": "npm run check:traceability && npm run safety:deps && npm run audit:ci && npm run build && npm run type-check && npm run lint-plugin-check && npm run lint -- --max-warnings=0 && npm run duplication && npm run test -- --coverage && npm run format:check && npm audit --omit=dev --audit-level=high && npm run audit:dev-high && npm run check:ci-artifacts",
34
+ "ci-verify:full": "npm run check:traceability && npm run safety:deps && npm run audit:ci && npm run build && npm run smoke:runtime && npm run type-check && npm run lint-plugin-check && npm run lint -- --max-warnings=0 && npm run duplication && npm run test -- --coverage && npm run format:check && npm audit --omit=dev --audit-level=high && npm run audit:dev-high && npm run check:ci-artifacts",
35
35
  "ci-verify:fast": "npm run type-check && npm run check:traceability && npm run duplication && jest --ci --bail --passWithNoTests --testPathPatterns 'tests/(rules|maintenance)'",
36
36
  "format": "prettier --write .",
37
37
  "format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"",
@@ -46,7 +46,7 @@
46
46
  "security:secrets": "secretlint \"**/*\"",
47
47
  "smoke-test": "./scripts/smoke-test.sh",
48
48
  "smoke:runtime": "./scripts/runtime-smoke.sh",
49
- "run:cli": "node lib/src/maintenance/cli.js",
49
+ "run:cli": "node lib/maintenance/cli.js",
50
50
  "debug:cli": "node scripts/cli-debug.js",
51
51
  "debug:require-story": "node scripts/debug-require-story.js",
52
52
  "debug:repro": "node scripts/debug-repro.js",
@@ -32,6 +32,31 @@ All three rule keys can still be configured individually if you need fine-graine
32
32
 
33
33
  Description: Unified function-level traceability rule that composes the behavior of `traceability/require-story-annotation` and `traceability/require-req-annotation`. When enabled, it enforces that in‑scope functions and methods carry both a story reference (`@story` or an equivalent `@supports` tag) and at least one requirement reference (`@req` or, when configured, `@supports`). The recommended flat‑config presets in this plugin enable `traceability/require-traceability` by default alongside the legacy rule keys for backward compatibility, so that existing configurations referring to `traceability/require-story-annotation` or `traceability/require-req-annotation` continue to work without change.
34
34
 
35
+ When run with `--fix`, the rule delegates auto-fix behavior to its composed rules, primarily adding placeholder `@story` annotations for missing story coverage via the underlying `require-story-annotation` implementation. The rule supports the same `autoFix` option as the legacy rules, allowing you to disable automatic fixes while retaining diagnostics. All options (including `annotationTemplate`, `methodAnnotationTemplate`, `autoFix`, `scope`, `exportPriority`, `excludeTestCallbacks`, and `annotationPlacement`) are passed through to the composed rules, ensuring consistent behavior across the unified and legacy rule keys.
36
+
37
+ Options:
38
+
39
+ - `scope` (string[], optional) – Controls which function-like node types are required to have traceability annotations. Passed through to composed rules. Default behavior matches require-story-annotation defaults.
40
+ - `exportPriority` ("all" | "exported" | "non-exported", optional) – Controls whether the rule checks all functions, only exported ones, or only non-exported ones. Passed through to composed rules. Default: "all".
41
+ - `annotationTemplate` (string, optional) – Overrides the default placeholder JSDoc used when inserting missing `@story` annotations. Passed through to require-story-annotation. When omitted or blank, the built-in template from Story 008.0 is used.
42
+ - `methodAnnotationTemplate` (string, optional) – Overrides the default placeholder JSDoc used for class methods and TypeScript method signatures. Passed through to require-story-annotation.
43
+ - `autoFix` (boolean, optional) – When set to `false`, disables all automatic fix behavior for this rule while retaining its suggestions and diagnostics. When omitted or `true`, the rule behaves as before, inserting placeholder annotations in `--fix` mode. This option is passed through to the composed rules.
44
+ - `excludeTestCallbacks` (boolean, optional) – When `true` (default), excludes anonymous arrow functions that are direct callbacks to common test framework functions from annotation requirements. Passed through to composed rules.
45
+ - `annotationPlacement` ("before" | "inside", optional) – Controls whether annotations are expected before functions (`"before"`, default) or as the first lines inside function bodies (`"inside"`). Passed through to composed rules.
46
+
47
+ Default Severity: `error`
48
+ Example:
49
+
50
+ ```javascript
51
+ /**
52
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
53
+ * @req REQ-ANNOTATION-REQUIRED
54
+ */
55
+ function initAuth() {
56
+ // authentication logic
57
+ }
58
+ ```
59
+
35
60
  ### traceability/require-story-annotation
36
61
 
37
62
  Description: **Legacy function-level key:** This rule key is retained for backward compatibility and conceptually composes the same checks as `traceability/require-traceability`. New configurations should normally enable `traceability/require-traceability` instead and rely on this key only when you need to tune it independently. Ensures every function declaration has a traceability annotation, preferring `@supports` for story coverage while still accepting legacy `@story` annotations referencing the related user story. When you adopt multi-story `@supports` annotations, this rule also accepts `@supports` as an alternative way to prove story coverage, so either `@story` or at least one `@supports` tag will satisfy the presence check. When run with `--fix`, the rule inserts a single-line placeholder JSDoc `@story` annotation above missing functions, methods, TypeScript declare functions, and interface method signatures using a built-in template aligned with Story 008.0. This template is now configurable on a per-rule basis, and the rule exposes an explicit auto-fix toggle so you can choose between diagnostic-only behavior and automatic placeholder insertion. The default template remains aligned with Story 008.0, but you can now customize it per rule configuration and optionally disable auto-fix entirely when you only want diagnostics without edits.
@@ -1 +0,0 @@
1
- export {};
@@ -1,54 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- /**
7
- * Tests for CLI error handling when plugin loading fails
8
- * @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
9
- * @req REQ-ERROR-HANDLING - Plugin CLI should exit with error on rule load failure
10
- * @supports docs/stories/001.0-DEV-PLUGIN-SETUP.story.md REQ-ERROR-HANDLING
11
- */
12
- const child_process_1 = require("child_process");
13
- const path_1 = __importDefault(require("path"));
14
- const originalNodePath = process.env.NODE_PATH;
15
- describe("CLI Error Handling for Traceability Plugin (Story 001.0-DEV-PLUGIN-SETUP)", () => {
16
- beforeAll(() => {
17
- // Simulate missing plugin build by deleting lib directory (if exist)
18
- // In tests, assume plugin built to lib/src/index.js; point plugin import to src/index.ts via env
19
- process.env.NODE_PATH = path_1.default.resolve(__dirname, "../src");
20
- });
21
- afterAll(() => {
22
- if (originalNodePath === undefined) {
23
- delete process.env.NODE_PATH;
24
- }
25
- else {
26
- process.env.NODE_PATH = originalNodePath;
27
- }
28
- });
29
- it("[REQ-ERROR-HANDLING] should exit with error when rule module missing", () => {
30
- const eslintPkgDir = path_1.default.dirname(require.resolve("eslint/package.json"));
31
- const eslintCliPath = path_1.default.join(eslintPkgDir, "bin", "eslint.js");
32
- const configPath = path_1.default.resolve(__dirname, "../eslint.config.js");
33
- const code = `function foo() {}`;
34
- const args = [
35
- "--no-config-lookup",
36
- "--config",
37
- configPath,
38
- "--stdin",
39
- "--stdin-filename",
40
- "foo.js",
41
- "--rule",
42
- "traceability/require-story-annotation:error",
43
- ];
44
- // Rename one of the rule files to simulate missing module
45
- // However, modifying fs at CLI runtime isn't straightforward here; skip this test as implementation placeholder
46
- const result = (0, child_process_1.spawnSync)(process.execPath, [eslintCliPath, ...args], {
47
- encoding: "utf-8",
48
- input: code,
49
- });
50
- // Expect non-zero exit and missing annotation message on stdout
51
- expect(result.status).not.toBe(0);
52
- expect(result.stdout).toContain("Function 'foo' must declare a traceability annotation. Prefer adding an @supports line that links this function to at least one story (for example, '@supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-ANNOTATION-REQUIRED'), or, when you only need a single-story reference, add a legacy @story annotation that points to the implementing story file, such as docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md");
53
- });
54
- });
@@ -1,9 +0,0 @@
1
- /**
2
- * Tests for ESLint config rule schemas.
3
- *
4
- * @supports docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
5
- * @req REQ-RULE-OPTIONS
6
- * @req REQ-CONFIG-VALIDATION
7
- * @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
8
- */
9
- export {};
@@ -1,101 +0,0 @@
1
- "use strict";
2
- /* eslint-disable traceability/valid-annotation-format */
3
- /**
4
- * Tests for ESLint config rule schemas.
5
- *
6
- * @supports docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
7
- * @req REQ-RULE-OPTIONS
8
- * @req REQ-CONFIG-VALIDATION
9
- * @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
10
- */
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- const valid_story_reference_1 = __importDefault(require("../../src/rules/valid-story-reference"));
16
- const use_at_your_own_risk_1 = require("eslint/use-at-your-own-risk");
17
- const index_1 = __importDefault(require("../../src/index"));
18
- /** @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md */
19
- describe("ESLint Configuration Setup (Story 002.0-DEV-ESLINT-CONFIG)", () => {
20
- it("[REQ-RULE-OPTIONS] rule meta.schema defines expected properties", () => {
21
- const schema = valid_story_reference_1.default.meta.schema[0];
22
- expect(schema.properties).toHaveProperty("storyDirectories");
23
- expect(schema.properties).toHaveProperty("allowAbsolutePaths");
24
- expect(schema.properties).toHaveProperty("requireStoryExtension");
25
- });
26
- it("[REQ-CONFIG-VALIDATION] schema disallows unknown options", () => {
27
- const schema = valid_story_reference_1.default.meta.schema[0];
28
- expect(schema.additionalProperties).toBe(false);
29
- });
30
- it("[REQ-CONFIG-VALIDATION] ESLint throws on unknown rule option", async () => {
31
- const eslint = new use_at_your_own_risk_1.FlatESLint({
32
- overrideConfig: [
33
- {
34
- plugins: {
35
- traceability: index_1.default,
36
- },
37
- rules: {
38
- "traceability/valid-story-reference": [
39
- "error",
40
- {
41
- storyDirectories: ["stories"],
42
- allowAbsolutePaths: false,
43
- requireStoryExtension: true,
44
- unknownOptionKey: true,
45
- },
46
- ],
47
- },
48
- },
49
- ],
50
- overrideConfigFile: true,
51
- ignore: false,
52
- });
53
- let caughtError;
54
- try {
55
- await eslint.lintText("const x = 1;");
56
- }
57
- catch (err) {
58
- caughtError = err;
59
- }
60
- expect(caughtError).toBeInstanceOf(Error);
61
- const message = String(caughtError.message || caughtError);
62
- expect(message).toContain("traceability/valid-story-reference");
63
- expect(message.toLowerCase()).toContain("additional");
64
- expect(message.toLowerCase()).toContain("unexpected property");
65
- expect(message).toContain("unknownOptionKey");
66
- });
67
- it("[REQ-CONFIG-VALIDATION] ESLint throws on invalid option type", async () => {
68
- const eslint = new use_at_your_own_risk_1.FlatESLint({
69
- overrideConfig: [
70
- {
71
- plugins: {
72
- traceability: index_1.default,
73
- },
74
- rules: {
75
- "traceability/valid-story-reference": [
76
- "error",
77
- {
78
- // storyDirectories must be an array, not a string
79
- storyDirectories: "not-an-array",
80
- },
81
- ],
82
- },
83
- },
84
- ],
85
- overrideConfigFile: true,
86
- ignore: false,
87
- });
88
- let caughtError;
89
- try {
90
- await eslint.lintText("const y = 2;");
91
- }
92
- catch (err) {
93
- caughtError = err;
94
- }
95
- expect(caughtError).toBeInstanceOf(Error);
96
- const message = String(caughtError.message || caughtError);
97
- expect(message).toContain("traceability/valid-story-reference");
98
- expect(message).toContain("not-an-array");
99
- expect(message.toLowerCase()).toContain("array");
100
- });
101
- });
@@ -1,76 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- /* eslint-disable traceability/valid-annotation-format */
37
- /**
38
- * Tests for: docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
39
- * @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
40
- * @supports docs/stories/002.0-DEV-ESLINT-CONFIG.story.md REQ-CONFIG-PRESETS REQ-FLAT-CONFIG REQ-PROJECT-INTEGRATION
41
- */
42
- const use_at_your_own_risk_1 = require("eslint/use-at-your-own-risk");
43
- const index_1 = __importStar(require("../../src/index"));
44
- const baseConfig = {
45
- plugins: {
46
- traceability: index_1.default,
47
- },
48
- rules: {},
49
- };
50
- async function lintTextWithConfig(text, config) {
51
- const eslint = new use_at_your_own_risk_1.FlatESLint({
52
- overrideConfig: config,
53
- overrideConfigFile: true,
54
- ignore: false,
55
- });
56
- const [result] = await eslint.lintText(text, { filePath: "example.js" });
57
- return result;
58
- }
59
- describe("Flat config presets integration (Story 002.0-DEV-ESLINT-CONFIG)", () => {
60
- it("[REQ-CONFIG-PRESETS] recommended preset enables traceability rules via documented usage", async () => {
61
- const config = [baseConfig, ...index_1.configs.recommended];
62
- const code = "function foo() {}";
63
- const result = await lintTextWithConfig(code, config);
64
- const ruleIds = result.messages.map((m) => m.ruleId).sort();
65
- expect(ruleIds).toContain("traceability/require-traceability");
66
- expect(ruleIds).toContain("traceability/require-story-annotation");
67
- });
68
- it("[REQ-CONFIG-PRESETS] strict preset also enables traceability rules via documented usage", async () => {
69
- const config = [baseConfig, ...index_1.configs.strict];
70
- const code = "function bar() {}";
71
- const result = await lintTextWithConfig(code, config);
72
- const ruleIds = result.messages.map((m) => m.ruleId).sort();
73
- expect(ruleIds).toContain("traceability/require-traceability");
74
- expect(ruleIds).toContain("traceability/require-story-annotation");
75
- });
76
- });
@@ -1,10 +0,0 @@
1
- /**
2
- * Tests for the require-story-annotation rule schema configuration.
3
- *
4
- * Verifies that the ESLint rule options for require-story-annotation
5
- * define the expected schema properties and constraints.
6
- *
7
- * @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
8
- * @supports docs/stories/002.0-DEV-ESLINT-CONFIG.story.md REQ-RULE-OPTIONS
9
- */
10
- export {};
@@ -1,26 +0,0 @@
1
- "use strict";
2
- /* eslint-disable traceability/valid-annotation-format */
3
- /**
4
- * Tests for the require-story-annotation rule schema configuration.
5
- *
6
- * Verifies that the ESLint rule options for require-story-annotation
7
- * define the expected schema properties and constraints.
8
- *
9
- * @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
10
- * @supports docs/stories/002.0-DEV-ESLINT-CONFIG.story.md REQ-RULE-OPTIONS
11
- */
12
- var __importDefault = (this && this.__importDefault) || function (mod) {
13
- return (mod && mod.__esModule) ? mod : { "default": mod };
14
- };
15
- Object.defineProperty(exports, "__esModule", { value: true });
16
- const require_story_annotation_1 = __importDefault(require("../../src/rules/require-story-annotation"));
17
- /** @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md */
18
- describe("ESLint Configuration Rule Options (Story 002.0-DEV-ESLINT-CONFIG)", () => {
19
- it("[REQ-RULE-OPTIONS] require-story-annotation schema defines expected properties", () => {
20
- const schema = require_story_annotation_1.default.meta.schema[0];
21
- expect(schema.properties).toHaveProperty("scope");
22
- expect(schema.properties).toHaveProperty("exportPriority");
23
- expect(schema.properties).toHaveProperty("annotationPlacement");
24
- expect(schema.additionalProperties).toBe(false);
25
- });
26
- });
File without changes
@@ -1,4 +0,0 @@
1
- "use strict";
2
- /* eslint-disable traceability/valid-annotation-format */
3
- // Sample code with stale annotation
4
- // @story docs/stories/non-existent.story.md
File without changes
@@ -1,4 +0,0 @@
1
- "use strict";
2
- /* eslint-disable traceability/valid-annotation-format */
3
- // Sample code with annotation to update
4
- // @story docs/stories/old.story.md
File without changes
@@ -1,3 +0,0 @@
1
- "use strict";
2
- // Valid annotation
3
- // @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
@@ -1,133 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- /* eslint-disable traceability/valid-annotation-format */
7
- /**
8
- * Prettier integration tests for annotationPlacement: "inside" across multiple branch types.
9
- * @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
10
- * @supports docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md REQ-PRETTIER-STABLE REQ-INSIDE-BRACE-PLACEMENT REQ-PLACEMENT-CONFIG
11
- */
12
- const path_1 = __importDefault(require("path"));
13
- const child_process_1 = require("child_process");
14
- const prettier_test_helpers_1 = require("./prettier-test-helpers");
15
- describe("annotationPlacement: 'inside' with Prettier (Story 028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION)", () => {
16
- const eslintPkgDir = path_1.default.dirname(require.resolve("eslint/package.json"));
17
- const eslintCliPath = path_1.default.join(eslintPkgDir, "bin", "eslint.js");
18
- const configPath = path_1.default.resolve(__dirname, "../../eslint.config.js");
19
- function buildInsidePlacementArgs(stdinFilename) {
20
- return [
21
- "--no-config-lookup",
22
- "--config",
23
- configPath,
24
- "--stdin",
25
- "--stdin-filename",
26
- stdinFilename,
27
- "--rule",
28
- "no-unused-vars:off",
29
- "--rule",
30
- "no-magic-numbers:off",
31
- "--rule",
32
- "no-undef:off",
33
- "--rule",
34
- "no-console:off",
35
- "--rule",
36
- 'traceability/require-branch-annotation:["error",{"annotationPlacement":"inside"}]',
37
- ];
38
- }
39
- function runEslintWithInsidePlacement(code, _filename) {
40
- // Pin stdin filename to a tsconfig-included path to satisfy @typescript-eslint/parser's project lookup in these integration tests.
41
- const args = buildInsidePlacementArgs("src/annotation-placement-inside.ts");
42
- return (0, child_process_1.spawnSync)(process.execPath, [eslintCliPath, ...args], {
43
- encoding: "utf-8",
44
- input: code,
45
- });
46
- }
47
- function formatWithPrettier(source) {
48
- return (0, prettier_test_helpers_1.formatWithPrettier)(source, { parser: "typescript" });
49
- }
50
- it("[REQ-PRETTIER-STABLE][REQ-INSIDE-BRACE-PLACEMENT] accepts formatted code with inside-brace annotations for if/else and loops", () => {
51
- const original = `
52
- function demo(value: number) {
53
- if (value > 0) {
54
- // @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
55
- // @req REQ-IF-INSIDE
56
- console.log('positive');
57
- } else if (value < 0) {
58
- // @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
59
- // @req REQ-ELSE-IF-INSIDE
60
- console.log('negative');
61
- } else {
62
- // @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
63
- // @req REQ-ELSE-INSIDE
64
- console.log('zero');
65
- }
66
-
67
- for (const item of [1, 2, 3]) {
68
- // @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
69
- // @req REQ-LOOP-INSIDE
70
- console.log(item);
71
- }
72
- }
73
- `;
74
- const formatted = formatWithPrettier(original);
75
- const result = runEslintWithInsidePlacement(formatted, "annotation-placement-inside-if-loop.ts");
76
- expect(result.stdout).not.toContain("traceability/require-branch-annotation");
77
- expect([0, 1]).toContain(result.status);
78
- });
79
- it("[REQ-PRETTIER-STABLE][REQ-INSIDE-BRACE-PLACEMENT] accepts formatted code with inside-brace annotations for try/finally and catch", () => {
80
- const original = `
81
- function demoTry(flag: boolean) {
82
- try {
83
- // @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
84
- // @req REQ-TRY-INSIDE
85
- if (flag) {
86
- throw new Error('boom');
87
- }
88
- } catch (error) {
89
- // @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
90
- // @req REQ-CATCH-INSIDE
91
- console.error(error);
92
- } finally {
93
- // @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
94
- // @req REQ-FINALLY-INSIDE
95
- console.log('cleanup');
96
- }
97
- }
98
- `;
99
- const formatted = formatWithPrettier(original);
100
- const result = runEslintWithInsidePlacement(formatted, "annotation-placement-inside-try.ts");
101
- expect(result.stdout).not.toContain("traceability/require-branch-annotation");
102
- expect([0, 1]).toContain(result.status);
103
- });
104
- it("[REQ-PRETTIER-STABLE][REQ-INSIDE-BRACE-PLACEMENT] accepts formatted code with inside-brace annotations for switch cases", () => {
105
- const original = `
106
- function demoSwitch(status: 'pending' | 'done' | 'other') {
107
- switch (status) {
108
- case 'pending': {
109
- // @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
110
- // @req REQ-SWITCH-PENDING-INSIDE
111
- console.log('pending');
112
- break;
113
- }
114
- case 'done': {
115
- // @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
116
- // @req REQ-SWITCH-DONE-INSIDE
117
- console.log('done');
118
- break;
119
- }
120
- default: {
121
- // @story docs/stories/028.0-DEV-ANNOTATION-PLACEMENT-STANDARDIZATION.story.md
122
- // @req REQ-SWITCH-DEFAULT-INSIDE
123
- console.log('other');
124
- }
125
- }
126
- }
127
- `;
128
- const formatted = formatWithPrettier(original);
129
- const result = runEslintWithInsidePlacement(formatted, "annotation-placement-inside-switch.ts");
130
- expect(result.stdout).not.toContain("traceability/require-branch-annotation");
131
- expect([0, 1]).toContain(result.status);
132
- });
133
- });