From 15c8df4c78095bbc831fd02a5dc1feca2245afe3 Mon Sep 17 00:00:00 2001 From: Randi <55005611+rdself@users.noreply.github.com> Date: Mon, 15 Jun 2026 18:49:48 -0400 Subject: [PATCH] Fix failed model auto-hide defaults (#3930) Integrated into release/v3.8.26 --- .../useModelVisibilityHandlers.test.tsx | 121 ++++++++++++++++++ .../providers/[id]/components/ModelRow.tsx | 9 +- .../components/PassthroughModelsSection.tsx | 2 +- .../[id]/hooks/useModelVisibilityHandlers.ts | 33 ++--- src/i18n/messages/en.json | 1 + src/i18n/messages/zh-CN.json | 1 + 6 files changed, 146 insertions(+), 21 deletions(-) create mode 100644 src/app/(dashboard)/dashboard/providers/[id]/__tests__/useModelVisibilityHandlers.test.tsx diff --git a/src/app/(dashboard)/dashboard/providers/[id]/__tests__/useModelVisibilityHandlers.test.tsx b/src/app/(dashboard)/dashboard/providers/[id]/__tests__/useModelVisibilityHandlers.test.tsx new file mode 100644 index 0000000000..eb5a42a23a --- /dev/null +++ b/src/app/(dashboard)/dashboard/providers/[id]/__tests__/useModelVisibilityHandlers.test.tsx @@ -0,0 +1,121 @@ +// @vitest-environment jsdom +import React, { act } from "react"; +import { createRoot } from "react-dom/client"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +import { + useModelVisibilityHandlers, + type UseModelVisibilityHandlersReturn, +} from "../hooks/useModelVisibilityHandlers"; + +type HookResult = UseModelVisibilityHandlersReturn; + +const t = ((key: string) => key) as ((key: string) => string) & { + has: (key: string) => boolean; +}; +t.has = () => false; + +const notify = { + success: vi.fn(), + error: vi.fn(), + warning: vi.fn(), + info: vi.fn(), +}; + +const baseProps = { + providerId: "anthropic-compatible-cc-test", + modelAliases: {}, + customMap: new Map(), + providerStorageAlias: "anthropic-compatible-cc-test", + fetchProviderModelMeta: vi.fn().mockResolvedValue(undefined), + fetchAliases: vi.fn().mockResolvedValue(undefined), + notify, + t, + selectedConnection: { id: "conn-1", provider: "anthropic-compatible-cc-test" }, + providerNode: { id: "anthropic-compatible-cc-test" }, +}; + +function renderHook(): { get: () => HookResult } { + let latestResult: HookResult | null = null; + + function Wrapper() { + const result = useModelVisibilityHandlers(baseProps); + React.useEffect(() => { + latestResult = result; + }); + return null; + } + + const el = document.createElement("div"); + document.body.appendChild(el); + const root = createRoot(el); + + act(() => { + root.render(); + }); + + roots.push({ root, el }); + + return { + get: () => { + if (!latestResult) throw new Error("Hook did not render"); + return latestResult; + }, + }; +} + +const roots: Array<{ root: ReturnType; el: HTMLDivElement }> = []; + +beforeEach(() => { + ( + globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean } + ).IS_REACT_ACT_ENVIRONMENT = true; + vi.stubGlobal("fetch", vi.fn()); + vi.clearAllMocks(); +}); + +afterEach(() => { + for (const { root, el } of roots.splice(0)) { + act(() => root.unmount()); + el.remove(); + } + vi.unstubAllGlobals(); +}); + +describe("useModelVisibilityHandlers", () => { + it("defaults auto-hide failed models to off", () => { + const hook = renderHook(); + + expect(hook.get().autoHideFailed).toBe(false); + }); + + it("does not hide a model when a single-model test fails", async () => { + const fetchMock = vi.mocked(fetch); + fetchMock.mockResolvedValueOnce({ + ok: false, + json: () => + Promise.resolve({ + status: "error", + error: "model unavailable", + }), + } as Response); + + const hook = renderHook(); + + await act(async () => { + await hook + .get() + .onTestModel("claude-opus-4-8", "anthropic-compatible-cc-test/claude-opus-4-8"); + }); + + expect(fetchMock).toHaveBeenCalledTimes(1); + expect(fetchMock).toHaveBeenCalledWith( + "/api/models/test", + expect.objectContaining({ method: "POST" }) + ); + expect( + fetchMock.mock.calls.some(([url]) => String(url).startsWith("/api/provider-models")) + ).toBe(false); + expect(hook.get().modelTestStatus["claude-opus-4-8"]).toBe("error"); + }); +}); diff --git a/src/app/(dashboard)/dashboard/providers/[id]/components/ModelRow.tsx b/src/app/(dashboard)/dashboard/providers/[id]/components/ModelRow.tsx index 1b51365760..c73ef5917a 100644 --- a/src/app/(dashboard)/dashboard/providers/[id]/components/ModelRow.tsx +++ b/src/app/(dashboard)/dashboard/providers/[id]/components/ModelRow.tsx @@ -149,7 +149,14 @@ export function ModelVisibilityToolbar({ )} {onAutoHideFailedChange && ( -