Files
0pt/tests/api/source-failure-honesty.test.ts
admin 5137bf87a1
CI (SIAX Cloud) / integration (push) Skipped
CI (SIAX Cloud) / sonar (push) Skipped
masterplan-lock / check (push) Successful in 4s
CI (SIAX Cloud) / sonar (pull_request) Skipped
CI (SIAX Cloud) / security (push) Successful in 15s
masterplan-lock / check (pull_request) Successful in 7s
Security Scan (SIAX Cloud) / security (push) Successful in 18s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 17s
CI (SIAX Cloud) / security (pull_request) Successful in 20s
CI (SIAX Cloud) / integration (pull_request) Successful in 35s
CI (SIAX Cloud) / quality (pull_request) Successful in 39s
CI (SIAX Cloud) / quality (push) Successful in 48s
fix: distinguish failed sources from empty results
2026-11-02 06:58:15 +01:00

43 lines
2.3 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from 'vitest';
import { NextRequest } from 'next/server';
import { GET as screen } from '@/app/api/screen/route';
import { GET as vehicles } from '@/app/api/vehicles/route';
const originalEngine = process.env.ENGINE_URL;
afterEach(() => { if (originalEngine === undefined) delete process.env.ENGINE_URL; else process.env.ENGINE_URL = originalEngine; vi.unstubAllGlobals(); });
const screening = () => screen(new NextRequest('http://localhost/api/screen?q=example'));
const vehicle = () => vehicles(new NextRequest('http://localhost/api/vehicles?plate=AB123'));
describe('source failure cannot mean absence', () => {
it.each([screening, vehicle])('returns 503 for source failures and malformed responses', async (call) => {
delete process.env.ENGINE_URL;
for (const response of [new Response('down', { status: 503 }), Response.json({}), new Response('{')]) {
vi.stubGlobal('fetch', vi.fn(async () => response));
const result = await call();
expect(result.status).toBe(503);
expect(await result.json()).toEqual({ error: expect.objectContaining({ code: 'source_unavailable' }) });
}
});
it('preserves an actual empty screening result', async () => {
delete process.env.ENGINE_URL;
vi.stubGlobal('fetch', vi.fn(async () => Response.json({ results: [] })));
expect(await (await screening()).json()).toEqual({ source: 'opensanctions', matches: [] });
});
it('preserves an actual missing vehicle', async () => {
delete process.env.ENGINE_URL;
vi.stubGlobal('fetch', vi.fn(async () => Response.json([])));
expect(await (await vehicle()).json()).toEqual({ vehicle: null });
});
it.each([screening, vehicle])('does not trust an old engine which can fabricate empty results', async (call) => {
process.env.ENGINE_URL = 'https://engine.test';
vi.stubGlobal('fetch', vi.fn(async () => Response.json({ matches: [], vehicle: null })));
expect((await call()).status).toBe(503);
expect(fetch).toHaveBeenCalledOnce();
});
it('accepts verified engine screening results', async () => {
process.env.ENGINE_URL = 'https://engine.test';
vi.stubGlobal('fetch', vi.fn(async () => Response.json({ source: 'opensanctions', source_status: 'ok', matches: [] })));
expect((await screening()).status).toBe(200);
});
});