Files
hyperframes/packages/cli/src/cli.dotEnv.test.ts
Miguel Ángel 6f0e1f1185 test(cli): stop the dotenv startup test failing at random under load (#5701)
Each case left the CLI's background imports in flight. Under load they resolved
vitest's pending mock queue at the same time as the next case's import, which
then loaded the real command module. Wait for dynamic imports to settle before
resetting the mocks.
2026-10-16 17:07:16 +00:00

90 lines
3.2 KiB
TypeScript

import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, expect, it, vi } from "vitest";
import { mockTelemetry } from "./cliDispatchTestUtils.js";
const originalArgv = [...process.argv];
const originalExitCode = process.exitCode;
const dirs: string[] = [];
const eventNames = ["exit", "uncaughtException", "unhandledRejection"] as const;
const listeners = eventNames.map((event) => [event, process.listeners(event)] as const);
const streams = [process.stdout, process.stderr].map(
(stream) => [stream, stream.listeners("error")] as const,
);
afterEach(async () => {
await vi.dynamicImportSettled();
process.argv = [...originalArgv];
process.exitCode = originalExitCode;
vi.restoreAllMocks();
vi.unstubAllEnvs();
for (const path of [
"./commands/capture.js",
"./commands/init.js",
"./telemetry/index.js",
"./telemetry/events.js",
])
vi.doUnmock(path);
vi.resetModules();
for (const [event, original] of listeners) {
for (const listener of process.listeners(event)) {
if (!original.includes(listener)) process.removeListener(event, listener);
}
}
for (const [stream, original] of streams) {
for (const listener of stream.listeners("error")) {
if (!original.includes(listener)) stream.removeListener("error", listener);
}
}
for (const dir of dirs.splice(0)) rmSync(dir, { recursive: true, force: true });
});
it.each(
(
[
["capture", false, undefined, "fixture-key", undefined],
["capture", true, undefined, undefined, undefined],
["init", false, process.execPath, "fixture-key", undefined],
["init", true, process.execPath, "fixture-key", undefined],
["capture", false, process.execPath, "fixture-key", process.execPath],
] as const
).flatMap((test) =>
[[], ["--json"], ["--json", "--verbose"]].map((prefix) => [...test, prefix] as const),
),
)(
"applies CWD dotenv policy at real CLI startup: %s, opt-out=%s",
async (command, skip, browser, key, inheritedBrowser, prefix) => {
const dir = mkdtempSync(join(tmpdir(), "hf-cli-dotenv-"));
dirs.push(dir);
writeFileSync(
join(dir, ".env"),
`HYPERFRAMES_BROWSER_PATH=${process.execPath}\nNODE_OPTIONS=--no-warnings\nGEMINI_API_KEY=fixture-key\n`,
);
vi.spyOn(process, "cwd").mockReturnValue(dir);
vi.stubEnv("HYPERFRAMES_BROWSER_PATH", inheritedBrowser);
vi.stubEnv("NODE_OPTIONS", undefined);
vi.stubEnv("GEMINI_API_KEY", undefined);
vi.stubEnv("HYPERFRAMES_NO_CAPTURE_DOTENV", skip ? "1" : undefined);
let observed: unknown;
const definition = {
default: {
meta: { name: command },
args: {},
run: () => {
observed = [
process.env.HYPERFRAMES_BROWSER_PATH,
process.env.NODE_OPTIONS,
process.env.GEMINI_API_KEY,
];
},
},
};
vi.doMock("./commands/capture.js", () => definition);
vi.doMock("./commands/init.js", () => definition);
mockTelemetry();
process.argv = ["node", "cli.ts", ...prefix, command];
await import("./cli.js");
expect(observed).toEqual([browser, command === "capture" ? undefined : "--no-warnings", key]);
},
);