#!/usr/bin/env node import { chromium } from 'playwright'; const MOBILE_VIEWPORT = { width: 375, height: 667 }; const LANDSCAPE_VIEWPORT = { width: 667, height: 375 }; (async () => { const browser = await chromium.launch({ headless: true }); console.log('🧪 Testing Modal Centering on Mobile\n'); // TEST 1: Portrait Mode console.log('📱 TEST 1: Portrait Mode (375×667)\n'); const portraitContext = await browser.newContext({ viewport: MOBILE_VIEWPORT, userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1', hasTouch: true }); const portraitPage = await portraitContext.newPage(); await portraitPage.goto('http://localhost:1999/?lang=en&view=extended'); await portraitPage.waitForLoadState('networkidle'); // Click info button to open modal await portraitPage.click('.info-button'); await portraitPage.waitForTimeout(500); // Wait for animation const portraitModal = await portraitPage.evaluate(() => { const modal = document.querySelector('.info-modal'); if (!modal) return null; const rect = modal.getBoundingClientRect(); const viewport = { width: window.innerWidth, height: window.innerHeight }; const modalCenterX = rect.left + rect.width / 2; const modalCenterY = rect.top + rect.height / 2; const viewportCenterX = viewport.width / 2; const viewportCenterY = viewport.height / 2; return { viewport, modal: { left: Math.round(rect.left), top: Math.round(rect.top), width: Math.round(rect.width), height: Math.round(rect.height), centerX: Math.round(modalCenterX), centerY: Math.round(modalCenterY) }, viewportCenter: { x: Math.round(viewportCenterX), y: Math.round(viewportCenterY) }, offsetX: Math.round(Math.abs(modalCenterX - viewportCenterX)), offsetY: Math.round(Math.abs(modalCenterY - viewportCenterY)), isCentered: Math.abs(modalCenterX - viewportCenterX) < 5 && Math.abs(modalCenterY - viewportCenterY) < 5 }; }); console.log('Portrait Modal:'); console.log(` • Viewport: ${portraitModal.viewport.width}×${portraitModal.viewport.height}`); console.log(` • Modal size: ${portraitModal.modal.width}×${portraitModal.modal.height}`); console.log(` • Modal center: (${portraitModal.modal.centerX}, ${portraitModal.modal.centerY})`); console.log(` • Viewport center: (${portraitModal.viewportCenter.x}, ${portraitModal.viewportCenter.y})`); console.log(` • Offset: X=${portraitModal.offsetX}px, Y=${portraitModal.offsetY}px`); console.log(` • Is centered: ${portraitModal.isCentered ? '✅' : '❌'}\n`); await portraitPage.screenshot({ path: 'tests/screenshots/modal-portrait.png', fullPage: true }); await portraitContext.close(); // TEST 2: Landscape Mode console.log('📱 TEST 2: Landscape Mode (667×375)\n'); const landscapeContext = await browser.newContext({ viewport: LANDSCAPE_VIEWPORT, userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1', hasTouch: true }); const landscapePage = await landscapeContext.newPage(); await landscapePage.goto('http://localhost:1999/?lang=en&view=extended'); await landscapePage.waitForLoadState('networkidle'); // Click info button to open modal await landscapePage.click('.info-button'); await landscapePage.waitForTimeout(500); // Wait for animation const landscapeModal = await landscapePage.evaluate(() => { const modal = document.querySelector('.info-modal'); if (!modal) return null; const rect = modal.getBoundingClientRect(); const viewport = { width: window.innerWidth, height: window.innerHeight }; const modalCenterX = rect.left + rect.width / 2; const modalCenterY = rect.top + rect.height / 2; const viewportCenterX = viewport.width / 2; const viewportCenterY = viewport.height / 2; return { viewport, modal: { left: Math.round(rect.left), top: Math.round(rect.top), width: Math.round(rect.width), height: Math.round(rect.height), centerX: Math.round(modalCenterX), centerY: Math.round(modalCenterY) }, viewportCenter: { x: Math.round(viewportCenterX), y: Math.round(viewportCenterY) }, offsetX: Math.round(Math.abs(modalCenterX - viewportCenterX)), offsetY: Math.round(Math.abs(modalCenterY - viewportCenterY)), isCentered: Math.abs(modalCenterX - viewportCenterX) < 5 && Math.abs(modalCenterY - viewportCenterY) < 5 }; }); console.log('Landscape Modal:'); console.log(` • Viewport: ${landscapeModal.viewport.width}×${landscapeModal.viewport.height}`); console.log(` • Modal size: ${landscapeModal.modal.width}×${landscapeModal.modal.height}`); console.log(` • Modal center: (${landscapeModal.modal.centerX}, ${landscapeModal.modal.centerY})`); console.log(` • Viewport center: (${landscapeModal.viewportCenter.x}, ${landscapeModal.viewportCenter.y})`); console.log(` • Offset: X=${landscapeModal.offsetX}px, Y=${landscapeModal.offsetY}px`); console.log(` • Is centered: ${landscapeModal.isCentered ? '✅' : '❌'}\n`); await landscapePage.screenshot({ path: 'tests/screenshots/modal-landscape.png', fullPage: true }); await landscapeContext.close(); const allPassed = portraitModal.isCentered && landscapeModal.isCentered; console.log(`${allPassed ? '✅' : '❌'} Tests ${allPassed ? 'PASSED' : 'FAILED'}\n`); await browser.close(); process.exit(allPassed ? 0 : 1); })();