mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 15:18:28 +00:00
test: group remaining suite cleanups
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
import { setDefaultChannelPluginRegistryForTests } from "./channel-test-helpers.js";
|
||||
import { configMocks, offsetMocks } from "./channels.mock-harness.js";
|
||||
import { baseConfigSnapshot, createTestRuntime } from "./test-runtime-config-helpers.js";
|
||||
@@ -7,6 +7,10 @@ const runtime = createTestRuntime();
|
||||
let channelsAddCommand: typeof import("./channels.js").channelsAddCommand;
|
||||
|
||||
describe("channelsAddCommand", () => {
|
||||
beforeAll(async () => {
|
||||
({ channelsAddCommand } = await import("./channels.js"));
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
configMocks.readConfigFileSnapshot.mockReset();
|
||||
configMocks.writeConfigFile.mockClear();
|
||||
@@ -15,7 +19,6 @@ describe("channelsAddCommand", () => {
|
||||
runtime.error.mockClear();
|
||||
runtime.exit.mockClear();
|
||||
setDefaultChannelPluginRegistryForTests();
|
||||
({ channelsAddCommand } = await import("./channels.js"));
|
||||
});
|
||||
|
||||
it("clears telegram update offsets when the token changes", async () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { setDefaultChannelPluginRegistryForTests } from "./channel-test-helpers.js";
|
||||
import { configMocks, offsetMocks } from "./channels.mock-harness.js";
|
||||
import { baseConfigSnapshot, createTestRuntime } from "./test-runtime-config-helpers.js";
|
||||
@@ -23,8 +23,13 @@ import {
|
||||
} from "./channels.js";
|
||||
|
||||
const runtime = createTestRuntime();
|
||||
let clackPrompterModule: typeof import("../wizard/clack-prompter.js");
|
||||
|
||||
describe("channels command", () => {
|
||||
beforeAll(async () => {
|
||||
clackPrompterModule = await import("../wizard/clack-prompter.js");
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
configMocks.readConfigFileSnapshot.mockReset();
|
||||
configMocks.writeConfigFile.mockClear();
|
||||
@@ -176,9 +181,8 @@ describe("channels command", () => {
|
||||
});
|
||||
|
||||
const prompt = { confirm: vi.fn().mockResolvedValue(true) };
|
||||
const prompterModule = await import("../wizard/clack-prompter.js");
|
||||
const promptSpy = vi
|
||||
.spyOn(prompterModule, "createClackPrompter")
|
||||
.spyOn(clackPrompterModule, "createClackPrompter")
|
||||
.mockReturnValue(prompt as never);
|
||||
|
||||
await channelsRemoveCommand({ channel: "discord", account: "default" }, runtime, {
|
||||
@@ -498,9 +502,8 @@ describe("channels command", () => {
|
||||
});
|
||||
|
||||
const prompt = { confirm: vi.fn().mockResolvedValue(true) };
|
||||
const prompterModule = await import("../wizard/clack-prompter.js");
|
||||
const promptSpy = vi
|
||||
.spyOn(prompterModule, "createClackPrompter")
|
||||
.spyOn(clackPrompterModule, "createClackPrompter")
|
||||
.mockReturnValue(prompt as never);
|
||||
|
||||
await channelsRemoveCommand({ channel: "telegram", account: "default" }, runtime, {
|
||||
|
||||
@@ -921,6 +921,10 @@ export async function loadAndMaybeMigrateDoctorConfig(params: {
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldRepair && pendingChanges) {
|
||||
shouldWriteConfig = true;
|
||||
}
|
||||
|
||||
noteOpencodeProviderOverrides(cfg);
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
arrangeLegacyStateMigrationTest,
|
||||
confirm,
|
||||
@@ -10,7 +10,15 @@ import {
|
||||
writeConfigFile,
|
||||
} from "./doctor.e2e-harness.js";
|
||||
|
||||
let doctorCommand: typeof import("./doctor.js").doctorCommand;
|
||||
let healthCommand: typeof import("./health.js").healthCommand;
|
||||
|
||||
describe("doctor command", () => {
|
||||
beforeAll(async () => {
|
||||
({ doctorCommand } = await import("./doctor.js"));
|
||||
({ healthCommand } = await import("./health.js"));
|
||||
});
|
||||
|
||||
it("runs legacy state migrations in yes mode without prompting", async () => {
|
||||
const { doctorCommand, runtime, runLegacyStateMigrations } =
|
||||
await arrangeLegacyStateMigrationTest();
|
||||
@@ -40,14 +48,12 @@ describe("doctor command", () => {
|
||||
it("skips gateway restarts in non-interactive mode", async () => {
|
||||
mockDoctorConfigSnapshot();
|
||||
|
||||
const { healthCommand } = await import("./health.js");
|
||||
vi.mocked(healthCommand).mockRejectedValueOnce(new Error("gateway closed"));
|
||||
|
||||
serviceIsLoaded.mockResolvedValueOnce(true);
|
||||
serviceRestart.mockClear();
|
||||
confirm.mockClear();
|
||||
|
||||
const { doctorCommand } = await import("./doctor.js");
|
||||
await doctorCommand(createDoctorRuntime(), { nonInteractive: true });
|
||||
|
||||
expect(serviceRestart).not.toHaveBeenCalled();
|
||||
@@ -79,7 +85,6 @@ describe("doctor command", () => {
|
||||
},
|
||||
});
|
||||
|
||||
const { doctorCommand } = await import("./doctor.js");
|
||||
await doctorCommand(createDoctorRuntime(), { yes: true });
|
||||
|
||||
const written = writeConfigFile.mock.calls.at(-1)?.[0] as Record<string, unknown>;
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import { createDoctorRuntime, mockDoctorConfigSnapshot, note } from "./doctor.e2e-harness.js";
|
||||
|
||||
let doctorCommand: typeof import("./doctor.js").doctorCommand;
|
||||
|
||||
describe("doctor command", () => {
|
||||
beforeAll(async () => {
|
||||
({ doctorCommand } = await import("./doctor.js"));
|
||||
});
|
||||
|
||||
it("warns when per-agent sandbox docker/browser/prune overrides are ignored under shared scope", async () => {
|
||||
mockDoctorConfigSnapshot({
|
||||
config: {
|
||||
@@ -34,7 +40,6 @@ describe("doctor command", () => {
|
||||
|
||||
note.mockClear();
|
||||
|
||||
const { doctorCommand } = await import("./doctor.js");
|
||||
await doctorCommand(createDoctorRuntime(), { nonInteractive: true });
|
||||
|
||||
expect(
|
||||
@@ -74,7 +79,6 @@ describe("doctor command", () => {
|
||||
return realExists(value as never);
|
||||
});
|
||||
|
||||
const { doctorCommand } = await import("./doctor.js");
|
||||
await doctorCommand(createDoctorRuntime(), { nonInteractive: true });
|
||||
|
||||
expect(note.mock.calls.some(([_, title]) => title === "Extra workspace")).toBe(false);
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { beforeAll, describe, expect, it } from "vitest";
|
||||
import { createDoctorRuntime, mockDoctorConfigSnapshot, note } from "./doctor.e2e-harness.js";
|
||||
|
||||
let doctorCommand: typeof import("./doctor.js").doctorCommand;
|
||||
|
||||
describe("doctor command", () => {
|
||||
beforeAll(async () => {
|
||||
({ doctorCommand } = await import("./doctor.js"));
|
||||
});
|
||||
|
||||
it("warns when the state directory is missing", async () => {
|
||||
mockDoctorConfigSnapshot();
|
||||
|
||||
@@ -13,7 +19,6 @@ describe("doctor command", () => {
|
||||
process.env.OPENCLAW_STATE_DIR = missingDir;
|
||||
note.mockClear();
|
||||
|
||||
const { doctorCommand } = await import("./doctor.js");
|
||||
await doctorCommand(createDoctorRuntime(), {
|
||||
nonInteractive: true,
|
||||
workspaceSuggestions: false,
|
||||
@@ -38,7 +43,6 @@ describe("doctor command", () => {
|
||||
},
|
||||
});
|
||||
|
||||
const { doctorCommand } = await import("./doctor.js");
|
||||
await doctorCommand(createDoctorRuntime(), {
|
||||
nonInteractive: true,
|
||||
workspaceSuggestions: false,
|
||||
@@ -63,7 +67,6 @@ describe("doctor command", () => {
|
||||
note.mockClear();
|
||||
|
||||
try {
|
||||
const { doctorCommand } = await import("./doctor.js");
|
||||
await doctorCommand(createDoctorRuntime(), {
|
||||
nonInteractive: true,
|
||||
workspaceSuggestions: false,
|
||||
|
||||
@@ -61,28 +61,6 @@ function createSelectAllMultiselect() {
|
||||
}
|
||||
|
||||
describe("promptDefaultModel", () => {
|
||||
it("filters internal router models from the selection list", async () => {
|
||||
loadModelCatalog.mockResolvedValue(OPENROUTER_CATALOG);
|
||||
|
||||
const select = vi.fn(async (params) => {
|
||||
const first = params.options[0];
|
||||
return first?.value ?? "";
|
||||
});
|
||||
const prompter = makePrompter({ select });
|
||||
const config = { agents: { defaults: {} } } as OpenClawConfig;
|
||||
|
||||
await promptDefaultModel({
|
||||
config,
|
||||
prompter,
|
||||
allowKeep: false,
|
||||
includeManual: false,
|
||||
ignoreAllowlist: true,
|
||||
});
|
||||
|
||||
const options = select.mock.calls[0]?.[0]?.options ?? [];
|
||||
expectRouterModelFiltering(options);
|
||||
});
|
||||
|
||||
it("supports configuring vLLM during onboarding", async () => {
|
||||
loadModelCatalog.mockResolvedValue([
|
||||
{
|
||||
@@ -133,21 +111,6 @@ describe("promptDefaultModel", () => {
|
||||
});
|
||||
|
||||
describe("promptModelAllowlist", () => {
|
||||
it("filters internal router models from the selection list", async () => {
|
||||
loadModelCatalog.mockResolvedValue(OPENROUTER_CATALOG);
|
||||
|
||||
const multiselect = createSelectAllMultiselect();
|
||||
const prompter = makePrompter({ multiselect });
|
||||
const config = { agents: { defaults: {} } } as OpenClawConfig;
|
||||
|
||||
await promptModelAllowlist({ config, prompter });
|
||||
|
||||
const call = multiselect.mock.calls[0]?.[0];
|
||||
const options = call?.options ?? [];
|
||||
expectRouterModelFiltering(options as Array<{ value: string }>);
|
||||
expect(call?.searchable).toBe(true);
|
||||
});
|
||||
|
||||
it("filters to allowed keys when provided", async () => {
|
||||
loadModelCatalog.mockResolvedValue([
|
||||
{
|
||||
@@ -184,6 +147,37 @@ describe("promptModelAllowlist", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("router model filtering", () => {
|
||||
it("filters internal router models in both default and allowlist prompts", async () => {
|
||||
loadModelCatalog.mockResolvedValue(OPENROUTER_CATALOG);
|
||||
|
||||
const select = vi.fn(async (params) => {
|
||||
const first = params.options[0];
|
||||
return first?.value ?? "";
|
||||
});
|
||||
const multiselect = createSelectAllMultiselect();
|
||||
const defaultPrompter = makePrompter({ select });
|
||||
const allowlistPrompter = makePrompter({ multiselect });
|
||||
const config = { agents: { defaults: {} } } as OpenClawConfig;
|
||||
|
||||
await promptDefaultModel({
|
||||
config,
|
||||
prompter: defaultPrompter,
|
||||
allowKeep: false,
|
||||
includeManual: false,
|
||||
ignoreAllowlist: true,
|
||||
});
|
||||
await promptModelAllowlist({ config, prompter: allowlistPrompter });
|
||||
|
||||
const defaultOptions = select.mock.calls[0]?.[0]?.options ?? [];
|
||||
expectRouterModelFiltering(defaultOptions);
|
||||
|
||||
const allowlistCall = multiselect.mock.calls[0]?.[0];
|
||||
expectRouterModelFiltering(allowlistCall?.options as Array<{ value: string }>);
|
||||
expect(allowlistCall?.searchable).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("applyModelAllowlist", () => {
|
||||
it("preserves existing entries for selected models", () => {
|
||||
const config = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const readConfigFileSnapshot = vi.fn();
|
||||
const writeConfigFile = vi.fn().mockResolvedValue(undefined);
|
||||
@@ -43,7 +43,15 @@ function expectWrittenPrimaryModel(model: string) {
|
||||
});
|
||||
}
|
||||
|
||||
let modelsSetCommand: typeof import("./models/set.js").modelsSetCommand;
|
||||
let modelsFallbacksAddCommand: typeof import("./models/fallbacks.js").modelsFallbacksAddCommand;
|
||||
|
||||
describe("models set + fallbacks", () => {
|
||||
beforeAll(async () => {
|
||||
({ modelsSetCommand } = await import("./models/set.js"));
|
||||
({ modelsFallbacksAddCommand } = await import("./models/fallbacks.js"));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
readConfigFileSnapshot.mockReset();
|
||||
writeConfigFile.mockClear();
|
||||
@@ -52,7 +60,6 @@ describe("models set + fallbacks", () => {
|
||||
it("normalizes z.ai provider in models set", async () => {
|
||||
mockConfigSnapshot({});
|
||||
const runtime = makeRuntime();
|
||||
const { modelsSetCommand } = await import("./models/set.js");
|
||||
|
||||
await modelsSetCommand("z.ai/glm-4.7", runtime);
|
||||
|
||||
@@ -62,7 +69,6 @@ describe("models set + fallbacks", () => {
|
||||
it("normalizes z-ai provider in models fallbacks add", async () => {
|
||||
mockConfigSnapshot({ agents: { defaults: { model: { fallbacks: [] } } } });
|
||||
const runtime = makeRuntime();
|
||||
const { modelsFallbacksAddCommand } = await import("./models/fallbacks.js");
|
||||
|
||||
await modelsFallbacksAddCommand("z-ai/glm-4.7", runtime);
|
||||
|
||||
@@ -79,7 +85,6 @@ describe("models set + fallbacks", () => {
|
||||
it("normalizes provider casing in models set", async () => {
|
||||
mockConfigSnapshot({});
|
||||
const runtime = makeRuntime();
|
||||
const { modelsSetCommand } = await import("./models/set.js");
|
||||
|
||||
await modelsSetCommand("Z.AI/glm-4.7", runtime);
|
||||
|
||||
|
||||
@@ -324,16 +324,6 @@ describe("applyMinimaxApiConfig", () => {
|
||||
expect(cfg.models?.providers?.minimax?.models[0]?.reasoning).toBe(false);
|
||||
});
|
||||
|
||||
it("preserves existing model fallbacks", () => {
|
||||
const cfg = applyMinimaxApiConfig(createConfigWithFallbacks());
|
||||
expectFallbacksPreserved(cfg);
|
||||
});
|
||||
|
||||
it("adds model alias", () => {
|
||||
const cfg = applyMinimaxApiConfig({}, "MiniMax-M2.1");
|
||||
expect(cfg.agents?.defaults?.models?.["minimax/MiniMax-M2.1"]?.alias).toBe("Minimax");
|
||||
});
|
||||
|
||||
it("preserves existing model params when adding alias", () => {
|
||||
const cfg = applyMinimaxApiConfig(
|
||||
{
|
||||
@@ -530,19 +520,9 @@ describe("applyXaiConfig", () => {
|
||||
});
|
||||
expect(cfg.agents?.defaults?.model?.primary).toBe(XAI_DEFAULT_MODEL_REF);
|
||||
});
|
||||
|
||||
it("preserves existing model fallbacks", () => {
|
||||
const cfg = applyXaiConfig(createConfigWithFallbacks());
|
||||
expectFallbacksPreserved(cfg);
|
||||
});
|
||||
});
|
||||
|
||||
describe("applyXaiProviderConfig", () => {
|
||||
it("adds model alias", () => {
|
||||
const cfg = applyXaiProviderConfig({});
|
||||
expect(cfg.agents?.defaults?.models?.[XAI_DEFAULT_MODEL_REF]?.alias).toBe("Grok");
|
||||
});
|
||||
|
||||
it("merges xAI models and keeps existing provider overrides", () => {
|
||||
const cfg = applyXaiProviderConfig(
|
||||
createLegacyProviderConfig({
|
||||
@@ -560,6 +540,37 @@ describe("applyXaiProviderConfig", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("fallback preservation helpers", () => {
|
||||
it("preserves existing model fallbacks", () => {
|
||||
const fallbackCases = [applyMinimaxApiConfig, applyXaiConfig] as const;
|
||||
for (const applyConfig of fallbackCases) {
|
||||
const cfg = applyConfig(createConfigWithFallbacks());
|
||||
expectFallbacksPreserved(cfg);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("provider alias defaults", () => {
|
||||
it("adds expected alias for provider defaults", () => {
|
||||
const aliasCases = [
|
||||
{
|
||||
applyConfig: () => applyMinimaxApiConfig({}, "MiniMax-M2.1"),
|
||||
modelRef: "minimax/MiniMax-M2.1",
|
||||
alias: "Minimax",
|
||||
},
|
||||
{
|
||||
applyConfig: () => applyXaiProviderConfig({}),
|
||||
modelRef: XAI_DEFAULT_MODEL_REF,
|
||||
alias: "Grok",
|
||||
},
|
||||
] as const;
|
||||
for (const testCase of aliasCases) {
|
||||
const cfg = testCase.applyConfig();
|
||||
expect(cfg.agents?.defaults?.models?.[testCase.modelRef]?.alias).toBe(testCase.alias);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("allowlist provider helpers", () => {
|
||||
it("adds allowlist entry and preserves alias", () => {
|
||||
const providerCases = [
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { setTimeout as delay } from "node:timers/promises";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { beforeAll, describe, expect, it } from "vitest";
|
||||
import { makeTempWorkspace } from "../test-helpers/workspace.js";
|
||||
import { withEnvAsync } from "../test-utils/env.js";
|
||||
import { MINIMAX_API_BASE_URL, MINIMAX_CN_API_BASE_URL } from "./onboard-auth.js";
|
||||
@@ -17,6 +17,8 @@ type OnboardEnv = {
|
||||
configPath: string;
|
||||
runtime: NonInteractiveRuntime;
|
||||
};
|
||||
let ensureAuthProfileStore: typeof import("../agents/auth-profiles.js").ensureAuthProfileStore;
|
||||
let upsertAuthProfile: typeof import("../agents/auth-profiles.js").upsertAuthProfile;
|
||||
|
||||
type ProviderAuthConfigSnapshot = {
|
||||
auth?: { profiles?: Record<string, { provider?: string; mode?: string }> };
|
||||
@@ -121,7 +123,6 @@ async function expectApiKeyProfile(params: {
|
||||
key: string;
|
||||
metadata?: Record<string, string>;
|
||||
}): Promise<void> {
|
||||
const { ensureAuthProfileStore } = await import("../agents/auth-profiles.js");
|
||||
const store = ensureAuthProfileStore();
|
||||
const profile = store.profiles[params.profileId];
|
||||
expect(profile?.type).toBe("api_key");
|
||||
@@ -135,6 +136,10 @@ async function expectApiKeyProfile(params: {
|
||||
}
|
||||
|
||||
describe("onboard (non-interactive): provider auth", () => {
|
||||
beforeAll(async () => {
|
||||
({ ensureAuthProfileStore, upsertAuthProfile } = await import("../agents/auth-profiles.js"));
|
||||
});
|
||||
|
||||
it("stores MiniMax API key and uses global baseUrl by default", async () => {
|
||||
await withOnboardEnv("openclaw-onboard-minimax-", async (env) => {
|
||||
const cfg = await runOnboardingAndReadConfig(env, {
|
||||
@@ -274,7 +279,6 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
expect(cfg.auth?.profiles?.["anthropic:default"]?.provider).toBe("anthropic");
|
||||
expect(cfg.auth?.profiles?.["anthropic:default"]?.mode).toBe("token");
|
||||
|
||||
const { ensureAuthProfileStore } = await import("../agents/auth-profiles.js");
|
||||
const store = ensureAuthProfileStore();
|
||||
const profile = store.profiles["anthropic:default"];
|
||||
expect(profile?.type).toBe("token");
|
||||
@@ -465,7 +469,6 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
await withOnboardEnv(
|
||||
"openclaw-onboard-custom-provider-profile-fallback-",
|
||||
async ({ configPath, runtime }) => {
|
||||
const { upsertAuthProfile } = await import("../agents/auth-profiles.js");
|
||||
upsertAuthProfile({
|
||||
profileId: `${CUSTOM_LOCAL_PROVIDER_ID}:default`,
|
||||
credential: {
|
||||
|
||||
@@ -49,6 +49,36 @@ function expectConfigUnchanged(
|
||||
expect(applied.next).toEqual(cfg);
|
||||
}
|
||||
|
||||
type SharedDefaultModelCase = {
|
||||
apply: (cfg: OpenClawConfig) => { changed: boolean; next: OpenClawConfig };
|
||||
defaultModel: string;
|
||||
overrideConfig: OpenClawConfig;
|
||||
alreadyDefaultConfig: OpenClawConfig;
|
||||
};
|
||||
|
||||
const SHARED_DEFAULT_MODEL_CASES: SharedDefaultModelCase[] = [
|
||||
{
|
||||
apply: applyGoogleGeminiModelDefault,
|
||||
defaultModel: GOOGLE_GEMINI_DEFAULT_MODEL,
|
||||
overrideConfig: {
|
||||
agents: { defaults: { model: { primary: "anthropic/claude-opus-4-5" } } },
|
||||
} as OpenClawConfig,
|
||||
alreadyDefaultConfig: {
|
||||
agents: { defaults: { model: { primary: GOOGLE_GEMINI_DEFAULT_MODEL } } },
|
||||
} as OpenClawConfig,
|
||||
},
|
||||
{
|
||||
apply: applyOpencodeZenModelDefault,
|
||||
defaultModel: OPENCODE_ZEN_DEFAULT_MODEL,
|
||||
overrideConfig: {
|
||||
agents: { defaults: { model: "anthropic/claude-opus-4-5" } },
|
||||
} as OpenClawConfig,
|
||||
alreadyDefaultConfig: {
|
||||
agents: { defaults: { model: OPENCODE_ZEN_DEFAULT_MODEL } },
|
||||
} as OpenClawConfig,
|
||||
},
|
||||
];
|
||||
|
||||
describe("applyDefaultModelChoice", () => {
|
||||
it("ensures allowlist entry exists when returning an agent override", async () => {
|
||||
const defaultModel = "vercel-ai-gateway/anthropic/claude-opus-4.6";
|
||||
@@ -109,27 +139,27 @@ describe("applyDefaultModelChoice", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("applyGoogleGeminiModelDefault", () => {
|
||||
it("sets gemini default when model is unset", () => {
|
||||
const cfg: OpenClawConfig = { agents: { defaults: {} } };
|
||||
const applied = applyGoogleGeminiModelDefault(cfg);
|
||||
expectPrimaryModelChanged(applied, GOOGLE_GEMINI_DEFAULT_MODEL);
|
||||
describe("shared default model behavior", () => {
|
||||
it("sets defaults when model is unset", () => {
|
||||
for (const testCase of SHARED_DEFAULT_MODEL_CASES) {
|
||||
const cfg: OpenClawConfig = { agents: { defaults: {} } };
|
||||
const applied = testCase.apply(cfg);
|
||||
expectPrimaryModelChanged(applied, testCase.defaultModel);
|
||||
}
|
||||
});
|
||||
|
||||
it("overrides existing model", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
agents: { defaults: { model: { primary: "anthropic/claude-opus-4-5" } } },
|
||||
};
|
||||
const applied = applyGoogleGeminiModelDefault(cfg);
|
||||
expectPrimaryModelChanged(applied, GOOGLE_GEMINI_DEFAULT_MODEL);
|
||||
it("overrides existing models", () => {
|
||||
for (const testCase of SHARED_DEFAULT_MODEL_CASES) {
|
||||
const applied = testCase.apply(testCase.overrideConfig);
|
||||
expectPrimaryModelChanged(applied, testCase.defaultModel);
|
||||
}
|
||||
});
|
||||
|
||||
it("no-ops when already gemini default", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
agents: { defaults: { model: { primary: GOOGLE_GEMINI_DEFAULT_MODEL } } },
|
||||
};
|
||||
const applied = applyGoogleGeminiModelDefault(cfg);
|
||||
expectConfigUnchanged(applied, cfg);
|
||||
it("no-ops when already on the target default", () => {
|
||||
for (const testCase of SHARED_DEFAULT_MODEL_CASES) {
|
||||
const applied = testCase.apply(testCase.alreadyDefaultConfig);
|
||||
expectConfigUnchanged(applied, testCase.alreadyDefaultConfig);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -200,28 +230,6 @@ describe("applyOpenAICodexModelDefault", () => {
|
||||
});
|
||||
|
||||
describe("applyOpencodeZenModelDefault", () => {
|
||||
it("sets opencode default when model is unset", () => {
|
||||
const cfg: OpenClawConfig = { agents: { defaults: {} } };
|
||||
const applied = applyOpencodeZenModelDefault(cfg);
|
||||
expectPrimaryModelChanged(applied, OPENCODE_ZEN_DEFAULT_MODEL);
|
||||
});
|
||||
|
||||
it("overrides existing model", () => {
|
||||
const cfg = {
|
||||
agents: { defaults: { model: "anthropic/claude-opus-4-5" } },
|
||||
} as OpenClawConfig;
|
||||
const applied = applyOpencodeZenModelDefault(cfg);
|
||||
expectPrimaryModelChanged(applied, OPENCODE_ZEN_DEFAULT_MODEL);
|
||||
});
|
||||
|
||||
it("no-ops when already opencode-zen default", () => {
|
||||
const cfg = {
|
||||
agents: { defaults: { model: OPENCODE_ZEN_DEFAULT_MODEL } },
|
||||
} as OpenClawConfig;
|
||||
const applied = applyOpencodeZenModelDefault(cfg);
|
||||
expectConfigUnchanged(applied, cfg);
|
||||
});
|
||||
|
||||
it("no-ops when already legacy opencode-zen default", () => {
|
||||
const cfg = {
|
||||
agents: { defaults: { model: "opencode-zen/claude-opus-4-5" } },
|
||||
|
||||
Reference in New Issue
Block a user