@codeperfect/eslint-plugin 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 (248) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +128 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/architecture/consistent-barrel-files/consistent-barrel-files-listeners.d.ts +16 -0
  5. package/dist/architecture/consistent-barrel-files/consistent-barrel-files-listeners.d.ts.map +1 -0
  6. package/dist/architecture/consistent-barrel-files/consistent-barrel-files-listeners.js +131 -0
  7. package/dist/architecture/consistent-barrel-files/consistent-barrel-files-options.d.ts +48 -0
  8. package/dist/architecture/consistent-barrel-files/consistent-barrel-files-options.d.ts.map +1 -0
  9. package/dist/architecture/consistent-barrel-files/consistent-barrel-files-options.js +126 -0
  10. package/dist/architecture/consistent-barrel-files/exports-only-rule-test-utilities.d.ts +40 -0
  11. package/dist/architecture/consistent-barrel-files/exports-only-rule-test-utilities.d.ts.map +1 -0
  12. package/dist/architecture/consistent-barrel-files/exports-only-rule-test-utilities.js +90 -0
  13. package/dist/architecture/consistent-barrel-files/exports-only-rule.d.ts +11 -0
  14. package/dist/architecture/consistent-barrel-files/exports-only-rule.d.ts.map +1 -0
  15. package/dist/architecture/consistent-barrel-files/exports-only-rule.js +218 -0
  16. package/dist/architecture/consistent-barrel-files/index.d.ts +5 -0
  17. package/dist/architecture/consistent-barrel-files/index.d.ts.map +1 -0
  18. package/dist/architecture/consistent-barrel-files/index.js +4 -0
  19. package/dist/architecture/consistent-barrel-files/no-reexports-outside-barrels-rule.d.ts +11 -0
  20. package/dist/architecture/consistent-barrel-files/no-reexports-outside-barrels-rule.d.ts.map +1 -0
  21. package/dist/architecture/consistent-barrel-files/no-reexports-outside-barrels-rule.js +100 -0
  22. package/dist/architecture/consistent-barrel-files/no-reexports-outside-barrels-test-utilities.d.ts +40 -0
  23. package/dist/architecture/consistent-barrel-files/no-reexports-outside-barrels-test-utilities.d.ts.map +1 -0
  24. package/dist/architecture/consistent-barrel-files/no-reexports-outside-barrels-test-utilities.js +90 -0
  25. package/dist/architecture/consistent-barrel-files/no-reexports-outside-barrels-utilities.d.ts +65 -0
  26. package/dist/architecture/consistent-barrel-files/no-reexports-outside-barrels-utilities.d.ts.map +1 -0
  27. package/dist/architecture/consistent-barrel-files/no-reexports-outside-barrels-utilities.js +154 -0
  28. package/dist/architecture/consistent-barrel-files/rule.d.ts +11 -0
  29. package/dist/architecture/consistent-barrel-files/rule.d.ts.map +1 -0
  30. package/dist/architecture/consistent-barrel-files/rule.js +58 -0
  31. package/dist/architecture/consistent-barrel-files/test-helpers.d.ts +141 -0
  32. package/dist/architecture/consistent-barrel-files/test-helpers.d.ts.map +1 -0
  33. package/dist/architecture/consistent-barrel-files/test-helpers.js +229 -0
  34. package/dist/architecture/consistent-barrel-files/types.d.ts +25 -0
  35. package/dist/architecture/consistent-barrel-files/types.d.ts.map +1 -0
  36. package/dist/architecture/consistent-barrel-files/types.js +2 -0
  37. package/dist/architecture/index.d.ts +2 -0
  38. package/dist/architecture/index.d.ts.map +1 -0
  39. package/dist/architecture/index.js +2 -0
  40. package/dist/benchmark-rules.d.ts +83 -0
  41. package/dist/benchmark-rules.d.ts.map +1 -0
  42. package/dist/benchmark-rules.js +175 -0
  43. package/dist/codeperfect-eslint-plugin-1.0.0.tgz +0 -0
  44. package/dist/codeperfect-plugin.d.ts +46 -0
  45. package/dist/codeperfect-plugin.d.ts.map +1 -0
  46. package/dist/codeperfect-plugin.js +29 -0
  47. package/dist/core/index.d.ts +3 -0
  48. package/dist/core/index.d.ts.map +1 -0
  49. package/dist/core/index.js +3 -0
  50. package/dist/core/no-multiple-declarators/index.d.ts +2 -0
  51. package/dist/core/no-multiple-declarators/index.d.ts.map +1 -0
  52. package/dist/core/no-multiple-declarators/index.js +2 -0
  53. package/dist/core/no-multiple-declarators/rule.d.ts +4 -0
  54. package/dist/core/no-multiple-declarators/rule.d.ts.map +1 -0
  55. package/dist/core/no-multiple-declarators/rule.js +100 -0
  56. package/dist/core/prefer-interface-types/index.d.ts +2 -0
  57. package/dist/core/prefer-interface-types/index.d.ts.map +1 -0
  58. package/dist/core/prefer-interface-types/index.js +2 -0
  59. package/dist/core/prefer-interface-types/rule.d.ts +5 -0
  60. package/dist/core/prefer-interface-types/rule.d.ts.map +1 -0
  61. package/dist/core/prefer-interface-types/rule.js +145 -0
  62. package/dist/core/prefer-interface-types/test-helpers.d.ts +110 -0
  63. package/dist/core/prefer-interface-types/test-helpers.d.ts.map +1 -0
  64. package/dist/core/prefer-interface-types/test-helpers.js +116 -0
  65. package/dist/custom-rule-documentation.d.ts +36 -0
  66. package/dist/custom-rule-documentation.d.ts.map +1 -0
  67. package/dist/custom-rule-documentation.js +35 -0
  68. package/dist/custom-rules.d.ts +61 -0
  69. package/dist/custom-rules.d.ts.map +1 -0
  70. package/dist/custom-rules.js +70 -0
  71. package/dist/docs/index.d.ts +4 -0
  72. package/dist/docs/index.d.ts.map +1 -0
  73. package/dist/docs/index.js +4 -0
  74. package/dist/docs/no-interface-member-docs/comment-utilities-test-helpers.d.ts +89 -0
  75. package/dist/docs/no-interface-member-docs/comment-utilities-test-helpers.d.ts.map +1 -0
  76. package/dist/docs/no-interface-member-docs/comment-utilities-test-helpers.js +129 -0
  77. package/dist/docs/no-interface-member-docs/comment-utilities.d.ts +48 -0
  78. package/dist/docs/no-interface-member-docs/comment-utilities.d.ts.map +1 -0
  79. package/dist/docs/no-interface-member-docs/comment-utilities.js +146 -0
  80. package/dist/docs/no-interface-member-docs/index.d.ts +2 -0
  81. package/dist/docs/no-interface-member-docs/index.d.ts.map +1 -0
  82. package/dist/docs/no-interface-member-docs/index.js +2 -0
  83. package/dist/docs/no-interface-member-docs/parameter-tags.d.ts +13 -0
  84. package/dist/docs/no-interface-member-docs/parameter-tags.d.ts.map +1 -0
  85. package/dist/docs/no-interface-member-docs/parameter-tags.js +101 -0
  86. package/dist/docs/no-interface-member-docs/parameter-utilities.d.ts +24 -0
  87. package/dist/docs/no-interface-member-docs/parameter-utilities.d.ts.map +1 -0
  88. package/dist/docs/no-interface-member-docs/parameter-utilities.js +125 -0
  89. package/dist/docs/no-interface-member-docs/rule.d.ts +5 -0
  90. package/dist/docs/no-interface-member-docs/rule.d.ts.map +1 -0
  91. package/dist/docs/no-interface-member-docs/rule.js +168 -0
  92. package/dist/docs/no-interface-member-docs/test-helpers.d.ts +103 -0
  93. package/dist/docs/no-interface-member-docs/test-helpers.d.ts.map +1 -0
  94. package/dist/docs/no-interface-member-docs/test-helpers.js +157 -0
  95. package/dist/docs/no-interface-member-docs/types.d.ts +30 -0
  96. package/dist/docs/no-interface-member-docs/types.d.ts.map +1 -0
  97. package/dist/docs/no-interface-member-docs/types.js +2 -0
  98. package/dist/docs/require-example-language/empty-fence-fixes.d.ts +29 -0
  99. package/dist/docs/require-example-language/empty-fence-fixes.d.ts.map +1 -0
  100. package/dist/docs/require-example-language/empty-fence-fixes.js +169 -0
  101. package/dist/docs/require-example-language/example-utilities.d.ts +70 -0
  102. package/dist/docs/require-example-language/example-utilities.d.ts.map +1 -0
  103. package/dist/docs/require-example-language/example-utilities.js +76 -0
  104. package/dist/docs/require-example-language/examples.d.ts +36 -0
  105. package/dist/docs/require-example-language/examples.d.ts.map +1 -0
  106. package/dist/docs/require-example-language/examples.js +181 -0
  107. package/dist/docs/require-example-language/fixes.d.ts +49 -0
  108. package/dist/docs/require-example-language/fixes.d.ts.map +1 -0
  109. package/dist/docs/require-example-language/fixes.js +182 -0
  110. package/dist/docs/require-example-language/index.d.ts +3 -0
  111. package/dist/docs/require-example-language/index.d.ts.map +1 -0
  112. package/dist/docs/require-example-language/index.js +2 -0
  113. package/dist/docs/require-example-language/reporting.d.ts +60 -0
  114. package/dist/docs/require-example-language/reporting.d.ts.map +1 -0
  115. package/dist/docs/require-example-language/reporting.js +145 -0
  116. package/dist/docs/require-example-language/rule.d.ts +7 -0
  117. package/dist/docs/require-example-language/rule.d.ts.map +1 -0
  118. package/dist/docs/require-example-language/rule.js +34 -0
  119. package/dist/docs/require-example-language/types.d.ts +22 -0
  120. package/dist/docs/require-example-language/types.d.ts.map +1 -0
  121. package/dist/docs/require-example-language/types.js +2 -0
  122. package/dist/docs/single-line-jsdoc/index.d.ts +2 -0
  123. package/dist/docs/single-line-jsdoc/index.d.ts.map +1 -0
  124. package/dist/docs/single-line-jsdoc/index.js +2 -0
  125. package/dist/docs/single-line-jsdoc/rule.d.ts +5 -0
  126. package/dist/docs/single-line-jsdoc/rule.d.ts.map +1 -0
  127. package/dist/docs/single-line-jsdoc/rule.js +196 -0
  128. package/dist/docs/single-line-jsdoc/single-line-jsdoc-content.d.ts +16 -0
  129. package/dist/docs/single-line-jsdoc/single-line-jsdoc-content.d.ts.map +1 -0
  130. package/dist/docs/single-line-jsdoc/single-line-jsdoc-content.js +95 -0
  131. package/dist/docs/single-line-jsdoc/single-line-jsdoc-utilities.d.ts +25 -0
  132. package/dist/docs/single-line-jsdoc/single-line-jsdoc-utilities.d.ts.map +1 -0
  133. package/dist/docs/single-line-jsdoc/single-line-jsdoc-utilities.js +140 -0
  134. package/dist/docs/test-helpers.d.ts +50 -0
  135. package/dist/docs/test-helpers.d.ts.map +1 -0
  136. package/dist/docs/test-helpers.js +107 -0
  137. package/dist/index.d.ts +6 -0
  138. package/dist/index.d.ts.map +1 -0
  139. package/dist/index.js +6 -0
  140. package/dist/presets.d.ts +10 -0
  141. package/dist/presets.d.ts.map +1 -0
  142. package/dist/presets.js +50 -0
  143. package/dist/rules/index.d.ts +5 -0
  144. package/dist/rules/index.d.ts.map +1 -0
  145. package/dist/rules/index.js +6 -0
  146. package/dist/testing/aaa/analyzer.d.ts +36 -0
  147. package/dist/testing/aaa/analyzer.d.ts.map +1 -0
  148. package/dist/testing/aaa/analyzer.js +490 -0
  149. package/dist/testing/aaa/index.d.ts +3 -0
  150. package/dist/testing/aaa/index.d.ts.map +1 -0
  151. package/dist/testing/aaa/index.js +2 -0
  152. package/dist/testing/aaa/types.d.ts +31 -0
  153. package/dist/testing/aaa/types.d.ts.map +1 -0
  154. package/dist/testing/aaa/types.js +2 -0
  155. package/dist/testing/assert-actual-expected-names/index.d.ts +2 -0
  156. package/dist/testing/assert-actual-expected-names/index.d.ts.map +1 -0
  157. package/dist/testing/assert-actual-expected-names/index.js +2 -0
  158. package/dist/testing/assert-actual-expected-names/rule.d.ts +4 -0
  159. package/dist/testing/assert-actual-expected-names/rule.d.ts.map +1 -0
  160. package/dist/testing/assert-actual-expected-names/rule.js +54 -0
  161. package/dist/testing/enforce-aaa-phase-purity/index.d.ts +2 -0
  162. package/dist/testing/enforce-aaa-phase-purity/index.d.ts.map +1 -0
  163. package/dist/testing/enforce-aaa-phase-purity/index.js +2 -0
  164. package/dist/testing/enforce-aaa-phase-purity/rule.d.ts +4 -0
  165. package/dist/testing/enforce-aaa-phase-purity/rule.d.ts.map +1 -0
  166. package/dist/testing/enforce-aaa-phase-purity/rule.js +110 -0
  167. package/dist/testing/enforce-aaa-structure/index.d.ts +2 -0
  168. package/dist/testing/enforce-aaa-structure/index.d.ts.map +1 -0
  169. package/dist/testing/enforce-aaa-structure/index.js +2 -0
  170. package/dist/testing/enforce-aaa-structure/rule.d.ts +4 -0
  171. package/dist/testing/enforce-aaa-structure/rule.d.ts.map +1 -0
  172. package/dist/testing/enforce-aaa-structure/rule.js +48 -0
  173. package/dist/testing/index.d.ts +9 -0
  174. package/dist/testing/index.d.ts.map +1 -0
  175. package/dist/testing/index.js +9 -0
  176. package/dist/testing/prefer-vi-mocked-import/fix.d.ts +16 -0
  177. package/dist/testing/prefer-vi-mocked-import/fix.d.ts.map +1 -0
  178. package/dist/testing/prefer-vi-mocked-import/fix.js +224 -0
  179. package/dist/testing/prefer-vi-mocked-import/index.d.ts +2 -0
  180. package/dist/testing/prefer-vi-mocked-import/index.d.ts.map +1 -0
  181. package/dist/testing/prefer-vi-mocked-import/index.js +2 -0
  182. package/dist/testing/prefer-vi-mocked-import/match-bindings.d.ts +16 -0
  183. package/dist/testing/prefer-vi-mocked-import/match-bindings.d.ts.map +1 -0
  184. package/dist/testing/prefer-vi-mocked-import/match-bindings.js +52 -0
  185. package/dist/testing/prefer-vi-mocked-import/match-declarations.d.ts +16 -0
  186. package/dist/testing/prefer-vi-mocked-import/match-declarations.d.ts.map +1 -0
  187. package/dist/testing/prefer-vi-mocked-import/match-declarations.js +99 -0
  188. package/dist/testing/prefer-vi-mocked-import/match-helpers.d.ts +66 -0
  189. package/dist/testing/prefer-vi-mocked-import/match-helpers.d.ts.map +1 -0
  190. package/dist/testing/prefer-vi-mocked-import/match-helpers.js +102 -0
  191. package/dist/testing/prefer-vi-mocked-import/match-imports.d.ts +17 -0
  192. package/dist/testing/prefer-vi-mocked-import/match-imports.d.ts.map +1 -0
  193. package/dist/testing/prefer-vi-mocked-import/match-imports.js +156 -0
  194. package/dist/testing/prefer-vi-mocked-import/match-rewrites.d.ts +42 -0
  195. package/dist/testing/prefer-vi-mocked-import/match-rewrites.d.ts.map +1 -0
  196. package/dist/testing/prefer-vi-mocked-import/match-rewrites.js +119 -0
  197. package/dist/testing/prefer-vi-mocked-import/match-walk.d.ts +13 -0
  198. package/dist/testing/prefer-vi-mocked-import/match-walk.d.ts.map +1 -0
  199. package/dist/testing/prefer-vi-mocked-import/match-walk.js +62 -0
  200. package/dist/testing/prefer-vi-mocked-import/match.d.ts +15 -0
  201. package/dist/testing/prefer-vi-mocked-import/match.d.ts.map +1 -0
  202. package/dist/testing/prefer-vi-mocked-import/match.js +193 -0
  203. package/dist/testing/prefer-vi-mocked-import/rule.d.ts +5 -0
  204. package/dist/testing/prefer-vi-mocked-import/rule.d.ts.map +1 -0
  205. package/dist/testing/prefer-vi-mocked-import/rule.js +32 -0
  206. package/dist/testing/prefer-vi-mocked-import/types.d.ts +83 -0
  207. package/dist/testing/prefer-vi-mocked-import/types.d.ts.map +1 -0
  208. package/dist/testing/prefer-vi-mocked-import/types.js +2 -0
  209. package/dist/testing/require-aaa-sections/index.d.ts +2 -0
  210. package/dist/testing/require-aaa-sections/index.d.ts.map +1 -0
  211. package/dist/testing/require-aaa-sections/index.js +2 -0
  212. package/dist/testing/require-aaa-sections/rule.d.ts +4 -0
  213. package/dist/testing/require-aaa-sections/rule.d.ts.map +1 -0
  214. package/dist/testing/require-aaa-sections/rule.js +111 -0
  215. package/dist/testing/require-act-result-capture/index.d.ts +2 -0
  216. package/dist/testing/require-act-result-capture/index.d.ts.map +1 -0
  217. package/dist/testing/require-act-result-capture/index.js +2 -0
  218. package/dist/testing/require-act-result-capture/rule.d.ts +4 -0
  219. package/dist/testing/require-act-result-capture/rule.d.ts.map +1 -0
  220. package/dist/testing/require-act-result-capture/rule.js +34 -0
  221. package/dist/testing/require-test-companion/index.d.ts +3 -0
  222. package/dist/testing/require-test-companion/index.d.ts.map +1 -0
  223. package/dist/testing/require-test-companion/index.js +3 -0
  224. package/dist/testing/require-test-companion/require-test-companion-listeners.d.ts +16 -0
  225. package/dist/testing/require-test-companion/require-test-companion-listeners.d.ts.map +1 -0
  226. package/dist/testing/require-test-companion/require-test-companion-listeners.js +145 -0
  227. package/dist/testing/require-test-companion/require-test-companion-options.d.ts +54 -0
  228. package/dist/testing/require-test-companion/require-test-companion-options.d.ts.map +1 -0
  229. package/dist/testing/require-test-companion/require-test-companion-options.js +112 -0
  230. package/dist/testing/require-test-companion/require-test-companion-test-helpers.d.ts +51 -0
  231. package/dist/testing/require-test-companion/require-test-companion-test-helpers.d.ts.map +1 -0
  232. package/dist/testing/require-test-companion/require-test-companion-test-helpers.js +183 -0
  233. package/dist/testing/require-test-companion/require-test-companion-utilities.d.ts +28 -0
  234. package/dist/testing/require-test-companion/require-test-companion-utilities.d.ts.map +1 -0
  235. package/dist/testing/require-test-companion/require-test-companion-utilities.js +26 -0
  236. package/dist/testing/require-test-companion/rule.d.ts +5 -0
  237. package/dist/testing/require-test-companion/rule.d.ts.map +1 -0
  238. package/dist/testing/require-test-companion/rule.js +57 -0
  239. package/dist/testing/require-test-companion/types.d.ts +11 -0
  240. package/dist/testing/require-test-companion/types.d.ts.map +1 -0
  241. package/dist/testing/require-test-companion/types.js +2 -0
  242. package/dist/testing/single-act-statement/index.d.ts +2 -0
  243. package/dist/testing/single-act-statement/index.d.ts.map +1 -0
  244. package/dist/testing/single-act-statement/index.js +2 -0
  245. package/dist/testing/single-act-statement/rule.d.ts +4 -0
  246. package/dist/testing/single-act-statement/rule.d.ts.map +1 -0
  247. package/dist/testing/single-act-statement/rule.js +33 -0
  248. package/package.json +106 -0
