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.
@@ -68,7 +68,6 @@ function createMethodFix(node) {
68
68
  exports.DEFAULT_SCOPE = [
69
69
  "FunctionDeclaration",
70
70
  "FunctionExpression",
71
- "ArrowFunctionExpression",
72
71
  "MethodDefinition",
73
72
  "TSMethodSignature",
74
73
  "TSDeclareFunction",
@@ -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: [
@@ -17,7 +17,7 @@ const rule = {
17
17
  },
18
18
  hasSuggestions: true,
19
19
  messages: {
20
- missingStory: "Missing @story annotation (REQ-ANNOTATION-REQUIRED)",
20
+ missingStory: "Missing @story annotation for function '{{name}}' (REQ-ANNOTATION-REQUIRED)",
21
21
  },
22
22
  schema: [
23
23
  {
@@ -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.10",
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",