import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { buildApp } from '@/app'; import { prismaClient } from '@/infrastructure/database'; import { FastifyInstance } from 'fastify'; /** Covers specs/005-ai-support/contracts/ai-support-contract.md's confidence-policy admin * surface (FR-005) — no LLM call involved, so this runs unconditionally against a real * Postgres, unlike the AI-diagnosis/reasoning tests in this same directory. */ describe('AI confidence policy — admin config (FR-005)', () => { let app: FastifyInstance; const externalProductId = `TEST_AI_POLICY_PROD_${Date.now()}`; beforeAll(async () => { app = await buildApp(); await prismaClient.product.create({ data: { externalProductId, name: 'AI Policy Test Product', status: 'active' }, }); }); afterAll(async () => { const product = await prismaClient.product.findUnique({ where: { externalProductId } }); if (product) { await prismaClient.aIConfidencePolicy.deleteMany({ where: { productId: product.id } }); } await prismaClient.product.deleteMany({ where: { externalProductId } }); await app.close(); }); it('rejects a highThreshold at or below lowThreshold', async () => { const response = await app.inject({ method: 'PUT', url: `/admin/products/${externalProductId}/ai-policy`, payload: { highThreshold: 0.4, lowThreshold: 0.4, maxClarifyingQuestions: 2 }, }); expect(response.statusCode).toBe(400); }); it('upserts a product-wide policy and reflects it on GET, alongside the system defaults', async () => { const putResponse = await app.inject({ method: 'PUT', url: `/admin/products/${externalProductId}/ai-policy`, payload: { highThreshold: 0.8, lowThreshold: 0.3, maxClarifyingQuestions: 3 }, }); expect(putResponse.statusCode).toBe(200); expect(putResponse.json().data.highThreshold).toBe(0.8); const getResponse = await app.inject({ method: 'GET', url: `/admin/products/${externalProductId}/ai-policy`, }); expect(getResponse.statusCode).toBe(200); const body = getResponse.json().data; expect(body.configured).toHaveLength(1); expect(body.configured[0].highThreshold).toBe(0.8); expect(body.systemDefaults).toHaveProperty('highThreshold'); expect(body.systemDefaults).toHaveProperty('lowThreshold'); expect(body.systemDefaults).toHaveProperty('maxClarifyingQuestions'); }); it('a second PUT for the same product (no category) updates the existing row rather than creating a duplicate', async () => { await app.inject({ method: 'PUT', url: `/admin/products/${externalProductId}/ai-policy`, payload: { highThreshold: 0.9, lowThreshold: 0.2, maxClarifyingQuestions: 1 }, }); const getResponse = await app.inject({ method: 'GET', url: `/admin/products/${externalProductId}/ai-policy`, }); const configured = getResponse.json().data.configured; expect(configured).toHaveLength(1); expect(configured[0].highThreshold).toBe(0.9); }); it('404s for an unregistered product', async () => { const response = await app.inject({ method: 'PUT', url: `/admin/products/TEST_NEVER_REGISTERED_${Date.now()}/ai-policy`, payload: { highThreshold: 0.8, lowThreshold: 0.3, maxClarifyingQuestions: 2 }, }); expect(response.statusCode).toBe(404); }); });