test: assert exact cancellation reasons across browser and desktop

This commit is contained in:
morluto committed 2026-11-10 16:02:45 -05:00
1 parent 93dc8d044d
commit 0ec73a8102
7 files changed
+43 -20

No files matched your search

@@ -910,6 +910,7 @@ describe("inspectDesktopApplicationState database sidecars", () => {
it("reports cancellation during the last database read instead of Evidence", async () => {
const controller = new AbortController();
const reason = { stage: "last database read" };
let reads = 0;
const folder = await writeCaptureFolder(
extended({
@@ -925,7 +926,7 @@ describe("inspectDesktopApplicationState database sidecars", () => {
...readers,
sqlite: async (database, signal) => {
reads += 1;
if (reads === 3) controller.abort(new Error("stopped"));
if (reads === 3) controller.abort(reason);
return readers.sqlite(database, signal);
},
},
@@ -934,6 +935,9 @@ describe("inspectDesktopApplicationState database sidecars", () => {
expect(reads).toBe(3);
expect(result).toBeInstanceOf(AnalysisCancelledError);
expect(result instanceof AnalysisCancelledError && result.cause).toBe(
reason,
);
});
});
@@ -321,6 +321,7 @@ it.each([
expect(result.error.cleanupResources).toContain(join(bundle, suffix));
if (cancel) {
expect(result.error._tag).toBe("AnalysisCancelledError");
expect(result.error.cause).toBe(reason);
expect(result.error.partialObservation).toMatchObject({
kind: "partial-task-measurement",
solves: [{}, {}, {}],
@@ -57,11 +57,14 @@ it("keeps the place of a call cancelled while it waits, so the one after it stil
return ok("last");
});
await settled();
caller.abort(new Error("the client went away"));
expect(await cancelled).toMatchObject({
const reason = { caller: "the client went away" };
caller.abort(reason);
const cancellation = await cancelled;
expect(cancellation).toMatchObject({
ok: false,
error: { _tag: "AnalysisCancelledError", operation: "cancelled" },
});
expect(!cancellation.ok && cancellation.error.cause).toBe(reason);
await settled();
expect(log).toEqual(["running"]);
running.end();
@@ -81,9 +81,9 @@ it("waits for an interrupted reader before removing its folder", async () => {
it("preserves a completed view when cancellation arrives during successful cleanup", async () => {
const controller = new AbortController();
const reason = { stage: "reader final cleanup" };
const owner = new DesktopRemoteTaskReaders(async (argv) => {
if (argv[3] === PYTHON_READER_CLEANUP)
controller.abort(new Error("cancelled"));
if (argv[3] === PYTHON_READER_CLEANUP) controller.abort(reason);
return success;
});
const failure = await owner
@@ -91,6 +91,7 @@ it("preserves a completed view when cancellation arrives during successful clean
.catch((error: unknown) => error);
if (!(failure instanceof AnalysisCancelledError))
throw new Error("expected cancellation");
expect(failure.cause).toBe(reason);
expect(failure.diagnostics).toMatchObject({
completed_reader_views: { note: { view: { value: 7 } } },
});
@@ -99,12 +100,13 @@ it("preserves a completed view when cancellation arrives during successful clean
it("keeps cancellation and a completed view when final cleanup also fails", async () => {
const controller = new AbortController();
const reason = { stage: "reader final cleanup" };
let fail = true;
const owner = new DesktopRemoteTaskReaders(async (argv) => {
if (argv[3] !== PYTHON_READER_CLEANUP) return success;
if (fail) {
fail = false;
controller.abort(new Error("cancelled"));
controller.abort(reason);
return { ...success, exit_code: 1, stderr: "denied" };
}
return success;
@@ -115,6 +117,7 @@ it("keeps cancellation and a completed view when final cleanup also fails", asyn
if (!(failure instanceof ProviderCleanupError))
throw new Error("expected cleanup failure");
expect(failure.cleanupPrimary).toBeInstanceOf(AnalysisCancelledError);
expect(failure.cleanupPrimary?.cause).toBe(reason);
expect(failure.diagnostics).toMatchObject({
completed_reader_views: { note: { view: { value: 7 } } },
});
+6 -2
View File
@@ -37,7 +37,9 @@ describe("cancellable browser observation delays", () => {
).catch((error: unknown) => error);
expect(beforeStart).toBeInstanceOf(AnalysisCancelledError);
expect(beforeStart).toMatchObject({ cause: preAbortedReason });
expect(
beforeStart instanceof AnalysisCancelledError && beforeStart.cause,
).toBe(preAbortedReason);
vi.useFakeTimers();
const reason = new Error("capture wait cancelled");
@@ -51,7 +53,9 @@ describe("cancellable browser observation delays", () => {
const duringWait = await waiting;
expect(duringWait).toBeInstanceOf(AnalysisCancelledError);
expect(duringWait).toMatchObject({ cause: reason });
expect(
duringWait instanceof AnalysisCancelledError && duringWait.cause,
).toBe(reason);
expect(vi.getTimerCount()).toBe(0);
});
});
+9 -3
View File
@@ -136,7 +136,9 @@ describe("CDP discovery cancellation ownership", () => {
).catch((error: unknown) => error);
expect(failure).toBeInstanceOf(AnalysisCancelledError);
expect(failure).toMatchObject({ cause: reason });
expect(failure instanceof AnalysisCancelledError && failure.cause).toBe(
reason,
);
expect(requests).toBe(0);
});
@@ -164,7 +166,9 @@ describe("CDP discovery cancellation ownership", () => {
expect(requestedPath).toBe("/json/version");
expect(failure).toBeInstanceOf(AnalysisCancelledError);
expect(failure).toMatchObject({ cause: reason });
expect(failure instanceof AnalysisCancelledError && failure.cause).toBe(
reason,
);
});
it("does not replace a primary discovery failure when cancellation arrives later", async () => {
@@ -259,7 +263,9 @@ describe("CDP discovery cancellation ownership", () => {
).catch((error: unknown) => error);
expect(failure).toBeInstanceOf(AnalysisCancelledError);
expect(failure).toMatchObject({ cause: reason });
expect(failure instanceof AnalysisCancelledError && failure.cause).toBe(
reason,
);
});
it("keeps a deadline rejection when the caller aborts only after timeout", async () => {
+11 -9
View File
@@ -112,15 +112,17 @@ it("preserves the caller cancellation reason when a source read is pending", asy
signal: controller.signal,
} as unknown as CaptureContext;
await expect(
captureScripts({
context,
events,
rawResources: [],
resources: [],
frameIds: new Set(),
}),
).rejects.toMatchObject({ _tag: "AnalysisCancelledError", cause: reason });
const failure = await captureScripts({
context,
events,
rawResources: [],
resources: [],
frameIds: new Set(),
}).catch((error: unknown) => error);
expect(failure).toBeInstanceOf(AnalysisCancelledError);
expect(failure instanceof AnalysisCancelledError && failure.cause).toBe(
reason,
);
});
it.each([