mirror of
https://github.com/morluto/rea
synced 2026-10-27 14:42:18 -04:00
refactor(javascript): group application workflows and verification (#896)
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { AnalysisCapabilityUnavailableError } from "../../domain/analysisErrorCore.js";
|
||||
import { err, ok } from "../../domain/result.js";
|
||||
import type {
|
||||
JavaScriptRecoveryInput,
|
||||
JavaScriptRecoveryResult,
|
||||
} from "../../domain/javascriptRecovery.js";
|
||||
import { createAnalysisExecution } from "../AnalysisProvider.js";
|
||||
import { JavaScriptRecoveryService } from "./JavaScriptRecoveryService.js";
|
||||
|
||||
const artifact = { path: "/tmp/bundle.js", sha256: "a".repeat(64), bytes: 20 };
|
||||
const recoveryResult = (): JavaScriptRecoveryResult => ({
|
||||
source: {
|
||||
...artifact,
|
||||
snapshot_path: "/tmp/work/inputs/bundle.js",
|
||||
published_copy: artifact,
|
||||
},
|
||||
engine: {
|
||||
id: "fixture-recovery",
|
||||
version: "1",
|
||||
executable: artifact,
|
||||
audited_source_revision: "pinned",
|
||||
executed_source_revision: null,
|
||||
},
|
||||
options: { extraction_mode: "structural", rewrite_level: "standard" },
|
||||
status: "complete",
|
||||
detected_formats: [],
|
||||
reported_safety: "normal",
|
||||
reported_strategy: "structural",
|
||||
reported_format: "unknown",
|
||||
total: 0,
|
||||
failed: 0,
|
||||
modules: [],
|
||||
warnings: [],
|
||||
report: artifact,
|
||||
provenance: artifact,
|
||||
manifest: artifact,
|
||||
analysis_input: null,
|
||||
runtime_equivalence: "unknown",
|
||||
limitations: ["Not executed"],
|
||||
});
|
||||
const providerIdentity = {
|
||||
id: "fixture-recovery",
|
||||
name: "Fixture recovery",
|
||||
version: "1",
|
||||
};
|
||||
const input = { path: artifact.path, output_directory: "/tmp/output" };
|
||||
|
||||
describe("JavaScript recovery workflow", () => {
|
||||
it("passes normalized requests to a typed port and returns derived Evidence", async () => {
|
||||
const received: JavaScriptRecoveryInput[] = [];
|
||||
const service = new JavaScriptRecoveryService({
|
||||
recover: async (request) => {
|
||||
received.push(request);
|
||||
return ok(
|
||||
createAnalysisExecution(recoveryResult(), providerIdentity, {
|
||||
subject: { ...artifact, format: "javascript" },
|
||||
limitations: ["Not executed"],
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
const result = await service.recover(input);
|
||||
if (!result.ok) throw result.error;
|
||||
expect(received).toEqual([
|
||||
{ ...input, extraction_mode: "structural", rewrite_level: "standard" },
|
||||
]);
|
||||
expect(result.value).toMatchObject({
|
||||
operation: "recover_javascript_sources",
|
||||
confidence: "derived",
|
||||
authority: "shipped-artifact",
|
||||
provider: providerIdentity,
|
||||
});
|
||||
});
|
||||
it("preserves a missing provider reason", async () => {
|
||||
const failure = new AnalysisCapabilityUnavailableError(
|
||||
"fixture-recovery",
|
||||
"recover_javascript_sources",
|
||||
"fixture missing engine",
|
||||
);
|
||||
const result = await new JavaScriptRecoveryService({
|
||||
recover: async () => err(failure),
|
||||
}).recover(input);
|
||||
expect(result).toEqual(err(failure));
|
||||
});
|
||||
it.each([
|
||||
"invalid-result",
|
||||
"missing-subject",
|
||||
"subject-mismatch",
|
||||
"engine-mismatch",
|
||||
])("rejects %s returned across the port", async (mode) => {
|
||||
const service = new JavaScriptRecoveryService({
|
||||
recover: async () =>
|
||||
ok(
|
||||
createAnalysisExecution(
|
||||
mode === "invalid-result" ? {} : recoveryResult(),
|
||||
mode === "engine-mismatch"
|
||||
? { ...providerIdentity, id: "another-engine" }
|
||||
: providerIdentity,
|
||||
mode === "missing-subject"
|
||||
? {}
|
||||
: {
|
||||
subject: {
|
||||
path:
|
||||
mode === "subject-mismatch" ? "/wrong.js" : artifact.path,
|
||||
sha256: artifact.sha256,
|
||||
format: "javascript" as const,
|
||||
},
|
||||
},
|
||||
),
|
||||
),
|
||||
});
|
||||
const result = await service.recover(input);
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) throw new Error("expected invalid port output");
|
||||
expect(result.error._tag).toBe("AnalysisOutputError");
|
||||
});
|
||||
it.each(["path", "output_directory"])(
|
||||
"rejects relative %s before acquiring the recovery engine",
|
||||
async (field) => {
|
||||
let invoked = false;
|
||||
const service = new JavaScriptRecoveryService({
|
||||
recover: async () => {
|
||||
invoked = true;
|
||||
return err(
|
||||
new AnalysisCapabilityUnavailableError(
|
||||
"fixture",
|
||||
"recover_javascript_sources",
|
||||
"engine missing",
|
||||
),
|
||||
);
|
||||
},
|
||||
});
|
||||
const result = await service.recover({
|
||||
...input,
|
||||
[field]: "relative.js",
|
||||
});
|
||||
expect(invoked).toBe(false);
|
||||
if (result.ok) throw new Error("expected invalid path");
|
||||
expect(result.error._tag).toBe("AnalysisInputError");
|
||||
expect(result.error).toMatchObject({
|
||||
issues: [{ path: [field], reason: "invalid_format" }],
|
||||
});
|
||||
},
|
||||
);
|
||||
it("rejects malformed and pre-cancelled input before acquiring the port", async () => {
|
||||
const service = new JavaScriptRecoveryService({
|
||||
recover: async () => {
|
||||
throw new Error("port must not execute");
|
||||
},
|
||||
});
|
||||
const invalid = await service.recover({});
|
||||
if (invalid.ok) throw new Error("expected malformed input");
|
||||
expect(invalid.error._tag).toBe("AnalysisInputError");
|
||||
const cancelled = await service.recover(input, {
|
||||
signal: AbortSignal.abort(),
|
||||
});
|
||||
if (cancelled.ok) throw new Error("expected cancellation");
|
||||
expect(cancelled.error._tag).toBe("AnalysisCancelledError");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user