From 0545b5428937d2e311546b760a4490cc1adec043 Mon Sep 17 00:00:00 2001 From: ht Date: Sun, 6 Sep 2026 12:53:33 +0300 Subject: [PATCH] Verify notification failure recovery and persisted read state in browser --- docs/quality/qa-notification-acknowledgement.json | 12 ++++++++++++ docs/quality/uygulama-durumu.md | 6 ++++++ tests/browser-qa.mjs | 7 +++++++ 3 files changed, 25 insertions(+) create mode 100644 docs/quality/qa-notification-acknowledgement.json diff --git a/docs/quality/qa-notification-acknowledgement.json b/docs/quality/qa-notification-acknowledgement.json new file mode 100644 index 0000000..9e9b1b3 --- /dev/null +++ b/docs/quality/qa-notification-acknowledgement.json @@ -0,0 +1,12 @@ +{ + "checks": { + "listFailure": true, + "twoUnreadAfterLoad": true, + "failedAckPreservesUnread": true, + "successfulAck": true, + "persistedAfterReload": true, + "noDuplicates": true + }, + "scope": "Local browser, seeded synthetic notifications, real API and SQLite; injected read/write 503; no external delivery", + "snapshot": "- banner:\n - text: İhale\n - generic: ist\n - textbox \"İhale, kurum veya İKN no ile arayın...\"\n - button \"ARA\":\n - generic: ARA\n - button \"ÜRÜN ARA\":\n - generic: ÜRÜN ARA\n - button \"Detaylı İhale Arama\":\n - button \"AI Şartname Analizi\":\n - generic: AI Şartname Analizi\n - button \"Web Siteni Tara (AI)\":\n - generic: Web Siteni Tara (AI)\n - generic: 7 gün\n - button \"Bildirimler\" [active]:\n - heading \"Bildirimler\" [level=4]\n - button \"Tümünü Okundu İşaretle\" [disabled]\n - generic: QA tarih değişikliği\n - generic: 06.09.2026 12:52:45\n - paragraph: \"Sentetik bildirim: ihale tarihi güncellendi.\"\n - generic: QA sonuç bildirimi\n - generic: 06.09.2026 12:52:45\n - paragraph: Sentetik sonuç inceleme bildirimi.\n - button \"Hesap menüsü\":\n - generic: L\n - generic: Laboratuvar\n- generic: \"5\"\n- generic: Canlı İhale Havuzu\n- generic: \"5\"\n- generic: Yüklü İhale\n- generic: \"0\"\n- generic: Bugün Eklenen\n- generic: \"5\"\n- generic: Kalem\n- generic: \"0\"\n- generic: Sonuç Arşivi\n- generic: \"0\"\n- generic: Takibimdeki\n- button \"Sonraki sekmeler\":\n- button \"Ana İhale Listesi\":\n - generic: Ana İhale Listesi\n- button \"Günlük Bülten\":\n - generic: Günlük Bülten\n- button \"Sonuç Sorgula\":\n - generic: Sonuç Sorgula\n- button \"İhale Takvimi\":\n - generic: İhale Takvimi\n- button \"Sözleşme Sorgula\":\n - generic: Sözleşme Sorgula\n- button \"KDV Hesapla\":\n - generic: KDV Hesapla\n- button \"Sınır Değer\":\n - generic: Sınır Değer\n- button \"Fiyat Analizi\":\n - generic: Fiyat Analizi\n- button \"Kanban Pano Sürükle Takip\":\n - generic: Kanban Pano\n - generic: Sürükle Takip\n- button \"Rakip Radar Canlı Uyar\":\n - generic: Rakip Radar\n - generic: Canlı Uyar\n- button \"Doküman Deposu\":\n - generic: Doküman Deposu\n- button \"Analitik Dashboard\":\n - generic: Analitik Dashboard\n- button \"Kırmızı Bayrak Şeffaflık\":\n - generic: Kırmızı Bayrak\n - generic: Şeffaflık\n- button \"KİK Kurul Kararları\":\n - generic: KİK Kurul Kararları\n- button \"AB İhaleleri (TED)\":\n - generic: AB İhaleleri (TED)\n- button \"Planlar\":\n - generic: Planlar\n- button \"API & Webhooks\":\n - generic: API & Webhooks\n- button \"Mobil PWA\":\n - generic: Mobil PWA\n- main:\n - paragraph: AKTİF İHALELER\n - paragraph: \"5\"\n - paragraph: BUGÜN EKLENENLER\n - paragraph: \"0\"\n - paragraph: TAKİP ETTİKLERİM\n - paragraph: \"0\"\n - generic \"İlk ziyaretiniz — bugün yayımlanan ilanlar gösteriliyor\":\n - paragraph: SON GİRİŞTEN BERİ\n - paragraph: \"0\"\n - paragraph: İNCELENMEMİŞ\n - paragraph: \"5\"\n - complementary:\n " +} \ No newline at end of file diff --git a/docs/quality/uygulama-durumu.md b/docs/quality/uygulama-durumu.md index 2e04196..ed482bc 100644 --- a/docs/quality/uygulama-durumu.md +++ b/docs/quality/uygulama-durumu.md @@ -774,3 +774,9 @@ Taslak türü seçicisine erişilebilir ad eklendi. Üretim derlemesi geçti. Ö - Gerçek okundu düğmesi sunucu yanıtından sonra yakalanan bildirim kümesini günceller; hata/kısmi yanıtta yerel durum değişmez. İşlem sırasında gelen yeni kayıtlar yanlışlıkla işaretlenmez. Hesap değişimi ve geç eski okuma yanıtları atılır. - Sunucu okundu işlemi liste tip/boyut doğrulamasıyla tek transaction'da çalışır; yabancı hesap kayıtlarına erişemez. Desteklenmeyen HTTP metotları 405 döner; depoya erişilememesi boş liste gibi gösterilmez. - 173 test ve üretim derlemesi başarılı. Yeni testler kimliklerin/okunmamış durumun korunmasını, kayıt hatası/kısmi yanıtı ve işlem kümesini doğrular. Menü hata→tekrar deneme ve sayfa yenileme sonrası okundu davranışının tarayıcı kabulü henüz yapılmadı. Dış push/e-posta teslimi bu testlerin kapsamı dışındadır. + +### Bildirim menüsü tarayıcı kabulü — 6 Eylül 2026 +- 5180 yerel QA ortamında iki sentetik bildirim gerçek takip.sqlite deposuna yazıldı; normal test hesabıyla Header menüsü kullanıldı. +- GET 503 → görünür hata → yeniden yükle → iki okunmamış kayıt; POST 503 → hata ve okunmamış durumların korunması; hatayı kaldır → açık okundu işlemi → sayfayı yeniden yükle → iki kalıcı okunmuş kayıt ve yinelenmeme doğrulandı. +- Kanıt: `qa-notification-acknowledgement.json`, 6 kontrol doğru. Test altyapısına yalnız localhost hata kontrol sayfası ve sentetik kayıt eklendi; üretim kodu bu adımda değişmedi, önceki 173 test/build sonucu yeniden çalıştırılmadı. +- Bu kabul gerçek bildirim API/deposunu kullanır; dış e-posta, Telegram veya işletim sistemi push teslimi testi değildir. Planın diğer kabul maddeleri açık. diff --git a/tests/browser-qa.mjs b/tests/browser-qa.mjs index d78b554..710fdc2 100644 --- a/tests/browser-qa.mjs +++ b/tests/browser-qa.mjs @@ -29,7 +29,14 @@ 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 qaNotifications=await import('../server/zeyilname.mjs'); +qaNotifications.bildirimYaz({email:user.email,tur:'zeyilname',ikn:'2026/1582991',baslik:'QA tarih değişikliği',metin:'Sentetik bildirim: ihale tarihi güncellendi.'}); +qaNotifications.bildirimYaz({email:user.email,tur:'sonuc',ikn:'2026/1534665',baslik:'QA sonuç bildirimi',metin:'Sentetik sonuç inceleme bildirimi.'}); +let notificationFailure='read'; 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(async(req,res,next)=>{ + if(req.url==='/qa-notification-controls') {res.setHeader('Content-Type','text/html; charset=utf-8');res.end(`

Yerel bildirim testi

`);return;} + if(req.url?.startsWith('/qa-notification-failure?')&&req.method==='POST'){notificationFailure=new URL(req.url,'http://localhost').searchParams.get('mode');res.end('Bildirim test durumu: '+notificationFailure);return;} + if(req.url==='/api/me/bildirimler'&&((notificationFailure==='read'&&req.method==='GET')||(notificationFailure==='write'&&req.method==='POST'))){res.writeHead(503,{'Content-Type':'application/json'});res.end(JSON.stringify({success:false,error:'QA: Bildirim deposuna erişilemiyor.'}));return;} if(req.url==='/qa-ai-controls') {res.setHeader('Content-Type','text/html; charset=utf-8');res.end(`

Yerel AI işi testi

Sağlayıcı taklidi kullanılır; ücretli AI çağrısı yapılmaz.

`);return;} if(req.url==='/qa-ai-complete' && req.method==='POST') { for(const job of pendingQaJobs.values()) {