import { describe, expect, it } from 'vitest'; import { dispatchHostApiRequest } from '@electron/api/host-api-dispatcher'; import { shouldUseLoopbackHostApi } from '@electron/api/host-api-transport'; describe('Host API transport selection', () => { it('keeps long-lived and binary responses on loopback HTTP', () => { expect(shouldUseLoopbackHostApi('/api/events')).toBe(true); expect(shouldUseLoopbackHostApi('/api/events?token=session')).toBe(true); expect(shouldUseLoopbackHostApi('/api/coding/events')).toBe(true); expect(shouldUseLoopbackHostApi('/api/ai-proxy/v1/chat/completions', 'POST')).toBe(true); expect(shouldUseLoopbackHostApi('/api/image-workspace/workspaces/w1/conversations/c1/events')).toBe(true); expect(shouldUseLoopbackHostApi('/api/image-workspace/workspaces/w1/assets/a1/content?download=1')).toBe(true); }); it('dispatches JSON and control requests in Main', () => { expect(shouldUseLoopbackHostApi('/api/app/runtime-info')).toBe(false); expect(shouldUseLoopbackHostApi('/api/works/projects/release-jobs', 'POST')).toBe(false); expect(shouldUseLoopbackHostApi('/api/coding/projects')).toBe(false); }); it('reuses the existing route contract without opening a socket', async () => { const data = await dispatchHostApiRequest({ codingProducts: { runtime: { getDiagnostics: () => ({ revision: 3 }) } }, codingProjectStore: {}, eventBus: {}, mainWindow: null, } as never, { path: '/api/app/runtime-info' }); expect(data).toMatchObject({ status: 200, ok: true }); expect(data.json).toMatchObject({ runtime: 'pi', diagnostics: { revision: 3 } }); }); it('leaves the retired Learning Host API unregistered', async () => { const data = await dispatchHostApiRequest({} as never, { path: '/api/works/learning/projects', }); expect(data).toMatchObject({ status: 404, ok: false, json: { success: false, error: 'No route for GET /api/works/learning/projects', }, }); }); });