@@ -0,0 +1,111 @@
1
+ import { createRuleDocumentation } from "../../custom-rule-documentation";
2
+ import { aaaPhaseOrder, analyzeTestBlock, getLineStartRange, getPhaseBoundaryComments, hasBlankLineBeforeComment, } from "../aaa";
3
+ const requireAaaSectionsRule = {
4
+ create(context) {
5
+ return {
6
+ CallExpression(node) {
7
+ const analysis = analyzeTestBlock(context, node);
8
+ if (analysis === void 0) {
9
+ return;
10
+ }
11
+ reportMissingSections(context, analysis);
12
+ reportCodeBeforeArrange(context, analysis);
13
+ reportBlankLineSeparators(context, analysis);
14
+ },
15
+ };
16
+ },
17
+ meta: {
18
+ docs: createRuleDocumentation("require-aaa-sections", "Require strict // Arrange, // Act, and // Assert markers in supported test blocks."),
19
+ fixable: "code",
20
+ messages: {
21
+ blankLineBeforeSection: "Insert a blank line before the // {{section}} section comment.",
22
+ codeBeforeArrange: "Move setup statements below the first // Arrange section comment.",
23
+ missingSections: "Add the missing AAA section comments: {{sections}}.",
24
+ },
25
+ schema: [],
26
+ type: "layout",
27
+ },
28
+ };
29
+ function reportBlankLineSeparators(context, analysis) {
30
+ for (const sectionComment of getPhaseBoundaryComments(analysis)) {
31
+ if (hasBlankLineBeforeComment(analysis.sourceText, sectionComment.comment)) {
32
+ continue;
33
+ }
34
+ context.report({
35
+ data: { section: sectionComment.phases.join(" & ") },
36
+ fix: (fixer) => fixer.insertTextBeforeRange(getLineStartRange(analysis.sourceText, sectionComment.comment.loc.start.line), analysis.newline),
37
+ messageId: "blankLineBeforeSection",
38
+ node: sectionComment.comment,
39
+ });
40
+ }
41
+ }
42
+ function reportCodeBeforeArrange(context, analysis) {
43
+ const firstArrangeLine = analysis.sectionComments.find((sectionComment) => sectionComment.phases.includes("Arrange"))?.comment.loc.start.line;
44
+ if (firstArrangeLine === void 0) {
45
+ return;
46
+ }
47
+ const statementBeforeArrange = analysis.statements.find((statement) => statement.node.loc.start.line < firstArrangeLine);
48
+ if (statementBeforeArrange === void 0) {
49
+ return;
50
+ }
51
+ context.report({
52
+ messageId: "codeBeforeArrange",
53
+ node: statementBeforeArrange.node,
54
+ });
55
+ }
56
+ function reportMissingSections(context, analysis) {
57
+ const presentSections = new Set(analysis.sectionComments.flatMap((sectionComment) => sectionComment.phases));
58
+ const missingSections = ["Arrange", "Act", "Assert"].filter((phase) => !presentSections.has(phase));
59
+ if (missingSections.length === 0) {
60
+ return;
61
+ }
62
+ context.report({
63
+ data: { sections: missingSections.join(", ") },
64
+ fix: analysis.bodyLineCount >= 3
65
+ ? (fixer) => buildMissingSectionFixes(analysis, missingSections, fixer)
66
+ : null,
67
+ messageId: "missingSections",
68
+ node: analysis.callExpression,
69
+ });
70
+ }
71
+ function buildMissingSectionFixes(analysis, missingSections, fixer) {
72
+ if (analysis.statements.length === 0) {
73
+ return [];
74
+ }
75
+ const anchorMap = new Map();
76
+ const sourceLines = analysis.sourceText.split(/\r\n|\n/u);
77
+ const firstStatement = analysis.statements[0]?.node;
78
+ const middleStatement = analysis.statements[Math.min(analysis.statements.length - 1, Math.floor(analysis.statements.length / 2))]?.node;
79
+ const lastStatement = analysis.statements.at(-1)?.node;
80
+ for (const phase of missingSections) {
81
+ const anchorNode = phase === "Arrange"
82
+ ? firstStatement
83
+ : phase === "Act"
84
+ ? middleStatement
85
+ : lastStatement;
86
+ /* v8 ignore start -- guarded by the empty-statements early return above. */
87
+ if (anchorNode === void 0) {
88
+ continue;
89
+ }
90
+ /* v8 ignore stop */
91
+ const existing = anchorMap.get(anchorNode.range[0]) ?? [];
92
+ existing.push(phase);
93
+ anchorMap.set(anchorNode.range[0], existing);
94
+ }
95
+ return [...anchorMap.entries()].map(([offset, phases]) => {
96
+ const sortedPhases = phases.toSorted((left, right) => aaaPhaseOrder[left] - aaaPhaseOrder[right]);
97
+ const statementLine = analysis.sourceText
98
+ .slice(0, offset)
99
+ .split(/\r\n|\n/u).length;
100
+ /* v8 ignore start -- fixer anchors always point to real statement lines in analyzed test blocks. */
101
+ const previousLine = sourceLines[statementLine - 2] ?? "";
102
+ const lineStartRange = getLineStartRange(analysis.sourceText, statementLine);
103
+ const needsLeadingBlankLine = sortedPhases.some((phase) => phase !== "Arrange") &&
104
+ previousLine.trim().length > 0;
105
+ const indentation = /^\s*/u.exec(sourceLines[statementLine - 1] ?? "")?.[0] ?? "";
106
+ /* v8 ignore stop */
107
+ return fixer.insertTextBeforeRange(lineStartRange, `${needsLeadingBlankLine ? analysis.newline : ""}${indentation}// ${sortedPhases.join(" & ")}${analysis.newline}`);
108
+ });
109
+ }
110
+ export { requireAaaSectionsRule };
111
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZXN0aW5nL3JlcXVpcmUtYWFhLXNlY3Rpb25zL3J1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBSUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUNMLGFBQWEsRUFDYixnQkFBZ0IsRUFFaEIsaUJBQWlCLEVBQ2pCLHdCQUF3QixFQUN4Qix5QkFBeUIsR0FDMUIsTUFBTSxRQUFRLENBQUM7QUFFaEIsTUFBTSxzQkFBc0IsR0FBb0I7SUFDOUMsTUFBTSxDQUFDLE9BQXlCO1FBQzlCLE9BQU87WUFDTCxjQUFjLENBQUMsSUFBSTtnQkFDakIsTUFBTSxRQUFRLEdBQUcsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUNqRCxJQUFJLFFBQVEsS0FBSyxLQUFLLENBQUMsRUFBRSxDQUFDO29CQUN4QixPQUFPO2dCQUNULENBQUM7Z0JBRUQscUJBQXFCLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO2dCQUN6Qyx1QkFBdUIsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQzNDLHlCQUF5QixDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztZQUMvQyxDQUFDO1NBQzBCLENBQUM7SUFDaEMsQ0FBQztJQUNELElBQUksRUFBRTtRQUNKLElBQUksRUFBRSx1QkFBdUIsQ0FDM0Isc0JBQXNCLEVBQ3RCLG9GQUFvRixDQUNyRjtRQUNELE9BQU8sRUFBRSxNQUFNO1FBQ2YsUUFBUSxFQUFFO1lBQ1Isc0JBQXNCLEVBQ3BCLGdFQUFnRTtZQUNsRSxpQkFBaUIsRUFDZixtRUFBbUU7WUFDckUsZUFBZSxFQUFFLHFEQUFxRDtTQUN2RTtRQUNELE1BQU0sRUFBRSxFQUFFO1FBQ1YsSUFBSSxFQUFFLFFBQVE7S0FDZjtDQUNGLENBQUM7QUFFRixTQUFTLHlCQUF5QixDQUNoQyxPQUF5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Q0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2hFLG9CQUFvQjtRQUVwQixPQUFPLEtBQUssQ0FBQyxxQkFBcUIsQ0FDaEMsY0FBYyxFQUNkLEdBQUcscUJBQXFCLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxXQUFXLE1BQU0sWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQ2xILENBQUM7SUFDSixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgUnVsZSB9IGZyb20gXCJlc2xpbnRcIjtcblxuaW1wb3J0IHR5cGUgeyBBYWFQaGFzZSwgVGVzdEJsb2NrQW5hbHlzaXMgfSBmcm9tIFwiLi4vYWFhXCI7XG5cbmltcG9ydCB7IGNyZWF0ZVJ1bGVEb2N1bWVudGF0aW9uIH0gZnJvbSBcIi4uLy4uL2N1c3RvbS1ydWxlLWRvY3VtZW50YXRpb25cIjtcbmltcG9ydCB7XG4gIGFhYVBoYXNlT3JkZXIsXG4gIGFuYWx5emVUZXN0QmxvY2ssXG4gIGdldEluZGVudGF0aW9uQXRPZmZzZXQsXG4gIGdldExpbmVTdGFydFJhbmdlLFxuICBnZXRQaGFzZUJvdW5kYXJ5Q29tbWVudHMsXG4gIGhhc0JsYW5rTGluZUJlZm9yZUNvbW1lbnQsXG59IGZyb20gXCIuLi9hYWFcIjtcblxuY29uc3QgcmVxdWlyZUFhYVNlY3Rpb25zUnVsZTogUnVsZS5SdWxlTW9kdWxlID0ge1xuICBjcmVhdGUoY29udGV4dDogUnVsZS5SdWxlQ29udGV4dCk6IFJ1bGUuUnVsZUxpc3RlbmVyIHtcbiAgICByZXR1cm4ge1xuICAgICAgQ2FsbEV4cHJlc3Npb24obm9kZSk6IHZvaWQge1xuICAgICAgICBjb25zdCBhbmFseXNpcyA9IGFuYWx5emVUZXN0QmxvY2soY29udGV4dCwgbm9kZSk7XG4gICAgICAgIGlmIChhbmFseXNpcyA9PT0gdm9pZCAwKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVwb3J0TWlzc2luZ1NlY3Rpb25zKGNvbnRleHQsIGFuYWx5c2lzKTtcbiAgICAgICAgcmVwb3J0Q29kZUJlZm9yZUFycmFuZ2UoY29udGV4dCwgYW5hbHlzaXMpO1xuICAgICAgICByZXBvcnRCbGFua0xpbmVTZXBhcmF0b3JzKGNvbnRleHQsIGFuYWx5c2lzKTtcbiAgICAgIH0sXG4gICAgfSBzYXRpc2ZpZXMgUnVsZS5SdWxlTGlzdGVuZXI7XG4gIH0sXG4gIG1ldGE6IHtcbiAgICBkb2NzOiBjcmVhdGVSdWxlRG9jdW1lbnRhdGlvbihcbiAgICAgIFwicmVxdWlyZS1hYWEtc2VjdGlvbnNcIixcbiAgICAgIFwiUmVxdWlyZSBzdHJpY3QgLy8gQXJyYW5nZSwgLy8gQWN0LCBhbmQgLy8gQXNzZXJ0IG1hcmtlcnMgaW4gc3VwcG9ydGVkIHRlc3QgYmxvY2tzLlwiLFxuICAgICksXG4gICAgZml4YWJsZTogXCJjb2RlXCIsXG4gICAgbWVzc2FnZXM6IHtcbiAgICAgIGJsYW5rTGluZUJlZm9yZVNlY3Rpb246XG4gICAgICAgIFwiSW5zZXJ0IGEgYmxhbmsgbGluZSBiZWZvcmUgdGhlIC8vIHt7c2VjdGlvbn19IHNlY3Rpb24gY29tbWVudC5cIixcbiAgICAgIGNvZGVCZWZvcmVBcnJhbmdlOlxuICAgICAgICBcIk1vdmUgc2V0dXAgc3RhdGVtZW50cyBiZWxvdyB0aGUgZmlyc3QgLy8gQXJyYW5nZSBzZWN0aW9uIGNvbW1lbnQuXCIsXG4gICAgICBtaXNzaW5nU2VjdGlvbnM6IFwiQWRkIHRoZSBtaXNzaW5nIEFBQSBzZWN0aW9uIGNvbW1lbnRzOiB7e3NlY3Rpb25zfX0uXCIsXG4gICAgfSxcbiAgICBzY2hlbWE6IFtdLFxuICAgIHR5cGU6IFwibGF5b3V0XCIsXG4gIH0sXG59O1xuXG5mdW5jdGlvbiByZXBvcnRCbGFua0xpbmVTZXBhcmF0b3JzKFxuICBjb250ZXh0OiBSdWxlLlJ1bGVDb250ZXh0LFxuICBhbmFseXNpczogVGVzdEJsb2NrQW5hbHlzaXMsXG4pOiB2b2lkIHtcbiAgZm9yIChjb25zdCBzZWN0aW9uQ29tbWVudCBvZiBnZXRQaGFzZUJvdW5kYXJ5Q29tbWVudHMoYW5hbHlzaXMpKSB7XG4gICAgaWYgKFxuICAgICAgaGFzQmxhbmtMaW5lQmVmb3JlQ29tbWVudChhbmFseXNpcy5zb3VyY2VUZXh0LCBzZWN0aW9uQ29tbWVudC5jb21tZW50KVxuICAgICkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29udGV4dC5yZXBvcnQoe1xuICAgICAgZGF0YTogeyBzZWN0aW9uOiBzZWN0aW9uQ29tbWVudC5waGFzZXMuam9pbihcIiAmIFwiKSB9LFxuICAgICAgZml4OiAoZml4ZXIpID0+XG4gICAgICAgIGZpeGVyLmluc2VydFRleHRCZWZvcmVSYW5nZShcbiAgICAgICAgICBnZXRMaW5lU3RhcnRSYW5nZShcbiAgICAgICAgICAgIGFuYWx5c2lzLnNvdXJjZVRleHQsXG4gICAgICAgICAgICBzZWN0aW9uQ29tbWVudC5jb21tZW50LmxvYy5zdGFydC5saW5lLFxuICAgICAgICAgICksXG4gICAgICAgICAgYW5hbHlzaXMubmV3bGluZSxcbiAgICAgICAgKSxcbiAgICAgIG1lc3NhZ2VJZDogXCJibGFua0xpbmVCZWZvcmVTZWN0aW9uXCIsXG4gICAgICBub2RlOiBzZWN0aW9uQ29tbWVudC5jb21tZW50LFxuICAgIH0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlcG9ydENvZGVCZWZvcmVBcnJhbmdlKFxuICBjb250ZXh0OiBSdWxlLlJ1bGVDb250ZXh0LFxuICBhbmFseXNpczogVGVzdEJsb2NrQW5hbHlzaXMsXG4pOiB2b2lkIHtcbiAgY29uc3QgZmlyc3RBcnJhbmdlTGluZSA9IGFuYWx5c2lzLnNlY3Rpb25Db21tZW50cy5maW5kKChzZWN0aW9uQ29tbWVudCkgPT5cbiAgICBzZWN0aW9uQ29tbWVudC5waGFzZXMuaW5jbHVkZXMoXCJBcnJhbmdlXCIpLFxuICApPy5jb21tZW50LmxvYy5zdGFydC5saW5lO1xuICBpZiAoZmlyc3RBcnJhbmdlTGluZSA9PT0gdm9pZCAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3Qgc3RhdGVtZW50QmVmb3JlQXJyYW5nZSA9IGFuYWx5c2lzLnN0YXRlbWVudHMuZmluZChcbiAgICAoc3RhdGVtZW50KSA9PiBzdGF0ZW1lbnQubm9kZS5sb2Muc3RhcnQubGluZSA8IGZpcnN0QXJyYW5nZUxpbmUsXG4gICk7XG4gIGlmIChzdGF0ZW1lbnRCZWZvcmVBcnJhbmdlID09PSB2b2lkIDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb250ZXh0LnJlcG9ydCh7XG4gICAgbWVzc2FnZUlkOiBcImNvZGVCZWZvcmVBcnJhbmdlXCIsXG4gICAgbm9kZTogc3RhdGVtZW50QmVmb3JlQXJyYW5nZS5ub2RlLFxuICB9KTtcbn1cblxuZnVuY3Rpb24gcmVwb3J0TWlzc2luZ1NlY3Rpb25zKFxuICBjb250ZXh0OiBSdWxlLlJ1bGVDb250ZXh0LFxuICBhbmFseXNpczogVGVzdEJsb2NrQW5hbHlzaXMsXG4pOiB2b2lkIHtcbiAgY29uc3QgcHJlc2VudFNlY3Rpb25zID0gbmV3IFNldChcbiAgICBhbmFseXNpcy5zZWN0aW9uQ29tbWVudHMuZmxhdE1hcCgoc2VjdGlvbkNvbW1lbnQpID0+IHNlY3Rpb25Db21tZW50LnBoYXNlcyksXG4gICk7XG4gIGNvbnN0IG1pc3NpbmdTZWN0aW9ucyA9IChbXCJBcnJhbmdlXCIsIFwiQWN0XCIsIFwiQXNzZXJ0XCJdIGFzIGNvbnN0KS5maWx0ZXIoXG4gICAgKHBoYXNlKSA9PiAhcHJlc2VudFNlY3Rpb25zLmhhcyhwaGFzZSksXG4gICk7XG5cbiAgaWYgKG1pc3NpbmdTZWN0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb250ZXh0LnJlcG9ydCh7XG4gICAgZGF0YTogeyBzZWN0aW9uczogbWlzc2luZ1NlY3Rpb25zLmpvaW4oXCIsIFwiKSB9LFxuICAgIGZpeDpcbiAgICAgIGFuYWx5c2lzLmJvZHlMaW5lQ291bnQgPj0gM1xuICAgICAgICA/IChmaXhlcikgPT4gYnVpbGRNaXNzaW5nU2VjdGlvbkZpeGVzKGFuYWx5c2lzLCBtaXNzaW5nU2VjdGlvbnMsIGZpeGVyKVxuICAgICAgICA6IG51bGwsXG4gICAgbWVzc2FnZUlkOiBcIm1pc3NpbmdTZWN0aW9uc1wiLFxuICAgIG5vZGU6IGFuYWx5c2lzLmNhbGxFeHByZXNzaW9uLFxuICB9KTtcbn1cblxuZnVuY3Rpb24gYnVpbGRNaXNzaW5nU2VjdGlvbkZpeGVzKFxuICBhbmFseXNpczogVGVzdEJsb2NrQW5hbHlzaXMsXG4gIG1pc3NpbmdTZWN0aW9uczogcmVhZG9ubHkgQWFhUGhhc2VbXSxcbiAgZml4ZXI6IFJ1bGUuUnVsZUZpeGVyLFxuKTogUnVsZS5GaXhbXSB7XG4gIGlmIChhbmFseXNpcy5zdGF0ZW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGNvbnN0IGFuY2hvck1hcCA9IG5ldyBNYXA8bnVtYmVyLCBBYWFQaGFzZVtdPigpO1xuICBjb25zdCBzb3VyY2VMaW5lcyA9IGFuYWx5c2lzLnNvdXJjZVRleHQuc3BsaXQoL1xcclxcbnxcXG4vdSk7XG4gIGNvbnN0IGZpcnN0U3RhdGVtZW50ID0gYW5hbHlzaXMuc3RhdGVtZW50c1swXT8ubm9kZTtcbiAgY29uc3QgbWlkZGxlU3RhdGVtZW50ID1cbiAgICBhbmFseXNpcy5zdGF0ZW1lbnRzW1xuICAgICAgTWF0aC5taW4oXG4gICAgICAgIGFuYWx5c2lzLnN0YXRlbWVudHMubGVuZ3RoIC0gMSxcbiAgICAgICAgTWF0aC5mbG9vcihhbmFseXNpcy5zdGF0ZW1lbnRzLmxlbmd0aCAvIDIpLFxuICAgICAgKVxuICAgIF0/Lm5vZGU7XG4gIGNvbnN0IGxhc3RTdGF0ZW1lbnQgPSBhbmFseXNpcy5zdGF0ZW1lbnRzLmF0KC0xKT8ubm9kZTtcblxuICBmb3IgKGNvbnN0IHBoYXNlIG9mIG1pc3NpbmdTZWN0aW9ucykge1xuICAgIGNvbnN0IGFuY2hvck5vZGUgPVxuICAgICAgcGhhc2UgPT09IFwiQXJyYW5nZVwiXG4gICAgICAgID8gZmlyc3RTdGF0ZW1lbnRcbiAgICAgICAgOiBwaGFzZSA9PT0gXCJBY3RcIlxuICAgICAgICAgID8gbWlkZGxlU3RhdGVtZW50XG4gICAgICAgICAgOiBsYXN0U3RhdGVtZW50O1xuICAgIC8qIHY4IGlnbm9yZSBzdGFydCAtLSBndWFyZGVkIGJ5IHRoZSBlbXB0eS1zdGF0ZW1lbnRzIGVhcmx5IHJldHVybiBhYm92ZS4gKi9cbiAgICBpZiAoYW5jaG9yTm9kZSA9PT0gdm9pZCAwKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgLyogdjggaWdub3JlIHN0b3AgKi9cblxuICAgIGNvbnN0IGV4aXN0aW5nID0gYW5jaG9yTWFwLmdldChhbmNob3JOb2RlLnJhbmdlWzBdKSA/PyBbXTtcbiAgICBleGlzdGluZy5wdXNoKHBoYXNlKTtcbiAgICBhbmNob3JNYXAuc2V0KGFuY2hvck5vZGUucmFuZ2VbMF0sIGV4aXN0aW5nKTtcbiAgfVxuXG4gIHJldHVybiBbLi4uYW5jaG9yTWFwLmVudHJpZXMoKV0ubWFwKChbb2Zmc2V0LCBwaGFzZXNdKSA9PiB7XG4gICAgY29uc3Qgc29ydGVkUGhhc2VzID0gcGhhc2VzLnRvU29ydGVkKFxuICAgICAgKGxlZnQsIHJpZ2h0KSA9PiBhYWFQaGFzZU9yZGVyW2xlZnRdIC0gYWFhUGhhc2VPcmRlcltyaWdodF0sXG4gICAgKTtcbiAgICBjb25zdCBzdGF0ZW1lbnRMaW5lID0gYW5hbHlzaXMuc291cmNlVGV4dFxuICAgICAgLnNsaWNlKDAsIG9mZnNldClcbiAgICAgIC5zcGxpdCgvXFxyXFxufFxcbi91KS5sZW5ndGg7XG4gICAgLyogdjggaWdub3JlIHN0YXJ0IC0tIGZpeGVyIGFuY2hvcnMgYWx3YXlzIHBvaW50IHRvIHJlYWwgc3RhdGVtZW50IGxpbmVzIGluIGFuYWx5emVkIHRlc3QgYmxvY2tzLiAqL1xuICAgIGNvbnN0IHByZXZpb3VzTGluZSA9IHNvdXJjZUxpbmVzW3N0YXRlbWVudExpbmUgLSAyXSA/PyBcIlwiO1xuICAgIGNvbnN0IGxpbmVTdGFydFJhbmdlID0gZ2V0TGluZVN0YXJ0UmFuZ2UoXG4gICAgICBhbmFseXNpcy5zb3VyY2VUZXh0LFxuICAgICAgc3RhdGVtZW50TGluZSxcbiAgICApO1xuICAgIGNvbnN0IG5lZWRzTGVhZGluZ0JsYW5rTGluZSA9XG4gICAgICBzb3J0ZWRQaGFzZXMuc29tZSgocGhhc2UpID0+IHBoYXNlICE9PSBcIkFycmFuZ2VcIikgJiZcbiAgICAgIHByZXZpb3VzTGluZS50cmltKCkubGVuZ3RoID4gMDtcbiAgICBjb25zdCBpbmRlbnRhdGlvbiA9XG4gICAgICAvXlxccyovdS5leGVjKHNvdXJjZUxpbmVzW3N0YXRlbWVudExpbmUgLSAxXSA/PyBcIlwiKT8uWzBdID8/IFwiXCI7XG4gICAgLyogdjggaWdub3JlIHN0b3AgKi9cblxuICAgIHJldHVybiBmaXhlci5pbnNlcnRUZXh0QmVmb3JlUmFuZ2UoXG4gICAgICBsaW5lU3RhcnRSYW5nZSxcbiAgICAgIGAke25lZWRzTGVhZGluZ0JsYW5rTGluZSA/IGFuYWx5c2lzLm5ld2xpbmUgOiBcIlwifSR7aW5kZW50YXRpb259Ly8gJHtzb3J0ZWRQaGFzZXMuam9pbihcIiAmIFwiKX0ke2FuYWx5c2lzLm5ld2xpbmV9YCxcbiAgICApO1xuICB9KTtcbn1cblxuZXhwb3J0IHsgcmVxdWlyZUFhYVNlY3Rpb25zUnVsZSB9O1xuIl19
@@ -0,0 +1,2 @@
1
+ export { requireActResultCaptureRule } from "./rule";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testing/require-act-result-capture/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,QAAQ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { requireActResultCaptureRule } from "./rule";
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdGVzdGluZy9yZXF1aXJlLWFjdC1yZXN1bHQtY2FwdHVyZS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgeyByZXF1aXJlQWN0UmVzdWx0Q2FwdHVyZVJ1bGUgfSBmcm9tIFwiLi9ydWxlXCI7XG4iXX0=
@@ -0,0 +1,4 @@
1
+ import type { Rule } from "eslint";
2
+ declare const requireActResultCaptureRule: Rule.RuleModule;
3
+ export { requireActResultCaptureRule };
4
+ //# sourceMappingURL=rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule.d.ts","sourceRoot":"","sources":["../../../src/testing/require-act-result-capture/rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAKnC,QAAA,MAAM,2BAA2B,EAAE,IAAI,CAAC,UAqCvC,CAAC;AAEF,OAAO,EAAE,2BAA2B,EAAE,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { createRuleDocumentation } from "../../custom-rule-documentation";
2
+ import { analyzeTestBlock, hasCapturableActResult } from "../aaa";
3
+ const requireActResultCaptureRule = {
4
+ create(context) {
5
+ return {
6
+ CallExpression(node) {
7
+ const analysis = analyzeTestBlock(context, node);
8
+ if (analysis === void 0) {
9
+ return;
10
+ }
11
+ for (const statement of analysis.statements) {
12
+ if (statement.phase !== "Act" ||
13
+ !hasCapturableActResult(statement.node)) {
14
+ continue;
15
+ }
16
+ context.report({
17
+ messageId: "captureActResult",
18
+ node: statement.node,
19
+ });
20
+ }
21
+ },
22
+ };
23
+ },
24
+ meta: {
25
+ docs: createRuleDocumentation("require-act-result-capture", "Require non-void Act expressions to store the observed result before assertions."),
26
+ messages: {
27
+ captureActResult: "Capture the // Act result in a named variable before asserting on it.",
28
+ },
29
+ schema: [],
30
+ type: "suggestion",
31
+ },
32
+ };
33
+ export { requireActResultCaptureRule };
34
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZXN0aW5nL3JlcXVpcmUtYWN0LXJlc3VsdC1jYXB0dXJlL3J1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLHNCQUFzQixFQUFFLE1BQU0sUUFBUSxDQUFDO0FBRWxFLE1BQU0sMkJBQTJCLEdBQW9CO0lBQ25ELE1BQU0sQ0FBQyxPQUF5QjtRQUM5QixPQUFPO1lBQ0wsY0FBYyxDQUFDLElBQUk7Z0JBQ2pCLE1BQU0sUUFBUSxHQUFHLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFDakQsSUFBSSxRQUFRLEtBQUssS0FBSyxDQUFDLEVBQUUsQ0FBQztvQkFDeEIsT0FBTztnQkFDVCxDQUFDO2dCQUVELEtBQUssTUFBTSxTQUFTLElBQUksUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDO29CQUM1QyxJQUNFLFNBQVMsQ0FBQyxLQUFLLEtBQUssS0FBSzt3QkFDekIsQ0FBQyxzQkFBc0IsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQ3ZDLENBQUM7d0JBQ0QsU0FBUztvQkFDWCxDQUFDO29CQUVELE9BQU8sQ0FBQyxNQUFNLENBQUM7d0JBQ2IsU0FBUyxFQUFFLGtCQUFrQjt3QkFDN0IsSUFBSSxFQUFFLFNBQVMsQ0FBQyxJQUFJO3FCQUNyQixDQUFDLENBQUM7Z0JBQ0wsQ0FBQztZQUNILENBQUM7U0FDMEIsQ0FBQztJQUNoQyxDQUFDO0lBQ0QsSUFBSSxFQUFFO1FBQ0osSUFBSSxFQUFFLHVCQUF1QixDQUMzQiw0QkFBNEIsRUFDNUIsa0ZBQWtGLENBQ25GO1FBQ0QsUUFBUSxFQUFFO1lBQ1IsZ0JBQWdCLEVBQ2QsdUVBQXVFO1NBQzFFO1FBQ0QsTUFBTSxFQUFFLEVBQUU7UUFDVixJQUFJLEVBQUUsWUFBWTtLQUNuQjtDQUNGLENBQUM7QUFFRixPQUFPLEVBQUUsMkJBQTJCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgUnVsZSB9IGZyb20gXCJlc2xpbnRcIjtcblxuaW1wb3J0IHsgY3JlYXRlUnVsZURvY3VtZW50YXRpb24gfSBmcm9tIFwiLi4vLi4vY3VzdG9tLXJ1bGUtZG9jdW1lbnRhdGlvblwiO1xuaW1wb3J0IHsgYW5hbHl6ZVRlc3RCbG9jaywgaGFzQ2FwdHVyYWJsZUFjdFJlc3VsdCB9IGZyb20gXCIuLi9hYWFcIjtcblxuY29uc3QgcmVxdWlyZUFjdFJlc3VsdENhcHR1cmVSdWxlOiBSdWxlLlJ1bGVNb2R1bGUgPSB7XG4gIGNyZWF0ZShjb250ZXh0OiBSdWxlLlJ1bGVDb250ZXh0KTogUnVsZS5SdWxlTGlzdGVuZXIge1xuICAgIHJldHVybiB7XG4gICAgICBDYWxsRXhwcmVzc2lvbihub2RlKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGFuYWx5c2lzID0gYW5hbHl6ZVRlc3RCbG9jayhjb250ZXh0LCBub2RlKTtcbiAgICAgICAgaWYgKGFuYWx5c2lzID09PSB2b2lkIDApIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IHN0YXRlbWVudCBvZiBhbmFseXNpcy5zdGF0ZW1lbnRzKSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgc3RhdGVtZW50LnBoYXNlICE9PSBcIkFjdFwiIHx8XG4gICAgICAgICAgICAhaGFzQ2FwdHVyYWJsZUFjdFJlc3VsdChzdGF0ZW1lbnQubm9kZSlcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnRleHQucmVwb3J0KHtcbiAgICAgICAgICAgIG1lc3NhZ2VJZDogXCJjYXB0dXJlQWN0UmVzdWx0XCIsXG4gICAgICAgICAgICBub2RlOiBzdGF0ZW1lbnQubm9kZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9IHNhdGlzZmllcyBSdWxlLlJ1bGVMaXN0ZW5lcjtcbiAgfSxcbiAgbWV0YToge1xuICAgIGRvY3M6IGNyZWF0ZVJ1bGVEb2N1bWVudGF0aW9uKFxuICAgICAgXCJyZXF1aXJlLWFjdC1yZXN1bHQtY2FwdHVyZVwiLFxuICAgICAgXCJSZXF1aXJlIG5vbi12b2lkIEFjdCBleHByZXNzaW9ucyB0byBzdG9yZSB0aGUgb2JzZXJ2ZWQgcmVzdWx0IGJlZm9yZSBhc3NlcnRpb25zLlwiLFxuICAgICksXG4gICAgbWVzc2FnZXM6IHtcbiAgICAgIGNhcHR1cmVBY3RSZXN1bHQ6XG4gICAgICAgIFwiQ2FwdHVyZSB0aGUgLy8gQWN0IHJlc3VsdCBpbiBhIG5hbWVkIHZhcmlhYmxlIGJlZm9yZSBhc3NlcnRpbmcgb24gaXQuXCIsXG4gICAgfSxcbiAgICBzY2hlbWE6IFtdLFxuICAgIHR5cGU6IFwic3VnZ2VzdGlvblwiLFxuICB9LFxufTtcblxuZXhwb3J0IHsgcmVxdWlyZUFjdFJlc3VsdENhcHR1cmVSdWxlIH07XG4iXX0=
@@ -0,0 +1,3 @@
1
+ export { buildListenerForFilename, getOptions, } from "./require-test-companion-utilities";
2
+ export { requireTestCompanionRule } from "./rule";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testing/require-test-companion/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,UAAU,GACX,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,QAAQ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { buildListenerForFilename, getOptions, } from "./require-test-companion-utilities";
2
+ export { requireTestCompanionRule } from "./rule";
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdGVzdGluZy9yZXF1aXJlLXRlc3QtY29tcGFuaW9uL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCx3QkFBd0IsRUFDeEIsVUFBVSxHQUNYLE1BQU0sb0NBQW9DLENBQUM7QUFDNUMsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHtcbiAgYnVpbGRMaXN0ZW5lckZvckZpbGVuYW1lLFxuICBnZXRPcHRpb25zLFxufSBmcm9tIFwiLi9yZXF1aXJlLXRlc3QtY29tcGFuaW9uLXV0aWxpdGllc1wiO1xuZXhwb3J0IHsgcmVxdWlyZVRlc3RDb21wYW5pb25SdWxlIH0gZnJvbSBcIi4vcnVsZVwiO1xuIl19
@@ -0,0 +1,16 @@
1
+ import type { Rule } from "eslint";
2
+ import type { RequireTestCompanionState } from "./require-test-companion-options";
3
+ /**
4
+ * Builds a listener for a specific filename.
5
+ * @param context Input context value.
6
+ * @param filename Input filename value.
7
+ * @param options Input options value.
8
+ * @returns Rule listener for the filename.
9
+ * @example
10
+ * ```typescript
11
+ * const listener = buildListenerForFilename(context, filename, options);
12
+ * ```
13
+ */
14
+ declare const buildListenerForFilename: (context: Rule.RuleContext, filename: string, options: RequireTestCompanionState) => Rule.RuleListener;
15
+ export { buildListenerForFilename };
16
+ //# sourceMappingURL=require-test-companion-listeners.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-test-companion-listeners.d.ts","sourceRoot":"","sources":["../../../src/testing/require-test-companion/require-test-companion-listeners.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAKnC,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAuLlF;;;;;;;;;;GAUG;AACH,QAAA,MAAM,wBAAwB,GAC5B,SAAS,IAAI,CAAC,WAAW,EACzB,UAAU,MAAM,EAChB,SAAS,yBAAyB,KACjC,IAAI,CAAC,YAuBP,CAAC;AAEF,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
@@ -0,0 +1,145 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { isLintableFilename, isPathMatch, isTypeScriptFile, TYPESCRIPT_EXTENSION, } from "./require-test-companion-options";
4
+ /**
5
+ * Gets the test suffix for a file name when present.
6
+ * @param basename Input basename value.
7
+ * @param testSuffixes Input testSuffixes value.
8
+ * @returns Matched test suffix when present.
9
+ * @example
10
+ * ```typescript
11
+ * const suffix = getTestSuffix("feature.spec.ts", ["spec"]);
12
+ * ```
13
+ */
14
+ const getTestSuffix = (basename, testSuffixes) => testSuffixes.find((suffix) => basename.endsWith(`.${suffix}${TYPESCRIPT_EXTENSION}`));
15
+ /**
16
+ * Checks for any test companion file in the directory.
17
+ * @param directory Input directory value.
18
+ * @param baseStem Input baseStem value.
19
+ * @param testSuffixes Input testSuffixes value.
20
+ * @returns True when any test companion exists.
21
+ * @example
22
+ * ```typescript
23
+ * const ok = hasAnyTestCompanion(dir, "feature", ["spec"]);
24
+ * ```
25
+ */
26
+ const hasAnyTestCompanion = (directory, baseStem, testSuffixes) => testSuffixes.some((suffix) => fs.existsSync(path.join(directory, `${baseStem}.${suffix}.ts`)));
27
+ /**
28
+ * Builds a listener that reports missing test companions.
29
+ * @param context Input context value.
30
+ * @param options Input options value.
31
+ * @returns Rule listener for missing tests.
32
+ * @example
33
+ * ```typescript
34
+ * const listener = buildMissingTestListener(context, options);
35
+ * ```
36
+ */
37
+ const buildMissingTestListener = (context, options) => {
38
+ const { basename, directory, testSuffixes } = options;
39
+ const baseStem = basename.slice(0, -TYPESCRIPT_EXTENSION.length);
40
+ if (baseStem.length === 0) {
41
+ return {};
42
+ }
43
+ if (hasAnyTestCompanion(directory, baseStem, testSuffixes)) {
44
+ return {};
45
+ }
46
+ return {
47
+ Program(node) {
48
+ const testFiles = testSuffixes
49
+ .map((suffix) => `${baseStem}.${suffix}${TYPESCRIPT_EXTENSION}`)
50
+ .join(", ");
51
+ context.report({
52
+ data: { testFiles },
53
+ messageId: "missingTest",
54
+ node,
55
+ });
56
+ },
57
+ };
58
+ };
59
+ /**
60
+ * Builds a listener that reports missing source files.
61
+ * @param context Input context value.
62
+ * @param options Input options value.
63
+ * @returns Rule listener for missing sources.
64
+ * @example
65
+ * ```typescript
66
+ * const listener = buildMissingSourceListener(context, options);
67
+ * ```
68
+ */
69
+ const buildMissingSourceListener = (context, options) => {
70
+ const { basename, directory, suffix } = options;
71
+ const sourceBasename = basename.slice(0, -`.${suffix}${TYPESCRIPT_EXTENSION}`.length);
72
+ if (sourceBasename.length === 0) {
73
+ return {};
74
+ }
75
+ const sourceFile = `${sourceBasename}${TYPESCRIPT_EXTENSION}`;
76
+ if (fs.existsSync(path.join(directory, sourceFile))) {
77
+ return {};
78
+ }
79
+ return {
80
+ Program(node) {
81
+ context.report({
82
+ data: { sourceFile },
83
+ messageId: "missingSource",
84
+ node,
85
+ });
86
+ },
87
+ };
88
+ };
89
+ /**
90
+ * Determines whether a file should be linted.
91
+ * @param filename Input filename value.
92
+ * @param options Input options value.
93
+ * @returns True when the file should be linted.
94
+ * @example
95
+ * ```typescript
96
+ * const ok = shouldLintFile(filename, options);
97
+ * ```
98
+ */
99
+ const shouldLintFile = (filename, options) => {
100
+ const { enforceIn, ignorePatterns } = options;
101
+ if (!isLintableFilename(filename)) {
102
+ return false;
103
+ }
104
+ if (!isTypeScriptFile(filename)) {
105
+ return false;
106
+ }
107
+ if (!isPathMatch(filename, enforceIn)) {
108
+ return false;
109
+ }
110
+ return !isPathMatch(filename, ignorePatterns);
111
+ };
112
+ /**
113
+ * Builds a listener for a specific filename.
114
+ * @param context Input context value.
115
+ * @param filename Input filename value.
116
+ * @param options Input options value.
117
+ * @returns Rule listener for the filename.
118
+ * @example
119
+ * ```typescript
120
+ * const listener = buildListenerForFilename(context, filename, options);
121
+ * ```
122
+ */
123
+ const buildListenerForFilename = (context, filename, options) => {
124
+ if (!shouldLintFile(filename, options)) {
125
+ return {};
126
+ }
127
+ const basename = path.basename(filename);
128
+ const directory = path.dirname(filename);
129
+ const { testSuffixes } = options;
130
+ const testSuffix = getTestSuffix(basename, testSuffixes);
131
+ if (testSuffix !== void 0) {
132
+ return buildMissingSourceListener(context, {
133
+ basename,
134
+ directory,
135
+ suffix: testSuffix,
136
+ });
137
+ }
138
+ return buildMissingTestListener(context, {
139
+ basename,
140
+ directory,
141
+ testSuffixes,
142
+ });
143
+ };
144
+ export { buildListenerForFilename };
145
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWlyZS10ZXN0LWNvbXBhbmlvbi1saXN0ZW5lcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdGVzdGluZy9yZXF1aXJlLXRlc3QtY29tcGFuaW9uL3JlcXVpcmUtdGVzdC1jb21wYW5pb24tbGlzdGVuZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUN6QixPQUFPLElBQUksTUFBTSxXQUFXLENBQUM7QUFJN0IsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixXQUFXLEVBQ1gsZ0JBQWdCLEVBQ2hCLG9CQUFvQixHQUNyQixNQUFNLGtDQUFrQyxDQUFDO0FBMEIxQzs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLGFBQWEsR0FBRyxDQUNwQixRQUFnQixFQUNoQixZQUFzQixFQUNGLEVBQUUsQ0FDdEIsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQzNCLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxNQUFNLEdBQUcsb0JBQW9CLEVBQUUsQ0FBQyxDQUN2RCxDQUFDO0FBRUo7Ozs7Ozs7Ozs7R0FVRztBQUNILE1BQU0sbUJBQW1CLEdBQUcsQ0FDMUIsU0FBaUIsRUFDakIsUUFBZ0IsRUFDaEIsWUFBc0IsRUFDYixFQUFFLENBQ1gsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQzNCLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsR0FBRyxRQUFRLElBQUksTUFBTSxLQUFLLENBQUMsQ0FBQyxDQUNoRSxDQUFDO0FBRUo7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSx3QkFBd0IsR0FBRyxDQUMvQixPQUF5QixFQUN6QixPQUFtQyxFQUNoQixFQUFFO0lBQ3JCLE1BQU0sRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxHQUFHLE9BQU8sQ0FBQztJQUN0RCxN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QUFFLENBQUM7SUFDWixDQUFDO0lBRUQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN6QyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sRUFBRSxZQUFZLEVBQUUsR0FBRyxPQUFPLENBQUM7SUFDakMsTUFBTSxVQUFVLEdBQUcsYUFBYSxDQUFDLFFBQVEsRUFBRSxZQUFZLENBQUMsQ0FBQztJQUV6RCxJQUFJLFVBQVUsS0FBSyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzFCLE9BQU8sMEJBQTBCLENBQUMsT0FBTyxFQUFFO1lBQ3pDLFFBQVE7WUFDUixTQUFTO1lBQ1QsTUFBTSxFQUFFLFVBQVU7U0FDbkIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELE9BQU8sd0JBQXdCLENBQUMsT0FBTyxFQUFFO1FBQ3ZDLFFBQVE7UUFDUixTQUFTO1FBQ1QsWUFBWTtLQUNiLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQztBQUVGLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBSdWxlIH0gZnJvbSBcImVzbGludFwiO1xuXG5pbXBvcnQgZnMgZnJvbSBcIm5vZGU6ZnNcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcblxuaW1wb3J0IHR5cGUgeyBSZXF1aXJlVGVzdENvbXBhbmlvblN0YXRlIH0gZnJvbSBcIi4vcmVxdWlyZS10ZXN0LWNvbXBhbmlvbi1vcHRpb25zXCI7XG5cbmltcG9ydCB7XG4gIGlzTGludGFibGVGaWxlbmFtZSxcbiAgaXNQYXRoTWF0Y2gsXG4gIGlzVHlwZVNjcmlwdEZpbGUsXG4gIFRZUEVTQ1JJUFRfRVhURU5TSU9OLFxufSBmcm9tIFwiLi9yZXF1aXJlLXRlc3QtY29tcGFuaW9uLW9wdGlvbnNcIjtcblxuLyoqIFR5cGUgZGVmaW5pdGlvbiBmb3IgcnVsZSBkYXRhLiAqL1xuaW50ZXJmYWNlIE1pc3NpbmdTb3VyY2VMaXN0ZW5lck9wdGlvbnMge1xuICAvKiogQmFzZW5hbWUgZmllbGQgdmFsdWUuICovXG4gIGJhc2VuYW1lOiBzdHJpbmc7XG5cbiAgLyoqIERpcmVjdG9yeSBmaWVsZCB2YWx1ZS4gKi9cbiAgZGlyZWN0b3J5OiBzdHJpbmc7XG5cbiAgLyoqIFN1ZmZpeCBmaWVsZCB2YWx1ZS4gKi9cbiAgc3VmZml4OiBzdHJpbmc7XG59XG5cbi8qKiBUeXBlIGRlZmluaXRpb24gZm9yIHJ1bGUgZGF0YS4gKi9cbmludGVyZmFjZSBNaXNzaW5nVGVzdExpc3RlbmVyT3B0aW9ucyB7XG4gIC8qKiBCYXNlbmFtZSBmaWVsZCB2YWx1ZS4gKi9cbiAgYmFzZW5hbWU6IHN0cmluZztcblxuICAvKiogRGlyZWN0b3J5IGZpZWxkIHZhbHVlLiAqL1xuICBkaXJlY3Rvcnk6IHN0cmluZztcblxuICAvKiogVGVzdFN1ZmZpeGVzIGZpZWxkIHZhbHVlLiAqL1xuICB0ZXN0U3VmZml4ZXM6IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHRlc3Qgc3VmZml4IGZvciBhIGZpbGUgbmFtZSB3aGVuIHByZXNlbnQuXG4gKiBAcGFyYW0gYmFzZW5hbWUgSW5wdXQgYmFzZW5hbWUgdmFsdWUuXG4gKiBAcGFyYW0gdGVzdFN1ZmZpeGVzIElucHV0IHRlc3RTdWZmaXhlcyB2YWx1ZS5cbiAqIEByZXR1cm5zIE1hdGNoZWQgdGVzdCBzdWZmaXggd2hlbiBwcmVzZW50LlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHN1ZmZpeCA9IGdldFRlc3RTdWZmaXgoXCJmZWF0dXJlLnNwZWMudHNcIiwgW1wic3BlY1wiXSk7XG4gKiBgYGBcbiAqL1xuY29uc3QgZ2V0VGVzdFN1ZmZpeCA9IChcbiAgYmFzZW5hbWU6IHN0cmluZyxcbiAgdGVzdFN1ZmZpeGVzOiBzdHJpbmdbXSxcbik6IHN0cmluZyB8IHVuZGVmaW5lZCA9PlxuICB0ZXN0U3VmZml4ZXMuZmluZCgoc3VmZml4KSA9PlxuICAgIGJhc2VuYW1lLmVuZHNXaXRoKGAuJHtzdWZmaXh9JHtUWVBFU0NSSVBUX0VYVEVOU0lPTn1gKSxcbiAgKTtcblxuLyoqXG4gKiBDaGVja3MgZm9yIGFueSB0ZXN0IGNvbXBhbmlvbiBmaWxlIGluIHRoZSBkaXJlY3RvcnkuXG4gKiBAcGFyYW0gZGlyZWN0b3J5IElucHV0IGRpcmVjdG9yeSB2YWx1ZS5cbiAqIEBwYXJhbSBiYXNlU3RlbSBJbnB1dCBiYXNlU3RlbSB2YWx1ZS5cbiAqIEBwYXJhbSB0ZXN0U3VmZml4ZXMgSW5wdXQgdGVzdFN1ZmZpeGVzIHZhbHVlLlxuICogQHJldHVybnMgVHJ1ZSB3aGVuIGFueSB0ZXN0IGNvbXBhbmlvbiBleGlzdHMuXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3Qgb2sgPSBoYXNBbnlUZXN0Q29tcGFuaW9uKGRpciwgXCJmZWF0dXJlXCIsIFtcInNwZWNcIl0pO1xuICogYGBgXG4gKi9cbmNvbnN0IGhhc0FueVRlc3RDb21wYW5pb24gPSAoXG4gIGRpcmVjdG9yeTogc3RyaW5nLFxuICBiYXNlU3RlbTogc3RyaW5nLFxuICB0ZXN0U3VmZml4ZXM6IHN0cmluZ1tdLFxuKTogYm9vbGVhbiA9PlxuICB0ZXN0U3VmZml4ZXMuc29tZSgoc3VmZml4KSA9PlxuICAgIGZzLmV4aXN0c1N5bmMocGF0aC5qb2luKGRpcmVjdG9yeSwgYCR7YmFzZVN0ZW19LiR7c3VmZml4fS50c2ApKSxcbiAgKTtcblxuLyoqXG4gKiBCdWlsZHMgYSBsaXN0ZW5lciB0aGF0IHJlcG9ydHMgbWlzc2luZyB0ZXN0IGNvbXBhbmlvbnMuXG4gKiBAcGFyYW0gY29udGV4dCBJbnB1dCBjb250ZXh0IHZhbHVlLlxuICogQHBhcmFtIG9wdGlvbnMgSW5wdXQgb3B0aW9ucyB2YWx1ZS5cbiAqIEByZXR1cm5zIFJ1bGUgbGlzdGVuZXIgZm9yIG1pc3NpbmcgdGVzdHMuXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgbGlzdGVuZXIgPSBidWlsZE1pc3NpbmdUZXN0TGlzdGVuZXIoY29udGV4dCwgb3B0aW9ucyk7XG4gKiBgYGBcbiAqL1xuY29uc3QgYnVpbGRNaXNzaW5nVGVzdExpc3RlbmVyID0gKFxuICBjb250ZXh0OiBSdWxlLlJ1bGVDb250ZXh0LFxuICBvcHRpb25zOiBNaXNzaW5nVGVzdExpc3RlbmVyT3B0aW9ucyxcbik6IFJ1bGUuUnVsZUxpc3RlbmVyID0+IHtcbiAgY29uc3QgeyBiYXNlbmFtZSwgZGlyZWN0b3J5LCB0ZXN0U3VmZml4ZXMgfSA9IG9wdGlvbnM7XG4gIGNvbnN0IGJhc2VTdGVtID0gYmFzZW5hbWUuc2xpY2UoMCwgLVRZUEVTQ1JJUFRfRVhURU5TSU9OLmxlbmd0aCk7XG5cbiAgaWYgKGJhc2VTdGVtLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIGlmIChoYXNBbnlUZXN0Q29tcGFuaW9uKGRpcmVjdG9yeSwgYmFzZVN0ZW0sIHRlc3RTdWZmaXhlcykpIHtcbiAgICByZXR1cm4ge307XG4gIH1cblxuICByZXR1cm4ge1xuICAgIFByb2dyYW0obm9kZSk6IHZvaWQge1xuICAgICAgY29uc3QgdGVzdEZpbGVzID0gdGVzdFN1ZmZpeGVzXG4gICAgICAgIC5tYXAoKHN1ZmZpeCkgPT4gYCR7YmFzZVN0ZW19LiR7c3VmZml4fSR7VFlQRVNDUklQVF9FWFRFTlNJT059YClcbiAgICAgICAgLmpvaW4oXCIsIFwiKTtcblxuICAgICAgY29udGV4dC5yZXBvcnQoe1xuICAgICAgICBkYXRhOiB7IHRlc3RGaWxlcyB9LFxuICAgICAgICBtZXNzYWdlSWQ6IFwibWlzc2luZ1Rlc3RcIixcbiAgICAgICAgbm9kZSxcbiAgICAgIH0pO1xuICAgIH0sXG4gIH07XG59O1xuXG4vKipcbiAqIEJ1aWxkcyBhIGxpc3RlbmVyIHRoYXQgcmVwb3J0cyBtaXNzaW5nIHNvdXJjZSBmaWxlcy5cbiAqIEBwYXJhbSBjb250ZXh0IElucHV0IGNvbnRleHQgdmFsdWUuXG4gKiBAcGFyYW0gb3B0aW9ucyBJbnB1dCBvcHRpb25zIHZhbHVlLlxuICogQHJldHVybnMgUnVsZSBsaXN0ZW5lciBmb3IgbWlzc2luZyBzb3VyY2VzLlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGxpc3RlbmVyID0gYnVpbGRNaXNzaW5nU291cmNlTGlzdGVuZXIoY29udGV4dCwgb3B0aW9ucyk7XG4gKiBgYGBcbiAqL1xuY29uc3QgYnVpbGRNaXNzaW5nU291cmNlTGlzdGVuZXIgPSAoXG4gIGNvbnRleHQ6IFJ1bGUuUnVsZUNvbnRleHQsXG4gIG9wdGlvbnM6IE1pc3NpbmdTb3VyY2VMaXN0ZW5lck9wdGlvbnMsXG4pOiBSdWxlLlJ1bGVMaXN0ZW5lciA9PiB7XG4gIGNvbnN0IHsgYmFzZW5hbWUsIGRpcmVjdG9yeSwgc3VmZml4IH0gPSBvcHRpb25zO1xuICBjb25zdCBzb3VyY2VCYXNlbmFtZSA9IGJhc2VuYW1lLnNsaWNlKFxuICAgIDAsXG4gICAgLWAuJHtzdWZmaXh9JHtUWVBFU0NSSVBUX0VYVEVOU0lPTn1gLmxlbmd0aCxcbiAgKTtcblxuICBpZiAoc291cmNlQmFzZW5hbWUubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG5cbiAgY29uc3Qgc291cmNlRmlsZSA9IGAke3NvdXJjZUJhc2VuYW1lfSR7VFlQRVNDUklQVF9FWFRFTlNJT059YDtcblxuICBpZiAoZnMuZXhpc3RzU3luYyhwYXRoLmpvaW4oZGlyZWN0b3J5LCBzb3VyY2VGaWxlKSkpIHtcbiAgICByZXR1cm4ge307XG4gIH1cblxuICByZXR1cm4ge1xuICAgIFByb2dyYW0obm9kZSk6IHZvaWQge1xuICAgICAgY29udGV4dC5yZXBvcnQoe1xuICAgICAgICBkYXRhOiB7IHNvdXJjZUZpbGUgfSxcbiAgICAgICAgbWVzc2FnZUlkOiBcIm1pc3NpbmdTb3VyY2VcIixcbiAgICAgICAgbm9kZSxcbiAgICAgIH0pO1xuICAgIH0sXG4gIH07XG59O1xuXG4vKipcbiAqIERldGVybWluZXMgd2hldGhlciBhIGZpbGUgc2hvdWxkIGJlIGxpbnRlZC5cbiAqIEBwYXJhbSBmaWxlbmFtZSBJbnB1dCBmaWxlbmFtZSB2YWx1ZS5cbiAqIEBwYXJhbSBvcHRpb25zIElucHV0IG9wdGlvbnMgdmFsdWUuXG4gKiBAcmV0dXJucyBUcnVlIHdoZW4gdGhlIGZpbGUgc2hvdWxkIGJlIGxpbnRlZC5cbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBvayA9IHNob3VsZExpbnRGaWxlKGZpbGVuYW1lLCBvcHRpb25zKTtcbiAqIGBgYFxuICovXG5jb25zdCBzaG91bGRMaW50RmlsZSA9IChcbiAgZmlsZW5hbWU6IHN0cmluZyxcbiAgb3B0aW9uczogUmVxdWlyZVRlc3RDb21wYW5pb25TdGF0ZSxcbik6IGJvb2xlYW4gPT4ge1xuICBjb25zdCB7IGVuZm9yY2VJbiwgaWdub3JlUGF0dGVybnMgfSA9IG9wdGlvbnM7XG5cbiAgaWYgKCFpc0xpbnRhYmxlRmlsZW5hbWUoZmlsZW5hbWUpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKCFpc1R5cGVTY3JpcHRGaWxlKGZpbGVuYW1lKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmICghaXNQYXRoTWF0Y2goZmlsZW5hbWUsIGVuZm9yY2VJbikpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gIWlzUGF0aE1hdGNoKGZpbGVuYW1lLCBpZ25vcmVQYXR0ZXJucyk7XG59O1xuXG4vKipcbiAqIEJ1aWxkcyBhIGxpc3RlbmVyIGZvciBhIHNwZWNpZmljIGZpbGVuYW1lLlxuICogQHBhcmFtIGNvbnRleHQgSW5wdXQgY29udGV4dCB2YWx1ZS5cbiAqIEBwYXJhbSBmaWxlbmFtZSBJbnB1dCBmaWxlbmFtZSB2YWx1ZS5cbiAqIEBwYXJhbSBvcHRpb25zIElucHV0IG9wdGlvbnMgdmFsdWUuXG4gKiBAcmV0dXJucyBSdWxlIGxpc3RlbmVyIGZvciB0aGUgZmlsZW5hbWUuXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgbGlzdGVuZXIgPSBidWlsZExpc3RlbmVyRm9yRmlsZW5hbWUoY29udGV4dCwgZmlsZW5hbWUsIG9wdGlvbnMpO1xuICogYGBgXG4gKi9cbmNvbnN0IGJ1aWxkTGlzdGVuZXJGb3JGaWxlbmFtZSA9IChcbiAgY29udGV4dDogUnVsZS5SdWxlQ29udGV4dCxcbiAgZmlsZW5hbWU6IHN0cmluZyxcbiAgb3B0aW9uczogUmVxdWlyZVRlc3RDb21wYW5pb25TdGF0ZSxcbik6IFJ1bGUuUnVsZUxpc3RlbmVyID0+IHtcbiAgaWYgKCFzaG91bGRMaW50RmlsZShmaWxlbmFtZSwgb3B0aW9ucykpIHtcbiAgICByZXR1cm4ge307XG4gIH1cblxuICBjb25zdCBiYXNlbmFtZSA9IHBhdGguYmFzZW5hbWUoZmlsZW5hbWUpO1xuICBjb25zdCBkaXJlY3RvcnkgPSBwYXRoLmRpcm5hbWUoZmlsZW5hbWUpO1xuICBjb25zdCB7IHRlc3RTdWZmaXhlcyB9ID0gb3B0aW9ucztcbiAgY29uc3QgdGVzdFN1ZmZpeCA9IGdldFRlc3RTdWZmaXgoYmFzZW5hbWUsIHRlc3RTdWZmaXhlcyk7XG5cbiAgaWYgKHRlc3RTdWZmaXggIT09IHZvaWQgMCkge1xuICAgIHJldHVybiBidWlsZE1pc3NpbmdTb3VyY2VMaXN0ZW5lcihjb250ZXh0LCB7XG4gICAgICBiYXNlbmFtZSxcbiAgICAgIGRpcmVjdG9yeSxcbiAgICAgIHN1ZmZpeDogdGVzdFN1ZmZpeCxcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBidWlsZE1pc3NpbmdUZXN0TGlzdGVuZXIoY29udGV4dCwge1xuICAgIGJhc2VuYW1lLFxuICAgIGRpcmVjdG9yeSxcbiAgICB0ZXN0U3VmZml4ZXMsXG4gIH0pO1xufTtcblxuZXhwb3J0IHsgYnVpbGRMaXN0ZW5lckZvckZpbGVuYW1lIH07XG4iXX0=
@@ -0,0 +1,54 @@
1
+ /** File extension used to detect TypeScript source files. */
2
+ declare const TYPESCRIPT_EXTENSION = ".ts";
3
+ /** Type definition for rule data. */
4
+ interface RequireTestCompanionState {
5
+ /** EnforceIn field value. */
6
+ enforceIn: string[];
7
+ /** IgnorePatterns field value. */
8
+ ignorePatterns: string[];
9
+ /** TestSuffixes field value. */
10
+ testSuffixes: string[];
11
+ }
12
+ /**
13
+ * Checks isLintableFilename.
14
+ * @param filename Input filename value.
15
+ * @returns Return value output.
16
+ * @example
17
+ * ```typescript
18
+ * isLintableFilename();
19
+ * ```
20
+ */
21
+ declare const isLintableFilename: (filename: string) => boolean;
22
+ /**
23
+ * Checks isTypeScriptFile.
24
+ * @param filename Input filename value.
25
+ * @returns Return value output.
26
+ * @example
27
+ * ```typescript
28
+ * isTypeScriptFile();
29
+ * ```
30
+ */
31
+ declare const isTypeScriptFile: (filename: string) => boolean;
32
+ /**
33
+ * Gets getOptions.
34
+ * @param options Input options value.
35
+ * @returns Return value output.
36
+ * @example
37
+ * ```typescript
38
+ * getOptions();
39
+ * ```
40
+ */
41
+ declare const getOptions: (options: readonly unknown[]) => RequireTestCompanionState;
42
+ /**
43
+ * Checks isPathMatch.
44
+ * @param filename Input filename value.
45
+ * @param patterns Input patterns value.
46
+ * @returns Return value output.
47
+ * @example
48
+ * ```typescript
49
+ * isPathMatch();
50
+ * ```
51
+ */
52
+ declare const isPathMatch: (filename: string, patterns: string[]) => boolean;
53
+ export { getOptions, isLintableFilename, isPathMatch, isTypeScriptFile, type RequireTestCompanionState, TYPESCRIPT_EXTENSION, };
54
+ //# sourceMappingURL=require-test-companion-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-test-companion-options.d.ts","sourceRoot":"","sources":["../../../src/testing/require-test-companion/require-test-companion-options.ts"],"names":[],"mappings":"AAcA,6DAA6D;AAC7D,QAAA,MAAM,oBAAoB,QAAQ,CAAC;AAEnC,qCAAqC;AACrC,UAAU,yBAAyB;IACjC,6BAA6B;IAC7B,SAAS,EAAE,MAAM,EAAE,CAAC;IAEpB,kCAAkC;IAClC,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB,gCAAgC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,QAAA,MAAM,kBAAkB,GAAI,UAAU,MAAM,KAAG,OACG,CAAC;AAEnD;;;;;;;;GAQG;AACH,QAAA,MAAM,gBAAgB,GAAI,UAAU,MAAM,KAAG,OAC2B,CAAC;AA+BzE;;;;;;;;GAQG;AACH,QAAA,MAAM,UAAU,GAAI,SAAS,SAAS,OAAO,EAAE,KAAG,yBAcjD,CAAC;AA0BF;;;;;;;;;GASG;AACH,QAAA,MAAM,WAAW,GAAI,UAAU,MAAM,EAAE,UAAU,MAAM,EAAE,KAAG,OAc3D,CAAC;AAEF,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,KAAK,yBAAyB,EAC9B,oBAAoB,GACrB,CAAC"}
@@ -0,0 +1,112 @@
1
+ import { minimatch } from "minimatch";
2
+ import path from "node:path";
3
+ /** Default value used by this module. */
4
+ const DEFAULT_TEST_SUFFIXES = ["spec", "test"];
5
+ /** Default value used by this module. */
6
+ const DEFAULT_IGNORE_PATTERNS = ["/*.d.ts", "/index.ts"];
7
+ /** Default folders where test companions are enforced. */
8
+ const DEFAULT_ENFORCE_IN = ["src/**"];
9
+ /** File extension used to detect TypeScript source files. */
10
+ const TYPESCRIPT_EXTENSION = ".ts";
11
+ /**
12
+ * Checks isLintableFilename.
13
+ * @param filename Input filename value.
14
+ * @returns Return value output.
15
+ * @example
16
+ * ```typescript
17
+ * isLintableFilename();
18
+ * ```
19
+ */
20
+ const isLintableFilename = (filename) => filename.length > 0 && path.isAbsolute(filename);
21
+ /**
22
+ * Checks isTypeScriptFile.
23
+ * @param filename Input filename value.
24
+ * @returns Return value output.
25
+ * @example
26
+ * ```typescript
27
+ * isTypeScriptFile();
28
+ * ```
29
+ */
30
+ const isTypeScriptFile = (filename) => filename.endsWith(TYPESCRIPT_EXTENSION) && !filename.endsWith(".d.ts");
31
+ /**
32
+ * Normalizes a rule option into a string list.
33
+ * @param value Input value value.
34
+ * @param defaults Input defaults value.
35
+ * @returns Normalized list of strings.
36
+ * @example
37
+ * ```typescript
38
+ * const list = normalizeList("src/**", ["src/**"]);
39
+ * ```
40
+ */
41
+ const normalizeList = (value, defaults) => {
42
+ if (Array.isArray(value)) {
43
+ return value
44
+ .filter((entry) => typeof entry === "string")
45
+ .map((entry) => entry.trim())
46
+ .filter((entry) => entry.length > 0);
47
+ }
48
+ if (typeof value === "string") {
49
+ const trimmed = value.trim();
50
+ return trimmed.length === 0 ? [] : [trimmed];
51
+ }
52
+ return [...defaults];
53
+ };
54
+ /**
55
+ * Gets getOptions.
56
+ * @param options Input options value.
57
+ * @returns Return value output.
58
+ * @example
59
+ * ```typescript
60
+ * getOptions();
61
+ * ```
62
+ */
63
+ const getOptions = (options) => {
64
+ const rawOptions = options[0];
65
+ return {
66
+ enforceIn: normalizeList(rawOptions?.enforceIn, DEFAULT_ENFORCE_IN),
67
+ ignorePatterns: normalizeList(rawOptions?.ignorePatterns, DEFAULT_IGNORE_PATTERNS),
68
+ testSuffixes: normalizeList(rawOptions?.testSuffixes, DEFAULT_TEST_SUFFIXES),
69
+ };
70
+ };
71
+ /**
72
+ * Normalizes normalizeRelativePath.
73
+ * @param filename Input filename value.
74
+ * @returns Return value output.
75
+ * @example
76
+ * ```typescript
77
+ * normalizeRelativePath();
78
+ * ```
79
+ */
80
+ const normalizeRelativePath = (filename) => path.relative(process.cwd(), filename).split(path.sep).join("/");
81
+ /**
82
+ * Normalizes normalizePattern.
83
+ * @param pattern Input pattern value.
84
+ * @returns Return value output.
85
+ * @example
86
+ * ```typescript
87
+ * normalizePattern();
88
+ * ```
89
+ */
90
+ const normalizePattern = (pattern) => pattern.startsWith("/") ? `**${pattern}` : pattern;
91
+ /**
92
+ * Checks isPathMatch.
93
+ * @param filename Input filename value.
94
+ * @param patterns Input patterns value.
95
+ * @returns Return value output.
96
+ * @example
97
+ * ```typescript
98
+ * isPathMatch();
99
+ * ```
100
+ */
101
+ const isPathMatch = (filename, patterns) => {
102
+ if (patterns.length === 0) {
103
+ return false;
104
+ }
105
+ const relativePath = normalizeRelativePath(filename);
106
+ if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) {
107
+ return false;
108
+ }
109
+ return patterns.some((pattern) => minimatch(relativePath, normalizePattern(pattern), { dot: true }));
110
+ };
111
+ export { getOptions, isLintableFilename, isPathMatch, isTypeScriptFile, TYPESCRIPT_EXTENSION, };
112
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWlyZS10ZXN0LWNvbXBhbmlvbi1vcHRpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3Rlc3RpbmcvcmVxdWlyZS10ZXN0LWNvbXBhbmlvbi9yZXF1aXJlLXRlc3QtY29tcGFuaW9uLW9wdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUN0QyxPQUFPLElBQUksTUFBTSxXQUFXLENBQUM7QUFJN0IseUNBQXlDO0FBQ3pDLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFVLENBQUM7QUFFeEQseUNBQXlDO0FBQ3pDLE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxTQUFTLEVBQUUsV0FBVyxDQUFVLENBQUM7QUFFbEUsMERBQTBEO0FBQzFELE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxRQUFRLENBQVUsQ0FBQztBQUUvQyw2REFBNkQ7QUFDN0QsTUFBTSxvQkFBb0IsR0FBRyxLQUFLLENBQUM7QUFjbkM7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLGtCQUFrQixHQUFHLENBQUMsUUFBZ0IsRUFBVyxFQUFFLENBQ3ZELFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7QUFFbkQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLGdCQUFnQixHQUFHLENBQUMsUUFBZ0IsRUFBVyxFQUFFLENBQ3JELFFBQVEsQ0FBQyxRQUFRLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7QUFFekU7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxhQUFhLEdBQUcsQ0FDcEIsS0FBcUUsRUFDckUsUUFBMkIsRUFDakIsRUFBRTtJQUNaLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3pCLE9BQU8sS0FBSzthQUNULE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBbUIsRUFBRSxDQUFDLE9BQU8sS0FBSyxLQUFLLFFBQVEsQ0FBQzthQUM3RCxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQzthQUM1QixNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVELElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDOUIsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzdCLE9BQU8sT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBRUQsT0FBTyxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUM7QUFDdkIsQ0FBQyxDQUFDO0FBRUY7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLFVBQVUsR0FBRyxDQUFDLE9BQTJCLEVBQTZCLEVBQUU7SUFDNUUsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBNEMsQ0FBQztJQUV6RSxPQUFPO1FBQ0wsU0FBUyxFQUFFLGFBQWEsQ0FBQyxVQUFVLEVBQUUsU0FBUyxFQUFFLGtCQUFrQixDQUFDO1FBQ25FLGNBQWMsRUFBRSxhQUFhLENBQzNCLFVBQVUsRUFBRSxjQUFjLEVBQzFCLHVCQUF1QixDQUN4QjtRQUNELFlBQVksRUFBRSxhQUFhLENBQ3pCLFVBQVUsRUFBRSxZQUFZLEVBQ3hCLHFCQUFxQixDQUN0QjtLQUNGLENBQUM7QUFDSixDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7R0FRRztBQUNILE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxRQUFnQixFQUFVLEVBQUUsQ0FDekQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7QUFFbkU7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLGdCQUFnQixHQUFHLENBQUMsT0FBZSxFQUFVLEVBQUUsQ0FDbkQsT0FBTyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO0FBRXJEOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sV0FBVyxHQUFHLENBQUMsUUFBZ0IsRUFBRSxRQUFrQixFQUFXLEVBQUU7SUFDcEUsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzFCLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELE1BQU0sWUFBWSxHQUFHLHFCQUFxQixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRXJELElBQUksWUFBWSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7UUFDbkUsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsT0FBTyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FDL0IsU0FBUyxDQUFDLFlBQVksRUFBRSxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUNsRSxDQUFDO0FBQ0osQ0FBQyxDQUFDO0FBRUYsT0FBTyxFQUNMLFVBQVUsRUFDVixrQkFBa0IsRUFDbEIsV0FBVyxFQUNYLGdCQUFnQixFQUVoQixvQkFBb0IsR0FDckIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG1pbmltYXRjaCB9IGZyb20gXCJtaW5pbWF0Y2hcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcblxuaW1wb3J0IHR5cGUgeyBSZXF1aXJlVGVzdENvbXBhbmlvbk9wdGlvbnMgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKiogRGVmYXVsdCB2YWx1ZSB1c2VkIGJ5IHRoaXMgbW9kdWxlLiAqL1xuY29uc3QgREVGQVVMVF9URVNUX1NVRkZJWEVTID0gW1wic3BlY1wiLCBcInRlc3RcIl0gYXMgY29uc3Q7XG5cbi8qKiBEZWZhdWx0IHZhbHVlIHVzZWQgYnkgdGhpcyBtb2R1bGUuICovXG5jb25zdCBERUZBVUxUX0lHTk9SRV9QQVRURVJOUyA9IFtcIi8qLmQudHNcIiwgXCIvaW5kZXgudHNcIl0gYXMgY29uc3Q7XG5cbi8qKiBEZWZhdWx0IGZvbGRlcnMgd2hlcmUgdGVzdCBjb21wYW5pb25zIGFyZSBlbmZvcmNlZC4gKi9cbmNvbnN0IERFRkFVTFRfRU5GT1JDRV9JTiA9IFtcInNyYy8qKlwiXSBhcyBjb25zdDtcblxuLyoqIEZpbGUgZXh0ZW5zaW9uIHVzZWQgdG8gZGV0ZWN0IFR5cGVTY3JpcHQgc291cmNlIGZpbGVzLiAqL1xuY29uc3QgVFlQRVNDUklQVF9FWFRFTlNJT04gPSBcIi50c1wiO1xuXG4vKiogVHlwZSBkZWZpbml0aW9uIGZvciBydWxlIGRhdGEuICovXG5pbnRlcmZhY2UgUmVxdWlyZVRlc3RDb21wYW5pb25TdGF0ZSB7XG4gIC8qKiBFbmZvcmNlSW4gZmllbGQgdmFsdWUuICovXG4gIGVuZm9yY2VJbjogc3RyaW5nW107XG5cbiAgLyoqIElnbm9yZVBhdHRlcm5zIGZpZWxkIHZhbHVlLiAqL1xuICBpZ25vcmVQYXR0ZXJuczogc3RyaW5nW107XG5cbiAgLyoqIFRlc3RTdWZmaXhlcyBmaWVsZCB2YWx1ZS4gKi9cbiAgdGVzdFN1ZmZpeGVzOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaXNMaW50YWJsZUZpbGVuYW1lLlxuICogQHBhcmFtIGZpbGVuYW1lIElucHV0IGZpbGVuYW1lIHZhbHVlLlxuICogQHJldHVybnMgUmV0dXJuIHZhbHVlIG91dHB1dC5cbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpc0xpbnRhYmxlRmlsZW5hbWUoKTtcbiAqIGBgYFxuICovXG5jb25zdCBpc0xpbnRhYmxlRmlsZW5hbWUgPSAoZmlsZW5hbWU6IHN0cmluZyk6IGJvb2xlYW4gPT5cbiAgZmlsZW5hbWUubGVuZ3RoID4gMCAmJiBwYXRoLmlzQWJzb2x1dGUoZmlsZW5hbWUpO1xuXG4vKipcbiAqIENoZWNrcyBpc1R5cGVTY3JpcHRGaWxlLlxuICogQHBhcmFtIGZpbGVuYW1lIElucHV0IGZpbGVuYW1lIHZhbHVlLlxuICogQHJldHVybnMgUmV0dXJuIHZhbHVlIG91dHB1dC5cbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpc1R5cGVTY3JpcHRGaWxlKCk7XG4gKiBgYGBcbiAqL1xuY29uc3QgaXNUeXBlU2NyaXB0RmlsZSA9IChmaWxlbmFtZTogc3RyaW5nKTogYm9vbGVhbiA9PlxuICBmaWxlbmFtZS5lbmRzV2l0aChUWVBFU0NSSVBUX0VYVEVOU0lPTikgJiYgIWZpbGVuYW1lLmVuZHNXaXRoKFwiLmQudHNcIik7XG5cbi8qKlxuICogTm9ybWFsaXplcyBhIHJ1bGUgb3B0aW9uIGludG8gYSBzdHJpbmcgbGlzdC5cbiAqIEBwYXJhbSB2YWx1ZSBJbnB1dCB2YWx1ZSB2YWx1ZS5cbiAqIEBwYXJhbSBkZWZhdWx0cyBJbnB1dCBkZWZhdWx0cyB2YWx1ZS5cbiAqIEByZXR1cm5zIE5vcm1hbGl6ZWQgbGlzdCBvZiBzdHJpbmdzLlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGxpc3QgPSBub3JtYWxpemVMaXN0KFwic3JjLyoqXCIsIFtcInNyYy8qKlwiXSk7XG4gKiBgYGBcbiAqL1xuY29uc3Qgbm9ybWFsaXplTGlzdCA9IChcbiAgdmFsdWU6IFJlcXVpcmVUZXN0Q29tcGFuaW9uT3B0aW9uc1trZXlvZiBSZXF1aXJlVGVzdENvbXBhbmlvbk9wdGlvbnNdLFxuICBkZWZhdWx0czogcmVhZG9ubHkgc3RyaW5nW10sXG4pOiBzdHJpbmdbXSA9PiB7XG4gIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgIHJldHVybiB2YWx1ZVxuICAgICAgLmZpbHRlcigoZW50cnkpOiBlbnRyeSBpcyBzdHJpbmcgPT4gdHlwZW9mIGVudHJ5ID09PSBcInN0cmluZ1wiKVxuICAgICAgLm1hcCgoZW50cnkpID0+IGVudHJ5LnRyaW0oKSlcbiAgICAgIC5maWx0ZXIoKGVudHJ5KSA9PiBlbnRyeS5sZW5ndGggPiAwKTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICBjb25zdCB0cmltbWVkID0gdmFsdWUudHJpbSgpO1xuICAgIHJldHVybiB0cmltbWVkLmxlbmd0aCA9PT0gMCA/IFtdIDogW3RyaW1tZWRdO1xuICB9XG5cbiAgcmV0dXJuIFsuLi5kZWZhdWx0c107XG59O1xuXG4vKipcbiAqIEdldHMgZ2V0T3B0aW9ucy5cbiAqIEBwYXJhbSBvcHRpb25zIElucHV0IG9wdGlvbnMgdmFsdWUuXG4gKiBAcmV0dXJucyBSZXR1cm4gdmFsdWUgb3V0cHV0LlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGdldE9wdGlvbnMoKTtcbiAqIGBgYFxuICovXG5jb25zdCBnZXRPcHRpb25zID0gKG9wdGlvbnM6IHJlYWRvbmx5IHVua25vd25bXSk6IFJlcXVpcmVUZXN0Q29tcGFuaW9uU3RhdGUgPT4ge1xuICBjb25zdCByYXdPcHRpb25zID0gb3B0aW9uc1swXSBhcyBSZXF1aXJlVGVzdENvbXBhbmlvbk9wdGlvbnMgfCB1bmRlZmluZWQ7XG5cbiAgcmV0dXJuIHtcbiAgICBlbmZvcmNlSW46IG5vcm1hbGl6ZUxpc3QocmF3T3B0aW9ucz8uZW5mb3JjZUluLCBERUZBVUxUX0VORk9SQ0VfSU4pLFxuICAgIGlnbm9yZVBhdHRlcm5zOiBub3JtYWxpemVMaXN0KFxuICAgICAgcmF3T3B0aW9ucz8uaWdub3JlUGF0dGVybnMsXG4gICAgICBERUZBVUxUX0lHTk9SRV9QQVRURVJOUyxcbiAgICApLFxuICAgIHRlc3RTdWZmaXhlczogbm9ybWFsaXplTGlzdChcbiAgICAgIHJhd09wdGlvbnM/LnRlc3RTdWZmaXhlcyxcbiAgICAgIERFRkFVTFRfVEVTVF9TVUZGSVhFUyxcbiAgICApLFxuICB9O1xufTtcblxuLyoqXG4gKiBOb3JtYWxpemVzIG5vcm1hbGl6ZVJlbGF0aXZlUGF0aC5cbiAqIEBwYXJhbSBmaWxlbmFtZSBJbnB1dCBmaWxlbmFtZSB2YWx1ZS5cbiAqIEByZXR1cm5zIFJldHVybiB2YWx1ZSBvdXRwdXQuXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogbm9ybWFsaXplUmVsYXRpdmVQYXRoKCk7XG4gKiBgYGBcbiAqL1xuY29uc3Qgbm9ybWFsaXplUmVsYXRpdmVQYXRoID0gKGZpbGVuYW1lOiBzdHJpbmcpOiBzdHJpbmcgPT5cbiAgcGF0aC5yZWxhdGl2ZShwcm9jZXNzLmN3ZCgpLCBmaWxlbmFtZSkuc3BsaXQocGF0aC5zZXApLmpvaW4oXCIvXCIpO1xuXG4vKipcbiAqIE5vcm1hbGl6ZXMgbm9ybWFsaXplUGF0dGVybi5cbiAqIEBwYXJhbSBwYXR0ZXJuIElucHV0IHBhdHRlcm4gdmFsdWUuXG4gKiBAcmV0dXJucyBSZXR1cm4gdmFsdWUgb3V0cHV0LlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIG5vcm1hbGl6ZVBhdHRlcm4oKTtcbiAqIGBgYFxuICovXG5jb25zdCBub3JtYWxpemVQYXR0ZXJuID0gKHBhdHRlcm46IHN0cmluZyk6IHN0cmluZyA9PlxuICBwYXR0ZXJuLnN0YXJ0c1dpdGgoXCIvXCIpID8gYCoqJHtwYXR0ZXJufWAgOiBwYXR0ZXJuO1xuXG4vKipcbiAqIENoZWNrcyBpc1BhdGhNYXRjaC5cbiAqIEBwYXJhbSBmaWxlbmFtZSBJbnB1dCBmaWxlbmFtZSB2YWx1ZS5cbiAqIEBwYXJhbSBwYXR0ZXJucyBJbnB1dCBwYXR0ZXJucyB2YWx1ZS5cbiAqIEByZXR1cm5zIFJldHVybiB2YWx1ZSBvdXRwdXQuXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaXNQYXRoTWF0Y2goKTtcbiAqIGBgYFxuICovXG5jb25zdCBpc1BhdGhNYXRjaCA9IChmaWxlbmFtZTogc3RyaW5nLCBwYXR0ZXJuczogc3RyaW5nW10pOiBib29sZWFuID0+IHtcbiAgaWYgKHBhdHRlcm5zLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IHJlbGF0aXZlUGF0aCA9IG5vcm1hbGl6ZVJlbGF0aXZlUGF0aChmaWxlbmFtZSk7XG5cbiAgaWYgKHJlbGF0aXZlUGF0aC5zdGFydHNXaXRoKFwiLi5cIikgfHwgcGF0aC5pc0Fic29sdXRlKHJlbGF0aXZlUGF0aCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gcGF0dGVybnMuc29tZSgocGF0dGVybikgPT5cbiAgICBtaW5pbWF0Y2gocmVsYXRpdmVQYXRoLCBub3JtYWxpemVQYXR0ZXJuKHBhdHRlcm4pLCB7IGRvdDogdHJ1ZSB9KSxcbiAgKTtcbn07XG5cbmV4cG9ydCB7XG4gIGdldE9wdGlvbnMsXG4gIGlzTGludGFibGVGaWxlbmFtZSxcbiAgaXNQYXRoTWF0Y2gsXG4gIGlzVHlwZVNjcmlwdEZpbGUsXG4gIHR5cGUgUmVxdWlyZVRlc3RDb21wYW5pb25TdGF0ZSxcbiAgVFlQRVNDUklQVF9FWFRFTlNJT04sXG59O1xuIl19
@@ -0,0 +1,51 @@
1
+ import type { RequireTestCompanionOptions } from "./types";
2
+ /** Type definition for rule data. */
3
+ interface RuleReport {
4
+ /** MessageId helper value. */
5
+ messageId: string | undefined;
6
+ }
7
+ /**
8
+ * Creates createTemporaryFile.
9
+ * @param root Input root value.
10
+ * @param filename Input filename value.
11
+ * @returns Return value output.
12
+ * @example
13
+ * ```typescript
14
+ * createTemporaryFile();
15
+ * ```
16
+ */
17
+ declare const createTemporaryFile: (root: "src" | "tmp", filename: string) => string;
18
+ /**
19
+ * Creates a temporary file pair for test/source combinations.
20
+ * @param root Input root value.
21
+ * @param first Input first value.
22
+ * @param second Input second value.
23
+ * @returns Tuple of created file paths.
24
+ * @throws {Error} When the file paths are missing.
25
+ * @example
26
+ * ```typescript
27
+ * const [source, test] = createTemporaryPair("tmp", "a.ts", "a.spec.ts");
28
+ * ```
29
+ */
30
+ declare const createTemporaryPair: (root: "src" | "tmp", first: string, second: string) => [string, string];
31
+ /**
32
+ * Runs the rule with the given options.
33
+ * @param filename Input filename value.
34
+ * @param options Input options value.
35
+ * @returns Collected rule reports.
36
+ * @example
37
+ * ```typescript
38
+ * const reports = runRule("/tmp/feature.ts");
39
+ * ```
40
+ */
41
+ declare const runRule: (filename: string, options?: RequireTestCompanionOptions) => RuleReport[];
42
+ /**
43
+ * Cleans up temporary directories created by tests.
44
+ * @example
45
+ * ```typescript
46
+ * cleanupTemporaryDirectories();
47
+ * ```
48
+ */
49
+ declare const cleanupTemporaryDirectories: () => void;
50
+ export { cleanupTemporaryDirectories, createTemporaryFile, createTemporaryPair, runRule, };
51
+ //# sourceMappingURL=require-test-companion-test-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-test-companion-test-helpers.d.ts","sourceRoot":"","sources":["../../../src/testing/require-test-companion/require-test-companion-test-helpers.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAU3D,qCAAqC;AACrC,UAAU,UAAU;IAClB,8BAA8B;IAC9B,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAgCD;;;;;;;;;GASG;AACH,QAAA,MAAM,mBAAmB,GAAI,MAAM,KAAK,GAAG,KAAK,EAAE,UAAU,MAAM,KAAG,MAMpE,CAAC;AAyBF;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,mBAAmB,GACvB,MAAM,KAAK,GAAG,KAAK,EACnB,OAAO,MAAM,EACb,QAAQ,MAAM,KACb,CAAC,MAAM,EAAE,MAAM,CAOjB,CAAC;AA2EF;;;;;;;;;GASG;AACH,QAAA,MAAM,OAAO,GACX,UAAU,MAAM,EAChB,UAAU,2BAA2B,KACpC,UAAU,EAUZ,CAAC;AAEF;;;;;;GAMG;AACH,QAAA,MAAM,2BAA2B,QAAO,IAIvC,CAAC;AAEF,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,mBAAmB,EACnB,OAAO,GACR,CAAC"}