/** * Sprint 7 item 2 — визуальная проверка ConfirmDialog на стейдже. * Логинимся под demo-orgом, открываем карточку любого товара, жмём * «Удалить», скриншот, отмена → проверяем что товар не удалился. * * Запуск: cd tests/e2e && pnpm exec tsx scripts/screenshot-confirm-dialog.ts * Env: E2E_ADMIN_URL (default https://test.admin.food-market.kz), * E2E_EMAIL / E2E_PASSWORD (если нет — создаст временный signup + * запустит seed демо-данных). */ import { chromium } from 'playwright' import { makeClient, login } from '../lib/api.js' const BASE = process.env.E2E_ADMIN_URL ?? 'https://test.admin.food-market.kz' const TS = Date.now() const EMAIL = process.env.E2E_EMAIL ?? `confirm-shot-${TS}@food-market.local` const PASS = process.env.E2E_PASSWORD ?? 'ConfirmShot12345!' async function ensureSession() { const api = makeClient() // если signup провалится 409 — значит юзер уже есть, просто залогинимся const r = await api.post('/api/auth/signup', { email: EMAIL, password: PASS, organizationName: `ConfirmShot ${TS}`, phone: '+77011190001', plan: 'start', }) if (r.status !== 200 && r.status !== 409) { throw new Error(`signup ${r.status}: ${JSON.stringify(r.data)}`) } const sess = await login(EMAIL, PASS) // Seed демо-данных — нам нужен хотя бы один товар, чтобы зайти в edit. const seed = makeClient(sess.accessToken) await seed.post('/api/admin/seed-demo', {}) return sess } async function main() { const sess = await ensureSession() console.log(`[shot] session ok email=${sess.email}`) const browser = await chromium.launch({ headless: true }) const ctx = await browser.newContext({ ignoreHTTPSErrors: true, viewport: { width: 1280, height: 800 }, }) const page = await ctx.newPage() // Авто-логин через токен: положим в localStorage то, что ожидает web // (web использует ключ fm.access_token, см. src/lib/auth.ts). await page.goto(`${BASE}/`) await page.evaluate(({ token }) => { localStorage.setItem('fm.access_token', token) }, { token: sess.accessToken }) await page.goto(`${BASE}/catalog/products`, { waitUntil: 'domcontentloaded' }) await page.waitForLoadState('networkidle') await page.screenshot({ path: `reports/confirm-list-${TS}.png`, fullPage: false }) // Ждём первую строку таблицы товаров await page.locator('tbody tr').first().waitFor({ timeout: 15000 }) await page.locator('tbody tr').first().click() await page.waitForLoadState('networkidle') // Кнопка «Удалить» — danger variant в правом верхнем углу const deleteBtn = page.getByRole('button', { name: /удалить/i }).first() await deleteBtn.click() // Ждём появления нашего диалога await page.waitForSelector('[aria-labelledby="confirm-dialog-title"]', { timeout: 5000 }) const outDir = 'reports' await page.screenshot({ path: `${outDir}/confirm-dialog-${TS}.png`, fullPage: false }) console.log(`[shot] saved → ${outDir}/confirm-dialog-${TS}.png`) // Проверка: Esc закрывает (NOT удаляет) await page.keyboard.press('Escape') await page.waitForTimeout(300) const stillOpen = await page.locator('[aria-labelledby="confirm-dialog-title"]').count() console.log(`[shot] dialog closed after Esc: ${stillOpen === 0 ? '✓' : '✗ STILL OPEN'}`) await browser.close() } main().catch(err => { console.error(err); process.exit(1) })