Files
rea/tests/boundary/cli/directAnalysisStatus.test.ts
T

105 lines
3.5 KiB
TypeScript

import { Cli } from "incur";
import { expect, it, vi } from "vitest";
import { runSessionStatus } from "../../../src/application/DirectAnalysisStatus.js";
import { registerUtilityCommands } from "../../../src/cli/utilityCommands.js";
import { parseConfig } from "../../../src/config/parseConfig.js";
import { isCliOperationFailure } from "../../../src/cliLogging.js";
import { ProviderCleanupError } from "../../../src/domain/providerCleanupError.js";
import { err, ok } from "../../../src/domain/result.js";
import { silentLogger } from "../../../src/logger.js";
import { createTestBinarySession } from "../../fixtures/binarySession.js";
import { observed } from "../../fixtures/analysisExecution.js";
const createStatusSession = () =>
createTestBinarySession(() => ({
close: async () => ok(null),
execute: async () => observed(null),
}));
it.each(["capabilities", "providers"])(
"reports failed %s finalization with the completed status",
async (command) => {
const session = createStatusSession();
const cleanup = new ProviderCleanupError(
"fixture",
["retained profile reader"],
{ reason: "profile reader close failed" },
{ remediationAction: "Retry the retained profile reader cleanup." },
);
const close = vi
.spyOn(session, "close")
.mockResolvedValueOnce(err(cleanup));
const cli = Cli.create({ name: "rea" });
registerUtilityCommands(
cli,
silentLogger,
{},
{
runSessionStatus: () =>
runSessionStatus({
readConfiguration: () => parseConfig({}),
createBinarySession: () => session,
}),
runProviderAnalysis: async () => null,
},
);
let stdout = "";
try {
await cli.serve([command, "--json"], {
env: {},
stdout: (text) => {
stdout += text;
},
exit: () => {},
});
const output: unknown = JSON.parse(stdout);
expect(output).toMatchObject({
code: "cleanup_incomplete",
remediation: { action: "Retry the retained profile reader cleanup." },
details: {
resources: ["retained profile reader"],
partial_observation: {
capabilities: expect.any(Array),
server_identity: expect.any(Object),
},
},
});
expect(isCliOperationFailure(output)).toBe(true);
expect(close).toHaveBeenCalledTimes(1);
} finally {
close.mockRestore();
await session.close();
}
},
);
it.each([false, true])(
"keeps status failure when final cleanup also fails: %s",
async (cleanupFails) => {
const session = createStatusSession();
const failure = new Error("status observation failed");
const cleanup = new ProviderCleanupError("fixture", ["reader"], {});
const status = vi.spyOn(session, "status").mockRejectedValueOnce(failure);
const close = vi
.spyOn(session, "close")
.mockResolvedValueOnce(cleanupFails ? err(cleanup) : ok(null));
try {
const result = runSessionStatus({
readConfiguration: () => parseConfig({}),
createBinarySession: () => session,
});
if (cleanupFails)
await expect(result).rejects.toMatchObject({
cause: failure,
errors: [failure, cleanup],
});
else await expect(result).rejects.toBe(failure);
expect(close).toHaveBeenCalledTimes(1);
} finally {
status.mockRestore();
close.mockRestore();
await session.close();
}
},
);