Make CI independent of external CLIs
This commit is contained in:
@@ -1,10 +1,23 @@
|
||||
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
||||
import { execFileSync } from "node:child_process";
|
||||
|
||||
import {
|
||||
createDaemonTestContext,
|
||||
type DaemonTestContext,
|
||||
} from "../test-utils/index.js";
|
||||
|
||||
function isBinaryInstalled(binary: string): boolean {
|
||||
try {
|
||||
const out = execFileSync("which", [binary], { encoding: "utf8" }).trim();
|
||||
return out.length > 0;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const hasCodex = isBinaryInstalled("codex");
|
||||
const hasOpenCode = isBinaryInstalled("opencode");
|
||||
|
||||
describe("provider model catalogs (e2e)", () => {
|
||||
let ctx: DaemonTestContext;
|
||||
|
||||
@@ -33,7 +46,7 @@ describe("provider model catalogs (e2e)", () => {
|
||||
180_000
|
||||
);
|
||||
|
||||
test(
|
||||
test.runIf(hasCodex)(
|
||||
"Codex catalog exposes gpt-5.1-codex",
|
||||
async () => {
|
||||
const result = await ctx.client.listProviderModels("codex");
|
||||
@@ -45,7 +58,7 @@ describe("provider model catalogs (e2e)", () => {
|
||||
180_000
|
||||
);
|
||||
|
||||
test(
|
||||
test.runIf(hasOpenCode)(
|
||||
"OpenCode catalog returns models from multiple providers",
|
||||
async () => {
|
||||
const result = await ctx.client.listProviderModels("opencode");
|
||||
|
||||
@@ -2,6 +2,7 @@ import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
||||
import { mkdtempSync, rmSync } from "fs";
|
||||
import { tmpdir } from "os";
|
||||
import path from "path";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import {
|
||||
createDaemonTestContext,
|
||||
type DaemonTestContext,
|
||||
@@ -49,6 +50,18 @@ function pickTwoDistinctModels(models: Array<{ id: string }>): [string, string]
|
||||
return [ids[0]!, ids[1]!];
|
||||
}
|
||||
|
||||
function isBinaryInstalled(binary: string): boolean {
|
||||
try {
|
||||
const out = execFileSync("which", [binary], { encoding: "utf8" }).trim();
|
||||
return out.length > 0;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const hasCodex = isBinaryInstalled("codex");
|
||||
const hasOpenCode = isBinaryInstalled("opencode");
|
||||
|
||||
describe("daemon E2E", () => {
|
||||
let ctx: DaemonTestContext;
|
||||
let messages: SessionOutboundMessage[] = [];
|
||||
@@ -71,7 +84,12 @@ describe("daemon E2E", () => {
|
||||
describe.each(["claude", "codex", "opencode"] as const)(
|
||||
"live model switching (%s)",
|
||||
(provider) => {
|
||||
test(
|
||||
const shouldRun =
|
||||
provider === "claude" ||
|
||||
(provider === "codex" && hasCodex) ||
|
||||
(provider === "opencode" && hasOpenCode);
|
||||
|
||||
test.runIf(shouldRun)(
|
||||
"updates agent model without restarting",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
@@ -150,7 +168,7 @@ describe("daemon E2E", () => {
|
||||
120000
|
||||
);
|
||||
|
||||
test(
|
||||
test.runIf(hasCodex)(
|
||||
"live thinking switching works for Codex (default -> non-default)",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
@@ -198,7 +216,7 @@ describe("daemon E2E", () => {
|
||||
120000
|
||||
);
|
||||
|
||||
test(
|
||||
test.runIf(hasOpenCode)(
|
||||
"live thinking switching works for OpenCode",
|
||||
async () => {
|
||||
const cwd = tmpCwd();
|
||||
|
||||
@@ -2,6 +2,7 @@ import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
||||
import { mkdtempSync, writeFileSync, existsSync, rmSync, mkdirSync, readFileSync, readdirSync } from "fs";
|
||||
import { tmpdir } from "os";
|
||||
import path from "path";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import {
|
||||
createDaemonTestContext,
|
||||
type DaemonTestContext,
|
||||
@@ -15,6 +16,18 @@ function tmpCwd(): string {
|
||||
|
||||
const CODEX_TEST_MODEL = "gpt-5.1-codex-mini";
|
||||
|
||||
function isBinaryInstalled(binary: string): boolean {
|
||||
try {
|
||||
const out = execFileSync("which", [binary], { encoding: "utf8" }).trim();
|
||||
return out.length > 0;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const hasCodex = isBinaryInstalled("codex");
|
||||
const hasOpenCode = isBinaryInstalled("opencode");
|
||||
|
||||
describe("daemon E2E", () => {
|
||||
let ctx: DaemonTestContext;
|
||||
|
||||
@@ -27,7 +40,7 @@ describe("daemon E2E", () => {
|
||||
}, 60000);
|
||||
|
||||
describe("listProviderModels", () => {
|
||||
test(
|
||||
test.runIf(hasCodex)(
|
||||
"returns model list for Codex provider",
|
||||
async () => {
|
||||
// List models for Codex provider - no agent needed
|
||||
@@ -75,7 +88,7 @@ describe("daemon E2E", () => {
|
||||
60000 // 1 minute timeout
|
||||
);
|
||||
|
||||
test(
|
||||
test.runIf(hasOpenCode)(
|
||||
"returns model list for OpenCode provider",
|
||||
async () => {
|
||||
const result = await ctx.client.listProviderModels("opencode");
|
||||
|
||||
@@ -11,7 +11,9 @@ function tmpCwd(): string {
|
||||
return mkdtempSync(path.join(tmpdir(), "daemon-terminal-e2e-"));
|
||||
}
|
||||
|
||||
describe("daemon E2E terminal", () => {
|
||||
const shouldRun = !process.env.CI;
|
||||
|
||||
(shouldRun ? describe : describe.skip)("daemon E2E terminal", () => {
|
||||
let ctx: DaemonTestContext;
|
||||
|
||||
beforeEach(async () => {
|
||||
|
||||
@@ -393,7 +393,8 @@ export class TerminalManager {
|
||||
paneId,
|
||||
"#{pane_dead_status}",
|
||||
]);
|
||||
exitCode = parseInt(exitCodeStr, 10);
|
||||
const parsed = parseInt(exitCodeStr, 10);
|
||||
exitCode = Number.isFinite(parsed) ? parsed : null;
|
||||
}
|
||||
|
||||
commands.push({
|
||||
@@ -448,7 +449,8 @@ export class TerminalManager {
|
||||
paneId,
|
||||
"#{pane_dead_status}",
|
||||
]);
|
||||
exitCode = parseInt(exitCodeStr, 10);
|
||||
const parsed = parseInt(exitCodeStr, 10);
|
||||
exitCode = Number.isFinite(parsed) ? parsed : null;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user