Files
TREK/server/tests/unit/nest/llm-parse/llm-local.service.test.ts
T
2026-06-24 18:45:52 +02:00

61 lines
2.4 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { HttpException } from '@nestjs/common';
import { LlmLocalService } from '../../../../src/nest/llm-parse/llm-local.service';
const svc = () => new LlmLocalService();
function mockFetch(impl: any) {
const fn = vi.fn(impl);
vi.stubGlobal('fetch', fn);
return fn;
}
beforeEach(() => vi.unstubAllGlobals());
describe('LlmLocalService.ollamaRoot', () => {
it('strips a trailing /v1 and slashes', () => {
expect(svc().ollamaRoot('http://localhost:11434/v1')).toBe('http://localhost:11434');
expect(svc().ollamaRoot('http://localhost:11434/v1/')).toBe('http://localhost:11434');
expect(svc().ollamaRoot('http://host:1/')).toBe('http://host:1');
});
it('defaults when no base URL is given', () => {
expect(svc().ollamaRoot(undefined)).toBe('http://localhost:11434');
});
it('rejects non-http(s) and invalid URLs', () => {
expect(() => svc().ollamaRoot('ftp://x')).toThrow(HttpException);
expect(() => svc().ollamaRoot('not a url')).toThrow(HttpException);
});
});
describe('LlmLocalService.listModels', () => {
it('returns named models from /api/tags', async () => {
const fetchFn = mockFetch(async () => ({ ok: true, json: async () => ({ models: [{ name: 'nuextract', size: 100 }, { name: '' }] }) }));
const out = await svc().listModels('http://localhost:11434/v1');
expect(out.models).toEqual([{ name: 'nuextract', size: 100 }]);
expect(fetchFn.mock.calls[0][0]).toBe('http://localhost:11434/api/tags');
});
it('502s when the server is unreachable', async () => {
mockFetch(async () => { throw new Error('ECONNREFUSED'); });
await expect(svc().listModels('http://localhost:11434')).rejects.toThrow(HttpException);
});
});
describe('LlmLocalService.pull', () => {
it('requires a model', async () => {
await expect(svc().pull('http://localhost:11434', '')).rejects.toThrow(HttpException);
});
it('posts to /api/pull and returns the stream body', async () => {
const body = {} as ReadableStream<Uint8Array>;
const fetchFn = mockFetch(async () => ({ ok: true, body }));
const out = await svc().pull('http://localhost:11434/v1', 'nuextract');
expect(out).toBe(body);
expect(fetchFn.mock.calls[0][0]).toBe('http://localhost:11434/api/pull');
const init = fetchFn.mock.calls[0][1];
expect(JSON.parse(init.body)).toEqual({ model: 'nuextract', stream: true });
});
});