diff --git a/tests/boundary/providers/hopper/bridgeLauncher.test.ts b/tests/boundary/providers/hopper/bridgeLauncher.test.ts index c0da10224..722a25bed 100644 --- a/tests/boundary/providers/hopper/bridgeLauncher.test.ts +++ b/tests/boundary/providers/hopper/bridgeLauncher.test.ts @@ -165,10 +165,12 @@ describe("Hopper bridge launcher selection", () => { it("launches Hopper helpers with the caller-selected environment without restoring ambient values", async () => { const directory = await createTestTempDirectory("rea-hopper-selected-env-"); + const targetPath = join(directory, "target"); + await writeFile(targetPath, "fixture target"); const launcher = new HopperApplicationLauncher({ environment: { REA_SELECTED_VALUE: "caller-value" }, launcherPath: process.execPath, - targetPath: join(directory, "target"), + targetPath, targetKind: "executable", loaderArgs: [ "-e", diff --git a/tests/boundary/providers/hopper/hopperClient.cleanupRetry.test.ts b/tests/boundary/providers/hopper/hopperClient.cleanupRetry.test.ts index 030a192ac..62310facf 100644 --- a/tests/boundary/providers/hopper/hopperClient.cleanupRetry.test.ts +++ b/tests/boundary/providers/hopper/hopperClient.cleanupRetry.test.ts @@ -107,7 +107,7 @@ const failedStartup = async (launcher: RetryCleanupLauncher) => { error: { _tag: "ProviderAdapterError", cleanupIncomplete: true, - cause: { _tag: "HopperTimeoutError" }, + cause: { cause: { _tag: "HopperTimeoutError" } }, }, }); const session = launcher.sessions[0]; @@ -233,7 +233,7 @@ it("blocks a fresh launch while cleanup remains unverified", async () => { ok: false, error: { cleanupIncomplete: true, - cause: { _tag: "HopperTimeoutError" }, + cause: { cause: { _tag: "HopperTimeoutError" } }, diagnostics: { primary_error: { code: "provider_timeout" } }, }, }); @@ -263,7 +263,7 @@ it("preserves failed startup state through a blocked retry until cleanup succeed error: { _tag: "ProviderAdapterError", cleanupIncomplete: true, - cause: { _tag: "HopperTimeoutError" }, + cause: { cause: { _tag: "HopperTimeoutError" } }, }, }); // ...but must not wipe the failed-startup state: the client still diff --git a/tests/boundary/providers/hopper/hopperClient.helperFailure.test.ts b/tests/boundary/providers/hopper/hopperClient.helperFailure.test.ts index 13601e172..06e725dc1 100644 --- a/tests/boundary/providers/hopper/hopperClient.helperFailure.test.ts +++ b/tests/boundary/providers/hopper/hopperClient.helperFailure.test.ts @@ -1,8 +1,11 @@ import { spawn } from "node:child_process"; -import { access } from "node:fs/promises"; +import { access, writeFile } from "node:fs/promises"; +import { join } from "node:path"; import { expect, it, onTestFinished } from "vitest"; +import { createTestTempDirectory } from "../../../fixtures/temporaryDirectory.js"; + import { AnalysisError } from "../../../../src/domain/analysisErrorBase.js"; import { projectAnalysisError } from "../../../../src/domain/analysisErrorProjection.js"; import { ok } from "../../../../src/domain/result.js"; @@ -67,17 +70,23 @@ const trackFailedHelperClient = ( const projectPrimaryStartupFailure = (error: AnalysisError) => { if (!error.cleanupIncomplete) return projectAnalysisError(error); expect(projectAnalysisError(error).code).toBe("cleanup_incomplete"); - const primary = error.cause; + const cause = error.cause; + if (!(cause instanceof AggregateError)) + throw new Error("Cleanup failure did not retain its aggregate causes"); + const primary = cause.cause; if (!(primary instanceof AnalysisError)) throw new Error("Cleanup failure lost its typed startup cause"); return projectAnalysisError(primary); }; it("does not equate an owned native helper exit with an external GUI exit", async () => { + const directory = await createTestTempDirectory("rea-hopper-helper-failure-"); + const targetPath = join(directory, "target"); + await writeFile(targetPath, "fixture target"); const launcher = new HopperApplicationLauncher({ environment: {}, launcherPath: process.execPath, - targetPath: "/target", + targetPath, targetKind: "executable", loaderArgs: [ "-e", @@ -91,7 +100,10 @@ it("does not equate an owned native helper exit with an external GUI exit", asyn const result = await client.start(); expect(result).toMatchObject({ ok: false, - error: { cleanupIncomplete: true, cause: { _tag: "HopperStartError" } }, + error: { + cleanupIncomplete: true, + cause: { cause: { _tag: "HopperStartError" } }, + }, }); if (result.ok) throw new Error("Expected the native helper to fail"); expect(projectPrimaryStartupFailure(result.error)).toMatchObject({ @@ -140,7 +152,10 @@ it.each(["exit", "signal", "exit75"] as const)( const result = await client.start(); expect(result).toMatchObject({ ok: false, - error: { cleanupIncomplete: true, cause: { _tag: "HopperStartError" } }, + error: { + cleanupIncomplete: true, + cause: { cause: { _tag: "HopperStartError" } }, + }, }); if (result.ok) throw new Error("Expected the launcher to fail"); const projected = projectPrimaryStartupFailure(result.error);