Files
rea/tests/boundary/filesystem/javascript-applications/javascriptSelectedSourceCancellation.test.ts
T
Kaoru0822andClaude Opus 5.5 8a8efb8226 fix(javascript): keep unselected sources out of cancellation failures
With source_paths, the analysis loop checked cancellation before it
recognized an outside-analysis-scope file. Cancellation arriving after the
last selected source therefore recorded the next unselected file as a
cancelled analysis failure, and the completion loop skipped it as already
analyzed.

Give out-of-selection classification one owner, used by the loop, the
interruption handler and the completion loop. The cancellation is still
reported as the interruption.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:36:10 +00:00

63 lines
2.7 KiB
TypeScript

import { expect, it } from "vitest";
import { analyzeAndAdoptJavaScriptArtifactFiles } from "../../../../src/application/javascript/JavaScriptArtifactAnalysis.js";
import { createJavaScriptSemanticGraphProjection } from "../../../../src/application/javascript/JavaScriptSemanticGraphBuilder.js";
import { readJavaScriptArtifactFiles } from "../../../../src/artifacts/javascript/JavaScriptArtifactFiles.js";
import { createJavaScriptArtifactReader } from "../../../../src/artifacts/javascript/JavaScriptArtifactReader.js";
import { createJavaScriptSourceAnalysis } from "../../../../src/artifacts/javascript/JavaScriptSourceAnalysis.js";
import { JAVASCRIPT_ANALYSIS_RESOURCE_DEFAULTS } from "../../../../src/domain/javascript/javascriptAnalysisResourceControls.js";
import {
scanCanonicalArtifactInventory,
withArtifactResourceScope,
} from "../../../fixtures/artifactInventory.js";
import { writeJavaScriptSourceSelectionFixture } from "../../../fixtures/javascriptSourceSelection.js";
import { createTestTempDirectory } from "../../../fixtures/temporaryDirectory.js";
it("keeps unselected sources outside the selection when cancellation follows the last selected source", async () => {
const root = await createTestTempDirectory("rea-js-selected-late-cancel-");
await writeJavaScriptSourceSelectionFixture(root);
const snapshot = await scanCanonicalArtifactInventory(root, {});
const reader = createJavaScriptArtifactReader(root, "directory");
const worker = createJavaScriptSourceAnalysis(
JAVASCRIPT_ANALYSIS_RESOURCE_DEFAULTS,
1,
);
try {
const files = await withArtifactResourceScope((scope) =>
readJavaScriptArtifactFiles(reader, snapshot, scope, undefined, [
"main.mjs",
]),
);
const controller = new AbortController();
// Cancel after the only selected source completes, before the loop
// reaches the first unselected source.
const { analysis, interruption } =
await analyzeAndAdoptJavaScriptArtifactFiles(
files,
{
analyze: async (file, budget, signal) => {
const result = await worker.analyze(file, budget, signal);
controller.abort();
return result;
},
},
createJavaScriptSemanticGraphProjection(),
async () => {},
controller.signal,
);
expect(interruption?._tag).toBe("AnalysisCancelledError");
const unselected = analysis.files.filter(
({ file }) =>
!file.text.included && file.text.reason === "outside-analysis-scope",
);
expect(unselected).toHaveLength(5);
expect(
unselected.filter((entry) => entry.analysis_failure !== undefined),
).toEqual([]);
} finally {
await worker.close();
await reader.close();
}
});