Files
kochwas/tests/integration/searxng.test.ts
2026-04-17 15:33:21 +02:00

75 lines
2.3 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { createServer, type Server } from 'node:http';
import type { AddressInfo } from 'node:net';
import { openInMemoryForTest } from '../../src/lib/server/db';
import { addDomain } from '../../src/lib/server/domains/repository';
import { searchWeb } from '../../src/lib/server/search/searxng';
let server: Server;
let baseUrl: string;
function respondWith(results: Record<string, unknown>[]) {
server.on('request', (_req, res) => {
res.writeHead(200, { 'content-type': 'application/json' });
res.end(JSON.stringify({ results }));
});
}
beforeEach(async () => {
server = createServer();
await new Promise<void>((r) => server.listen(0, '127.0.0.1', r));
const addr = server.address() as AddressInfo;
baseUrl = `http://127.0.0.1:${addr.port}`;
});
afterEach(async () => {
await new Promise<void>((r) => server.close(() => r()));
});
describe('searchWeb', () => {
it('filters results by whitelist', async () => {
const db = openInMemoryForTest();
addDomain(db, 'chefkoch.de');
respondWith([
{
url: 'https://www.chefkoch.de/rezepte/123/a.html',
title: 'Carbonara',
content: 'Pasta'
},
{
url: 'https://fake.de/x',
title: 'Not allowed',
content: 'blocked'
}
]);
const hits = await searchWeb(db, 'carbonara', { searxngUrl: baseUrl });
expect(hits.length).toBe(1);
expect(hits[0].domain).toBe('chefkoch.de');
expect(hits[0].title).toBe('Carbonara');
});
it('dedupes identical URLs', async () => {
const db = openInMemoryForTest();
addDomain(db, 'chefkoch.de');
respondWith([
{ url: 'https://www.chefkoch.de/a', title: 'A', content: '' },
{ url: 'https://www.chefkoch.de/a', title: 'A dup', content: '' }
]);
const hits = await searchWeb(db, 'a', { searxngUrl: baseUrl });
expect(hits.length).toBe(1);
});
it('returns empty list when no domains configured', async () => {
const db = openInMemoryForTest();
const hits = await searchWeb(db, 'x', { searxngUrl: baseUrl });
expect(hits).toEqual([]);
});
it('returns empty for empty query', async () => {
const db = openInMemoryForTest();
addDomain(db, 'chefkoch.de');
const hits = await searchWeb(db, ' ', { searxngUrl: baseUrl });
expect(hits).toEqual([]);
});
});