From 2a5c227199c08defdcefae3e1353aa8d8971ea93 Mon Sep 17 00:00:00 2001 From: Yichen Jiang Date: Wed, 16 Sep 2026 15:22:05 +0800 Subject: [PATCH] test(web): cover model draft and provider input defaults --- .../tests/model-list-catalog.client.spec.tsx | 27 +++++++++++++++++ .../tests/provider-form.client.spec.tsx | 29 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/packages/client/ui-settings-models/tests/model-list-catalog.client.spec.tsx b/packages/client/ui-settings-models/tests/model-list-catalog.client.spec.tsx index 66fc62bbc4..4a142ec8d5 100644 --- a/packages/client/ui-settings-models/tests/model-list-catalog.client.spec.tsx +++ b/packages/client/ui-settings-models/tests/model-list-catalog.client.spec.tsx @@ -54,3 +54,30 @@ it('uses provider input defaults for a model absent from the installed catalog', fireEvent.click(text) expect(onChange).toHaveBeenCalledWith([{ id: 'custom', input: ['text', 'image'] }]) }) + +it('inherits catalog inputs once an incomplete draft has a model id', async () => { + const onChange = vi.fn() + const props = { + onChange, catalogProvider: 'openai', + probe: { settingsNs: 'llm-pi-ai', provider: 'openai' }, + disabled: false, t: (key: keyof typeof en) => en[key], + operations: operations(() => Promise.resolve({ + kind: 'found', models: [{ id: 'vision', inputModalities: ['text', 'image'] }], + })), + } + const { rerender } = render() + fireEvent.click(screen.getByRole('button', { name: `${en.modelAdvanced} 1` })) + const image = screen.getByRole('checkbox', { name: en.modelInputImage }) + await waitFor(() => { expect(image.disabled).toBe(false) }) + expect(screen.getByRole('checkbox', { name: en.modelInputText }).checked).toBe(true) + expect(image.checked).toBe(false) + expect(onChange).not.toHaveBeenCalled() + + const id = screen.getByLabelText(`${en.modelId} 1`) + expect(id.value).toBe('') + fireEvent.change(id, { target: { value: 'vision' } }) + expect(onChange).toHaveBeenCalledExactlyOnceWith([{ id: 'vision' }]) + rerender() + expect(image.checked).toBe(true) + expect(onChange).toHaveBeenCalledTimes(1) +}) diff --git a/packages/client/ui-settings-models/tests/provider-form.client.spec.tsx b/packages/client/ui-settings-models/tests/provider-form.client.spec.tsx index cbf207605a..0659607e8d 100644 --- a/packages/client/ui-settings-models/tests/provider-form.client.spec.tsx +++ b/packages/client/ui-settings-models/tests/provider-form.client.spec.tsx @@ -522,6 +522,35 @@ describe('endpoint interrogation', () => { expect(mutate).not.toHaveBeenCalled() }) + it('inherits a custom provider default input and persists an explicit model override', async () => { + const { discover, mutate } = await mountSection({ + providers: { + 'acme-gateway': { + api: 'openai-completions', baseURL: 'https://gateway.acme.example/v1', + defaultInput: ['text', 'image'], models: [{ id: 'custom' }], + }, + }, + declaredRoutes: ['acme-gateway'], + }) + openEditor('acme-gateway') + expandModel(1) + const types = within(screen.getByRole('group', { name: `${en.modelInputTypes} 1` })) + expect(types.getByRole('checkbox', { name: en.modelInputText }).checked).toBe(true) + const image = types.getByRole('checkbox', { name: en.modelInputImage }) + expect(image.checked).toBe(true) + expect(image.disabled).toBe(false) + expect(discover).not.toHaveBeenCalled() + expect(mutate).not.toHaveBeenCalled() + + fireEvent.click(image) + fireEvent.click(screen.getByText(en.apply)) + await waitFor(() => { expect(mutate).toHaveBeenCalledTimes(1) }) + expect(firstMutate(mutate).ops).toEqual([{ + op: 'set', path: ['providers', 'acme-gateway', 'models'], + value: [{ id: 'custom', input: ['text'] }], + }]) + }) + it('asks the endpoint the form shows, with a key that is not yet stored', async () => { const discover = vi.fn(() => Promise.resolve(ok([{ id: 'acme-large', contextWindow: 65_536 }]))) await mountSection({ discover })