eslint-plugin-traceability 1.11.0 → 1.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -4
- package/README.md +1 -1
- package/lib/src/index.d.ts +12 -1
- package/lib/src/index.js +43 -6
- package/lib/src/maintenance/commands.js +2 -3
- package/lib/src/maintenance/flags.js +111 -25
- package/lib/src/maintenance/update.js +1 -14
- package/lib/src/rules/helpers/require-story-core.d.ts +67 -0
- package/lib/src/rules/helpers/require-story-core.js +142 -23
- package/lib/src/rules/helpers/require-story-helpers.d.ts +9 -88
- package/lib/src/rules/helpers/require-story-helpers.js +118 -166
- package/lib/src/rules/helpers/require-story-io.js +51 -31
- package/lib/src/rules/helpers/valid-annotation-format-internal.d.ts +12 -13
- package/lib/src/rules/helpers/valid-annotation-format-internal.js +21 -16
- package/lib/src/rules/helpers/valid-annotation-format-validators.d.ts +29 -3
- package/lib/src/rules/helpers/valid-annotation-format-validators.js +29 -3
- package/lib/src/rules/helpers/valid-annotation-options.d.ts +3 -0
- package/lib/src/rules/helpers/valid-annotation-options.js +64 -21
- package/lib/src/rules/helpers/valid-annotation-utils.d.ts +3 -3
- package/lib/src/rules/helpers/valid-annotation-utils.js +10 -10
- package/lib/src/rules/helpers/valid-req-reference-helpers.d.ts +11 -0
- package/lib/src/rules/helpers/valid-req-reference-helpers.js +362 -0
- package/lib/src/rules/prefer-implements-annotation.js +7 -7
- package/lib/src/rules/require-story-annotation.d.ts +2 -0
- package/lib/src/rules/require-story-annotation.js +1 -1
- package/lib/src/rules/valid-req-reference.d.ts +4 -0
- package/lib/src/rules/valid-req-reference.js +5 -349
- package/lib/src/rules/valid-story-reference.d.ts +1 -1
- package/lib/src/rules/valid-story-reference.js +17 -10
- package/lib/src/utils/annotation-checker.js +31 -7
- package/lib/src/utils/branch-annotation-helpers.d.ts +2 -2
- package/lib/src/utils/branch-annotation-helpers.js +4 -4
- package/lib/src/utils/reqAnnotationDetection.js +36 -22
- package/lib/tests/cli-error-handling.test.js +2 -1
- package/lib/tests/config/eslint-config-validation.test.d.ts +8 -0
- package/lib/tests/config/eslint-config-validation.test.js +81 -0
- package/lib/tests/config/flat-config-presets-integration.test.js +1 -3
- package/lib/tests/config/require-story-annotation-config.test.d.ts +9 -0
- package/lib/tests/config/require-story-annotation-config.test.js +9 -0
- package/lib/tests/fixtures/stale/example.js +1 -1
- package/lib/tests/fixtures/update/example.js +1 -1
- package/lib/tests/integration/cli-integration.test.js +9 -1
- package/lib/tests/integration/dogfooding-validation.test.d.ts +1 -0
- package/lib/tests/integration/dogfooding-validation.test.js +94 -0
- package/lib/tests/maintenance/batch.test.js +1 -0
- package/lib/tests/maintenance/cli.test.js +38 -0
- package/lib/tests/maintenance/detect-isolated.test.js +6 -5
- package/lib/tests/maintenance/detect.test.js +1 -0
- package/lib/tests/maintenance/index.test.js +1 -0
- package/lib/tests/maintenance/report.test.js +1 -0
- package/lib/tests/maintenance/update-isolated.test.js +1 -0
- package/lib/tests/maintenance/update.test.js +1 -0
- package/lib/tests/perf/maintenance-cli-large-workspace.test.js +18 -0
- package/lib/tests/perf/require-branch-annotation-large-file.test.d.ts +1 -0
- package/lib/tests/perf/require-branch-annotation-large-file.test.js +67 -0
- package/lib/tests/plugin-default-export-and-configs.test.js +2 -0
- package/lib/tests/plugin-setup-error.test.d.ts +1 -0
- package/lib/tests/plugin-setup-error.test.js +1 -0
- package/lib/tests/plugin-setup.test.js +12 -1
- package/lib/tests/rules/auto-fix-behavior-008.test.js +16 -0
- package/lib/tests/rules/error-reporting.test.js +1 -0
- package/lib/tests/rules/prefer-implements-annotation.test.js +8 -0
- package/lib/tests/rules/require-branch-annotation.test.js +34 -0
- package/lib/tests/rules/require-story-core-edgecases.test.js +1 -0
- package/lib/tests/rules/require-story-core.autofix.test.js +1 -0
- package/lib/tests/rules/require-story-core.test.js +1 -0
- package/lib/tests/rules/require-story-helpers-edgecases.test.d.ts +1 -0
- package/lib/tests/rules/require-story-helpers-edgecases.test.js +1 -0
- package/lib/tests/rules/require-story-helpers.test.js +4 -3
- package/lib/tests/rules/require-story-io-behavior.test.d.ts +1 -0
- package/lib/tests/rules/require-story-io-behavior.test.js +1 -0
- package/lib/tests/rules/require-story-io.edgecases.test.d.ts +1 -0
- package/lib/tests/rules/require-story-io.edgecases.test.js +1 -0
- package/lib/tests/rules/require-story-visitors-edgecases.test.d.ts +1 -0
- package/lib/tests/rules/require-story-visitors-edgecases.test.js +1 -0
- package/lib/tests/rules/valid-annotation-format-internal.test.d.ts +8 -0
- package/lib/tests/rules/valid-annotation-format-internal.test.js +47 -0
- package/lib/tests/rules/valid-story-reference.test.js +2 -0
- package/lib/tests/utils/annotation-checker.test.js +2 -1
- package/lib/tests/utils/branch-annotation-helpers.test.js +2 -1
- package/package.json +2 -2
- package/user-docs/api-reference.md +115 -8
- package/user-docs/examples.md +1 -1
- package/user-docs/migration-guide.md +35 -2
|
@@ -11,6 +11,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
11
11
|
* @req REQ-ERROR-SPECIFIC - Branch-level missing-annotation error messages are specific and informative
|
|
12
12
|
* @req REQ-ERROR-CONSISTENCY - Branch-level missing-annotation error messages follow shared conventions
|
|
13
13
|
* @req REQ-ERROR-SUGGESTION - Branch-level missing-annotation errors include suggestions when applicable
|
|
14
|
+
* @req REQ-NESTED-HANDLING - Nested branch annotations are correctly enforced without duplicative reporting
|
|
15
|
+
* @supports docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md REQ-BRANCH-DETECTION REQ-NESTED-HANDLING
|
|
16
|
+
* @supports docs/stories/007.0-DEV-ERROR-REPORTING.story.md REQ-ERROR-SPECIFIC REQ-ERROR-CONSISTENCY REQ-ERROR-SUGGESTION
|
|
14
17
|
*/
|
|
15
18
|
const eslint_1 = require("eslint");
|
|
16
19
|
const require_branch_annotation_1 = __importDefault(require("../../src/rules/require-branch-annotation"));
|
|
@@ -120,6 +123,18 @@ while (condition) {
|
|
|
120
123
|
// @req REQ-BRANCH-DETECTION
|
|
121
124
|
case 'a':
|
|
122
125
|
break;
|
|
126
|
+
}`,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: "[REQ-NESTED-HANDLING] nested if-statements with annotations on outer and inner branches",
|
|
130
|
+
code: `// @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
|
|
131
|
+
// @req REQ-BRANCH-DETECTION
|
|
132
|
+
if (outer) {
|
|
133
|
+
// @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
|
|
134
|
+
// @req REQ-NESTED-HANDLING
|
|
135
|
+
if (inner) {
|
|
136
|
+
doWork();
|
|
137
|
+
}
|
|
123
138
|
}`,
|
|
124
139
|
},
|
|
125
140
|
{
|
|
@@ -244,6 +259,25 @@ try {
|
|
|
244
259
|
// @story <story-file>.story.md
|
|
245
260
|
case 'a':
|
|
246
261
|
break;
|
|
262
|
+
}`,
|
|
263
|
+
errors: makeMissingAnnotationErrors("@story", "@req"),
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
name: "[REQ-NESTED-HANDLING] missing annotations on nested if-statement inside annotated outer branch",
|
|
267
|
+
code: `// @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
|
|
268
|
+
// @req REQ-BRANCH-DETECTION
|
|
269
|
+
if (outer) {
|
|
270
|
+
if (inner) {
|
|
271
|
+
doWork();
|
|
272
|
+
}
|
|
273
|
+
}`,
|
|
274
|
+
output: `// @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
|
|
275
|
+
// @req REQ-BRANCH-DETECTION
|
|
276
|
+
if (outer) {
|
|
277
|
+
// @story <story-file>.story.md
|
|
278
|
+
if (inner) {
|
|
279
|
+
doWork();
|
|
280
|
+
}
|
|
247
281
|
}`,
|
|
248
282
|
errors: makeMissingAnnotationErrors("@story", "@req"),
|
|
249
283
|
},
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
* Edge-case tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
5
5
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
6
6
|
* @req REQ-AUTOFIX - Cover additional branch cases in require-story-core (addStoryFixer/reportMissing)
|
|
7
|
+
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-AUTOFIX
|
|
7
8
|
*/
|
|
8
9
|
const require_story_core_1 = require("../../src/rules/helpers/require-story-core");
|
|
9
10
|
const require_story_core_test_helpers_1 = require("../utils/require-story-core-test-helpers");
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
* Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
5
5
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
6
6
|
* @req REQ-AUTOFIX - Cover additional branch cases in require-story-core (addStoryFixer/reportMissing)
|
|
7
|
+
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-AUTOFIX
|
|
7
8
|
*/
|
|
8
9
|
const require_story_core_1 = require("../../src/rules/helpers/require-story-core");
|
|
9
10
|
const require_story_helpers_1 = require("../../src/rules/helpers/require-story-helpers");
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
* Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
5
5
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
6
6
|
* @req REQ-AUTOFIX - Verify createMethodFix and reportMethod behaviors
|
|
7
|
+
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-AUTOFIX
|
|
7
8
|
*/
|
|
8
9
|
const require_story_core_1 = require("../../src/rules/helpers/require-story-core");
|
|
9
10
|
const require_story_helpers_1 = require("../../src/rules/helpers/require-story-helpers");
|
|
@@ -2,5 +2,6 @@
|
|
|
2
2
|
* Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
3
3
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
4
4
|
* @req REQ-HELPERS-EDGE-CASES - Edge-case behavior tests for helpers in require-story-helpers.ts
|
|
5
|
+
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-HELPERS-EDGE-CASES
|
|
5
6
|
*/
|
|
6
7
|
export {};
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
4
4
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
5
5
|
* @req REQ-HELPERS-EDGE-CASES - Edge-case behavior tests for helpers in require-story-helpers.ts
|
|
6
|
+
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-HELPERS-EDGE-CASES
|
|
6
7
|
*/
|
|
7
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
9
|
const require_story_helpers_1 = require("../../src/rules/helpers/require-story-helpers");
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
* Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
5
5
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
6
6
|
* @req REQ-ANNOTATION-REQUIRED - Verify helper functions in require-story helpers produce correct fixes and reporting behavior
|
|
7
|
+
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-ANNOTATION-REQUIRED
|
|
7
8
|
*/
|
|
8
9
|
const require_story_core_1 = require("../../src/rules/helpers/require-story-core");
|
|
9
10
|
const require_story_helpers_1 = require("../../src/rules/helpers/require-story-helpers");
|
|
@@ -49,7 +50,7 @@ describe("Require Story Helpers (Story 003.0)", () => {
|
|
|
49
50
|
test("reportMissing does not call context.report if JSDoc contains @story", () => {
|
|
50
51
|
const node = {
|
|
51
52
|
type: "FunctionDeclaration",
|
|
52
|
-
id: { name: "fn" },
|
|
53
|
+
id: { type: "Identifier", name: "fn" },
|
|
53
54
|
range: [0, 10],
|
|
54
55
|
};
|
|
55
56
|
const fakeSource = {
|
|
@@ -68,7 +69,7 @@ describe("Require Story Helpers (Story 003.0)", () => {
|
|
|
68
69
|
test("reportMissing calls context.report when no JSDoc story present", () => {
|
|
69
70
|
const node = {
|
|
70
71
|
type: "FunctionDeclaration",
|
|
71
|
-
id: { name: "fn2" },
|
|
72
|
+
id: { type: "Identifier", name: "fn2" },
|
|
72
73
|
range: [0, 10],
|
|
73
74
|
};
|
|
74
75
|
const fakeSource = {
|
|
@@ -82,7 +83,7 @@ describe("Require Story Helpers (Story 003.0)", () => {
|
|
|
82
83
|
(0, require_story_helpers_1.reportMissing)(context, fakeSource, { node, target: node });
|
|
83
84
|
expect(context.report).toHaveBeenCalledTimes(1);
|
|
84
85
|
const call = context.report.mock.calls[0][0];
|
|
85
|
-
expect(call.node).toBe(node);
|
|
86
|
+
expect(call.node).toBe(node.id);
|
|
86
87
|
expect(call.messageId).toBe("missingStory");
|
|
87
88
|
});
|
|
88
89
|
/**
|
|
@@ -2,5 +2,6 @@
|
|
|
2
2
|
* Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
3
3
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
4
4
|
* @req REQ-IO-BEHAVIOR-EDGE-CASES - Edge-case behavior tests for IO helpers in require-story-io.ts
|
|
5
|
+
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-IO-BEHAVIOR-EDGE-CASES
|
|
5
6
|
*/
|
|
6
7
|
export {};
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
4
4
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
5
5
|
* @req REQ-IO-BEHAVIOR-EDGE-CASES - Edge-case behavior tests for IO helpers in require-story-io.ts
|
|
6
|
+
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-IO-BEHAVIOR-EDGE-CASES
|
|
6
7
|
*/
|
|
7
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
9
|
const require_story_io_1 = require("../../src/rules/helpers/require-story-io");
|
|
@@ -2,5 +2,6 @@
|
|
|
2
2
|
* Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
3
3
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
4
4
|
* @req REQ-ANNOTATION-REQUIRED - Edge case tests for IO helpers (linesBeforeHasStory/fallbackTextBeforeHasStory/parentChainHasStory)
|
|
5
|
+
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-ANNOTATION-REQUIRED
|
|
5
6
|
*/
|
|
6
7
|
export {};
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
4
4
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
5
5
|
* @req REQ-ANNOTATION-REQUIRED - Edge case tests for IO helpers (linesBeforeHasStory/fallbackTextBeforeHasStory/parentChainHasStory)
|
|
6
|
+
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-ANNOTATION-REQUIRED
|
|
6
7
|
*/
|
|
7
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
9
|
const require_story_io_1 = require("../../src/rules/helpers/require-story-io");
|
|
@@ -2,5 +2,6 @@
|
|
|
2
2
|
* Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
3
3
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
4
4
|
* @req REQ-VISITORS-BEHAVIOR - Behavior tests for visitors in require-story-visitors.ts
|
|
5
|
+
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-VISITORS-BEHAVIOR
|
|
5
6
|
*/
|
|
6
7
|
export {};
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
4
4
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
5
5
|
* @req REQ-VISITORS-BEHAVIOR - Behavior tests for visitors in require-story-visitors.ts
|
|
6
|
+
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-VISITORS-BEHAVIOR
|
|
6
7
|
*/
|
|
7
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
9
|
const require_story_visitors_1 = require("../../src/rules/helpers/require-story-visitors");
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for: docs/stories/024.0-DEV-IGNORE-INLINE-CODE-REFS.story.md
|
|
3
|
+
* @story docs/stories/024.0-DEV-IGNORE-INLINE-CODE-REFS.story.md
|
|
4
|
+
* @req REQ-IGNORE-INLINE-CODE - Strip backtick-wrapped content before annotation detection
|
|
5
|
+
* @req REQ-PRESERVE-BOUNDARIES - Replace backtick-wrapped content with spaces to preserve word boundaries
|
|
6
|
+
* @req REQ-CENTRALIZED-FILTER - Apply backtick filtering in normalizeCommentLine for all rules
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tests for: docs/stories/024.0-DEV-IGNORE-INLINE-CODE-REFS.story.md
|
|
4
|
+
* @story docs/stories/024.0-DEV-IGNORE-INLINE-CODE-REFS.story.md
|
|
5
|
+
* @req REQ-IGNORE-INLINE-CODE - Strip backtick-wrapped content before annotation detection
|
|
6
|
+
* @req REQ-PRESERVE-BOUNDARIES - Replace backtick-wrapped content with spaces to preserve word boundaries
|
|
7
|
+
* @req REQ-CENTRALIZED-FILTER - Apply backtick filtering in normalizeCommentLine for all rules
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
const globals_1 = require("@jest/globals");
|
|
11
|
+
const valid_annotation_format_internal_1 = require("../../src/rules/helpers/valid-annotation-format-internal");
|
|
12
|
+
(0, globals_1.describe)("normalizeCommentLine inline code filtering (Story 024.0-DEV-IGNORE-INLINE-CODE-REFS)", () => {
|
|
13
|
+
(0, globals_1.it)("[REQ-IGNORE-INLINE-CODE] ignores backtick-wrapped @story in line without real annotations", () => {
|
|
14
|
+
const raw = "This rule uses `@story` and other tags";
|
|
15
|
+
const normalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(raw);
|
|
16
|
+
(0, globals_1.expect)(normalized).toBe("This rule uses and other tags");
|
|
17
|
+
(0, globals_1.expect)(normalized).not.toMatch(/@story|@req|@supports/);
|
|
18
|
+
});
|
|
19
|
+
(0, globals_1.it)("[REQ-IGNORE-INLINE-CODE] ignores backtick-wrapped @req in line without real annotations", () => {
|
|
20
|
+
const raw = "Legacy pattern `@req` should not be treated as annotation";
|
|
21
|
+
const normalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(raw);
|
|
22
|
+
(0, globals_1.expect)(normalized).toBe("Legacy pattern should not be treated as annotation");
|
|
23
|
+
(0, globals_1.expect)(normalized).not.toMatch(/@story|@req|@supports/);
|
|
24
|
+
});
|
|
25
|
+
(0, globals_1.it)("[REQ-IGNORE-INLINE-CODE][REQ-PRESERVE-BOUNDARIES] preserves spacing when removing backtick segments", () => {
|
|
26
|
+
const raw = "`@story` + `@req` docs";
|
|
27
|
+
const normalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(raw);
|
|
28
|
+
(0, globals_1.expect)(normalized).toBe(" + docs");
|
|
29
|
+
(0, globals_1.expect)(normalized).not.toMatch(/@story|@req|@supports/);
|
|
30
|
+
});
|
|
31
|
+
(0, globals_1.it)("[REQ-IGNORE-INLINE-CODE] still detects real @story annotation outside backticks", () => {
|
|
32
|
+
const raw = "using `@supports` and real @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md";
|
|
33
|
+
const normalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(raw);
|
|
34
|
+
(0, globals_1.expect)(normalized).toBe("@story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md");
|
|
35
|
+
});
|
|
36
|
+
(0, globals_1.it)("[REQ-IGNORE-INLINE-CODE][REQ-PRESERVE-BOUNDARIES] handles multiple backtick segments on one line", () => {
|
|
37
|
+
const raw = "first `@story` and second `@req` markers";
|
|
38
|
+
const normalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(raw);
|
|
39
|
+
(0, globals_1.expect)(normalized).toBe("first and second markers");
|
|
40
|
+
(0, globals_1.expect)(normalized).not.toMatch(/@story|@req|@supports/);
|
|
41
|
+
});
|
|
42
|
+
(0, globals_1.it)("[REQ-IGNORE-INLINE-CODE] leaves lines without backticks unchanged apart from existing normalization", () => {
|
|
43
|
+
const raw = " * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md";
|
|
44
|
+
const normalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(raw);
|
|
45
|
+
(0, globals_1.expect)(normalized).toBe("@story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md");
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -45,6 +45,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
45
45
|
* @req REQ-ERROR-CONTEXT - Verify file-related error messages include contextual information (path, underlying error)
|
|
46
46
|
* @req REQ-ERROR-CONSISTENCY - Verify file-related error messages follow consistent formatting and identifiers
|
|
47
47
|
* @req REQ-ERROR-HANDLING - Verify file-related errors are reported via diagnostics instead of uncaught exceptions
|
|
48
|
+
* @supports docs/stories/006.0-DEV-FILE-VALIDATION.story.md REQ-FILE-EXISTENCE REQ-CONFIGURABLE-PATHS
|
|
49
|
+
* @supports docs/stories/007.0-DEV-ERROR-REPORTING.story.md REQ-ERROR-SPECIFIC REQ-ERROR-CONTEXT REQ-ERROR-CONSISTENCY REQ-ERROR-HANDLING
|
|
48
50
|
*/
|
|
49
51
|
const eslint_1 = require("eslint");
|
|
50
52
|
const valid_story_reference_1 = __importDefault(require("../../src/rules/valid-story-reference"));
|
|
@@ -6,6 +6,7 @@ exports.runAnnotationCheckerTests = runAnnotationCheckerTests;
|
|
|
6
6
|
* @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
7
7
|
* @req REQ-TYPESCRIPT-SUPPORT - Support TypeScript-specific function syntax
|
|
8
8
|
* @req REQ-TEST-UTILS-TS-LANG - Shared TS RuleTester language options helper
|
|
9
|
+
* @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-TYPESCRIPT-SUPPORT REQ-TEST-UTILS-TS-LANG
|
|
9
10
|
*/
|
|
10
11
|
const eslint_1 = require("eslint");
|
|
11
12
|
const annotation_checker_1 = require("../../src/utils/annotation-checker");
|
|
@@ -52,7 +53,7 @@ const rule = {
|
|
|
52
53
|
};
|
|
53
54
|
},
|
|
54
55
|
};
|
|
55
|
-
describe("annotation-checker helper", () => {
|
|
56
|
+
describe("annotation-checker helper (Story 003.0-DEV-FUNCTION-ANNOTATIONS)", () => {
|
|
56
57
|
runAnnotationCheckerTests("annotation-checker", {
|
|
57
58
|
rule,
|
|
58
59
|
valid: [
|
|
@@ -5,9 +5,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
5
5
|
* Tests for: docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
|
|
6
6
|
* @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
|
|
7
7
|
* @req REQ-CONFIGURABLE-SCOPE - Allow configuration of branch types for annotation enforcement
|
|
8
|
+
* @supports docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md REQ-CONFIGURABLE-SCOPE
|
|
8
9
|
*/
|
|
9
10
|
const branch_annotation_helpers_1 = require("../../src/utils/branch-annotation-helpers");
|
|
10
|
-
describe("validateBranchTypes helper", () => {
|
|
11
|
+
describe("validateBranchTypes helper (Story 004.0-DEV-BRANCH-ANNOTATIONS)", () => {
|
|
11
12
|
let context;
|
|
12
13
|
beforeEach(() => {
|
|
13
14
|
context = { options: [], report: jest.fn() };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-traceability",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.2",
|
|
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
5
|
"main": "lib/src/index.js",
|
|
6
6
|
"types": "lib/src/index.d.ts",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"lint": "eslint --config eslint.config.js \"src/**/*.{js,ts}\" \"tests/**/*.{js,ts}\" --max-warnings=0",
|
|
30
30
|
"test": "jest --ci --bail",
|
|
31
31
|
"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",
|
|
32
|
-
"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",
|
|
32
|
+
"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",
|
|
33
33
|
"ci-verify:fast": "npm run type-check && npm run check:traceability && npm run duplication && jest --ci --bail --passWithNoTests --testPathPatterns 'tests/(rules|maintenance)'",
|
|
34
34
|
"format": "prettier --write .",
|
|
35
35
|
"format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"",
|
|
@@ -86,19 +86,19 @@ if (error) {
|
|
|
86
86
|
|
|
87
87
|
### traceability/valid-annotation-format
|
|
88
88
|
|
|
89
|
-
Description: Validates that all traceability annotations (`@story`, `@req`) follow the correct JSDoc or inline comment format. When run with `--fix`, the rule limits changes to safe `@story` path suffix normalization only—for example, adding `.md` when the path ends with `.story`, or adding `.story.md` when the base path has no extension—using targeted replacements implemented in the `getFixedStoryPath` and `reportInvalidStoryFormatWithFix` helpers. It does not change directories, infer new story names, or modify any surrounding comment text or whitespace, in line with Story 008.0
|
|
89
|
+
Description: Validates that all traceability annotations (`@story`, `@req`) follow the correct JSDoc or inline comment format. When run with `--fix`, the rule limits changes to safe `@story` path suffix normalization only—for example, adding `.md` when the path ends with `.story`, or adding `.story.md` when the base path has no extension—using targeted replacements implemented in the `getFixedStoryPath` and `reportInvalidStoryFormatWithFix` helpers. It does not change directories, infer new story names, or modify any surrounding comment text or whitespace, in line with Story 008.0. Selective disabling of this suffix-normalization auto-fix behavior is available via the `autoFix` option, which defaults to `true` for backward compatibility.
|
|
90
90
|
|
|
91
91
|
Options:
|
|
92
92
|
|
|
93
93
|
This rule accepts an optional configuration object. The primary configuration shape is **nested**:
|
|
94
94
|
|
|
95
95
|
- `story` (object, optional) – Configuration for `@story` values.
|
|
96
|
-
- `pattern` (string, optional) – A JavaScript regular expression **source** (without leading and trailing `/`) that all `@story` values must match. If provided, the rule validates each `@story` against this pattern in addition to its built‑in structural checks. By default, the plugin uses a pattern equivalent to `^docs/stories
|
|
97
|
-
- `example` (string, optional) – A short example `@story` path shown in error messages when `story.pattern` is configured. The built-in default example is `"docs/stories/
|
|
96
|
+
- `pattern` (string, optional) – A JavaScript regular expression **source** (without leading and trailing `/`) that all `@story` values must match. If provided, the rule validates each `@story` against this pattern in addition to its built‑in structural checks. By default, the plugin uses a pattern equivalent to `^docs/stories/[0-9]+\.[0-9]+-DEV-[\w-]+\.story\.md$`, which matches typical project conventions such as `docs/stories/005.0-DEV-EXAMPLE.story.md`; you can override this to match however your own project organizes story files.
|
|
97
|
+
- `example` (string, optional) – A short example `@story` path shown in error messages when `story.pattern` is configured. The built-in default example is `"docs/stories/005.0-DEV-EXAMPLE.story.md"`, intended as a generic illustration of a project story file, and does not refer to this plugin’s internal documentation.
|
|
98
98
|
- `req` (object, optional) – Configuration for `@req` values.
|
|
99
|
-
- `pattern` (string, optional) – A JavaScript regular expression **source** (without leading and trailing `/`) that all `@req` values must match. If provided, the rule validates each `@req` identifier against this pattern. Defaults to the value returned by `getDefaultReqPattern()`, which is equivalent to `^REQ-[A-Z0-
|
|
100
|
-
- `example` (string, optional) – A short example requirement ID shown in error messages when `req.pattern` is configured. Defaults to the value returned by `getDefaultReqExample()`, `"REQ-
|
|
101
|
-
- `autoFix` (boolean, optional) – When set to `false`, disables all automatic suffix-normalization fixes while keeping validation and error messages intact. When omitted or `true`, the rule continues to apply safe suffix-only auto-fixes in `--fix` mode.
|
|
99
|
+
- `pattern` (string, optional) – A JavaScript regular expression **source** (without leading and trailing `/`) that all `@req` values must match. If provided, the rule validates each `@req` identifier against this pattern. Defaults to the value returned by `getDefaultReqPattern()`, which is equivalent to `^REQ-[A-Z0-9-]+$`, matching IDs such as `REQ-USER-AUTH` or `REQ-1234`.
|
|
100
|
+
- `example` (string, optional) – A short example requirement ID shown in error messages when `req.pattern` is configured. Defaults to the value returned by `getDefaultReqExample()`, `"REQ-EXAMPLE"`. This value is used **only** for guidance and does not affect validation.
|
|
101
|
+
- `autoFix` (boolean, optional) – When set to `false`, disables all automatic suffix-normalization fixes while keeping validation and error messages intact. When omitted or `true`, the rule continues to apply safe `@story` suffix-only auto-fixes in `--fix` mode.
|
|
102
102
|
|
|
103
103
|
For backward compatibility, the rule also supports **flat shorthand** fields that map directly to the nested properties:
|
|
104
104
|
|
|
@@ -113,6 +113,8 @@ Behavior notes:
|
|
|
113
113
|
- When options are omitted, the rule behaves exactly as in earlier versions, relying on its built‑in defaults and path‑suffix normalization logic only.
|
|
114
114
|
- The pattern checks are additional validation; they do not change the existing auto‑fix behavior, which remains limited to safe `@story` suffix normalization described above.
|
|
115
115
|
|
|
116
|
+
You can customize these validations to match your own naming conventions by overriding `story.pattern`/`storyPathPattern` and `req.pattern`/`requirementIdPattern`. This is useful when you store stories outside `docs/stories`, avoid `DEV` in filenames, or use a different requirement ID scheme instead of the default `REQ-...` format. Any custom values must still be valid JavaScript regular expression **sources** (without surrounding `/` characters).
|
|
117
|
+
|
|
116
118
|
#### Migration and mixed usage
|
|
117
119
|
|
|
118
120
|
The `valid-annotation-format` rule is intentionally **backward compatible** with existing code that only uses `@story` and `@req`. You can:
|
|
@@ -210,16 +212,18 @@ The rule accepts an optional configuration object:
|
|
|
210
212
|
- `testFilePatterns` (string[], optional) – **Path-substring patterns** used to identify test files. For each file, the rule normalizes the file path to use forward slashes and then checks whether it contains at least one of the configured pattern strings. This is intentionally simpler than full glob matching and avoids adding extra runtime dependencies. Defaults to `["/tests/", "/test/", "/__tests__", ".test.", ".spec."]`. For most projects, these defaults behave like "any file under a `tests` or `test` directory, or any file whose name includes `.test.` or `.spec.`". If you prefer a different layout, supply custom substrings that uniquely identify your test files.
|
|
211
213
|
- `requireDescribeStory` (boolean, optional) – When `true` (default), requires that each top-level `describe` block include a story reference somewhere in its description text (for example, a path such as `docs/stories/010.0-PAYMENTS.story.md` or a shorter project-specific alias that your team uses consistently).
|
|
212
214
|
- `requireTestReqPrefix` (boolean, optional) – When `true` (default), requires each `it`/`test` block name to begin with a requirement identifier in square brackets, such as `[REQ-PAYMENTS-REFUND]`. The exact `REQ-` pattern is shared with the `valid-annotation-format` rule’s requirement ID checks.
|
|
213
|
-
- `describePattern` (string, optional) – A JavaScript regular expression **source** (without leading and trailing `/`) that the `describe` description text must match when `requireDescribeStory` is enabled. This lets you enforce a project-specific format such as requiring a canonical story path or a `STORY-` style identifier in the `describe` string. If omitted,
|
|
215
|
+
- `describePattern` (string, optional) – A JavaScript regular expression **source** (without leading and trailing `/`) that the `describe` description text must match when `requireDescribeStory` is enabled. This lets you enforce a project-specific format such as requiring a canonical story path or a `STORY-` style identifier in the `describe` string. If omitted, the default is equivalent to `"Story [0-9]+\\.[0-9]+-"`, which expects the description to include a story label such as `"Story 021.0-DEV-TEST-TRACEABILITY"`. You can override this to instead require full story paths or whatever story-labeling convention your project prefers.
|
|
214
216
|
- `autoFixTestTemplate` (boolean, optional) – When `true` (default), allows the rule’s `--fix` mode to insert a file-level `@supports` placeholder template at the top of test files that are missing it. The template is intentionally non-semantic and includes TODO-style guidance so humans can later replace it with a real story path and requirement IDs; disabling this option prevents the rule from inserting the template automatically.
|
|
215
217
|
- `autoFixTestPrefixFormat` (boolean, optional) – When `true` (default), enables safe normalization of malformed `[REQ-XXX]` prefixes in `it`/`test` names during `--fix`. The rule only rewrites prefixes that already contain a recognizable requirement identifier and limits changes to formatting concerns (spacing, square brackets vs. parentheses, underscore and dash usage, and letter casing) without fabricating new IDs or guessing requirement names.
|
|
216
218
|
- `testSupportsTemplate` (string, optional) – Overrides the default file-level `@supports` placeholder template used when `autoFixTestTemplate` is enabled. This string should be a complete JSDoc-style block (for example, including `/**`, `*`, and `*/`) that encodes your project’s preferred TODO guidance or placeholder story path; it is inserted verbatim at the top of matching test files that lack a `@supports` annotation, and is never interpreted or expanded by the rule.
|
|
217
219
|
|
|
220
|
+
You can tune these options to fit your own testing and naming conventions: adjust `testFilePatterns` to match your project’s test layout (including monorepos or non-standard folders), override `describePattern` if you prefer full `docs/stories/...` paths or a different story-labeling scheme in `describe` strings, and change `requireTestReqPrefix` and `autoFixTestPrefixFormat` if you want to relax, enforce, or customize the `[REQ-...]` prefix requirements for test names.
|
|
221
|
+
|
|
218
222
|
Behavior notes:
|
|
219
223
|
|
|
220
224
|
- The rule only analyzes files whose normalized paths contain at least one of the `testFilePatterns` substrings.
|
|
221
225
|
- File-level `@supports` annotations are typically placed in a JSDoc block at the top of the file; the rule checks that at least one `@supports` tag is present and that it includes a story/requirement reference (for example, `@supports docs/stories/010.0-PAYMENTS.story.md#REQ-PAYMENTS-REFUND`).
|
|
222
|
-
- Top-level `describe` calls (such as `describe("
|
|
226
|
+
- Top-level `describe` calls (such as `describe("Story 010.0-DEV-PAYMENTS", ...)`) are inspected when `requireDescribeStory` is `true`. Their first argument must be a string literal that satisfies `describePattern`.
|
|
223
227
|
- Test cases declared via `it(...)` or `test(...)` must use a string literal name beginning with a requirement prefix like `[REQ-PAYMENTS-REFUND]` when `requireTestReqPrefix` is `true`.
|
|
224
228
|
|
|
225
229
|
Default Severity: `error`
|
|
@@ -242,6 +246,109 @@ describe("Refunds flow docs/stories/010.0-PAYMENTS.story.md", () => {
|
|
|
242
246
|
});
|
|
243
247
|
```
|
|
244
248
|
|
|
249
|
+
### traceability/prefer-implements-annotation
|
|
250
|
+
|
|
251
|
+
Description: An optional, opt-in migration helper that encourages converting legacy single‑story `@story` + `@req` JSDoc blocks into the newer multi‑story `@supports` format. The rule is **disabled by default** and is **not included in any built‑in preset**; you enable it explicitly and control its behavior entirely via ESLint severity (`"off" | "warn" | "error"`). It does not change what the core rules consider valid—it only adds migration recommendations and safe auto‑fixes on top of existing validation.
|
|
252
|
+
|
|
253
|
+
Options: None – this rule does not accept a configuration object. All tuning is done via the ESLint rule level (`"off"`, `"warn"`, `"error"`).
|
|
254
|
+
|
|
255
|
+
This rule focuses on **single‑story** legacy blocks where automatic migration is unambiguous. It inspects JSDoc comments attached to function‑like constructs and looks for the following patterns:
|
|
256
|
+
|
|
257
|
+
- A single `@story` annotation with one story path.
|
|
258
|
+
- One or more simple `@req` lines in the same block (each with a single requirement ID).
|
|
259
|
+
- No `@supports` annotations yet present in that block.
|
|
260
|
+
|
|
261
|
+
When these conditions are met, the rule recommends replacing the legacy block with a single `@supports` line that encodes the same relationship between the story and its requirements.
|
|
262
|
+
|
|
263
|
+
Main behaviors:
|
|
264
|
+
|
|
265
|
+
1. **Single‑story legacy blocks → `preferImplements` (auto‑fixable)**
|
|
266
|
+
When a JSDoc block contains exactly one `@story` path and one or more simple `@req` identifiers, and no `@supports` tags, the rule reports a `preferImplements` diagnostic. In `--fix` mode, and when it is safe to do so, it rewrites the block to a consolidated `@supports` annotation of the form:
|
|
267
|
+
|
|
268
|
+
```js
|
|
269
|
+
/**
|
|
270
|
+
* @supports docs/stories/010.0-PAYMENTS.story.md#REQ-PAYMENTS-REFUND REQ-PAYMENTS-EDGE
|
|
271
|
+
*/
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Conceptually, the auto‑fix:
|
|
275
|
+
- Extracts the single `@story` value.
|
|
276
|
+
- Collects the requirement IDs from each `@req` line in that block.
|
|
277
|
+
- Emits a single `@supports story-path#REQ-1 REQ-2 ...` line (or your project’s equivalent anchor scheme).
|
|
278
|
+
|
|
279
|
+
All legacy `@story` and `@req` tags in that block are removed as part of the fix, since their meaning is now captured by the `@supports` line. The fix is only applied when the story path and requirement IDs are straightforward to parse; complex or ambiguous shapes are left for manual migration.
|
|
280
|
+
|
|
281
|
+
2. **Mixed usage with existing `@supports` → `cannotAutoFix` (manual migration)**
|
|
282
|
+
If a JSDoc block already contains at least one `@supports` annotation **and** still has legacy `@story`/`@req` tags, the rule treats this as a mixed‑style block. In this case, it reports a `cannotAutoFix` diagnostic that includes a human‑readable `reason` explaining that the block already uses `@supports` and must be cleaned up manually.
|
|
283
|
+
|
|
284
|
+
The rule **does not** attempt to merge or rewrite mixed blocks automatically, to avoid guessing your intended story/requirement grouping. All annotations in such blocks are left unchanged; you are expected to convert them to your preferred `@supports` shape by hand.
|
|
285
|
+
|
|
286
|
+
3. **Multiple distinct `@story` paths → `multiStoryDetected` (manual migration)**
|
|
287
|
+
When the same JSDoc block contains **multiple different `@story` paths**, the rule reports a `multiStoryDetected` diagnostic and leaves the block unchanged. This scenario usually indicates integration code that implements requirements from several stories, and the correct multi-story `@supports` representation depends on how your project organizes those relationships.
|
|
288
|
+
|
|
289
|
+
Because there is no universally safe way to automatically group requirements across multiple stories, the rule does **not** attempt any auto‑fix in this case. Instead, it highlights the block so humans can migrate it to one or more explicit `@supports` annotations following your multi‑story conventions.
|
|
290
|
+
|
|
291
|
+
Deliberate non‑targets and ignored comments:
|
|
292
|
+
|
|
293
|
+
- JSDoc blocks that contain **only** `@story`, **only** `@req`, or **only** `@supports` are **not** modified by this rule. They remain valid and continue to be governed solely by the core rules such as `require-story-annotation`, `require-req-annotation`, and `valid-annotation-format`.
|
|
294
|
+
- Inline or line comments like `// @story ...`, `// @req ...`, or `// @supports ...` are intentionally ignored by this migration helper; they are still checked by the underlying validation rules where applicable.
|
|
295
|
+
- Any block that does not match the “single story + simple requirements, no supports” shape is treated conservatively: the rule may report a diagnostic to flag the legacy/mixed pattern, but it will not rewrite comments unless it is clearly safe.
|
|
296
|
+
|
|
297
|
+
Interaction with other rules:
|
|
298
|
+
|
|
299
|
+
- Enabling this rule does **not** change what is required or permitted by:
|
|
300
|
+
- `traceability/valid-annotation-format`
|
|
301
|
+
- `traceability/valid-req-reference`
|
|
302
|
+
- `traceability/require-story-annotation`
|
|
303
|
+
- `traceability/require-req-annotation`
|
|
304
|
+
- All existing `@story` + `@req` blocks that pass those rules are still valid when this rule is off. Turning it on simply adds a migration layer that nudges you toward the consolidated `@supports` style and, where unambiguous, performs structural rewrites on your behalf.
|
|
305
|
+
|
|
306
|
+
Example: single‑story auto‑fix
|
|
307
|
+
|
|
308
|
+
Given this legacy JSDoc block:
|
|
309
|
+
|
|
310
|
+
```js
|
|
311
|
+
/**
|
|
312
|
+
* @story docs/stories/010.0-PAYMENTS.story.md
|
|
313
|
+
* @req REQ-PAYMENTS-REFUND
|
|
314
|
+
* @req REQ-PAYMENTS-REFUND-EDGE
|
|
315
|
+
*/
|
|
316
|
+
function issueRefund() {
|
|
317
|
+
// ...
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
With `traceability/prefer-implements-annotation` enabled and ESLint run with `--fix`, the rule rewrites it to:
|
|
322
|
+
|
|
323
|
+
```js
|
|
324
|
+
/**
|
|
325
|
+
* @supports docs/stories/010.0-PAYMENTS.story.md#REQ-PAYMENTS-REFUND REQ-PAYMENTS-REFUND-EDGE
|
|
326
|
+
*/
|
|
327
|
+
function issueRefund() {
|
|
328
|
+
// ...
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
All other function‑level rules (such as `require-story-annotation`, `require-req-annotation`, and `valid-annotation-format`) continue to validate the resulting `@supports` annotation according to your existing configuration.
|
|
333
|
+
|
|
334
|
+
Configuration example (opt‑in at `"warn"`):
|
|
335
|
+
|
|
336
|
+
```js
|
|
337
|
+
// eslint.config.js (flat config)
|
|
338
|
+
import js from "@eslint/js";
|
|
339
|
+
import traceability from "eslint-plugin-traceability";
|
|
340
|
+
|
|
341
|
+
export default [
|
|
342
|
+
js.configs.recommended,
|
|
343
|
+
traceability.configs.recommended,
|
|
344
|
+
{
|
|
345
|
+
rules: {
|
|
346
|
+
"traceability/prefer-implements-annotation": "warn",
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
];
|
|
350
|
+
```
|
|
351
|
+
|
|
245
352
|
## Configuration Presets
|
|
246
353
|
|
|
247
354
|
The plugin provides two built-in presets for easy configuration:
|
package/user-docs/examples.md
CHANGED
|
@@ -84,7 +84,7 @@ Create a Jest test file, for example `tests/dev-test-traceability.spec.ts`:
|
|
|
84
84
|
* @supports docs/stories/021.0-DEV-TEST-TRACEABILITY.story.md#REQ-TEST-TRACEABILITY
|
|
85
85
|
*/
|
|
86
86
|
|
|
87
|
-
describe("
|
|
87
|
+
describe("Story 021.0-DEV-TEST-TRACEABILITY", () => {
|
|
88
88
|
it("[REQ-TEST-TRACEABILITY] should handle the primary test scenario", () => {
|
|
89
89
|
// Arrange
|
|
90
90
|
const input = "happy-path";
|
|
@@ -73,8 +73,41 @@ For teams that want to gradually migrate from `@story` + `@req` to `@supports`,
|
|
|
73
73
|
}
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
This rule is an **optional migration aid**, not a deprecation notice. `@story` and `@req` remain fully supported, and there is no hard requirement or deadline to migrate existing annotations. Use the rule only where `@supports` gives you clearer, multi-story traceability.
|
|
77
|
+
|
|
78
|
+
When enabled, it offers **conservative auto-fixes** that rewrite eligible `@story` + `@req` combinations into equivalent `@supports` lines, without attempting risky or ambiguous transformations. It intentionally refuses to modify comments that are even slightly unclear, and will instead surface diagnostics that explain what needs manual attention.
|
|
79
|
+
|
|
80
|
+
Aligned with the internal rule behavior, the key cases are:
|
|
81
|
+
|
|
82
|
+
- **Simple, single-story JSDoc blocks**
|
|
83
|
+
For comments that contain exactly one `@story` path and one or more simple `@req` lines, the rule:
|
|
84
|
+
- Reports a recommendation to consolidate them, and
|
|
85
|
+
- In `--fix` mode, converts them into a single `@supports` line that keeps the same story path and requirement IDs.
|
|
86
|
+
|
|
87
|
+
- **Mixed `@story` / `@req` plus existing `@supports`**
|
|
88
|
+
For comments that already contain one or more `@supports` lines alongside `@story` and/or `@req`, the rule:
|
|
89
|
+
- Reports a diagnostic explaining that mixed usage cannot be auto-fixed safely, and
|
|
90
|
+
- Leaves the comment unchanged so you can decide how to migrate it manually.
|
|
91
|
+
|
|
92
|
+
- **Multiple distinct `@story` paths**
|
|
93
|
+
For comments that refer to more than one different `@story` path, the rule:
|
|
94
|
+
- Reports that multiple stories were detected, and
|
|
95
|
+
- Requires you to manually convert them into separate `@supports` lines (one per story path, each followed by the appropriate requirement IDs).
|
|
96
|
+
|
|
97
|
+
- **Intentionally ignored comments**
|
|
98
|
+
The following are **ignored** by this rule and remain valid:
|
|
99
|
+
- Comments that contain only `@story` lines,
|
|
100
|
+
- Comments that contain only `@req` lines,
|
|
101
|
+
- Comments that contain only `@supports` lines, and
|
|
102
|
+
- Line comments such as `// @story ...`.
|
|
103
|
+
|
|
104
|
+
These forms are still supported by the plugin and are not modified by `traceability/prefer-implements-annotation`.
|
|
105
|
+
|
|
106
|
+
A typical migration path is:
|
|
107
|
+
|
|
108
|
+
- Start with the rule set to `"off"` while you introduce `@supports` in new or refactored code.
|
|
109
|
+
- Enable it as `"warn"` to get non-breaking guidance and auto-fixes for straightforward cases.
|
|
110
|
+
- Optionally move to `"error"` once you want to strictly enforce `@supports` usage for all JSDoc blocks that are eligible for safe conversion.
|
|
78
111
|
|
|
79
112
|
#### When to keep `@story` + `@req`
|
|
80
113
|
|