test: cover provider-filtered catalog fast path

This commit is contained in:
Shakker
2026-04-24 04:19:12 +01:00
committed by Shakker
parent a50aef82ba
commit 29d0e930bb
2 changed files with 38 additions and 0 deletions

View File

@@ -62,6 +62,7 @@ const mocks = vi.hoisted(() => {
loadModelRegistry: vi.fn(),
loadModelCatalog: vi.fn(),
loadProviderCatalogModelsForList: vi.fn(),
hasProviderStaticCatalogForFilter: vi.fn(),
resolveConfiguredEntries: vi.fn(),
printModelTable: vi.fn(),
listProfilesForProvider: vi.fn(),
@@ -88,6 +89,7 @@ function resetMocks() {
});
mocks.loadModelCatalog.mockResolvedValue([]);
mocks.loadProviderCatalogModelsForList.mockResolvedValue([]);
mocks.hasProviderStaticCatalogForFilter.mockResolvedValue(false);
mocks.resolveConfiguredEntries.mockReturnValue({
entries: [
{
@@ -141,6 +143,10 @@ function installModelsListCommandForwardCompatMocks() {
printModelTable: mocks.printModelTable,
}));
vi.doMock("./list.provider-catalog.js", () => ({
hasProviderStaticCatalogForFilter: mocks.hasProviderStaticCatalogForFilter,
}));
vi.doMock("./list.registry-load.js", () => ({
loadListModelRegistry: async (
cfg: unknown,
@@ -427,6 +433,7 @@ describe("modelsListCommand forward-compat", () => {
describe("--all catalog supplementation", () => {
it("uses the provider catalog fast path for Codex provider lists", async () => {
mocks.resolveConfiguredEntries.mockReturnValueOnce({ entries: [] });
mocks.hasProviderStaticCatalogForFilter.mockResolvedValueOnce(true);
mocks.loadProviderCatalogModelsForList.mockResolvedValueOnce([
{
provider: "codex",
@@ -451,6 +458,7 @@ describe("modelsListCommand forward-compat", () => {
cfg: mocks.resolvedConfig,
agentDir: "/tmp/openclaw-agent",
providerFilter: "codex",
staticOnly: true,
});
expect(lastPrintedRows<{ key: string; available: boolean }>()).toEqual([
expect.objectContaining({
@@ -460,6 +468,21 @@ describe("modelsListCommand forward-compat", () => {
]);
});
it("keeps the registry path for provider filters without static catalog coverage", async () => {
mocks.resolveConfiguredEntries.mockReturnValueOnce({ entries: [] });
mocks.hasProviderStaticCatalogForFilter.mockResolvedValueOnce(false);
const runtime = createRuntime();
await modelsListCommand({ all: true, provider: "openrouter", json: true }, runtime as never);
expect(mocks.loadModelRegistry).toHaveBeenCalledWith(
mocks.resolvedConfig,
expect.objectContaining({
providerFilter: "openrouter",
}),
);
});
it("includes synthetic codex gpt-5.4 in --all output when catalog supports it", async () => {
mocks.resolveConfiguredEntries.mockReturnValueOnce({ entries: [] });
mocks.loadModelRegistry.mockResolvedValueOnce({

View File

@@ -135,6 +135,21 @@ describe("loadProviderCatalogModelsForList", () => {
);
});
it("requires complete discovery-entry coverage for static-only loads", async () => {
await loadProviderCatalogModelsForList({
...baseParams,
providerFilter: "moonshot",
staticOnly: true,
});
expect(providerDiscoveryMocks.resolvePluginDiscoveryProviders).toHaveBeenCalledWith(
expect.objectContaining({
onlyPluginIds: ["moonshot"],
requireCompleteDiscoveryEntryCoverage: true,
}),
);
});
it("recognizes bundled provider hook aliases before the unknown-provider short-circuit", async () => {
await expect(
resolveProviderCatalogPluginIdsForFilter({