eslint-plugin-traceability 1.23.0 → 1.24.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/CHANGELOG.md +2 -2
- package/lib/{src/rules → rules}/require-traceability.js +49 -4
- package/package.json +8 -8
- package/user-docs/api-reference.md +25 -0
- package/lib/tests/cli-error-handling.test.d.ts +0 -1
- package/lib/tests/cli-error-handling.test.js +0 -54
- package/lib/tests/config/eslint-config-validation.test.d.ts +0 -9
- package/lib/tests/config/eslint-config-validation.test.js +0 -101
- package/lib/tests/config/flat-config-presets-integration.test.d.ts +0 -1
- package/lib/tests/config/flat-config-presets-integration.test.js +0 -76
- package/lib/tests/config/require-story-annotation-config.test.d.ts +0 -10
- package/lib/tests/config/require-story-annotation-config.test.js +0 -26
- package/lib/tests/fixtures/stale/example.d.ts +0 -0
- package/lib/tests/fixtures/stale/example.js +0 -4
- package/lib/tests/fixtures/update/example.d.ts +0 -0
- package/lib/tests/fixtures/update/example.js +0 -4
- package/lib/tests/fixtures/valid-annotations/example.d.ts +0 -0
- package/lib/tests/fixtures/valid-annotations/example.js +0 -3
- package/lib/tests/integration/annotation-placement-inside-prettier.integration.test.d.ts +0 -1
- package/lib/tests/integration/annotation-placement-inside-prettier.integration.test.js +0 -133
- package/lib/tests/integration/catch-annotation-prettier.integration.test.d.ts +0 -1
- package/lib/tests/integration/catch-annotation-prettier.integration.test.js +0 -121
- package/lib/tests/integration/cli-integration.test.d.ts +0 -1
- package/lib/tests/integration/cli-integration.test.js +0 -96
- package/lib/tests/integration/else-if-annotation-prettier.integration.test.d.ts +0 -1
- package/lib/tests/integration/else-if-annotation-prettier.integration.test.js +0 -100
- package/lib/tests/integration/no-redundant-annotation.integration.test.d.ts +0 -1
- package/lib/tests/integration/no-redundant-annotation.integration.test.js +0 -129
- package/lib/tests/integration/prettier-test-helpers.d.ts +0 -9
- package/lib/tests/integration/prettier-test-helpers.js +0 -35
- package/lib/tests/integration/require-traceability-aliases.integration.test.d.ts +0 -1
- package/lib/tests/integration/require-traceability-aliases.integration.test.js +0 -152
- package/lib/tests/integration/require-traceability-test-callbacks.integration.test.d.ts +0 -1
- package/lib/tests/integration/require-traceability-test-callbacks.integration.test.js +0 -149
- package/lib/tests/maintenance/batch.test.d.ts +0 -1
- package/lib/tests/maintenance/batch.test.js +0 -80
- package/lib/tests/maintenance/cli.test.d.ts +0 -1
- package/lib/tests/maintenance/cli.test.js +0 -306
- package/lib/tests/maintenance/detect-isolated.test.d.ts +0 -1
- package/lib/tests/maintenance/detect-isolated.test.js +0 -187
- package/lib/tests/maintenance/detect.test.d.ts +0 -1
- package/lib/tests/maintenance/detect.test.js +0 -46
- package/lib/tests/maintenance/index.test.d.ts +0 -1
- package/lib/tests/maintenance/index.test.js +0 -26
- package/lib/tests/maintenance/report.test.d.ts +0 -1
- package/lib/tests/maintenance/report.test.js +0 -68
- package/lib/tests/maintenance/storyParser.test.d.ts +0 -8
- package/lib/tests/maintenance/storyParser.test.js +0 -505
- package/lib/tests/maintenance/update-isolated.test.d.ts +0 -1
- package/lib/tests/maintenance/update-isolated.test.js +0 -71
- package/lib/tests/maintenance/update.test.d.ts +0 -1
- package/lib/tests/maintenance/update.test.js +0 -27
- package/lib/tests/perf/maintenance-cli-large-workspace.test.d.ts +0 -1
- package/lib/tests/perf/maintenance-cli-large-workspace.test.js +0 -229
- package/lib/tests/perf/maintenance-large-workspace.test.d.ts +0 -1
- package/lib/tests/perf/maintenance-large-workspace.test.js +0 -169
- package/lib/tests/perf/require-branch-annotation-large-file.test.d.ts +0 -1
- package/lib/tests/perf/require-branch-annotation-large-file.test.js +0 -67
- package/lib/tests/perf/valid-annotation-format-large-file.test.d.ts +0 -1
- package/lib/tests/perf/valid-annotation-format-large-file.test.js +0 -75
- package/lib/tests/plugin-default-export-and-configs.test.d.ts +0 -1
- package/lib/tests/plugin-default-export-and-configs.test.js +0 -121
- package/lib/tests/plugin-setup-error.test.d.ts +0 -6
- package/lib/tests/plugin-setup-error.test.js +0 -38
- package/lib/tests/plugin-setup.test.d.ts +0 -1
- package/lib/tests/plugin-setup.test.js +0 -63
- package/lib/tests/rules/auto-fix-behavior-008.test.d.ts +0 -1
- package/lib/tests/rules/auto-fix-behavior-008.test.js +0 -285
- package/lib/tests/rules/error-reporting.test.d.ts +0 -1
- package/lib/tests/rules/error-reporting.test.js +0 -99
- package/lib/tests/rules/no-redundant-annotation.test.d.ts +0 -1
- package/lib/tests/rules/no-redundant-annotation.test.js +0 -163
- package/lib/tests/rules/prefer-implements-annotation.test.d.ts +0 -1
- package/lib/tests/rules/prefer-implements-annotation.test.js +0 -162
- package/lib/tests/rules/require-branch-annotation.test.d.ts +0 -1
- package/lib/tests/rules/require-branch-annotation.test.js +0 -593
- package/lib/tests/rules/require-req-annotation.test.d.ts +0 -1
- package/lib/tests/rules/require-req-annotation.test.js +0 -264
- package/lib/tests/rules/require-story-annotation.test.d.ts +0 -1
- package/lib/tests/rules/require-story-annotation.test.js +0 -376
- package/lib/tests/rules/require-story-core-edgecases.test.d.ts +0 -1
- package/lib/tests/rules/require-story-core-edgecases.test.js +0 -15
- package/lib/tests/rules/require-story-core.autofix.test.d.ts +0 -1
- package/lib/tests/rules/require-story-core.autofix.test.js +0 -66
- package/lib/tests/rules/require-story-core.test.d.ts +0 -1
- package/lib/tests/rules/require-story-core.test.js +0 -65
- package/lib/tests/rules/require-story-helpers-edgecases.test.d.ts +0 -7
- package/lib/tests/rules/require-story-helpers-edgecases.test.js +0 -80
- package/lib/tests/rules/require-story-helpers.test.d.ts +0 -1
- package/lib/tests/rules/require-story-helpers.test.js +0 -474
- package/lib/tests/rules/require-story-io-behavior.test.d.ts +0 -7
- package/lib/tests/rules/require-story-io-behavior.test.js +0 -46
- package/lib/tests/rules/require-story-io.edgecases.test.d.ts +0 -7
- package/lib/tests/rules/require-story-io.edgecases.test.js +0 -46
- package/lib/tests/rules/require-story-utils.test.d.ts +0 -7
- package/lib/tests/rules/require-story-utils.test.js +0 -158
- package/lib/tests/rules/require-story-visitors-edgecases.test.d.ts +0 -7
- package/lib/tests/rules/require-story-visitors-edgecases.test.js +0 -27
- package/lib/tests/rules/require-test-traceability.test.d.ts +0 -1
- package/lib/tests/rules/require-test-traceability.test.js +0 -95
- package/lib/tests/rules/valid-annotation-format-internal.test.d.ts +0 -8
- package/lib/tests/rules/valid-annotation-format-internal.test.js +0 -47
- package/lib/tests/rules/valid-annotation-format.test.d.ts +0 -1
- package/lib/tests/rules/valid-annotation-format.test.js +0 -634
- package/lib/tests/rules/valid-req-reference.test.d.ts +0 -1
- package/lib/tests/rules/valid-req-reference.test.js +0 -129
- package/lib/tests/rules/valid-story-reference.test.d.ts +0 -1
- package/lib/tests/rules/valid-story-reference.test.js +0 -413
- package/lib/tests/utils/annotation-checker-autofix-behavior.test.d.ts +0 -5
- package/lib/tests/utils/annotation-checker-autofix-behavior.test.js +0 -103
- package/lib/tests/utils/annotation-checker.test.d.ts +0 -24
- package/lib/tests/utils/annotation-checker.test.js +0 -84
- package/lib/tests/utils/annotation-scope-analyzer.test.d.ts +0 -1
- package/lib/tests/utils/annotation-scope-analyzer.test.js +0 -211
- package/lib/tests/utils/branch-annotation-catch-insert-position.test.d.ts +0 -1
- package/lib/tests/utils/branch-annotation-catch-insert-position.test.js +0 -69
- package/lib/tests/utils/branch-annotation-catch-position.test.d.ts +0 -1
- package/lib/tests/utils/branch-annotation-catch-position.test.js +0 -115
- package/lib/tests/utils/branch-annotation-else-if-insert-position.test.d.ts +0 -1
- package/lib/tests/utils/branch-annotation-else-if-insert-position.test.js +0 -82
- package/lib/tests/utils/branch-annotation-else-if-position.test.d.ts +0 -1
- package/lib/tests/utils/branch-annotation-else-if-position.test.js +0 -145
- package/lib/tests/utils/branch-annotation-helpers.test.d.ts +0 -1
- package/lib/tests/utils/branch-annotation-helpers.test.js +0 -462
- package/lib/tests/utils/fsTestHelpers.d.ts +0 -7
- package/lib/tests/utils/fsTestHelpers.js +0 -26
- package/lib/tests/utils/ioTestHelpers.d.ts +0 -7
- package/lib/tests/utils/ioTestHelpers.js +0 -24
- package/lib/tests/utils/req-annotation-detection.test.d.ts +0 -1
- package/lib/tests/utils/req-annotation-detection.test.js +0 -358
- package/lib/tests/utils/require-story-core-test-helpers.d.ts +0 -10
- package/lib/tests/utils/require-story-core-test-helpers.js +0 -75
- package/lib/tests/utils/temp-dir-helpers.d.ts +0 -19
- package/lib/tests/utils/temp-dir-helpers.js +0 -62
- package/lib/tests/utils/ts-language-options.d.ts +0 -16
- package/lib/tests/utils/ts-language-options.js +0 -30
- /package/lib/{src/index.d.ts → index.d.ts} +0 -0
- /package/lib/{src/index.js → index.js} +0 -0
- /package/lib/{src/maintenance → maintenance}/batch.d.ts +0 -0
- /package/lib/{src/maintenance → maintenance}/batch.js +0 -0
- /package/lib/{src/maintenance → maintenance}/cli.d.ts +0 -0
- /package/lib/{src/maintenance → maintenance}/cli.js +0 -0
- /package/lib/{src/maintenance → maintenance}/commands.d.ts +0 -0
- /package/lib/{src/maintenance → maintenance}/commands.js +0 -0
- /package/lib/{src/maintenance → maintenance}/detect.d.ts +0 -0
- /package/lib/{src/maintenance → maintenance}/detect.js +0 -0
- /package/lib/{src/maintenance → maintenance}/flags.d.ts +0 -0
- /package/lib/{src/maintenance → maintenance}/flags.js +0 -0
- /package/lib/{src/maintenance → maintenance}/index.d.ts +0 -0
- /package/lib/{src/maintenance → maintenance}/index.js +0 -0
- /package/lib/{src/maintenance → maintenance}/report.d.ts +0 -0
- /package/lib/{src/maintenance → maintenance}/report.js +0 -0
- /package/lib/{src/maintenance → maintenance}/storyParser.d.ts +0 -0
- /package/lib/{src/maintenance → maintenance}/storyParser.js +0 -0
- /package/lib/{src/maintenance → maintenance}/update.d.ts +0 -0
- /package/lib/{src/maintenance → maintenance}/update.js +0 -0
- /package/lib/{src/maintenance → maintenance}/utils.d.ts +0 -0
- /package/lib/{src/maintenance → maintenance}/utils.js +0 -0
- /package/lib/{src/rules → rules}/helpers/pattern-validators.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/pattern-validators.js +0 -0
- /package/lib/{src/rules → rules}/helpers/prefer-implements-inline.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/prefer-implements-inline.js +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-comment-detection.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-comment-detection.js +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-core.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-core.js +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-helpers.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-helpers.js +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-io.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-io.js +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-name-extraction.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-name-extraction.js +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-node-utils.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-node-utils.js +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-utils.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-utils.js +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-visitors.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/require-story-visitors.js +0 -0
- /package/lib/{src/rules → rules}/helpers/require-test-traceability-helpers.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/require-test-traceability-helpers.js +0 -0
- /package/lib/{src/rules → rules}/helpers/test-callback-exclusion.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/test-callback-exclusion.js +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-annotation-format-internal.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-annotation-format-internal.js +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-annotation-format-validators.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-annotation-format-validators.js +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-annotation-options.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-annotation-options.js +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-annotation-utils.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-annotation-utils.js +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-implements-utils.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-implements-utils.js +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-req-reference-helpers.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-req-reference-helpers.js +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-story-reference-helpers.d.ts +0 -0
- /package/lib/{src/rules → rules}/helpers/valid-story-reference-helpers.js +0 -0
- /package/lib/{src/rules → rules}/no-redundant-annotation.d.ts +0 -0
- /package/lib/{src/rules → rules}/no-redundant-annotation.js +0 -0
- /package/lib/{src/rules → rules}/prefer-implements-annotation.d.ts +0 -0
- /package/lib/{src/rules → rules}/prefer-implements-annotation.js +0 -0
- /package/lib/{src/rules → rules}/require-branch-annotation.d.ts +0 -0
- /package/lib/{src/rules → rules}/require-branch-annotation.js +0 -0
- /package/lib/{src/rules → rules}/require-req-annotation.d.ts +0 -0
- /package/lib/{src/rules → rules}/require-req-annotation.js +0 -0
- /package/lib/{src/rules → rules}/require-story-annotation.d.ts +0 -0
- /package/lib/{src/rules → rules}/require-story-annotation.js +0 -0
- /package/lib/{src/rules → rules}/require-test-traceability.d.ts +0 -0
- /package/lib/{src/rules → rules}/require-test-traceability.js +0 -0
- /package/lib/{src/rules → rules}/require-traceability.d.ts +0 -0
- /package/lib/{src/rules → rules}/valid-annotation-format.d.ts +0 -0
- /package/lib/{src/rules → rules}/valid-annotation-format.js +0 -0
- /package/lib/{src/rules → rules}/valid-req-reference.d.ts +0 -0
- /package/lib/{src/rules → rules}/valid-req-reference.js +0 -0
- /package/lib/{src/rules → rules}/valid-story-reference.d.ts +0 -0
- /package/lib/{src/rules → rules}/valid-story-reference.js +0 -0
- /package/lib/{src/utils → utils}/annotation-checker.d.ts +0 -0
- /package/lib/{src/utils → utils}/annotation-checker.js +0 -0
- /package/lib/{src/utils → utils}/annotation-scope-analyzer.d.ts +0 -0
- /package/lib/{src/utils → utils}/annotation-scope-analyzer.js +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-catch-helpers.d.ts +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-catch-helpers.js +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-helpers.d.ts +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-helpers.js +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-if-helpers.d.ts +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-if-helpers.js +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-indent-helpers.d.ts +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-indent-helpers.js +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-loop-helpers.d.ts +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-loop-helpers.js +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-report-helpers.d.ts +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-report-helpers.js +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-story-fix-helpers.d.ts +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-story-fix-helpers.js +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-switch-helpers.d.ts +0 -0
- /package/lib/{src/utils → utils}/branch-annotation-switch-helpers.js +0 -0
- /package/lib/{src/utils → utils}/branch-validation.d.ts +0 -0
- /package/lib/{src/utils → utils}/branch-validation.js +0 -0
- /package/lib/{src/utils → utils}/comment-text-helpers.d.ts +0 -0
- /package/lib/{src/utils → utils}/comment-text-helpers.js +0 -0
- /package/lib/{src/utils → utils}/function-annotation-helpers.d.ts +0 -0
- /package/lib/{src/utils → utils}/function-annotation-helpers.js +0 -0
- /package/lib/{src/utils → utils}/redundancy-detector.d.ts +0 -0
- /package/lib/{src/utils → utils}/redundancy-detector.js +0 -0
- /package/lib/{src/utils → utils}/reqAnnotationDetection.d.ts +0 -0
- /package/lib/{src/utils → utils}/reqAnnotationDetection.js +0 -0
- /package/lib/{src/utils → utils}/storyReferenceUtils.d.ts +0 -0
- /package/lib/{src/utils → utils}/storyReferenceUtils.js +0 -0
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
/**
|
|
37
|
-
* CLI-level performance tests for maintenance tools on large workspaces.
|
|
38
|
-
* @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT REQ-MAINT-REPORT REQ-MAINT-SAFE
|
|
39
|
-
*/
|
|
40
|
-
const fs = __importStar(require("fs"));
|
|
41
|
-
const os = __importStar(require("os"));
|
|
42
|
-
const path = __importStar(require("path"));
|
|
43
|
-
const perf_hooks_1 = require("perf_hooks");
|
|
44
|
-
const cli_1 = require("../../src/maintenance/cli");
|
|
45
|
-
// Performance budget documented in docs/maintenance-performance-tests.md
|
|
46
|
-
const CLI_LARGE_WORKSPACE_PERF_BUDGET_MS = 5000;
|
|
47
|
-
function createCliLargeWorkspace() {
|
|
48
|
-
const root = fs.mkdtempSync(path.join(os.tmpdir(), "traceability-cli-large-"));
|
|
49
|
-
// Create a modestly sized workspace reusing the same shape as the core perf tests,
|
|
50
|
-
// but with fewer files to keep end-to-end CLI timing predictable.
|
|
51
|
-
for (let moduleIndex = 0; moduleIndex < 5; moduleIndex += 1) {
|
|
52
|
-
const moduleDir = path.join(root, `module-${moduleIndex.toString().padStart(3, "0")}`);
|
|
53
|
-
fs.mkdirSync(moduleDir);
|
|
54
|
-
for (let fileIndex = 0; fileIndex < 20; fileIndex += 1) {
|
|
55
|
-
const filePath = path.join(moduleDir, `file-${fileIndex.toString().padStart(3, "0")}.ts`);
|
|
56
|
-
const validStory = "cli-valid.story.md";
|
|
57
|
-
const staleStory = "cli-stale.story.md";
|
|
58
|
-
const content = `/**
|
|
59
|
-
* @story ${validStory}
|
|
60
|
-
* @story ${staleStory}
|
|
61
|
-
*/
|
|
62
|
-
export function cli_example_${moduleIndex}_${fileIndex}() {}
|
|
63
|
-
`;
|
|
64
|
-
fs.writeFileSync(filePath, content, "utf8");
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
// Create the valid story file so that only the stale entries are reported.
|
|
68
|
-
fs.writeFileSync(path.join(root, "cli-valid.story.md"), "# cli valid", "utf8");
|
|
69
|
-
return {
|
|
70
|
-
root,
|
|
71
|
-
cleanup: () => {
|
|
72
|
-
fs.rmSync(root, { recursive: true, force: true });
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
function createDeepNestedCliWorkspace() {
|
|
77
|
-
const root = fs.mkdtempSync(path.join(os.tmpdir(), "traceability-cli-deep-nested-"));
|
|
78
|
-
// Create a deeply nested directory structure with a small number of files.
|
|
79
|
-
for (let branchIndex = 0; branchIndex < 3; branchIndex += 1) {
|
|
80
|
-
const level1 = path.join(root, `branch-${branchIndex.toString().padStart(3, "0")}`);
|
|
81
|
-
fs.mkdirSync(level1);
|
|
82
|
-
const level2 = path.join(level1, "deep", "nested", "structure");
|
|
83
|
-
fs.mkdirSync(path.join(level1, "deep"), { recursive: true });
|
|
84
|
-
fs.mkdirSync(path.join(level1, "deep", "nested"), { recursive: true });
|
|
85
|
-
fs.mkdirSync(level2, { recursive: true });
|
|
86
|
-
for (let fileIndex = 0; fileIndex < 3; fileIndex += 1) {
|
|
87
|
-
const filePath = path.join(level2, `deep-file-${fileIndex.toString().padStart(3, "0")}.ts`);
|
|
88
|
-
const validStory = "cli-valid.story.md";
|
|
89
|
-
const staleStory = "cli-deep-stale.story.md";
|
|
90
|
-
const content = `/**
|
|
91
|
-
* @story ${validStory}
|
|
92
|
-
* @story ${staleStory}
|
|
93
|
-
*/
|
|
94
|
-
export function cli_deep_example_${branchIndex}_${fileIndex}() {}
|
|
95
|
-
`;
|
|
96
|
-
fs.writeFileSync(filePath, content, "utf8");
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
// Create the valid story file so that only the stale entries are reported.
|
|
100
|
-
fs.writeFileSync(path.join(root, "cli-valid.story.md"), "# cli valid", "utf8");
|
|
101
|
-
return {
|
|
102
|
-
root,
|
|
103
|
-
cleanup: () => {
|
|
104
|
-
fs.rmSync(root, { recursive: true, force: true });
|
|
105
|
-
},
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
describe("Maintenance CLI on large workspaces (Story 009.0-DEV-MAINTENANCE-TOOLS)", () => {
|
|
109
|
-
it("[REQ-MAINT-DETECT] detect --json completes within a generous time budget and returns JSON payload", () => {
|
|
110
|
-
const { root, cleanup } = createCliLargeWorkspace();
|
|
111
|
-
const originalCwd = process.cwd();
|
|
112
|
-
process.chdir(root);
|
|
113
|
-
const logSpy = jest.spyOn(console, "log").mockImplementation(() => { });
|
|
114
|
-
try {
|
|
115
|
-
const start = perf_hooks_1.performance.now();
|
|
116
|
-
const exitCode = (0, cli_1.runMaintenanceCli)([
|
|
117
|
-
"node",
|
|
118
|
-
"traceability-maint",
|
|
119
|
-
"detect",
|
|
120
|
-
"--root",
|
|
121
|
-
root,
|
|
122
|
-
"--json",
|
|
123
|
-
]);
|
|
124
|
-
const durationMs = perf_hooks_1.performance.now() - start;
|
|
125
|
-
expect(exitCode === 0 || exitCode === 1).toBe(true);
|
|
126
|
-
expect(durationMs).toBeLessThan(CLI_LARGE_WORKSPACE_PERF_BUDGET_MS);
|
|
127
|
-
expect(logSpy).toHaveBeenCalledTimes(1);
|
|
128
|
-
const payloadRaw = String(logSpy.mock.calls[0][0]);
|
|
129
|
-
const payload = JSON.parse(payloadRaw);
|
|
130
|
-
expect(payload.root).toBe(root);
|
|
131
|
-
expect(Array.isArray(payload.stale)).toBe(true);
|
|
132
|
-
expect(payload.stale.length).toBeGreaterThan(0);
|
|
133
|
-
}
|
|
134
|
-
finally {
|
|
135
|
-
logSpy.mockRestore();
|
|
136
|
-
process.chdir(originalCwd);
|
|
137
|
-
cleanup();
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
it("[REQ-MAINT-REPORT] report --format=json completes within a generous time budget", () => {
|
|
141
|
-
const { root, cleanup } = createCliLargeWorkspace();
|
|
142
|
-
const originalCwd = process.cwd();
|
|
143
|
-
process.chdir(root);
|
|
144
|
-
const logSpy = jest.spyOn(console, "log").mockImplementation(() => { });
|
|
145
|
-
try {
|
|
146
|
-
const start = perf_hooks_1.performance.now();
|
|
147
|
-
const exitCode = (0, cli_1.runMaintenanceCli)([
|
|
148
|
-
"node",
|
|
149
|
-
"traceability-maint",
|
|
150
|
-
"report",
|
|
151
|
-
"--root",
|
|
152
|
-
root,
|
|
153
|
-
"--format",
|
|
154
|
-
"json",
|
|
155
|
-
]);
|
|
156
|
-
const durationMs = perf_hooks_1.performance.now() - start;
|
|
157
|
-
expect(exitCode).toBe(0);
|
|
158
|
-
expect(durationMs).toBeLessThan(CLI_LARGE_WORKSPACE_PERF_BUDGET_MS);
|
|
159
|
-
expect(logSpy).toHaveBeenCalledTimes(1);
|
|
160
|
-
const payloadRaw = String(logSpy.mock.calls[0][0]);
|
|
161
|
-
const payload = JSON.parse(payloadRaw);
|
|
162
|
-
expect(payload.root).toBe(root);
|
|
163
|
-
expect(typeof payload.report).toBe("string");
|
|
164
|
-
}
|
|
165
|
-
finally {
|
|
166
|
-
logSpy.mockRestore();
|
|
167
|
-
process.chdir(originalCwd);
|
|
168
|
-
cleanup();
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
it("[REQ-MAINT-VERIFY] verify completes within a generous time budget and reports stale annotations", () => {
|
|
172
|
-
const { root, cleanup } = createCliLargeWorkspace();
|
|
173
|
-
const originalCwd = process.cwd();
|
|
174
|
-
process.chdir(root);
|
|
175
|
-
const logSpy = jest.spyOn(console, "log").mockImplementation(() => { });
|
|
176
|
-
try {
|
|
177
|
-
const start = perf_hooks_1.performance.now();
|
|
178
|
-
const exitCode = (0, cli_1.runMaintenanceCli)([
|
|
179
|
-
"node",
|
|
180
|
-
"traceability-maint",
|
|
181
|
-
"verify",
|
|
182
|
-
"--root",
|
|
183
|
-
root,
|
|
184
|
-
]);
|
|
185
|
-
const durationMs = perf_hooks_1.performance.now() - start;
|
|
186
|
-
expect(exitCode).toBe(1);
|
|
187
|
-
expect(durationMs).toBeLessThan(CLI_LARGE_WORKSPACE_PERF_BUDGET_MS);
|
|
188
|
-
expect(logSpy).toHaveBeenCalledTimes(1);
|
|
189
|
-
const message = String(logSpy.mock.calls[0][0]);
|
|
190
|
-
expect(message).toContain("Stale or invalid traceability annotations detected under");
|
|
191
|
-
}
|
|
192
|
-
finally {
|
|
193
|
-
logSpy.mockRestore();
|
|
194
|
-
process.chdir(originalCwd);
|
|
195
|
-
cleanup();
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
it("[REQ-MAINT-DETECT] detect traverses deeply nested directories within a generous time budget", () => {
|
|
199
|
-
const { root, cleanup } = createDeepNestedCliWorkspace();
|
|
200
|
-
const originalCwd = process.cwd();
|
|
201
|
-
process.chdir(root);
|
|
202
|
-
const logSpy = jest.spyOn(console, "log").mockImplementation(() => { });
|
|
203
|
-
try {
|
|
204
|
-
const start = perf_hooks_1.performance.now();
|
|
205
|
-
const exitCode = (0, cli_1.runMaintenanceCli)([
|
|
206
|
-
"node",
|
|
207
|
-
"traceability-maint",
|
|
208
|
-
"detect",
|
|
209
|
-
"--root",
|
|
210
|
-
root,
|
|
211
|
-
"--json",
|
|
212
|
-
]);
|
|
213
|
-
const durationMs = perf_hooks_1.performance.now() - start;
|
|
214
|
-
expect(exitCode === 0 || exitCode === 1).toBe(true);
|
|
215
|
-
expect(durationMs).toBeLessThan(CLI_LARGE_WORKSPACE_PERF_BUDGET_MS);
|
|
216
|
-
expect(logSpy).toHaveBeenCalledTimes(1);
|
|
217
|
-
const payloadRaw = String(logSpy.mock.calls[0][0]);
|
|
218
|
-
const payload = JSON.parse(payloadRaw);
|
|
219
|
-
expect(payload.root).toBe(root);
|
|
220
|
-
expect(Array.isArray(payload.stale)).toBe(true);
|
|
221
|
-
expect(payload.stale.length).toBeGreaterThan(0);
|
|
222
|
-
}
|
|
223
|
-
finally {
|
|
224
|
-
logSpy.mockRestore();
|
|
225
|
-
process.chdir(originalCwd);
|
|
226
|
-
cleanup();
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
/* eslint-disable traceability/valid-annotation-format */
|
|
37
|
-
/**
|
|
38
|
-
* Performance and stress tests for maintenance tools on large workspaces.
|
|
39
|
-
* @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT REQ-MAINT-VERIFY REQ-MAINT-REPORT REQ-MAINT-UPDATE REQ-MAINT-BATCH
|
|
40
|
-
*/
|
|
41
|
-
const fs = __importStar(require("fs"));
|
|
42
|
-
const os = __importStar(require("os"));
|
|
43
|
-
const path = __importStar(require("path"));
|
|
44
|
-
const perf_hooks_1 = require("perf_hooks");
|
|
45
|
-
const detect_1 = require("../../src/maintenance/detect");
|
|
46
|
-
const batch_1 = require("../../src/maintenance/batch");
|
|
47
|
-
const report_1 = require("../../src/maintenance/report");
|
|
48
|
-
const update_1 = require("../../src/maintenance/update");
|
|
49
|
-
// Performance budget for large-workspace maintenance tests; documented in docs/maintenance-performance-tests.md.
|
|
50
|
-
const LARGE_WORKSPACE_PERF_BUDGET_MS = 5000;
|
|
51
|
-
/**
|
|
52
|
-
* Shape of the synthetic large workspace:
|
|
53
|
-
* - 10 modules (module-000 .. module-009)
|
|
54
|
-
* - 50 files per module (file-000.ts .. file-049.ts)
|
|
55
|
-
* - Each file includes a mix of valid and stale @story references.
|
|
56
|
-
*/
|
|
57
|
-
function createLargeWorkspace() {
|
|
58
|
-
const root = fs.mkdtempSync(path.join(os.tmpdir(), "traceability-large-"));
|
|
59
|
-
// Create a pool of story files that will be considered "valid".
|
|
60
|
-
const validStories = [];
|
|
61
|
-
for (let i = 0; i < 250; i += 1) {
|
|
62
|
-
const storyName = `valid-story-${i.toString().padStart(4, "0")}.story.md`;
|
|
63
|
-
const storyPath = path.join(root, storyName);
|
|
64
|
-
fs.writeFileSync(storyPath, `# ${storyName}`, "utf8");
|
|
65
|
-
validStories.push(storyName);
|
|
66
|
-
}
|
|
67
|
-
let validIndex = 0;
|
|
68
|
-
let staleIndex = 0;
|
|
69
|
-
for (let moduleIndex = 0; moduleIndex < 10; moduleIndex += 1) {
|
|
70
|
-
const moduleDir = path.join(root, `module-${moduleIndex.toString().padStart(3, "0")}`);
|
|
71
|
-
fs.mkdirSync(moduleDir);
|
|
72
|
-
for (let fileIndex = 0; fileIndex < 50; fileIndex += 1) {
|
|
73
|
-
const filePath = path.join(moduleDir, `file-${fileIndex.toString().padStart(3, "0")}.ts`);
|
|
74
|
-
const validStory = validStories[validIndex % validStories.length] ??
|
|
75
|
-
"valid-story-0000.story.md";
|
|
76
|
-
validIndex += 1;
|
|
77
|
-
const staleStory = `stale-story-${staleIndex
|
|
78
|
-
.toString()
|
|
79
|
-
.padStart(4, "0")}.story.md`;
|
|
80
|
-
staleIndex += 1;
|
|
81
|
-
const content = `/**
|
|
82
|
-
* @story ${validStory}
|
|
83
|
-
* @story ${staleStory}
|
|
84
|
-
*/
|
|
85
|
-
export function example_${moduleIndex}_${fileIndex}() {}
|
|
86
|
-
`;
|
|
87
|
-
fs.writeFileSync(filePath, content, "utf8");
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return {
|
|
91
|
-
root,
|
|
92
|
-
cleanup: () => {
|
|
93
|
-
fs.rmSync(root, { recursive: true, force: true });
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
describe("Maintenance tools on large workspaces (Story 009.0-DEV-MAINTENANCE-TOOLS)", () => {
|
|
98
|
-
it("[REQ-MAINT-DETECT] detectStaleAnnotations completes within a generous time budget", () => {
|
|
99
|
-
const workspace = createLargeWorkspace();
|
|
100
|
-
try {
|
|
101
|
-
const start = perf_hooks_1.performance.now();
|
|
102
|
-
const stale = (0, detect_1.detectStaleAnnotations)(workspace.root);
|
|
103
|
-
const durationMs = perf_hooks_1.performance.now() - start;
|
|
104
|
-
// Sanity check: we expect at least some stale entries due to the generated stale-story-* references.
|
|
105
|
-
expect(stale.length).toBeGreaterThan(0);
|
|
106
|
-
// Guardrail: this operation should remain comfortably under ~5 seconds on CI hardware.
|
|
107
|
-
expect(durationMs).toBeLessThan(LARGE_WORKSPACE_PERF_BUDGET_MS);
|
|
108
|
-
}
|
|
109
|
-
finally {
|
|
110
|
-
workspace.cleanup();
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
it("[REQ-MAINT-VERIFY] verifyAnnotations remains fast on large workspaces", () => {
|
|
114
|
-
const workspace = createLargeWorkspace();
|
|
115
|
-
try {
|
|
116
|
-
const start = perf_hooks_1.performance.now();
|
|
117
|
-
const result = (0, batch_1.verifyAnnotations)(workspace.root);
|
|
118
|
-
const durationMs = perf_hooks_1.performance.now() - start;
|
|
119
|
-
// With both valid and stale references, verification should report false.
|
|
120
|
-
expect(result).toBe(false);
|
|
121
|
-
expect(durationMs).toBeLessThan(LARGE_WORKSPACE_PERF_BUDGET_MS);
|
|
122
|
-
}
|
|
123
|
-
finally {
|
|
124
|
-
workspace.cleanup();
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
it("[REQ-MAINT-REPORT] generateMaintenanceReport produces output within a generous time budget", () => {
|
|
128
|
-
const workspace = createLargeWorkspace();
|
|
129
|
-
try {
|
|
130
|
-
const start = perf_hooks_1.performance.now();
|
|
131
|
-
const report = (0, report_1.generateMaintenanceReport)(workspace.root);
|
|
132
|
-
const durationMs = perf_hooks_1.performance.now() - start;
|
|
133
|
-
expect(report).not.toBe("");
|
|
134
|
-
expect(durationMs).toBeLessThan(LARGE_WORKSPACE_PERF_BUDGET_MS);
|
|
135
|
-
}
|
|
136
|
-
finally {
|
|
137
|
-
workspace.cleanup();
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
it("[REQ-MAINT-UPDATE] updateAnnotationReferences and batchUpdateAnnotations remain tractable", () => {
|
|
141
|
-
const workspace = createLargeWorkspace();
|
|
142
|
-
try {
|
|
143
|
-
const exampleOldPath = "stale-story-0000.story.md";
|
|
144
|
-
const exampleNewPath = "updated-story-0000.story.md";
|
|
145
|
-
const singleStart = perf_hooks_1.performance.now();
|
|
146
|
-
const updatedCount = (0, update_1.updateAnnotationReferences)(workspace.root, exampleOldPath, exampleNewPath);
|
|
147
|
-
const singleDuration = perf_hooks_1.performance.now() - singleStart;
|
|
148
|
-
expect(updatedCount).toBeGreaterThan(0);
|
|
149
|
-
expect(singleDuration).toBeLessThan(LARGE_WORKSPACE_PERF_BUDGET_MS);
|
|
150
|
-
const batchStart = perf_hooks_1.performance.now();
|
|
151
|
-
const totalUpdated = (0, batch_1.batchUpdateAnnotations)(workspace.root, [
|
|
152
|
-
{
|
|
153
|
-
oldPath: "stale-story-0001.story.md",
|
|
154
|
-
newPath: "updated-story-0001.story.md",
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
oldPath: "stale-story-0002.story.md",
|
|
158
|
-
newPath: "updated-story-0002.story.md",
|
|
159
|
-
},
|
|
160
|
-
]);
|
|
161
|
-
const batchDuration = perf_hooks_1.performance.now() - batchStart;
|
|
162
|
-
expect(totalUpdated).toBeGreaterThanOrEqual(2);
|
|
163
|
-
expect(batchDuration).toBeLessThan(LARGE_WORKSPACE_PERF_BUDGET_MS);
|
|
164
|
-
}
|
|
165
|
-
finally {
|
|
166
|
-
workspace.cleanup();
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
/**
|
|
7
|
-
* Performance tests for require-branch-annotation on large nested-branch files.
|
|
8
|
-
*
|
|
9
|
-
* @supports docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md REQ-PERFORMANCE-OPTIMIZATION REQ-NESTED-HANDLING
|
|
10
|
-
*/
|
|
11
|
-
const eslint_1 = require("eslint");
|
|
12
|
-
const perf_hooks_1 = require("perf_hooks");
|
|
13
|
-
const require_branch_annotation_1 = __importDefault(require("../../src/rules/require-branch-annotation"));
|
|
14
|
-
/**
|
|
15
|
-
* Build a large source file containing many nested branch structures
|
|
16
|
-
* (if-statements within if-statements) to exercise the rule at scale.
|
|
17
|
-
*
|
|
18
|
-
* The generated code intentionally omits annotations so that the rule
|
|
19
|
-
* produces diagnostics for both outer and inner branches.
|
|
20
|
-
*/
|
|
21
|
-
function buildLargeNestedBranchSource(functionCount, nestingDepth) {
|
|
22
|
-
const lines = [];
|
|
23
|
-
for (let i = 0; i < functionCount; i += 1) {
|
|
24
|
-
lines.push(`function fn_${i}() {`);
|
|
25
|
-
lines.push(" let x = 0;");
|
|
26
|
-
// Create a staircase of nested if-statements.
|
|
27
|
-
for (let depth = 0; depth < nestingDepth; depth += 1) {
|
|
28
|
-
const indent = " ".repeat(depth + 1);
|
|
29
|
-
lines.push(`${indent}if (x > ${depth}) {`);
|
|
30
|
-
}
|
|
31
|
-
const innerIndent = " ".repeat(nestingDepth + 1);
|
|
32
|
-
lines.push(`${innerIndent}if (x % 2 === 0) {`);
|
|
33
|
-
lines.push(`${innerIndent} x++;`);
|
|
34
|
-
lines.push(`${innerIndent}} else {`);
|
|
35
|
-
lines.push(`${innerIndent} x--;`);
|
|
36
|
-
lines.push(`${innerIndent}}`);
|
|
37
|
-
// Close all nested if blocks.
|
|
38
|
-
for (let depth = nestingDepth - 1; depth >= 0; depth -= 1) {
|
|
39
|
-
const indent = " ".repeat(depth + 1);
|
|
40
|
-
lines.push(`${indent}}`);
|
|
41
|
-
}
|
|
42
|
-
lines.push("}");
|
|
43
|
-
}
|
|
44
|
-
return lines.join("\n");
|
|
45
|
-
}
|
|
46
|
-
describe("require-branch-annotation performance on large nested-branch files (Story 004.0-DEV-BRANCH-ANNOTATIONS)", () => {
|
|
47
|
-
const ruleName = "traceability/require-branch-annotation";
|
|
48
|
-
it("[REQ-PERFORMANCE-OPTIMIZATION] analyzes a large nested-branch file within a generous time budget", () => {
|
|
49
|
-
const linter = new eslint_1.Linter({ configType: "eslintrc" });
|
|
50
|
-
linter.defineRule(ruleName, require_branch_annotation_1.default);
|
|
51
|
-
// 200 functions each with several nested branches gives us
|
|
52
|
-
// a substantial number of branch nodes without being extreme.
|
|
53
|
-
const source = buildLargeNestedBranchSource(200, 3);
|
|
54
|
-
const start = perf_hooks_1.performance.now();
|
|
55
|
-
const messages = linter.verify(source, {
|
|
56
|
-
parserOptions: { ecmaVersion: 2020, sourceType: "module" },
|
|
57
|
-
rules: {
|
|
58
|
-
[ruleName]: "error",
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
const durationMs = perf_hooks_1.performance.now() - start;
|
|
62
|
-
// Sanity check: we expect diagnostics for many branches.
|
|
63
|
-
expect(messages.length).toBeGreaterThan(0);
|
|
64
|
-
// Guardrail: keep analysis comfortably under ~5 seconds on CI hardware.
|
|
65
|
-
expect(durationMs).toBeLessThan(5000);
|
|
66
|
-
});
|
|
67
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
/* eslint-disable traceability/valid-annotation-format */
|
|
7
|
-
/**
|
|
8
|
-
* Performance tests for valid-annotation-format on large annotated files.
|
|
9
|
-
*
|
|
10
|
-
* @supports docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md REQ-MULTILINE-SUPPORT REQ-FLEXIBLE-PARSING REQ-SYNTAX-VALIDATION
|
|
11
|
-
*/
|
|
12
|
-
const eslint_1 = require("eslint");
|
|
13
|
-
const perf_hooks_1 = require("perf_hooks");
|
|
14
|
-
const valid_annotation_format_1 = __importDefault(require("../../src/rules/valid-annotation-format"));
|
|
15
|
-
/**
|
|
16
|
-
* Build a large source file containing many functions with traceability
|
|
17
|
-
* annotations in both line and block comments.
|
|
18
|
-
*
|
|
19
|
-
* The generated code mixes valid and invalid annotation formats to exercise
|
|
20
|
-
* parsing, multi-line handling, and error-reporting paths at scale without
|
|
21
|
-
* relying on auto-fix.
|
|
22
|
-
*/
|
|
23
|
-
function buildLargeAnnotatedSource(functionCount, annotationsPerFunction) {
|
|
24
|
-
const lines = [];
|
|
25
|
-
for (let i = 0; i < functionCount; i += 1) {
|
|
26
|
-
// JSDoc-style block comment with multi-line @story/@req values.
|
|
27
|
-
lines.push("/**");
|
|
28
|
-
lines.push(" * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md");
|
|
29
|
-
lines.push(" * @req REQ-FORMAT-SPECIFICATION");
|
|
30
|
-
lines.push(" */");
|
|
31
|
-
// Additional line comments with a mix of valid and intentionally
|
|
32
|
-
// invalid formats (missing extensions, traversal, malformed IDs).
|
|
33
|
-
for (let j = 0; j < annotationsPerFunction; j += 1) {
|
|
34
|
-
const selector = (i + j) % 4;
|
|
35
|
-
if (selector === 0) {
|
|
36
|
-
lines.push("// @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story");
|
|
37
|
-
}
|
|
38
|
-
else if (selector === 1) {
|
|
39
|
-
lines.push("// @req REQ-EXAMPLE-" + i.toString(10));
|
|
40
|
-
}
|
|
41
|
-
else if (selector === 2) {
|
|
42
|
-
lines.push("// @story ../outside-project.story.md");
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
lines.push("// @req invalid-format-id");
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
lines.push(`function annotated_fn_${i}() {`);
|
|
49
|
-
lines.push(' return "ok";\n}');
|
|
50
|
-
}
|
|
51
|
-
return lines.join("\n");
|
|
52
|
-
}
|
|
53
|
-
describe("valid-annotation-format performance on large annotated files (Story 005.0-DEV-ANNOTATION-VALIDATION)", () => {
|
|
54
|
-
const ruleName = "traceability/valid-annotation-format";
|
|
55
|
-
it("[REQ-MULTILINE-SUPPORT][REQ-FLEXIBLE-PARSING] analyzes a large annotated file within a generous time budget", () => {
|
|
56
|
-
const linter = new eslint_1.Linter({ configType: "eslintrc" });
|
|
57
|
-
linter.defineRule(ruleName, valid_annotation_format_1.default);
|
|
58
|
-
// 150 functions each with several annotations provides a substantial
|
|
59
|
-
// volume of comments and annotation patterns without being extreme.
|
|
60
|
-
const source = buildLargeAnnotatedSource(150, 3);
|
|
61
|
-
const start = perf_hooks_1.performance.now();
|
|
62
|
-
const messages = linter.verify(source, {
|
|
63
|
-
parserOptions: { ecmaVersion: 2020, sourceType: "module" },
|
|
64
|
-
rules: {
|
|
65
|
-
[ruleName]: "error",
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
const durationMs = perf_hooks_1.performance.now() - start;
|
|
69
|
-
// Sanity check: we expect diagnostics for some invalid annotations so the
|
|
70
|
-
// rule is definitely executing its validation logic.
|
|
71
|
-
expect(messages.length).toBeGreaterThan(0);
|
|
72
|
-
// Guardrail: keep analysis comfortably under ~5 seconds on CI hardware.
|
|
73
|
-
expect(durationMs).toBeLessThan(5000);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
/**
|
|
37
|
-
* Tests for: docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
38
|
-
* @supports docs/stories/001.0-DEV-PLUGIN-SETUP.story.md REQ-PLUGIN-STRUCTURE REQ-RULE-REGISTRY REQ-CONFIG-SYSTEM
|
|
39
|
-
* @supports docs/stories/007.0-DEV-ERROR-REPORTING.story.md REQ-ERROR-SEVERITY
|
|
40
|
-
* @story docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
41
|
-
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
42
|
-
* @req REQ-PLUGIN-STRUCTURE - Validate plugin default export and configs in src/index.ts
|
|
43
|
-
* @req REQ-ERROR-SEVERITY - Validate error severity configuration in plugin configs
|
|
44
|
-
*/
|
|
45
|
-
const index_1 = __importStar(require("../src/index"));
|
|
46
|
-
describe("Plugin Default Export and Configs (Story 001.0-DEV-PLUGIN-SETUP)", () => {
|
|
47
|
-
it("[REQ-PLUGIN-STRUCTURE] default export includes rules and configs", () => {
|
|
48
|
-
expect(index_1.default.rules).toBe(index_1.rules);
|
|
49
|
-
expect(index_1.default.configs).toBe(index_1.configs);
|
|
50
|
-
});
|
|
51
|
-
it("[REQ-PLUGIN-STRUCTURE] rules object has correct rule names", () => {
|
|
52
|
-
// Arrange: expected rule names in insertion order
|
|
53
|
-
const expected = [
|
|
54
|
-
"require-traceability",
|
|
55
|
-
"require-story-annotation",
|
|
56
|
-
"require-req-annotation",
|
|
57
|
-
"require-branch-annotation",
|
|
58
|
-
"valid-annotation-format",
|
|
59
|
-
"valid-story-reference",
|
|
60
|
-
"valid-req-reference",
|
|
61
|
-
"prefer-implements-annotation",
|
|
62
|
-
"require-test-traceability",
|
|
63
|
-
"no-redundant-annotation",
|
|
64
|
-
"prefer-supports-annotation",
|
|
65
|
-
];
|
|
66
|
-
// Act: get actual rule names from plugin
|
|
67
|
-
const actual = Object.keys(index_1.rules);
|
|
68
|
-
// Assert: actual matches expected
|
|
69
|
-
expect(actual).toEqual(expected);
|
|
70
|
-
});
|
|
71
|
-
it("[REQ-RULE-REGISTRY] configs.recommended contains correct rule configuration", () => {
|
|
72
|
-
const recommendedRules = index_1.configs.recommended[0].rules;
|
|
73
|
-
expect(recommendedRules).toHaveProperty("traceability/require-traceability", "error");
|
|
74
|
-
expect(recommendedRules).toHaveProperty("traceability/require-story-annotation", "error");
|
|
75
|
-
expect(recommendedRules).toHaveProperty("traceability/require-req-annotation", "error");
|
|
76
|
-
expect(recommendedRules).toHaveProperty("traceability/require-branch-annotation", "error");
|
|
77
|
-
});
|
|
78
|
-
it("[REQ-CONFIG-SYSTEM] configs.strict contains same rules as recommended", () => {
|
|
79
|
-
const strictRules = index_1.configs.strict[0].rules;
|
|
80
|
-
expect(strictRules).toEqual(index_1.configs.recommended[0].rules);
|
|
81
|
-
});
|
|
82
|
-
it("[REQ-ERROR-SEVERITY] configs.recommended maps valid-annotation-format to warn and others to error", () => {
|
|
83
|
-
const recommendedRules = index_1.configs.recommended[0].rules;
|
|
84
|
-
expect(recommendedRules).toHaveProperty("traceability/valid-annotation-format", "warn");
|
|
85
|
-
expect(recommendedRules).toHaveProperty("traceability/require-traceability", "error");
|
|
86
|
-
expect(recommendedRules).toHaveProperty("traceability/require-story-annotation", "error");
|
|
87
|
-
expect(recommendedRules).toHaveProperty("traceability/require-req-annotation", "error");
|
|
88
|
-
expect(recommendedRules).toHaveProperty("traceability/require-branch-annotation", "error");
|
|
89
|
-
expect(recommendedRules).toHaveProperty("traceability/valid-story-reference", "error");
|
|
90
|
-
expect(recommendedRules).toHaveProperty("traceability/valid-req-reference", "error");
|
|
91
|
-
expect(recommendedRules).toHaveProperty("traceability/require-test-traceability", "error");
|
|
92
|
-
});
|
|
93
|
-
it("[REQ-ERROR-SEVERITY] configs.strict uses same severity mapping as recommended", () => {
|
|
94
|
-
const strictRules = index_1.configs.strict[0].rules;
|
|
95
|
-
const recommendedRules = index_1.configs.recommended[0].rules;
|
|
96
|
-
expect(strictRules).toEqual(recommendedRules);
|
|
97
|
-
});
|
|
98
|
-
describe("Unified function-annotation rule aliases (Story 003.0-DEV-FUNCTION-ANNOTATIONS)", () => {
|
|
99
|
-
it("[REQ-ANNOTATION-REQUIRED] legacy rule names share the unified require-traceability implementation", () => {
|
|
100
|
-
const unified = index_1.rules["require-traceability"];
|
|
101
|
-
const storyAlias = index_1.rules["require-story-annotation"];
|
|
102
|
-
const reqAlias = index_1.rules["require-req-annotation"];
|
|
103
|
-
expect(typeof unified.create).toBe("function");
|
|
104
|
-
expect(storyAlias.create).toBe(unified.create);
|
|
105
|
-
expect(reqAlias.create).toBe(unified.create);
|
|
106
|
-
});
|
|
107
|
-
it("[REQ-CONFIGURABLE-SCOPE] alias rules preserve metadata needed for configuration and diagnostics", () => {
|
|
108
|
-
const unified = index_1.rules["require-traceability"];
|
|
109
|
-
const storyAlias = index_1.rules["require-story-annotation"];
|
|
110
|
-
const reqAlias = index_1.rules["require-req-annotation"];
|
|
111
|
-
// All variants should expose a schema and messages map so that options
|
|
112
|
-
// like scope/exportPriority and the core diagnostics remain available.
|
|
113
|
-
expect(unified.meta?.schema).toBeDefined();
|
|
114
|
-
expect(storyAlias.meta?.schema).toBeDefined();
|
|
115
|
-
expect(reqAlias.meta?.schema).toBeDefined();
|
|
116
|
-
expect(unified.meta?.messages).toBeDefined();
|
|
117
|
-
expect(storyAlias.meta?.messages).toBeDefined();
|
|
118
|
-
expect(reqAlias.meta?.messages).toBeDefined();
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
});
|