Files
OmniRoute/tests/unit/cli-auth-export-wiring.test.ts
Diego Rodrigues de Sa e Souza 5cf16028fe fix(cli): real OpenRouter key validation + auth export argument wiring (#11226) (#11264)
Two defects exposed by #11226 (the 401 "User not found." itself is upstream
OpenRouter's response to a bad key — not an OmniRoute bug):

1. OpenRouter key validation was vacuous. Both the dashboard Check (via
   validateProviderApiKey -> validateOpenAILikeProvider) and 'omniroute
   providers test' (bin/cli/provider-test.mjs) probed /api/v1/models, which is
   PUBLIC and answers 200 to any key — so invalid keys were saved/marked valid
   and only failed on real chat traffic. OpenRouter's authenticated key-info
   endpoint (GET /api/v1/auth/key, 200 = valid / 401 = invalid) is now the
   probe: registered as testKeyModelsUrl on the openrouter registry entry
   (same mechanism as perplexity) and as keyCheckPath in the CLI test configs.
   No other provider's probe changes; error results keep using canned strings,
   never the raw upstream body (Hard Rule #12).

2. 'omniroute auth export' crashed with "cmd.optsWithGlobals is not a
   function". .command("auth export") does not register a two-word command:
   commander parses the bare word 'export' as a required positional argument,
   so the action received (exportArgValue, options, command) while expecting
   (options, command). Registered 'export' as a proper nested subcommand of
   'auth' — the documented CLI surface 'omniroute auth export [--force]
   [--id] [--format] [--out]' is unchanged, and unknown positionals
   (e.g. 'omniroute auth bogus') are now rejected instead of silently running
   the export.

TDD: tests/unit/openrouter-key-validation-auth-endpoint.test.ts (stub mimics
the real OpenRouter: /models public-200, /auth/key 401 'User not found.') and
tests/unit/cli-auth-export-wiring.test.ts (real commander wiring via
createProgram) were RED before the fix and are GREEN after.

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
2026-08-23 14:26:08 -03:00

132 lines
4.4 KiB
TypeScript

// #11226 — `omniroute auth export` crashed with "cmd.optsWithGlobals is not a
// function" because the command was registered as `.command("auth export")`:
// commander parses the bare word `export` as a REQUIRED POSITIONAL ARGUMENT, so
// the action received ("export", options, command) while its signature expected
// (options, command) — the classic opts/cmd swap. The fix registers `export` as
// a proper nested subcommand of `auth`, restoring the documented CLI surface
// (docs/reference/CLI-TOOLS.md): `omniroute auth export [--force] [--id] [--format] [--out]`.
//
// These tests exercise the REAL commander wiring via createProgram() — no DB is
// touched on any of these paths (the no-force gate prints and returns before any
// DB access; an invalid --format fails validation before opening the DB).
import test from "node:test";
import assert from "node:assert/strict";
import { createProgram } from "../../bin/cli/program.mjs";
function captureConsole(): { captured: { logs: string[]; errors: string[] }; restore: () => void } {
const originalLog = console.log;
const originalError = console.error;
const captured = { logs: [] as string[], errors: [] as string[] };
console.log = (msg?: unknown) => {
captured.logs.push(String(msg ?? ""));
};
console.error = (msg?: unknown) => {
captured.errors.push(String(msg ?? ""));
};
return {
captured,
restore: () => {
console.log = originalLog;
console.error = originalError;
},
};
}
function stubProcessExit(): { exitCodes: number[]; restore: () => void } {
const originalExit = process.exit;
const exitCodes: number[] = [];
process.exit = ((code?: number) => {
exitCodes.push(code ?? 0);
}) as typeof process.exit;
return {
exitCodes,
restore: () => {
process.exit = originalExit;
},
};
}
test("auth command exposes 'export' as a subcommand, not a positional argument", () => {
const program = createProgram();
const auth = program.commands.find((c) => c.name() === "auth");
assert.ok(auth, "auth command exists");
const exportCmd = auth.commands.find((c) => c.name() === "export");
assert.ok(exportCmd, "export must be a nested subcommand of auth");
const registeredArgs = (auth as unknown as { registeredArguments?: unknown[] })
.registeredArguments;
assert.equal(
registeredArgs?.length ?? 0,
0,
"auth must not declare positional arguments (a bare word in .command() becomes one)"
);
});
test("auth export action receives (options, command): flags reach the handler end-to-end", async () => {
const program = createProgram();
const exitStub = stubProcessExit();
const { captured, restore } = captureConsole();
try {
// --format bogus makes runAuthExportCommand return 1 BEFORE any DB access;
// the action must then call process.exit(1). With the opts/cmd swap this
// parse rejects with "cmd.optsWithGlobals is not a function" instead.
await program.parseAsync([
"node",
"omniroute",
"auth",
"export",
"--force",
"--format",
"bogus",
]);
} finally {
restore();
exitStub.restore();
}
assert.deepEqual(
exitStub.exitCodes,
[1],
"handler must receive --format and exit 1 on bogus value"
);
assert.ok(
captured.errors.join("\n").includes("Invalid format"),
`expected the invalid-format error, got: ${captured.errors.join(" | ")}`
);
});
test("auth export without --force prints the confirmation gate (no crash, no DB)", async () => {
const program = createProgram();
const exitStub = stubProcessExit();
const { captured, restore } = captureConsole();
try {
await program.parseAsync(["node", "omniroute", "auth", "export"]);
} finally {
restore();
exitStub.restore();
}
assert.deepEqual(exitStub.exitCodes, [], "dry run exits 0 without calling process.exit");
assert.ok(
captured.logs.join("\n").includes("DECRYPTED"),
`expected the confirmation gate, got: ${captured.logs.join(" | ")}`
);
});
test("auth rejects an unknown positional (was silently accepted as the 'export' argument)", async () => {
const program = createProgram();
await assert.rejects(
program.parseAsync(["node", "omniroute", "auth", "bogus-word"]),
(err: unknown) => {
assert.ok(err instanceof Error);
assert.match(
(err as { code?: string }).code || "",
/commander\.(unknownCommand|helpDisplayed)/
);
return true;
}
);
});