eslint-plugin-traceability 1.4.10 → 1.4.11
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/rules/helpers/require-story-core.js +0 -1
- package/lib/src/rules/helpers/require-story-helpers.js +6 -2
- package/lib/src/rules/require-story-annotation.js +1 -1
- package/lib/tests/rules/require-story-annotation.test.js +9 -31
- package/lib/tests/rules/valid-story-reference.test.js +36 -0
- package/package.json +1 -1
|
@@ -252,8 +252,11 @@ function reportMissing(context, sourceCode, node, passedTarget) {
|
|
|
252
252
|
}
|
|
253
253
|
const resolvedTarget = passedTarget ?? resolveTargetNode(sourceCode, node);
|
|
254
254
|
const name = functionName;
|
|
255
|
+
const nameNode = (node.id && node.id.type === "Identifier" && node.id) ||
|
|
256
|
+
(node.key && node.key.type === "Identifier" && node.key) ||
|
|
257
|
+
node;
|
|
255
258
|
context.report({
|
|
256
|
-
node,
|
|
259
|
+
node: nameNode,
|
|
257
260
|
messageId: "missingStory",
|
|
258
261
|
data: { name },
|
|
259
262
|
suggest: [
|
|
@@ -285,8 +288,9 @@ function reportMethod(context, sourceCode, node, passedTarget) {
|
|
|
285
288
|
}
|
|
286
289
|
const resolvedTarget = passedTarget ?? resolveTargetNode(sourceCode, node);
|
|
287
290
|
const name = extractName(node);
|
|
291
|
+
const nameNode = (node.key && node.key.type === "Identifier" && node.key) || node;
|
|
288
292
|
context.report({
|
|
289
|
-
node,
|
|
293
|
+
node: nameNode,
|
|
290
294
|
messageId: "missingStory",
|
|
291
295
|
data: { name },
|
|
292
296
|
suggest: [
|
|
@@ -60,6 +60,10 @@ declare function tsDecl(): void;`,
|
|
|
60
60
|
parserOptions: { ecmaVersion: 2020, sourceType: "module" },
|
|
61
61
|
},
|
|
62
62
|
},
|
|
63
|
+
{
|
|
64
|
+
name: "[REQ-ANNOTATION-REQUIRED] unannotated arrow function allowed by default",
|
|
65
|
+
code: `const arrowFn = () => {};`,
|
|
66
|
+
},
|
|
63
67
|
],
|
|
64
68
|
invalid: [
|
|
65
69
|
{
|
|
@@ -92,21 +96,6 @@ declare function tsDecl(): void;`,
|
|
|
92
96
|
},
|
|
93
97
|
],
|
|
94
98
|
},
|
|
95
|
-
{
|
|
96
|
-
name: "[REQ-ANNOTATION-REQUIRED] missing @story on arrow function",
|
|
97
|
-
code: `const arrowFn = () => {};`,
|
|
98
|
-
errors: [
|
|
99
|
-
{
|
|
100
|
-
messageId: "missingStory",
|
|
101
|
-
suggestions: [
|
|
102
|
-
{
|
|
103
|
-
desc: `Add JSDoc @story annotation for function 'arrowFn', e.g., /** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */`,
|
|
104
|
-
output: `/** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */\nconst arrowFn = () => {};`,
|
|
105
|
-
},
|
|
106
|
-
],
|
|
107
|
-
},
|
|
108
|
-
],
|
|
109
|
-
},
|
|
110
99
|
{
|
|
111
100
|
name: "[REQ-ANNOTATION-REQUIRED] missing @story on class method",
|
|
112
101
|
code: `class C {\n method() {}\n}`,
|
|
@@ -174,6 +163,11 @@ declare function tsDecl(): void;`,
|
|
|
174
163
|
code: `// @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md\nexport function exportedAnnotated() {}`,
|
|
175
164
|
options: [{ exportPriority: "exported" }],
|
|
176
165
|
},
|
|
166
|
+
{
|
|
167
|
+
name: "[exportPriority] exported arrow function missing @story annotation",
|
|
168
|
+
code: `export const arrowExported = () => {};`,
|
|
169
|
+
options: [{ exportPriority: "exported" }],
|
|
170
|
+
},
|
|
177
171
|
],
|
|
178
172
|
invalid: [
|
|
179
173
|
{
|
|
@@ -192,22 +186,6 @@ declare function tsDecl(): void;`,
|
|
|
192
186
|
},
|
|
193
187
|
],
|
|
194
188
|
},
|
|
195
|
-
{
|
|
196
|
-
name: "[exportPriority] exported arrow function missing @story annotation",
|
|
197
|
-
code: `export const arrowExported = () => {};`,
|
|
198
|
-
options: [{ exportPriority: "exported" }],
|
|
199
|
-
errors: [
|
|
200
|
-
{
|
|
201
|
-
messageId: "missingStory",
|
|
202
|
-
suggestions: [
|
|
203
|
-
{
|
|
204
|
-
desc: `Add JSDoc @story annotation for function 'arrowExported', e.g., /** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */`,
|
|
205
|
-
output: `/** @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md */\nexport const arrowExported = () => {};`,
|
|
206
|
-
},
|
|
207
|
-
],
|
|
208
|
-
},
|
|
209
|
-
],
|
|
210
|
-
},
|
|
211
189
|
],
|
|
212
190
|
});
|
|
213
191
|
ruleTester.run("require-story-annotation with scope option", require_story_annotation_1.default, {
|
|
@@ -123,6 +123,42 @@ describe("Valid Story Reference Rule Error Handling (Story 006.0-DEV-FILE-VALIDA
|
|
|
123
123
|
expect(() => (0, storyReferenceUtils_1.storyExists)(["docs/stories/permission-denied.story.md"])).not.toThrow();
|
|
124
124
|
expect((0, storyReferenceUtils_1.storyExists)(["docs/stories/permission-denied.story.md"])).toBe(false);
|
|
125
125
|
});
|
|
126
|
+
/**
|
|
127
|
+
* @req REQ-ERROR-HANDLING - Verify storyExists handles EIO from fs.statSync
|
|
128
|
+
* by returning false and not throwing when fs.existsSync returns true.
|
|
129
|
+
* @story docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
130
|
+
*/
|
|
131
|
+
it("[REQ-ERROR-HANDLING] storyExists returns false when fs.statSync throws EIO and existsSync is true", () => {
|
|
132
|
+
jest.spyOn(fs, "existsSync").mockImplementation(() => true);
|
|
133
|
+
jest.spyOn(fs, "statSync").mockImplementation(() => {
|
|
134
|
+
const err = new Error("EIO: i/o error while reading file");
|
|
135
|
+
err.code = "EIO";
|
|
136
|
+
throw err;
|
|
137
|
+
});
|
|
138
|
+
expect(() => (0, storyReferenceUtils_1.storyExists)(["docs/stories/io-error.story.md"])).not.toThrow();
|
|
139
|
+
expect((0, storyReferenceUtils_1.storyExists)(["docs/stories/io-error.story.md"])).toBe(false);
|
|
140
|
+
});
|
|
141
|
+
/**
|
|
142
|
+
* @req REQ-ERROR-HANDLING - Verify rule reports fileAccessError when fs.statSync throws
|
|
143
|
+
* and fs.existsSync returns true, treating it as a filesystem access problem
|
|
144
|
+
* rather than a missing file.
|
|
145
|
+
* @story docs/stories/006.0-DEV-FILE-VALIDATION.story.md
|
|
146
|
+
*/
|
|
147
|
+
it("[REQ-ERROR-HANDLING] rule reports fileAccessError when fs.statSync throws and existsSync is true", () => {
|
|
148
|
+
const accessError = new Error("EIO: i/o error while reading file metadata");
|
|
149
|
+
accessError.code = "EIO";
|
|
150
|
+
jest.spyOn(fs, "existsSync").mockImplementation(() => true);
|
|
151
|
+
jest.spyOn(fs, "statSync").mockImplementation(() => {
|
|
152
|
+
throw accessError;
|
|
153
|
+
});
|
|
154
|
+
const diagnostics = runRuleOnCode(`// @story docs/stories/fs-stat-io-error.story.md`);
|
|
155
|
+
expect(diagnostics.length).toBeGreaterThan(0);
|
|
156
|
+
const fileAccessDiagnostics = diagnostics.filter((d) => d.messageId === "fileAccessError");
|
|
157
|
+
expect(fileAccessDiagnostics.length).toBeGreaterThan(0);
|
|
158
|
+
const errorData = fileAccessDiagnostics[0].data;
|
|
159
|
+
expect(errorData).toBeDefined();
|
|
160
|
+
expect(String(errorData.error)).toMatch(/EIO/i);
|
|
161
|
+
});
|
|
126
162
|
/**
|
|
127
163
|
* @req REQ-ERROR-HANDLING - Verify rule reports fileAccessError when filesystem operations fail
|
|
128
164
|
* instead of treating it as a missing file.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-traceability",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.11",
|
|
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",
|