Verify paginated source history in the browser and fix QA route matching
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -681,3 +681,11 @@ Resmi İKN ortak ihale anahtarıdır; doğrudan temin numarası kurumla birlikte
|
||||
Oturum gerektiren sayfalı geçmiş API'si ve ayrıntı ekranında isteğe bağlı geçmiş görünümü eklendi. Önce/sonra metinleri açılabilir, daha eski kayıtlar getirilebilir. Boş geçmiş değişiklik yokluğunun kanıtı olarak sunulmaz. Kayıt hatası havuz uyarısına, okuma hatası yeniden denemeli ekran durumuna yansır. Kaynak kaydı yalnız uygulamanın gözlemlediği andan itibaren birikir; geçmişe dönük resmi zeyilnameler yüklenmiş değildir.
|
||||
|
||||
Doğrulama: gerçek SQLite yeniden açılışları, aynı veriyi tekrar alma, değer geri dönüşü, kaynak ayrımı, kurum kapsamlı DT kimliği, sayfalama; HTTP oturum/boş sonuç/geçersiz sayfa/metot. Tüm 147 test ve üretim derlemesi geçti. Son depo-açılış temizliği değişikliğinden sonra iki depo testi tekrar geçti. Canlı kaynak birikimi, tarayıcıdan dolu geçmiş ve zeyilname bildirim kabulü açık. Bu volume kullanıcı yedeğinin kapsamı dışında; tam D11 yedeğine ayrıca dahil edilmeli. Canlı yayın yapılmadı.
|
||||
|
||||
### D04 / D09 — Kaynak geçmişi tarayıcı kabulü
|
||||
|
||||
Yerel QA yardımcı sunucusu geçici gerçek SQLite deposuna ilk gözlem ve 22 saat değişikliği ekleyecek şekilde genişletildi. İlk tarayıcı denemesi test middleware'inin `/api/tenders` önekli bütün yolları örnek listeyle karşıladığını ortaya çıkardı. Eşleşme yalnız liste yoluna ve sorgusuna daraltıldı; çalışan test sunucusu bu kod değişikliği için kontrollü yeniden başlatıldı.
|
||||
|
||||
Gerçek geçmiş API'si üzerinden Giresun ayrıntısı → Kaynak değişiklik geçmişi → Geçmişi yükle akışında 20 kayıt; ilk Saat değişti başlığında Önce 11:00 / Sonra 10:00; Daha eski kayıtlar ile toplam 23 kayıt ve ilk gözlem; son sayfada devam düğmesinin kaybolması doğrulandı. Altı kontrol doğru. Kanıt qa-source-history.json. Veriler sentetik ve geçici; canlı resmi zeyilname kabulü değildir.
|
||||
|
||||
Yeni açılır başlıkların klavye erişimi için modal odak döngüsüne summary öğeleri eklendi. Üretim derlemesi geçti. Önceki 147 otomatik test bu yalnız QA/odak seçicisi turunda tekrarlanmadı. Ağ hata/yeniden deneme ve gerçek kaynak birikimi kabulü açık. Canlı yayın yapılmadı.
|
||||
|
||||
@@ -31,7 +31,7 @@ export const TenderDetailModal = () => {
|
||||
e.preventDefault(); e.stopPropagation(); setActiveTenderDetail(null); return;
|
||||
}
|
||||
if (e.key !== 'Tab') return;
|
||||
const focusable = [...dialogRef.current.querySelectorAll('button, a[href], input, select, textarea, [tabindex]')]
|
||||
const focusable = [...dialogRef.current.querySelectorAll('button, a[href], input, select, textarea, summary, [tabindex]')]
|
||||
.filter(el => el.tabIndex >= 0 && !el.disabled && el.getClientRects().length && !el.closest('[inert]'));
|
||||
const first = focusable[0], last = focusable.at(-1);
|
||||
if (!first) { e.preventDefault(); dialogRef.current.focus(); }
|
||||
|
||||
@@ -18,12 +18,17 @@ const probe=netServer();await new Promise(r=>probe.listen(0,'127.0.0.1',r));cons
|
||||
const api=spawn(process.execPath,['server/index.js'],{cwd:new URL('..',import.meta.url),env:{PATH:process.env.PATH,NODE_ENV:'test',AUTH_SECRET:process.env.AUTH_SECRET,IHALEIST_USER_DATA_DIR:dir,IHALEIST_SHARED_DATA_DIR:join(dir,'shared'),PORT:String(port),UYUM_GOMME:'0'},stdio:'ignore'});
|
||||
const entries=[['1582991','Giresun','10.09.2026','10:00'],['1534665','Kayseri','22.09.2026','11:00'],['1499061','Akdeniz','22.09.2026','10:30'],['1573235','Aksaray','09.09.2026','10:00'],['1523851','Tepecik','11.09.2026','10:00']];
|
||||
const tenders=entries.map(([id,city,date,time])=>({id:'qa-'+id,ikn:'2026/'+id,baslik:'QA — '+city+' laboratuvar',kurum:city+' TEST KURUMU',sehir:city,tarih:date,saat:time,alimTuru:'Mal Alımı',sektor:'Laboratuvar & Ölçüm',sektorler:['Laboratuvar & Ölçüm'],durum:'Açık',takipte:false,kanbanStatus:'incelenecek',items:[{id:'1',ad:'Sentetik test kalemi',miktar:2,birim:'adet'}],aciklama:'Bu yalnızca yerel arayüz test verisidir. Teklif geçerlilik süresi 120 takvim günü. Birim fiyat teklif. '.repeat(3)}));
|
||||
// Seed actual persistent history only in this disposable QA volume.
|
||||
process.env.IHALEIST_SHARED_DATA_DIR=join(dir,'shared');
|
||||
const {observeTenders}=await import('../server/tender-history.mjs');
|
||||
observeTenders(tenders);
|
||||
for(let revision=1;revision<=22;revision++) observeTenders([{...tenders[0],saat:revision%2?'11:00':'10:00'}]);
|
||||
const ui=await createServer({server:{host:'127.0.0.1',port:0,proxy:{'/api':{target:'http://127.0.0.1:'+port}}},plugins:[{name:'qa-fixtures',configureServer(server){server.middlewares.use((req,res,next)=>{
|
||||
if(req.url==='/qa-api-controls') {res.setHeader('Content-Type','text/html; charset=utf-8');res.end(`<html lang="tr"><h1>Yerel API testi</h1><p>Yalnız geçici test deposunu etkiler.</p><button id="login">API test hesabıyla gir</button><button id="fail">Liste hatasını aç</button><button id="recover">Liste hatasını kapat</button><p role="status"></p><script type="module">import {setSession} from '/src/services/auth.js';document.querySelector('#login').onclick=()=>{setSession(${JSON.stringify(keyToken)},${JSON.stringify(keyUser)});location.href='/';};for(const [id,mode] of [['fail','on'],['recover','off']])document.getElementById(id).onclick=async()=>{await fetch('/qa-api-failure?mode='+mode,{method:'POST'});document.querySelector('[role=status]').textContent=mode==='on'?'Liste hatası açık':'Liste hatası kapalı';};</script></html>`);return;}
|
||||
if(req.method==='POST' && req.url?.startsWith('/qa-api-failure?')) {apiKeyListFailure=new URL(req.url,'http://localhost').searchParams.get('mode')==='on';res.end('ok');return;}
|
||||
if(apiKeyListFailure && req.method==='GET' && req.url==='/api/me/apikeys') {res.writeHead(503,{'Content-Type':'application/json'});res.end(JSON.stringify({success:false,error:'QA: Anahtar deposuna erişilemiyor.'}));return;}
|
||||
if(req.url==='/qa-signin') {res.setHeader('Content-Type','text/html; charset=utf-8');res.end(`<html lang="tr"><h1>Yerel laboratuvar testi</h1><p>Sentetik ihale verileri ve geçici kullanıcı deposu kullanılır.</p><button id="login">Test hesabıyla gir</button><script type="module">import {setSession} from '/src/services/auth.js';document.querySelector('#login').onclick=()=>{setSession(${JSON.stringify(token)},${JSON.stringify(user)});location.href='/';};</script></html>`);return;}
|
||||
if(req.url?.startsWith('/api/tenders')){res.setHeader('Content-Type','application/json');res.end(JSON.stringify({success:true,tenders,totalCount:5,todayCount:0,historyCount:0,source:'Yerel sentetik QA',fetchedAt:new Date().toISOString()}));return;}
|
||||
if(req.url==='/api/tenders' || req.url?.startsWith('/api/tenders?')){res.setHeader('Content-Type','application/json');res.end(JSON.stringify({success:true,tenders,totalCount:5,todayCount:0,historyCount:0,source:'Yerel sentetik QA',fetchedAt:new Date().toISOString()}));return;}
|
||||
next();
|
||||
});}}]});
|
||||
await ui.listen();console.log('QA_URL='+ui.resolvedUrls.local[0]+'qa-signin');
|
||||
|
||||
Reference in New Issue
Block a user