import { describe, it, expect, vi } from 'vitest'; import { apply as applyHost } from '../src/index'; import * as clientModule from '../src/client/index'; import { ENHANCER_CSS } from '../src/client/styles'; import React from 'react'; describe('Host plugin', () => { it('registers models dev exact proxy route', () => { const registerMock = vi.fn(); const mockCtx = { effect: (fn: any) => fn(), webServer: { register: registerMock, }, }; applyHost(mockCtx as any); expect(registerMock).toHaveBeenCalled(); const callArg = registerMock.mock.calls[0][0]; expect(callArg.path).toBe('/api/models-dev/models'); expect(callArg.kind).toBe('exact'); }); }); describe('Client plugin contracts', () => { it('registers settings extension slots only and leaves model selection untouched', async () => { const registeredSlots: string[] = []; const registeredEntries: any[] = []; const mockScope = { slots: { inject: (slotName: string, cb: any) => { registeredSlots.push(slotName); cb(); }, register: vi.fn((def: any, component: any) => { registeredEntries.push({ def, component }); return def; }), } }; const mockCtx = { inject: vi.fn((deps: string[], cb: any) => { cb(mockScope); }), get: vi.fn(), }; clientModule.apply(mockCtx as any); // Verify slots registered expect(registeredSlots).toContain('settings.models.footer'); expect(registeredSlots).toContain('settings.models.provider-card'); // Ensure no composer / model-selection slots are registered expect(registeredSlots).not.toContain('conversation.input.right'); expect(registeredSlots).not.toContain('conversation.input.model'); // Verify footer registration definition const footerEntry = registeredEntries.find(e => e.def.name === 'settings.models.footer'); expect(footerEntry).toBeDefined(); expect(footerEntry.def.id).toBe('me-models-footer'); // Verify provider card registration definition const cardEntry = registeredEntries.find(e => e.def.name === 'settings.models.provider-card'); expect(cardEntry).toBeDefined(); expect(cardEntry.def.key).toBe('llm-pi-ai'); }); it('ENHANCER_CSS contains only non-selector settings styles', () => { expect(ENHANCER_CSS).toContain('.me-footer-card'); expect(ENHANCER_CSS).toContain('.me-footer-title'); expect(ENHANCER_CSS).toContain('.me-diff-table'); // Ensure no selector styles or hide rules remain expect(ENHANCER_CSS).not.toContain('me-compact'); expect(ENHANCER_CSS).not.toContain('me-slider'); expect(ENHANCER_CSS).not.toContain('me-effort'); expect(ENHANCER_CSS).not.toContain('display: none'); }); });