eslint-plugin-traceability 1.6.4 → 1.7.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.
- package/README.md +38 -1
- package/lib/src/index.d.ts +28 -25
- package/lib/src/index.js +49 -31
- package/lib/src/maintenance/cli.d.ts +12 -0
- package/lib/src/maintenance/cli.js +279 -0
- package/lib/src/maintenance/detect.js +30 -15
- package/lib/src/maintenance/update.js +42 -34
- package/lib/src/maintenance/utils.js +30 -30
- package/lib/src/rules/helpers/require-story-io.js +51 -15
- package/lib/src/rules/helpers/require-story-visitors.js +5 -16
- package/lib/src/rules/helpers/valid-annotation-options.d.ts +118 -0
- package/lib/src/rules/helpers/valid-annotation-options.js +167 -0
- package/lib/src/rules/helpers/valid-annotation-utils.d.ts +68 -0
- package/lib/src/rules/helpers/valid-annotation-utils.js +103 -0
- package/lib/src/rules/helpers/valid-story-reference-helpers.d.ts +67 -0
- package/lib/src/rules/helpers/valid-story-reference-helpers.js +92 -0
- package/lib/src/rules/require-story-annotation.js +9 -14
- package/lib/src/rules/valid-annotation-format.js +168 -180
- package/lib/src/rules/valid-req-reference.js +139 -29
- package/lib/src/rules/valid-story-reference.d.ts +7 -0
- package/lib/src/rules/valid-story-reference.js +38 -80
- package/lib/src/utils/annotation-checker.js +2 -145
- package/lib/src/utils/branch-annotation-helpers.js +12 -3
- package/lib/src/utils/reqAnnotationDetection.d.ts +6 -0
- package/lib/src/utils/reqAnnotationDetection.js +152 -0
- package/lib/tests/maintenance/cli.test.d.ts +1 -0
- package/lib/tests/maintenance/cli.test.js +172 -0
- package/lib/tests/maintenance/detect-isolated.test.js +68 -1
- package/lib/tests/maintenance/report.test.js +2 -2
- package/lib/tests/rules/require-branch-annotation.test.js +3 -2
- package/lib/tests/rules/require-req-annotation.test.js +57 -68
- package/lib/tests/rules/require-story-annotation.test.js +13 -28
- package/lib/tests/rules/require-story-core-edgecases.test.js +3 -58
- package/lib/tests/rules/require-story-core.autofix.test.js +5 -41
- package/lib/tests/rules/valid-annotation-format.test.js +328 -51
- package/lib/tests/utils/annotation-checker.test.d.ts +23 -0
- package/lib/tests/utils/annotation-checker.test.js +24 -17
- package/lib/tests/utils/require-story-core-test-helpers.d.ts +10 -0
- package/lib/tests/utils/require-story-core-test-helpers.js +75 -0
- package/lib/tests/utils/ts-language-options.d.ts +22 -0
- package/lib/tests/utils/ts-language-options.js +27 -0
- package/package.json +12 -3
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
*/
|
|
11
11
|
const eslint_1 = require("eslint");
|
|
12
12
|
const require_story_annotation_1 = __importDefault(require("../../src/rules/require-story-annotation"));
|
|
13
|
+
const ts_language_options_1 = require("../utils/ts-language-options");
|
|
13
14
|
const ruleTester = new eslint_1.RuleTester({
|
|
14
15
|
languageOptions: {
|
|
15
16
|
parserOptions: { ecmaVersion: 2020, sourceType: "module" },
|
|
@@ -36,30 +37,22 @@ function foo() {}`,
|
|
|
36
37
|
code: `// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
|
|
37
38
|
const arrowFn = () => {};`,
|
|
38
39
|
},
|
|
39
|
-
{
|
|
40
|
+
(0, ts_language_options_1.withTsLanguageOptions)({
|
|
40
41
|
name: "[REQ-ANNOTATION-REQUIRED] valid on class method with annotation",
|
|
41
42
|
code: `class A {\n /** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */\n method() {}\n}`,
|
|
42
|
-
},
|
|
43
|
-
{
|
|
43
|
+
}),
|
|
44
|
+
(0, ts_language_options_1.withTsLanguageOptions)({
|
|
44
45
|
name: "[REQ-FUNCTION-DETECTION] valid with annotation on TS declare function",
|
|
45
46
|
code: `/** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */
|
|
46
47
|
declare function tsDecl(): void;`,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
parserOptions: { ecmaVersion: 2020, sourceType: "module" },
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
{
|
|
48
|
+
}),
|
|
49
|
+
(0, ts_language_options_1.withTsLanguageOptions)({
|
|
53
50
|
name: "[REQ-FUNCTION-DETECTION] valid with annotation on TS method signature",
|
|
54
51
|
code: `interface C {
|
|
55
52
|
/** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */
|
|
56
53
|
method(): void;
|
|
57
54
|
}`,
|
|
58
|
-
|
|
59
|
-
parser: require("@typescript-eslint/parser"),
|
|
60
|
-
parserOptions: { ecmaVersion: 2020, sourceType: "module" },
|
|
61
|
-
},
|
|
62
|
-
},
|
|
55
|
+
}),
|
|
63
56
|
{
|
|
64
57
|
name: "[REQ-ANNOTATION-REQUIRED] unannotated arrow function allowed by default",
|
|
65
58
|
code: `const arrowFn = () => {};`,
|
|
@@ -98,7 +91,7 @@ declare function tsDecl(): void;`,
|
|
|
98
91
|
},
|
|
99
92
|
],
|
|
100
93
|
},
|
|
101
|
-
{
|
|
94
|
+
(0, ts_language_options_1.withTsLanguageOptions)({
|
|
102
95
|
name: "[REQ-ANNOTATION-REQUIRED] missing @story on class method",
|
|
103
96
|
code: `class C {\n method() {}\n}`,
|
|
104
97
|
output: `class C {\n /** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */\n method() {}\n}`,
|
|
@@ -114,15 +107,11 @@ declare function tsDecl(): void;`,
|
|
|
114
107
|
],
|
|
115
108
|
},
|
|
116
109
|
],
|
|
117
|
-
},
|
|
118
|
-
{
|
|
110
|
+
}),
|
|
111
|
+
(0, ts_language_options_1.withTsLanguageOptions)({
|
|
119
112
|
name: "[REQ-ANNOTATION-REQUIRED] missing @story on TS declare function",
|
|
120
113
|
code: `declare function tsDecl(): void;`,
|
|
121
114
|
output: `/** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */\ndeclare function tsDecl(): void;`,
|
|
122
|
-
languageOptions: {
|
|
123
|
-
parser: require("@typescript-eslint/parser"),
|
|
124
|
-
parserOptions: { ecmaVersion: 2020, sourceType: "module" },
|
|
125
|
-
},
|
|
126
115
|
errors: [
|
|
127
116
|
{
|
|
128
117
|
messageId: "missingStory",
|
|
@@ -134,15 +123,11 @@ declare function tsDecl(): void;`,
|
|
|
134
123
|
],
|
|
135
124
|
},
|
|
136
125
|
],
|
|
137
|
-
},
|
|
138
|
-
{
|
|
126
|
+
}),
|
|
127
|
+
(0, ts_language_options_1.withTsLanguageOptions)({
|
|
139
128
|
name: "[REQ-ANNOTATION-REQUIRED] missing @story on TS method signature",
|
|
140
129
|
code: `interface D {\n method(): void;\n}`,
|
|
141
130
|
output: `/** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */\ninterface D {\n method(): void;\n}`,
|
|
142
|
-
languageOptions: {
|
|
143
|
-
parser: require("@typescript-eslint/parser"),
|
|
144
|
-
parserOptions: { ecmaVersion: 2020, sourceType: "module" },
|
|
145
|
-
},
|
|
146
131
|
errors: [
|
|
147
132
|
{
|
|
148
133
|
messageId: "missingStory",
|
|
@@ -154,7 +139,7 @@ declare function tsDecl(): void;`,
|
|
|
154
139
|
],
|
|
155
140
|
},
|
|
156
141
|
],
|
|
157
|
-
},
|
|
142
|
+
}),
|
|
158
143
|
],
|
|
159
144
|
});
|
|
160
145
|
ruleTester.run("require-story-annotation with exportPriority option", require_story_annotation_1.default, {
|
|
@@ -6,64 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
* @req REQ-AUTOFIX - Cover additional branch cases in require-story-core (addStoryFixer/reportMissing)
|
|
7
7
|
*/
|
|
8
8
|
const require_story_core_1 = require("../../src/rules/helpers/require-story-core");
|
|
9
|
-
const
|
|
9
|
+
const require_story_core_test_helpers_1 = require("../utils/require-story-core-test-helpers");
|
|
10
10
|
describe("Require Story Core - edge cases (Story 003.0)", () => {
|
|
11
|
-
test("createAddStoryFix
|
|
12
|
-
|
|
13
|
-
insertTextBeforeRange: jest.fn((r, t) => ({ r, t })),
|
|
14
|
-
};
|
|
15
|
-
const fixFn = (0, require_story_core_1.createAddStoryFix)(null);
|
|
16
|
-
const res = fixFn(fixer);
|
|
17
|
-
expect(fixer.insertTextBeforeRange).toHaveBeenCalledTimes(1);
|
|
18
|
-
const args = fixer.insertTextBeforeRange.mock.calls[0];
|
|
19
|
-
expect(args[0]).toEqual([0, 0]);
|
|
20
|
-
expect(args[1]).toBe(`${require_story_helpers_1.ANNOTATION}\n`);
|
|
21
|
-
expect(res).toEqual({ r: [0, 0], t: `${require_story_helpers_1.ANNOTATION}\n` });
|
|
22
|
-
});
|
|
23
|
-
test("createAddStoryFix uses target.range when parent not export and parent.range missing", () => {
|
|
24
|
-
const target = {
|
|
25
|
-
type: "FunctionDeclaration",
|
|
26
|
-
range: [21, 33],
|
|
27
|
-
parent: { type: "ClassBody" },
|
|
28
|
-
};
|
|
29
|
-
const fixer = {
|
|
30
|
-
insertTextBeforeRange: jest.fn((r, t) => ({ r, t })),
|
|
31
|
-
};
|
|
32
|
-
const fixFn = (0, require_story_core_1.createAddStoryFix)(target);
|
|
33
|
-
const res = fixFn(fixer);
|
|
34
|
-
expect(fixer.insertTextBeforeRange.mock.calls[0][0]).toEqual([21, 21]);
|
|
35
|
-
expect(fixer.insertTextBeforeRange.mock.calls[0][1]).toBe(`${require_story_helpers_1.ANNOTATION}\n`);
|
|
36
|
-
expect(res).toEqual({ r: [21, 21], t: `${require_story_helpers_1.ANNOTATION}\n` });
|
|
37
|
-
});
|
|
38
|
-
test("createAddStoryFix prefers ExportDefaultDeclaration parent.range when present", () => {
|
|
39
|
-
const target = {
|
|
40
|
-
type: "FunctionDeclaration",
|
|
41
|
-
range: [50, 70],
|
|
42
|
-
parent: { type: "ExportDefaultDeclaration", range: [5, 100] },
|
|
43
|
-
};
|
|
44
|
-
const fixer = {
|
|
45
|
-
insertTextBeforeRange: jest.fn((r, t) => ({ r, t })),
|
|
46
|
-
};
|
|
47
|
-
const fixFn = (0, require_story_core_1.createAddStoryFix)(target);
|
|
48
|
-
const res = fixFn(fixer);
|
|
49
|
-
expect(fixer.insertTextBeforeRange.mock.calls[0][0]).toEqual([5, 5]);
|
|
50
|
-
expect(fixer.insertTextBeforeRange.mock.calls[0][1]).toBe(`${require_story_helpers_1.ANNOTATION}\n`);
|
|
51
|
-
expect(res).toEqual({ r: [5, 5], t: `${require_story_helpers_1.ANNOTATION}\n` });
|
|
52
|
-
});
|
|
53
|
-
test("reportMissing uses context.getSourceCode fallback when sourceCode not provided and still reports", () => {
|
|
54
|
-
const node = {
|
|
55
|
-
type: "FunctionDeclaration",
|
|
56
|
-
id: { name: "fnX" },
|
|
57
|
-
range: [0, 10],
|
|
58
|
-
};
|
|
59
|
-
const fakeSource = {
|
|
60
|
-
/* intentionally missing getJSDocComment to exercise branch */ getText: () => "",
|
|
61
|
-
};
|
|
62
|
-
const context = { getSourceCode: () => fakeSource, report: jest.fn() };
|
|
63
|
-
(0, require_story_core_1.reportMissing)(context, undefined, node, node);
|
|
64
|
-
expect(context.report).toHaveBeenCalledTimes(1);
|
|
65
|
-
const call = context.report.mock.calls[0][0];
|
|
66
|
-
expect(call.node).toBe(node);
|
|
67
|
-
expect(call.messageId).toBe("missingStory");
|
|
11
|
+
test("createAddStoryFix covers primary branch combinations via shared helper (edge cases)", () => {
|
|
12
|
+
(0, require_story_core_test_helpers_1.exerciseCreateAddStoryFixBranches)(require_story_core_1.createAddStoryFix);
|
|
68
13
|
});
|
|
69
14
|
});
|
|
@@ -7,48 +7,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
*/
|
|
8
8
|
const require_story_core_1 = require("../../src/rules/helpers/require-story-core");
|
|
9
9
|
const require_story_helpers_1 = require("../../src/rules/helpers/require-story-helpers");
|
|
10
|
+
const require_story_core_test_helpers_1 = require("../utils/require-story-core-test-helpers");
|
|
10
11
|
describe("Require Story Core (Story 003.0)", () => {
|
|
11
|
-
test("createAddStoryFix
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
};
|
|
15
|
-
const fixFn = (0, require_story_core_1.createAddStoryFix)(null);
|
|
16
|
-
const res = fixFn(fixer);
|
|
17
|
-
expect(fixer.insertTextBeforeRange).toHaveBeenCalledTimes(1);
|
|
18
|
-
const args = fixer.insertTextBeforeRange.mock.calls[0];
|
|
19
|
-
expect(args[0]).toEqual([0, 0]);
|
|
20
|
-
expect(args[1]).toBe(`${require_story_helpers_1.ANNOTATION}\n`);
|
|
21
|
-
expect(res).toEqual({ r: [0, 0], t: `${require_story_helpers_1.ANNOTATION}\n` });
|
|
22
|
-
});
|
|
23
|
-
test("createAddStoryFix uses target.range when parent not export and parent.range missing", () => {
|
|
24
|
-
const target = {
|
|
25
|
-
type: "FunctionDeclaration",
|
|
26
|
-
range: [21, 33],
|
|
27
|
-
parent: { type: "ClassBody" },
|
|
28
|
-
};
|
|
29
|
-
const fixer = {
|
|
30
|
-
insertTextBeforeRange: jest.fn((r, t) => ({ r, t })),
|
|
31
|
-
};
|
|
32
|
-
const fixFn = (0, require_story_core_1.createAddStoryFix)(target);
|
|
33
|
-
const res = fixFn(fixer);
|
|
34
|
-
expect(fixer.insertTextBeforeRange.mock.calls[0][0]).toEqual([21, 21]);
|
|
35
|
-
expect(fixer.insertTextBeforeRange.mock.calls[0][1]).toBe(`${require_story_helpers_1.ANNOTATION}\n`);
|
|
36
|
-
expect(res).toEqual({ r: [21, 21], t: `${require_story_helpers_1.ANNOTATION}\n` });
|
|
37
|
-
});
|
|
38
|
-
test("createAddStoryFix prefers ExportDefaultDeclaration parent.range when present", () => {
|
|
39
|
-
const target = {
|
|
40
|
-
type: "FunctionDeclaration",
|
|
41
|
-
range: [50, 70],
|
|
42
|
-
parent: { type: "ExportDefaultDeclaration", range: [5, 100] },
|
|
43
|
-
};
|
|
44
|
-
const fixer = {
|
|
45
|
-
insertTextBeforeRange: jest.fn((r, t) => ({ r, t })),
|
|
46
|
-
};
|
|
47
|
-
const fixFn = (0, require_story_core_1.createAddStoryFix)(target);
|
|
48
|
-
const res = fixFn(fixer);
|
|
49
|
-
expect(fixer.insertTextBeforeRange.mock.calls[0][0]).toEqual([5, 5]);
|
|
50
|
-
expect(fixer.insertTextBeforeRange.mock.calls[0][1]).toBe(`${require_story_helpers_1.ANNOTATION}\n`);
|
|
51
|
-
expect(res).toEqual({ r: [5, 5], t: `${require_story_helpers_1.ANNOTATION}\n` });
|
|
12
|
+
test("createAddStoryFix covers primary branch combinations via shared helper", () => {
|
|
13
|
+
(0, require_story_core_test_helpers_1.exerciseCreateAddStoryFixBranches)(require_story_core_1.createAddStoryFix, {
|
|
14
|
+
annotationText: require_story_helpers_1.ANNOTATION + "\n",
|
|
15
|
+
});
|
|
52
16
|
});
|
|
53
17
|
test("reportMissing uses context.getSourceCode fallback when sourceCode not provided and still reports", () => {
|
|
54
18
|
const node = {
|