eslint-plugin-traceability 1.6.0 → 1.6.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/lib/src/index.d.ts +6 -0
- package/lib/src/index.js +6 -0
- package/lib/src/rules/helpers/require-story-helpers.d.ts +7 -0
- package/lib/src/rules/helpers/require-story-helpers.js +9 -2
- package/lib/src/rules/require-branch-annotation.js +5 -1
- package/lib/src/rules/require-req-annotation.d.ts +9 -4
- package/lib/src/rules/require-req-annotation.js +82 -22
- package/lib/src/rules/require-story-annotation.d.ts +8 -0
- package/lib/src/rules/require-story-annotation.js +17 -2
- package/lib/src/rules/valid-annotation-format.js +34 -2
- package/lib/src/rules/valid-req-reference.js +14 -0
- package/lib/src/rules/valid-story-reference.js +21 -0
- package/lib/src/utils/annotation-checker.d.ts +7 -1
- package/lib/src/utils/annotation-checker.js +145 -12
- package/lib/tests/cli-error-handling.test.js +1 -1
- package/lib/tests/plugin-default-export-and-configs.test.js +16 -0
- package/lib/tests/rules/auto-fix-behavior-008.test.js +76 -0
- package/lib/tests/rules/error-reporting.test.js +72 -23
- package/lib/tests/rules/require-branch-annotation.test.js +5 -1
- package/lib/tests/rules/require-req-annotation.test.js +228 -8
- package/lib/tests/rules/require-story-annotation.test.js +1 -0
- package/lib/tests/rules/valid-annotation-format.test.js +5 -0
- package/lib/tests/rules/valid-req-reference.test.js +6 -0
- package/lib/tests/rules/valid-story-reference.test.js +5 -0
- package/package.json +1 -1
|
@@ -44,25 +44,96 @@ describe("Require Req Annotation Rule (Story 003.0-DEV-FUNCTION-ANNOTATIONS)", (
|
|
|
44
44
|
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
|
|
45
45
|
},
|
|
46
46
|
},
|
|
47
|
+
{
|
|
48
|
+
name: "[REQ-FUNCTION-DETECTION][Story 003.0] valid FunctionExpression with @req annotation",
|
|
49
|
+
code: `const fn = /**\n * @req REQ-EXAMPLE\n */\nfunction() {};`,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "[REQ-FUNCTION-DETECTION][Story 003.0] valid MethodDefinition with @req annotation",
|
|
53
|
+
code: `class C {\n /**\n * @req REQ-EXAMPLE\n */\n m() {}\n}`,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "[REQ-TYPESCRIPT-SUPPORT][REQ-FUNCTION-DETECTION][Story 003.0] valid TS FunctionExpression in variable declarator with @req",
|
|
57
|
+
code: `const fn = /**\n * @req REQ-EXAMPLE\n */\nfunction () {};`,
|
|
58
|
+
languageOptions: {
|
|
59
|
+
parser: require("@typescript-eslint/parser"),
|
|
60
|
+
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: "[REQ-TYPESCRIPT-SUPPORT][REQ-FUNCTION-DETECTION][Story 003.0] valid exported TS FunctionExpression in variable declarator with @req",
|
|
65
|
+
code: `export const fn = /**\n * @req REQ-EXAMPLE\n */\nfunction () {};`,
|
|
66
|
+
languageOptions: {
|
|
67
|
+
parser: require("@typescript-eslint/parser"),
|
|
68
|
+
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "[REQ-CONFIGURABLE-SCOPE][Story 003.0] FunctionExpression ignored when scope only includes FunctionDeclaration",
|
|
73
|
+
code: `const fn = function () {};`,
|
|
74
|
+
options: [{ scope: ["FunctionDeclaration"] }],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "[REQ-EXPORT-PRIORITY][Story 003.0] non-exported function ignored when exportPriority is 'exported'",
|
|
78
|
+
code: `function nonExported() {}`,
|
|
79
|
+
options: [{ exportPriority: "exported" }],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: "[REQ-EXPORT-PRIORITY][Story 003.0] exported function required when exportPriority is 'exported'",
|
|
83
|
+
code: `/** @req REQ-EXAMPLE */\nexport function exportedFn() {}`,
|
|
84
|
+
options: [{ exportPriority: "exported" }],
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "[REQ-EXPORT-PRIORITY][Story 003.0] exported function ignored when exportPriority is 'non-exported'",
|
|
88
|
+
code: `export function exportedFn() {}`,
|
|
89
|
+
options: [{ exportPriority: "non-exported" }],
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: "[REQ-EXPORT-PRIORITY][Story 003.0] non-exported function required when exportPriority is 'non-exported'",
|
|
93
|
+
code: `/** @req REQ-EXAMPLE */\nfunction nonExported() {}`,
|
|
94
|
+
options: [{ exportPriority: "non-exported" }],
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "[REQ-EXPORT-PRIORITY][Story 003.0] exported method ignored when exportPriority is 'non-exported'",
|
|
98
|
+
code: `export class C {\n m() {}\n}`,
|
|
99
|
+
options: [{ exportPriority: "non-exported" }],
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "[REQ-EXPORT-PRIORITY][Story 003.0] non-exported method required when exportPriority is 'non-exported'",
|
|
103
|
+
code: `class C {\n /** @req REQ-EXAMPLE */\n m() {}\n}`,
|
|
104
|
+
options: [{ exportPriority: "non-exported" }],
|
|
105
|
+
},
|
|
47
106
|
],
|
|
48
107
|
invalid: [
|
|
49
108
|
{
|
|
50
109
|
name: "[REQ-ANNOTATION-REQUIRED] missing @req on function without JSDoc",
|
|
51
110
|
code: `function baz() {}`,
|
|
52
|
-
|
|
53
|
-
|
|
111
|
+
errors: [
|
|
112
|
+
{
|
|
113
|
+
messageId: "missingReq",
|
|
114
|
+
data: { name: "baz", functionName: "baz" },
|
|
115
|
+
},
|
|
116
|
+
],
|
|
54
117
|
},
|
|
55
118
|
{
|
|
56
119
|
name: "[REQ-ANNOTATION-REQUIRED] missing @req on function with only @story annotation",
|
|
57
120
|
code: `/**\n * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md\n */\nfunction qux() {}`,
|
|
58
|
-
|
|
59
|
-
|
|
121
|
+
errors: [
|
|
122
|
+
{
|
|
123
|
+
messageId: "missingReq",
|
|
124
|
+
data: { name: "qux", functionName: "qux" },
|
|
125
|
+
},
|
|
126
|
+
],
|
|
60
127
|
},
|
|
61
128
|
{
|
|
62
129
|
name: "[REQ-TYPESCRIPT-SUPPORT] missing @req on TSDeclareFunction",
|
|
63
130
|
code: `declare function baz(): void;`,
|
|
64
|
-
|
|
65
|
-
|
|
131
|
+
errors: [
|
|
132
|
+
{
|
|
133
|
+
messageId: "missingReq",
|
|
134
|
+
data: { name: "baz", functionName: "baz" },
|
|
135
|
+
},
|
|
136
|
+
],
|
|
66
137
|
languageOptions: {
|
|
67
138
|
parser: require("@typescript-eslint/parser"),
|
|
68
139
|
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
|
|
@@ -71,13 +142,162 @@ describe("Require Req Annotation Rule (Story 003.0-DEV-FUNCTION-ANNOTATIONS)", (
|
|
|
71
142
|
{
|
|
72
143
|
name: "[REQ-TYPESCRIPT-SUPPORT] missing @req on TSMethodSignature",
|
|
73
144
|
code: `interface I { method(): void; }`,
|
|
74
|
-
|
|
75
|
-
|
|
145
|
+
errors: [
|
|
146
|
+
{
|
|
147
|
+
messageId: "missingReq",
|
|
148
|
+
data: { name: "method", functionName: "method" },
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
languageOptions: {
|
|
152
|
+
parser: require("@typescript-eslint/parser"),
|
|
153
|
+
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: "[REQ-FUNCTION-DETECTION][Story 003.0] missing @req on FunctionExpression assigned to variable",
|
|
158
|
+
code: `const fn = function () {};`,
|
|
159
|
+
errors: [
|
|
160
|
+
{
|
|
161
|
+
messageId: "missingReq",
|
|
162
|
+
data: { name: "fn", functionName: "fn" },
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: "[REQ-FUNCTION-DETECTION][Story 003.0] missing @req on anonymous FunctionExpression (no variable name)",
|
|
168
|
+
code: `(function () {})();`,
|
|
169
|
+
errors: [
|
|
170
|
+
{
|
|
171
|
+
messageId: "missingReq",
|
|
172
|
+
data: { name: "(anonymous)", functionName: "(anonymous)" },
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: "[REQ-FUNCTION-DETECTION][Story 003.0] missing @req on MethodDefinition in class",
|
|
178
|
+
code: `class C {\n m() {}\n}`,
|
|
179
|
+
errors: [
|
|
180
|
+
{
|
|
181
|
+
messageId: "missingReq",
|
|
182
|
+
data: { name: "m", functionName: "m" },
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: "[REQ-FUNCTION-DETECTION][Story 003.0] missing @req on MethodDefinition in object literal",
|
|
188
|
+
code: `const o = { m() {} };`,
|
|
189
|
+
errors: [
|
|
190
|
+
{
|
|
191
|
+
messageId: "missingReq",
|
|
192
|
+
data: { name: "m", functionName: "m" },
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: "[REQ-TYPESCRIPT-SUPPORT][REQ-FUNCTION-DETECTION][Story 003.0] missing @req on TS FunctionExpression in variable declarator",
|
|
198
|
+
code: `const fn = function () {};`,
|
|
199
|
+
errors: [
|
|
200
|
+
{
|
|
201
|
+
messageId: "missingReq",
|
|
202
|
+
data: { name: "fn", functionName: "fn" },
|
|
203
|
+
},
|
|
204
|
+
],
|
|
205
|
+
languageOptions: {
|
|
206
|
+
parser: require("@typescript-eslint/parser"),
|
|
207
|
+
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: "[REQ-TYPESCRIPT-SUPPORT][REQ-FUNCTION-DETECTION][Story 003.0] missing @req on exported TS FunctionExpression in variable declarator",
|
|
212
|
+
code: `export const fn = function () {};`,
|
|
213
|
+
errors: [
|
|
214
|
+
{
|
|
215
|
+
messageId: "missingReq",
|
|
216
|
+
data: { name: "fn", functionName: "fn" },
|
|
217
|
+
},
|
|
218
|
+
],
|
|
76
219
|
languageOptions: {
|
|
77
220
|
parser: require("@typescript-eslint/parser"),
|
|
78
221
|
parserOptions: { ecmaVersion: 2022, sourceType: "module" },
|
|
79
222
|
},
|
|
80
223
|
},
|
|
224
|
+
{
|
|
225
|
+
name: "[REQ-CONFIGURABLE-SCOPE][Story 003.0] FunctionDeclaration still reported when scope only includes FunctionDeclaration",
|
|
226
|
+
code: `function scoped() {}`,
|
|
227
|
+
options: [{ scope: ["FunctionDeclaration"] }],
|
|
228
|
+
errors: [
|
|
229
|
+
{
|
|
230
|
+
messageId: "missingReq",
|
|
231
|
+
data: { name: "scoped", functionName: "scoped" },
|
|
232
|
+
},
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
name: "[REQ-EXPORT-PRIORITY][Story 003.0] exported function reported when exportPriority is 'exported'",
|
|
237
|
+
code: `export function exportedFn() {}`,
|
|
238
|
+
options: [{ exportPriority: "exported" }],
|
|
239
|
+
errors: [
|
|
240
|
+
{
|
|
241
|
+
messageId: "missingReq",
|
|
242
|
+
data: { name: "exportedFn", functionName: "exportedFn" },
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: "[REQ-EXPORT-PRIORITY][Story 003.0] non-exported function reported when exportPriority is 'non-exported'",
|
|
248
|
+
code: `function nonExported() {}`,
|
|
249
|
+
options: [{ exportPriority: "non-exported" }],
|
|
250
|
+
errors: [
|
|
251
|
+
{
|
|
252
|
+
messageId: "missingReq",
|
|
253
|
+
data: { name: "nonExported", functionName: "nonExported" },
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
name: "[REQ-EXPORT-PRIORITY][Story 003.0] exported method reported when exportPriority is 'exported'",
|
|
259
|
+
code: `export class C {\n m() {}\n}`,
|
|
260
|
+
errors: [
|
|
261
|
+
{
|
|
262
|
+
messageId: "missingReq",
|
|
263
|
+
data: { name: "m", functionName: "m" },
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
options: [{ exportPriority: "exported" }],
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
name: "[REQ-EXPORT-PRIORITY][Story 003.0] non-exported method reported when exportPriority is 'non-exported'",
|
|
270
|
+
code: `class C {\n m() {}\n}`,
|
|
271
|
+
errors: [
|
|
272
|
+
{
|
|
273
|
+
messageId: "missingReq",
|
|
274
|
+
data: { name: "m", functionName: "m" },
|
|
275
|
+
},
|
|
276
|
+
],
|
|
277
|
+
options: [{ exportPriority: "non-exported" }],
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
name: "[REQ-EXPORT-PRIORITY][Story 003.0] exported FunctionExpression reported when exportPriority is 'exported'",
|
|
281
|
+
code: `export const fn = function () {};`,
|
|
282
|
+
options: [{ exportPriority: "exported" }],
|
|
283
|
+
errors: [
|
|
284
|
+
{
|
|
285
|
+
messageId: "missingReq",
|
|
286
|
+
data: { name: "fn", functionName: "fn" },
|
|
287
|
+
},
|
|
288
|
+
],
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
name: "[REQ-EXPORT-PRIORITY][Story 003.0] non-exported FunctionExpression reported when exportPriority is 'non-exported'",
|
|
292
|
+
code: `const fn = function () {};`,
|
|
293
|
+
options: [{ exportPriority: "non-exported" }],
|
|
294
|
+
errors: [
|
|
295
|
+
{
|
|
296
|
+
messageId: "missingReq",
|
|
297
|
+
data: { name: "fn", functionName: "fn" },
|
|
298
|
+
},
|
|
299
|
+
],
|
|
300
|
+
},
|
|
81
301
|
],
|
|
82
302
|
});
|
|
83
303
|
});
|
|
@@ -105,6 +105,7 @@ declare function tsDecl(): void;`,
|
|
|
105
105
|
errors: [
|
|
106
106
|
{
|
|
107
107
|
messageId: "missingStory",
|
|
108
|
+
data: { name: "method", functionName: "method" },
|
|
108
109
|
suggestions: [
|
|
109
110
|
{
|
|
110
111
|
desc: `Add JSDoc @story annotation for function 'method', e.g., /** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */`,
|
|
@@ -7,6 +7,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
* Tests for: docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
|
|
8
8
|
* @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
|
|
9
9
|
* @req REQ-FORMAT-SPECIFICATION - Verify valid-annotation-format rule enforces annotation format syntax
|
|
10
|
+
* Tests for: docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
11
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
12
|
+
* @req REQ-ERROR-MESSAGES-CONSISTENT - Verify invalid annotation errors use consistent wording and structure
|
|
13
|
+
* @req REQ-ERROR-MESSAGES-ACTIONABLE - Verify invalid annotation errors provide actionable guidance and examples
|
|
14
|
+
* @req REQ-ERROR-MESSAGES-IDENTIFIERS - Verify invalid annotation errors echo the offending identifier/path in the message
|
|
10
15
|
*/
|
|
11
16
|
const eslint_1 = require("eslint");
|
|
12
17
|
const valid_annotation_format_1 = __importDefault(require("../../src/rules/valid-annotation-format"));
|
|
@@ -7,6 +7,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
* Tests for: docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
8
8
|
* @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
9
9
|
* @req REQ-DEEP-PARSE - Verify valid-req-reference rule enforces existing requirement content
|
|
10
|
+
*
|
|
11
|
+
* Additional coverage for error reporting behavior:
|
|
12
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
13
|
+
* @req REQ-ERROR-SPECIFIC - Verify requirement-level errors identify the exact missing requirement
|
|
14
|
+
* @req REQ-ERROR-CONTEXT - Verify requirement-level errors include relevant story path context
|
|
15
|
+
* @req REQ-ERROR-CONSISTENCY - Verify requirement-level error messages are consistent across cases
|
|
10
16
|
*/
|
|
11
17
|
const eslint_1 = require("eslint");
|
|
12
18
|
const valid_req_reference_1 = __importDefault(require("../../src/rules/valid-req-reference"));
|
|
@@ -7,6 +7,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
* Tests for: docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
8
8
|
* @story docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
9
9
|
* @req REQ-FILE-EXISTENCE - Verify valid-story-reference rule enforces existing .story.md files
|
|
10
|
+
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
11
|
+
* @req REQ-ERROR-SPECIFIC - Verify file-related error messages are specific about failure causes
|
|
12
|
+
* @req REQ-ERROR-CONTEXT - Verify file-related error messages include contextual information (path, underlying error)
|
|
13
|
+
* @req REQ-ERROR-CONSISTENCY - Verify file-related error messages follow consistent formatting and identifiers
|
|
14
|
+
* @req REQ-ERROR-HANDLING - Verify file-related errors are reported via diagnostics instead of uncaught exceptions
|
|
10
15
|
*/
|
|
11
16
|
const eslint_1 = require("eslint");
|
|
12
17
|
const valid_story_reference_1 = __importDefault(require("../../src/rules/valid-story-reference"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-traceability",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.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",
|