From 911db3e8c5b9c251ac530985e65be05f25ffc61f Mon Sep 17 00:00:00 2001 From: "[._.]/ Adam Eivy" Date: Wed, 9 Sep 2026 14:47:44 +0000 Subject: [PATCH 1/3] fix: read embedding models from public status (#6703) --- .../src/components/settings/EmbeddingsTab.jsx | 4 +-- .../settings/EmbeddingsTab.test.jsx | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 client/src/components/settings/EmbeddingsTab.test.jsx diff --git a/client/src/components/settings/EmbeddingsTab.jsx b/client/src/components/settings/EmbeddingsTab.jsx index 9cb37d5b78..f03d5d9bcd 100644 --- a/client/src/components/settings/EmbeddingsTab.jsx +++ b/client/src/components/settings/EmbeddingsTab.jsx @@ -39,8 +39,8 @@ export default function EmbeddingsTab() { setModelsLoading(true); const status = await getLocalLlmStatus({ silent: true }).catch(() => null); setModels({ - ollama: (status?.ollama?.installedModels || []).map((m) => m.id || m.name), - lmstudio: (status?.lmstudio?.installedModels || []).map((m) => m.id || m.name), + ollama: (status?.ollama?.models || []).map((m) => m.id || m.name), + lmstudio: (status?.lmstudio?.models || []).map((m) => m.id || m.name), }); setModelsLoading(false); }; diff --git a/client/src/components/settings/EmbeddingsTab.test.jsx b/client/src/components/settings/EmbeddingsTab.test.jsx new file mode 100644 index 0000000000..8acc7d1bdc --- /dev/null +++ b/client/src/components/settings/EmbeddingsTab.test.jsx @@ -0,0 +1,27 @@ +import { describe, expect, it, vi } from 'vitest'; +import { render, screen, waitFor } from '@testing-library/react'; +import { MemoryRouter } from 'react-router'; + +vi.mock('../../services/apiSystem', () => ({ + getSettings: vi.fn().mockResolvedValue({ embeddings: { provider: 'ollama', model: '' } }), + updateSettings: vi.fn(), +})); +vi.mock('../../services/apiLocalLlm', () => ({ + getLocalLlmStatus: vi.fn().mockResolvedValue({ + ollama: { models: [{ id: 'nomic-embed-text' }] }, + lmstudio: { models: [] }, + }), +})); +vi.mock('../ui/Toast', () => ({ + default: Object.assign(vi.fn(), { success: vi.fn(), error: vi.fn() }), +})); + +import EmbeddingsTab from './EmbeddingsTab.jsx'; + +describe('EmbeddingsTab', () => { + it('reads installed embedding choices from the public models field', async () => { + render(); + + await waitFor(() => expect(screen.getByRole('option', { name: 'nomic-embed-text' })).toBeInTheDocument()); + }); +}); From 0e81bf58040c32dd295437bea7a40bb40ed70b28 Mon Sep 17 00:00:00 2001 From: "[._.]/ Adam Eivy" Date: Wed, 9 Sep 2026 14:49:49 +0000 Subject: [PATCH 2/3] test: cover embedding model refresh responses (#6703) --- .../components/settings/EmbeddingsTab.test.jsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/client/src/components/settings/EmbeddingsTab.test.jsx b/client/src/components/settings/EmbeddingsTab.test.jsx index 8acc7d1bdc..63a112bb42 100644 --- a/client/src/components/settings/EmbeddingsTab.test.jsx +++ b/client/src/components/settings/EmbeddingsTab.test.jsx @@ -1,5 +1,5 @@ import { describe, expect, it, vi } from 'vitest'; -import { render, screen, waitFor } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { MemoryRouter } from 'react-router'; vi.mock('../../services/apiSystem', () => ({ @@ -7,10 +7,9 @@ vi.mock('../../services/apiSystem', () => ({ updateSettings: vi.fn(), })); vi.mock('../../services/apiLocalLlm', () => ({ - getLocalLlmStatus: vi.fn().mockResolvedValue({ - ollama: { models: [{ id: 'nomic-embed-text' }] }, - lmstudio: { models: [] }, - }), + getLocalLlmStatus: vi.fn() + .mockResolvedValueOnce({ ollama: { models: [{ id: 'custom-embed:latest' }] }, lmstudio: { models: [] } }) + .mockResolvedValueOnce({ ollama: { models: [] }, lmstudio: { models: [{ id: 'example/custom-embedding' }] } }), })); vi.mock('../ui/Toast', () => ({ default: Object.assign(vi.fn(), { success: vi.fn(), error: vi.fn() }), @@ -19,9 +18,14 @@ vi.mock('../ui/Toast', () => ({ import EmbeddingsTab from './EmbeddingsTab.jsx'; describe('EmbeddingsTab', () => { - it('reads installed embedding choices from the public models field', async () => { + it('reads installed embedding choices from the public models field for both backends', async () => { render(); - await waitFor(() => expect(screen.getByRole('option', { name: 'nomic-embed-text' })).toBeInTheDocument()); + const datalist = () => document.getElementById('embeddings-model-options'); + await waitFor(() => expect(datalist().querySelector('option[value="custom-embed:latest"]')).toBeTruthy()); + + fireEvent.change(screen.getByLabelText('Provider'), { target: { value: 'lmstudio' } }); + fireEvent.click(screen.getByRole('button', { name: 'Refresh' })); + await waitFor(() => expect(datalist().querySelector('option[value="example/custom-embedding"]')).toBeTruthy()); }); }); From c553fbd79a1528c92ee9370ca5be0f07b741591b Mon Sep 17 00:00:00 2001 From: "[._.]/ Adam Eivy" Date: Wed, 9 Sep 2026 14:51:36 +0000 Subject: [PATCH 3/3] test: cover empty embedding model refresh (#6703) --- client/src/components/settings/EmbeddingsTab.test.jsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/src/components/settings/EmbeddingsTab.test.jsx b/client/src/components/settings/EmbeddingsTab.test.jsx index 63a112bb42..8a47b442ee 100644 --- a/client/src/components/settings/EmbeddingsTab.test.jsx +++ b/client/src/components/settings/EmbeddingsTab.test.jsx @@ -9,6 +9,7 @@ vi.mock('../../services/apiSystem', () => ({ vi.mock('../../services/apiLocalLlm', () => ({ getLocalLlmStatus: vi.fn() .mockResolvedValueOnce({ ollama: { models: [{ id: 'custom-embed:latest' }] }, lmstudio: { models: [] } }) + .mockResolvedValueOnce({ ollama: { models: [] }, lmstudio: { models: [] } }) .mockResolvedValueOnce({ ollama: { models: [] }, lmstudio: { models: [{ id: 'example/custom-embedding' }] } }), })); vi.mock('../ui/Toast', () => ({ @@ -24,6 +25,12 @@ describe('EmbeddingsTab', () => { const datalist = () => document.getElementById('embeddings-model-options'); await waitFor(() => expect(datalist().querySelector('option[value="custom-embed:latest"]')).toBeTruthy()); + fireEvent.click(screen.getByRole('button', { name: 'Refresh' })); + await waitFor(() => expect(datalist().querySelector('option[value="custom-embed:latest"]')).toBeFalsy()); + expect(datalist().querySelector('option[value="nomic-embed-text"]')).toBeTruthy(); + fireEvent.change(screen.getByLabelText('Model'), { target: { value: 'manual-embedding-model' } }); + expect(screen.getByLabelText('Model')).toHaveValue('manual-embedding-model'); + fireEvent.change(screen.getByLabelText('Provider'), { target: { value: 'lmstudio' } }); fireEvent.click(screen.getByRole('button', { name: 'Refresh' })); await waitFor(() => expect(datalist().querySelector('option[value="example/custom-embedding"]')).toBeTruthy());