add automated browser acceptance runner
This commit is contained in:
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"url": "http://127.0.0.1:5173/qa-signin",
|
||||||
|
"checks": {
|
||||||
|
"signInStatus": 200,
|
||||||
|
"visibleCities": [
|
||||||
|
{
|
||||||
|
"city": "Giresun",
|
||||||
|
"count": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"city": "Kayseri",
|
||||||
|
"count": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"city": "Akdeniz",
|
||||||
|
"count": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"city": "Aksaray",
|
||||||
|
"count": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"city": "Tepecik",
|
||||||
|
"count": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"overviewStatus": 200,
|
||||||
|
"overviewFrames": 3
|
||||||
|
},
|
||||||
|
"scope": "Yerel sentetik QA; gerçek başvuru veya dış sağlayıcı çağrısı yapılmadı."
|
||||||
|
}
|
||||||
@@ -2104,3 +2104,9 @@ Doğrulama: ICS round-trip, İstanbul saat dönüşümü, kaçış karakterleri,
|
|||||||
İçe aktarılan harici etkinlikler artık `sessionStorage` içinde tutuluyor; kullanıcı takvim sekmesinden ayrılıp döndüğünde aynı tarayıcı oturumunda kayıtlar korunuyor. Temizleme düğmesi tüm harici etkinlikleri kaldırıyor; özel tarama modunda storage yazımı başarısız olursa uygulama akışı devam ediyor.
|
İçe aktarılan harici etkinlikler artık `sessionStorage` içinde tutuluyor; kullanıcı takvim sekmesinden ayrılıp döndüğünde aynı tarayıcı oturumunda kayıtlar korunuyor. Temizleme düğmesi tüm harici etkinlikleri kaldırıyor; özel tarama modunda storage yazımı başarısız olursa uygulama akışı devam ediyor.
|
||||||
|
|
||||||
Doğrulama: 292/292 otomatik test ve üretim derlemesi başarılı.
|
Doğrulama: 292/292 otomatik test ve üretim derlemesi başarılı.
|
||||||
|
|
||||||
|
### 2026-09-06 · Headless tarayıcı kabul koşucusu
|
||||||
|
|
||||||
|
`npm run qa:browser` komutu geçici QA sunucusunu başlatıp Playwright ile giriş sayfasını, beş sentetik sağlık ihalesinin görünürlüğünü ve 390/768/1440 piksel hazırlık özeti çerçevelerini doğruluyor. Çalışma zamanı kanıtı [`qa-browser-acceptance-runtime.json`](evidence/qa-browser-acceptance-runtime.json) içinde tutuluyor; resmi ihale başvurusu değildir.
|
||||||
|
|
||||||
|
Doğrulama: giriş HTTP 200, beş şehrin tamamı görünür (her biri 3 eşleşme), üç hazırlık özeti çerçevesi açıldı.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
"qa:browser": "node tests/browser-acceptance.mjs",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"server": "node server/index.js",
|
"server": "node server/index.js",
|
||||||
"test": "node --test tests/*.test.mjs"
|
"test": "node --test tests/*.test.mjs"
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// Local-only browser acceptance runner. It uses the disposable fixtures served by browser-qa.mjs.
|
||||||
|
import { spawn } from 'node:child_process';
|
||||||
|
import { writeFile, mkdir } from 'node:fs/promises';
|
||||||
|
import { chromium } from 'playwright';
|
||||||
|
|
||||||
|
const server = spawn(process.execPath, ['tests/browser-qa.mjs'], { cwd: new URL('..', import.meta.url), stdio: ['ignore', 'pipe', 'inherit'] });
|
||||||
|
let output = '';
|
||||||
|
const url = await new Promise((resolve, reject) => {
|
||||||
|
const timeout = setTimeout(() => reject(new Error('QA sunucusu başlatılamadı.')), 30_000);
|
||||||
|
server.stdout.on('data', chunk => {
|
||||||
|
output += chunk;
|
||||||
|
const match = /QA_URL=(\S+)/.exec(output);
|
||||||
|
if (match) { clearTimeout(timeout); resolve(match[1]); }
|
||||||
|
});
|
||||||
|
server.once('exit', code => { clearTimeout(timeout); reject(new Error(`QA sunucusu ${code} koduyla kapandı.`)); });
|
||||||
|
});
|
||||||
|
|
||||||
|
const browser = await chromium.launch({ headless: true });
|
||||||
|
const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } });
|
||||||
|
const evidence = { url, checks: {}, scope: 'Yerel sentetik QA; gerçek başvuru veya dış sağlayıcı çağrısı yapılmadı.' };
|
||||||
|
try {
|
||||||
|
const response = await page.goto(url, { waitUntil: 'networkidle' });
|
||||||
|
evidence.checks.signInStatus = response?.status();
|
||||||
|
await page.getByRole('button', { name: 'Test hesabıyla gir' }).click();
|
||||||
|
await page.waitForLoadState('networkidle');
|
||||||
|
evidence.checks.visibleCities = await Promise.all(['Giresun', 'Kayseri', 'Akdeniz', 'Aksaray', 'Tepecik'].map(async city => ({ city, count: await page.getByText(city, { exact: false }).count() })));
|
||||||
|
if (evidence.checks.visibleCities.some(item => item.count < 1)) throw new Error('Beş sentetik şehirden biri görünmedi.');
|
||||||
|
const overview = await page.goto(`${url.replace(/\/qa-signin$/, '')}/qa-overview`, { waitUntil: 'networkidle' });
|
||||||
|
evidence.checks.overviewStatus = overview?.status();
|
||||||
|
evidence.checks.overviewFrames = await page.locator('iframe[title^="Hazırlık"]').count();
|
||||||
|
if (evidence.checks.overviewFrames !== 3) throw new Error('Hazırlık özeti üç görünüm alanında açılmadı.');
|
||||||
|
} finally {
|
||||||
|
await page.close(); await browser.close(); server.kill('SIGTERM');
|
||||||
|
}
|
||||||
|
await mkdir('docs/quality/evidence', { recursive: true });
|
||||||
|
await writeFile('docs/quality/evidence/qa-browser-acceptance-runtime.json', JSON.stringify(evidence, null, 2) + '\n');
|
||||||
|
console.log(JSON.stringify(evidence));
|
||||||
Reference in New Issue
Block a user