mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:00:42 +00:00
test: cover default models list registry narrowing
This commit is contained in:
@@ -27,6 +27,7 @@ const modelRegistryState = {
|
||||
available: [] as Array<Record<string, unknown>>,
|
||||
getAllError: undefined as unknown,
|
||||
getAvailableError: undefined as unknown,
|
||||
findError: undefined as unknown,
|
||||
};
|
||||
let previousExitCode: typeof process.exitCode;
|
||||
|
||||
@@ -46,6 +47,9 @@ vi.mock("./models/load-config.js", () => ({
|
||||
vi.mock("./models/list.runtime.js", () => {
|
||||
class MockModelRegistry {
|
||||
find(provider: string, id: string) {
|
||||
if (modelRegistryState.findError !== undefined) {
|
||||
throw modelRegistryState.findError;
|
||||
}
|
||||
return (
|
||||
modelRegistryState.models.find((model) => model.provider === provider && model.id === id) ??
|
||||
null
|
||||
@@ -65,6 +69,12 @@ vi.mock("./models/list.runtime.js", () => {
|
||||
}
|
||||
return modelRegistryState.available;
|
||||
}
|
||||
|
||||
hasConfiguredAuth(model: { provider: string; id: string }) {
|
||||
return modelRegistryState.available.some(
|
||||
(available) => available.provider === model.provider && available.id === model.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -133,6 +143,7 @@ beforeEach(() => {
|
||||
process.exitCode = undefined;
|
||||
modelRegistryState.getAllError = undefined;
|
||||
modelRegistryState.getAvailableError = undefined;
|
||||
modelRegistryState.findError = undefined;
|
||||
getRuntimeConfig.mockReset();
|
||||
getRuntimeConfig.mockReturnValue({});
|
||||
listProfilesForProvider.mockReturnValue([]);
|
||||
@@ -390,22 +401,27 @@ describe("models list/status", () => {
|
||||
expect(loadProviderCatalogModelsForList).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("models list does not treat availability-unavailable code as discovery fallback", async () => {
|
||||
it("models list default does not enumerate all registry models", async () => {
|
||||
configureGoogleAntigravityModel("claude-opus-4-6-thinking");
|
||||
modelRegistryState.models = [
|
||||
makeGoogleAntigravityTemplate("claude-opus-4-6-thinking", "Claude Opus 4.6 Thinking"),
|
||||
];
|
||||
modelRegistryState.available = modelRegistryState.models;
|
||||
modelRegistryState.getAllError = Object.assign(new Error("model discovery failed"), {
|
||||
code: "MODEL_AVAILABILITY_UNAVAILABLE",
|
||||
});
|
||||
const runtime = makeRuntime();
|
||||
await modelsListCommand({ json: true }, runtime);
|
||||
|
||||
expectModelRegistryUnavailable(runtime, "model discovery failed");
|
||||
expect(runtime.error.mock.calls[0]?.[0]).not.toContain("configured models may appear missing");
|
||||
expect(runtime.error).not.toHaveBeenCalled();
|
||||
const payload = parseJsonLog(runtime);
|
||||
expect(payload.models[0]?.key).toBe("google-antigravity/claude-opus-4-6-thinking");
|
||||
});
|
||||
|
||||
it("models list fails fast when registry model discovery is unavailable", async () => {
|
||||
it("models list fails fast when configured registry lookup is unavailable", async () => {
|
||||
configureGoogleAntigravityModel("claude-opus-4-6-thinking");
|
||||
enableGoogleAntigravityAuthProfile();
|
||||
modelRegistryState.getAllError = Object.assign(new Error("model discovery unavailable"), {
|
||||
modelRegistryState.findError = Object.assign(new Error("model discovery unavailable"), {
|
||||
code: "MODEL_DISCOVERY_UNAVAILABLE",
|
||||
});
|
||||
const runtime = makeRuntime();
|
||||
|
||||
@@ -141,6 +141,43 @@ function installModelsListCommandForwardCompatMocks() {
|
||||
printModelTable: mocks.printModelTable,
|
||||
}));
|
||||
|
||||
vi.doMock("./list.registry-load.js", () => ({
|
||||
loadListModelRegistry: async (
|
||||
cfg: unknown,
|
||||
opts?: { providerFilter?: string },
|
||||
): Promise<{
|
||||
models: Array<{ provider: string; id: string }>;
|
||||
availableKeys?: Set<string>;
|
||||
registry?: unknown;
|
||||
discoveredKeys: Set<string>;
|
||||
}> => {
|
||||
const loaded = await mocks.loadModelRegistry(cfg, opts);
|
||||
return {
|
||||
...loaded,
|
||||
discoveredKeys: new Set(
|
||||
loaded.models.map(
|
||||
(model: { provider: string; id: string }) => `${model.provider}/${model.id}`,
|
||||
),
|
||||
),
|
||||
};
|
||||
},
|
||||
loadConfiguredListModelRegistry: (
|
||||
_cfg: unknown,
|
||||
_entries: unknown,
|
||||
opts?: { providerFilter?: string },
|
||||
) => {
|
||||
mocks.loadModelRegistry(mocks.resolvedConfig, opts);
|
||||
return {
|
||||
registry: {
|
||||
find: () => undefined,
|
||||
hasConfiguredAuth: () => false,
|
||||
},
|
||||
discoveredKeys: new Set(),
|
||||
availableKeys: new Set(),
|
||||
};
|
||||
},
|
||||
}));
|
||||
|
||||
vi.doMock("./list.runtime.js", () => ({
|
||||
ensureOpenClawModelsJson: mocks.ensureOpenClawModelsJson,
|
||||
ensureAuthProfileStore: mocks.ensureAuthProfileStore,
|
||||
@@ -363,7 +400,7 @@ describe("modelsListCommand forward-compat", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("exits with an error when configured-mode listing has no model registry", async () => {
|
||||
it("does not require the all-model registry result for configured-mode listing", async () => {
|
||||
const previousExitCode = process.exitCode;
|
||||
process.exitCode = undefined;
|
||||
mocks.loadModelRegistry.mockResolvedValueOnce({
|
||||
@@ -381,9 +418,9 @@ describe("modelsListCommand forward-compat", () => {
|
||||
process.exitCode = previousExitCode;
|
||||
}
|
||||
|
||||
expect(runtime.error).toHaveBeenCalledWith("Model registry unavailable.");
|
||||
expect(observedExitCode).toBe(1);
|
||||
expect(mocks.printModelTable).not.toHaveBeenCalled();
|
||||
expect(runtime.error).not.toHaveBeenCalled();
|
||||
expect(observedExitCode).toBeUndefined();
|
||||
expect(mocks.printModelTable).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user