diff --git a/src/application/analysisView/AnalysisViewService.test.ts b/src/application/analysisView/AnalysisViewService.test.ts index ad762d5881..e86c136258 100644 --- a/src/application/analysisView/AnalysisViewService.test.ts +++ b/src/application/analysisView/AnalysisViewService.test.ts @@ -42,6 +42,43 @@ import { } from "../../../tests/fixtures/browserScenarioCapture.js"; import { projectAnalysisError } from "../../domain/analysisErrorProjection.js"; +it.each(["inline", "retained-evidence", "invalid"] as const)( + "refuses an already cancelled %s view before source admission", + async (kind) => { + const parent = analysisViewLayoutEvidence(); + const ledger = new EvidenceLedger(); + expect(ledger.record(parent).ok).toBe(true); + const retained = ledger.forAnalysis(parent.evidence_id); + let lookups = 0; + const controller = new AbortController(); + const reason = Object.freeze({ requested: "cancel-before-view-admission" }); + controller.abort(reason); + const result = await inspectAnalysisView( + kind === "invalid" + ? null + : { + source: + kind === "inline" + ? { kind, evidence: parent } + : { kind, evidence_id: parent.evidence_id }, + view: { kind: "summary" }, + }, + (id) => { + lookups++; + return ledger.forAnalysis(id); + }, + { signal: controller.signal }, + ); + expect(result).toMatchObject({ + ok: false, + error: { _tag: "AnalysisCancelledError" }, + }); + expect(result.ok ? undefined : result.error.cause).toBe(reason); + expect(lookups).toBe(0); + expect(ledger.forAnalysis(parent.evidence_id)).toBe(retained); + }, +); + it.each([false, true])( "summarizes the selected observation path rather than older retained display metadata (history=%s)", (history) => { diff --git a/src/application/analysisView/AnalysisViewService.ts b/src/application/analysisView/AnalysisViewService.ts index 076cb4b25e..622a3efb9d 100644 --- a/src/application/analysisView/AnalysisViewService.ts +++ b/src/application/analysisView/AnalysisViewService.ts @@ -65,6 +65,7 @@ export const inspectAnalysisView = async ( INSPECT_ANALYSIS_VIEW_OPERATION, rawInput, inspectAnalysisViewInputSchema, + options.signal, ); if (!parsed.ok) return parsed; if (options.evidenceBundlePath !== undefined)