tts-voice-creator-clone-and.../tests/conversation-llm-picker.spec.js
2026-10-06 00:33:30 +02:00

77 lines
4.3 KiB
JavaScript

// @ts-check
// Conversation Playground LLM endpoint picker (all /api routes mocked).
const { test, expect } = require('./_guard');
const CONTAINERS = { containers: [
{ name: 'ollama', label: 'Ollama', role: 'llm', port: 11434, status: 'running' },
{ name: 'vllm', label: 'vLLM', role: 'llm', port: 8000, status: 'exited' },
{ name: 'ghost', label: 'Ghost', role: 'llm', port: 1, status: 'not_found' },
{ name: 'kokoro-tts', label: 'Kokoro', role: 'tts', port: 8880, status: 'running' },
] };
async function boot(page, settings, containers = CONTAINERS) {
/** @type {any[]} */ const patches = [];
/** @type {string[]} */ const modelReqs = [];
await page.route('**/api/**', route => route.request().method() === 'GET' ? route.fulfill({ json: {} }) : route.fulfill({ json: { ok: true } }));
await page.route('**/api/local-containers*', route => route.fulfill({ json: containers }));
await page.route('**/api/conversation/llm-models*', route => { modelReqs.push(route.request().url()); return route.fulfill({ json: { models: ['m1'] } }); });
await page.route('**/api/settings', route => {
if (route.request().method() === 'GET') return route.fulfill({ json: settings });
patches.push(route.request().postDataJSON());
return route.fulfill({ json: { ok: true } });
});
await page.route('**/static/dist/main.min.js*', r => r.abort());
await page.goto('/', { waitUntil: 'domcontentloaded' });
await page.waitForFunction(() => typeof window.navTo === 'function', null, { timeout: 15_000 });
await page.waitForSelector('#app-skeleton', { state: 'detached', timeout: 15_000 });
await page.evaluate(() => window.navTo('s-conversation'));
return { patches, modelReqs };
}
test('lists configured endpoints, picking one saves it and fetches models', async ({ page }) => {
const { patches, modelReqs } = await boot(page, {});
const pick = page.locator('#conv-llm-endpoint');
await expect(pick.locator('option')).toHaveCount(3);
await expect(pick.locator('option').nth(0)).toContainText('Ollama');
await expect(pick.locator('option').nth(0)).toContainText('http://host.docker.internal:11434/v1');
await expect(pick.locator('option').nth(1)).toContainText('✗');
const box = await pick.boundingBox();
expect(box && box.height).toBeGreaterThanOrEqual(44);
await pick.selectOption({ index: 1 });
await expect(page.locator('#conv-llm-url')).toBeHidden();
await expect.poll(() => patches.some(p => p && p.conv_llm_url === 'http://host.docker.internal:8000/v1')).toBe(true);
await expect.poll(() => modelReqs.some(u => u.includes(encodeURIComponent('http://host.docker.internal:8000/v1')))).toBe(true);
await expect(page.locator('#conv-llm-model-select')).toContainText('m1');
});
test('saved matching URL preselects its entry and hides the input', async ({ page }) => {
await boot(page, { conv_llm_url: 'http://host.docker.internal:11434/v1' });
await expect(page.locator('#conv-llm-endpoint')).toHaveValue('http://host.docker.internal:11434/v1');
await expect(page.locator('#conv-llm-url')).toBeHidden();
});
test('saved custom URL preselects Custom', async ({ page }) => {
await boot(page, { conv_llm_url: 'http://192.168.178.8:17861/v1' });
await expect(page.locator('#conv-llm-endpoint')).toHaveValue('__custom__');
await expect(page.locator('#conv-llm-url')).toBeVisible();
await expect(page.locator('#conv-llm-url')).toHaveValue('http://192.168.178.8:17861/v1');
});
test('Custom… reveals the input right after the select and focuses it', async ({ page }) => {
await boot(page, { conv_llm_url: 'http://host.docker.internal:11434/v1' });
await page.locator('#conv-llm-endpoint').selectOption('__custom__');
const inp = page.getByRole('textbox', { name: 'Custom LLM base URL' });
await expect(inp).toBeFocused();
expect(await page.evaluate(() => document.getElementById('conv-llm-endpoint').nextElementSibling.id)).toBe('conv-llm-url');
});
test('empty list shows only Custom… and the hint linking to Engines', async ({ page }) => {
await boot(page, {}, { containers: [] });
await expect(page.locator('#conv-llm-endpoint option')).toHaveCount(1);
await expect(page.locator('#conv-llm-url')).toBeVisible();
const hint = page.locator('#conv-llm-empty-hint a');
await expect(hint).toBeVisible();
await hint.click();
await expect(page.locator('#s-llms')).toBeVisible();
});