Validate assistant response contracts and bound AI request waiting
This commit is contained in:
@@ -34,3 +34,12 @@ test('late answer is rejected after account or active tender changes',async()=>{
|
||||
fetcher:async()=>{if(change==='account')token='second';else mounted=false;return Response.json({cevap:'Private answer'});}}),/Oturum veya ihale değişti/);
|
||||
}
|
||||
});
|
||||
test('HTML, null and incomplete success responses cannot replace a valid existing result',async()=>{
|
||||
for(const response of [new Response('<html>Gateway</html>'),Response.json(null),Response.json({}),Response.json({success:true,maddeler:[{durum:'unknown'}]})]) {
|
||||
await assert.rejects(requestOfferAssistant({url:'/api/ai/teklif-denetim',body,readToken:()=>'first',fetcher:async()=>response}));
|
||||
}
|
||||
});
|
||||
test('a stalled AI request times out instead of locking the assistant indefinitely',async()=>{
|
||||
await assert.rejects(requestOfferAssistant({url:'/api/ai/belge-sor',body,readToken:()=>'first',timeoutMs:5,
|
||||
fetcher:async(url,{signal})=>new Promise((resolve,reject)=>signal.addEventListener('abort',()=>reject(new DOMException('Aborted','AbortError')),{once:true}))}),/zaman aşımı/);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import {test} from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {validateOfferResponse} from '../src/services/offerResponse.js';
|
||||
import {qualifyOfferDraft} from '../server/offer-draft.mjs';
|
||||
import {qualifyOfferAudit} from '../server/offer-audit.mjs';
|
||||
import {qualifyQuestionAnswer} from '../server/document-question.mjs';
|
||||
test('all three server output contracts can be rendered by the client',()=>{
|
||||
const draft={success:true,...qualifyOfferDraft({bolumler:[{baslik:'Kapak',icerik:'Taslak metni'}]},['Kapak','Ekler'])};
|
||||
const audit={success:true,...qualifyOfferAudit({maddeler:[{gereklilik:'Numune',durum:'eksik'}]},['Numune'],'Taslak')};
|
||||
const answer={success:true,...qualifyQuestionAnswer({cevap:'Numune zorunlu [1].'},[{n:1,icerik:'Numune zorunlu.'}])};
|
||||
for(const [url,data] of [['teklif-taslak',draft],['teklif-denetim',audit],['belge-sor',answer]]) assert.equal(validateOfferResponse('/api/ai/'+url,data),data);
|
||||
});
|
||||
test('nested fields that would crash the view are rejected at the boundary',()=>{
|
||||
for(const [url,data] of [
|
||||
['belge-sor',{cevap:'Yanıt',kaynaklar:{}}],
|
||||
['teklif-denetim',{maddeler:[{gereklilik:'Numune',durum:'unexpected'}],eksikler:[],uyum_yuzde:100,belirsizSayisi:0}],
|
||||
['teklif-taslak',{bolumler:[{baslik:'Kapak',icerik:{text:'invalid'}}]}]]) assert.throws(()=>validateOfferResponse('/api/ai/'+url,{success:true,...data}),/beklenen biçimde/);
|
||||
});
|
||||
Reference in New Issue
Block a user