fix: withhold print action until bid validation finishes
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import {test} from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {belgeYazdir} from '../src/services/bidDocs.js';
|
||||
|
||||
test('validation window has no print action until replaced by the prepared document',()=>{
|
||||
let html='',focused=0;
|
||||
const popup={closed:false,document:{open(){html='';},write(value){html+=value;},close(){}},focus(){focused++;}};
|
||||
assert.equal(belgeYazdir('Dosya kontrolü','<p role="status">Belgeler kontrol ediliyor…</p>',popup,{pending:true}),popup);
|
||||
assert.match(html,/Belgeler kontrol ediliyor/);
|
||||
assert.doesNotMatch(html,/<button|window\.print\(/);
|
||||
assert.equal(belgeYazdir('Teklif <Cetveli>','<h1>Hazır cetvel</h1>',popup),popup);
|
||||
assert.match(html,/<title>Teklif <Cetveli><\/title>/);
|
||||
assert.match(html,/Hazır cetvel/);
|
||||
assert.match(html,/<button onclick="window\.print\(\)"/);
|
||||
assert.doesNotMatch(html,/Belgeler kontrol ediliyor/);
|
||||
assert.equal(focused,2);
|
||||
popup.closed=true;
|
||||
assert.throws(()=>belgeYazdir('Teklif','',popup),/penceresi kapatıldı/);
|
||||
});
|
||||
+19
-3
@@ -6,6 +6,8 @@ import {tmpdir} from 'node:os';
|
||||
import {join} from 'node:path';
|
||||
import {randomBytes} from 'node:crypto';
|
||||
import {createServer as netServer} from 'node:net';
|
||||
import {readyBid} from './fixtures/ready-bid.mjs';
|
||||
import {preparationSummary} from '../src/services/preparationSummary.js';
|
||||
const dir=mkdtempSync(join(tmpdir(),'ihaleist-browser-'));
|
||||
process.env.AUTH_SECRET=randomBytes(32).toString('hex');
|
||||
const {signToken}=await import('../server/auth.mjs');
|
||||
@@ -15,6 +17,8 @@ const keyUser={email:'keys-browser-qa@example.test',name:'API QA',isAdmin:true};
|
||||
const keyToken=signToken(keyUser);
|
||||
let apiKeyListFailure=false;
|
||||
let briefFailure='none';
|
||||
let holdDocuments=false;
|
||||
const pendingDocuments=new Set();
|
||||
process.env.IHALEIST_USER_DATA_DIR=dir;
|
||||
const {createBriefOutbox}=await import('../server/brief-outbox.mjs');
|
||||
const qaBriefOutbox=createBriefOutbox(dir);
|
||||
@@ -96,17 +100,29 @@ const ui=await createServer({server:{host:'127.0.0.1',port:0,proxy:{'/api':{targ
|
||||
res.setHeader('Content-Type','application/json');res.end(JSON.stringify({success:true,job:qaJobs.getAiJob(user.email,created.id)}));
|
||||
}catch(error){res.writeHead(400,{'Content-Type':'application/json'});res.end(JSON.stringify({success:false,error:error.message}));}});return;
|
||||
}
|
||||
if(req.url==='/qa-source-update') {
|
||||
if(req.url?.startsWith('/qa-output-documents?')&&req.method==='POST') {
|
||||
const mode=new URL(req.url,'http://localhost').searchParams.get('mode');
|
||||
if(mode==='hold')holdDocuments=true;
|
||||
if(mode==='release'){holdDocuments=false;for(const pending of pendingDocuments){pending.writeHead(200,{'Content-Type':'application/json'});pending.end(JSON.stringify({success:true,belgeler:[]}));}pendingDocuments.clear();}
|
||||
res.end('Belge yanıtı: '+mode);return;
|
||||
}
|
||||
if(req.url==='/api/me/documents'&&req.method==='GET'&&holdDocuments){pendingDocuments.add(res);res.on('close',()=>pendingDocuments.delete(res));return;}
|
||||
if(req.url==='/qa-source-update'||req.url==='/qa-source-update?ready=1') {
|
||||
const selected=req.url.endsWith('?ready=1')?readyBid(tenders[0]):tenders[0];
|
||||
if(selected.bidDraft){const summary=preparationSummary(selected,{loading:false,error:null,documents:[]});if(summary.issues.length)throw new Error('QA ready fixture: '+JSON.stringify(summary.issues));}
|
||||
const html=`<html lang="tr"><head><meta name="viewport" content="width=device-width,initial-scale=1"></head><body><div id="root"></div><script type="module">
|
||||
import React from '/node_modules/.vite/deps/react.js';
|
||||
import ReactDOM from '/node_modules/.vite/deps/react-dom_client.js';
|
||||
import {AppProvider,useApp} from '/src/context/AppContext.jsx';
|
||||
import {BidPackageBuilder} from '/src/components/BidPackageBuilder.jsx';
|
||||
import '/src/index.css';
|
||||
const selected=${JSON.stringify(tenders[0])};
|
||||
function Probe(){const {setTenders}=useApp();return React.createElement('main',{},
|
||||
const selected=${JSON.stringify(selected)};
|
||||
function Probe(){const {setTenders}=useApp();const [status,setStatus]=React.useState('');const control=async mode=>setStatus(await (await fetch('/qa-output-documents?mode='+mode,{method:'POST'})).text());return React.createElement('main',{},
|
||||
React.createElement('h1',{},'Yerel kaynak güncelleme testi'),
|
||||
React.createElement('p',{},'Yalnız sentetik veri. Açık dosya korunurken güncel kaynak değişir.'),
|
||||
React.createElement('button',{onClick:()=>control('hold')},'Belge yanıtını beklet'),
|
||||
React.createElement('button',{onClick:()=>control('release')},'Belge yanıtını serbest bırak'),
|
||||
React.createElement('p',{role:'status'},status),
|
||||
React.createElement('button',{onClick:()=>setTenders([{...selected,id:'qa-rotated-source',baslik:'QA Güncellenmiş alım',kazananFirma:'QA Kazanan'}])},'Aynı İKN için yeni kayıt ID ve kazanan yayımla'),
|
||||
React.createElement(BidPackageBuilder,{tender:selected}));}
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(React.createElement(AppProvider,{},React.createElement(Probe)));
|
||||
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
// Synthetic UI fixture, never a claim of official tender eligibility.
|
||||
import {sourceRows,bidSourceOptions,bidSourceSnapshot} from '../../src/services/bidSource.js';
|
||||
import {documentKey,HEALTH_CHECKS} from '../../src/services/preparationChecks.js';
|
||||
|
||||
export function readyBid(tender) {
|
||||
const document={document:'QA isteğe bağlı belge',mandatory:false,note:'Yalnız sentetik senaryo'};
|
||||
const analysis={documentChecklist:[document]},itemSource={};
|
||||
const partialBid={enabled:false,source:'',selected:[],assignments:{}};
|
||||
const options=bidSourceOptions(tender,analysis,itemSource);
|
||||
const rows=sourceRows(tender,analysis,options.selected || 'tender');
|
||||
const sourceSnapshot=JSON.stringify([bidSourceSnapshot(tender,analysis,rows),partialBid,itemSource,options.signature]);
|
||||
return {...tender,bidDraft:{
|
||||
firma:{firmaUnvan:'QA Sentetik Laboratuvar',adres:'QA Test Adresi',vergiDairesi:'QA',vergiNo:'0000000000',yetkiliAd:'QA Test Kullanıcısı',yetkiliGorev:'Test',telefon:'0000000000',eposta:'qa@example.test'},
|
||||
teklifTuru:'birim',gecerlilikGun:'120',kisim:'',goturuBedel:'',priceSchema:1,
|
||||
pricesBySource:Object.fromEntries(rows.map(row=>[row.priceKey,'125.50'])),
|
||||
sourceSnapshot,reviewedSource:sourceSnapshot,manualDocuments:[],partialBid,itemSource,analysisSource:analysis,
|
||||
checks:{documents:{[documentKey(document)]:{status:'notApplicable',evidence:'QA senaryosunda istenmiyor.'}},
|
||||
products:Object.fromEntries(rows.map(row=>[row.priceKey,{status:'suitable',product:'QA sentetik ürün',source:'QA teknik madde 1',
|
||||
...Object.fromEntries(HEALTH_CHECKS.map(([key])=>[key,{status:'notApplicable',evidence:'QA senaryosu.'}]))}]))},
|
||||
}};
|
||||
}
|
||||
Reference in New Issue
Block a user