#!/usr/bin/env node import { chromium } from 'playwright'; const MOBILE_VIEWPORT = { width: 375, height: 667 }; // iPhone SE size (async () => { const browser = await chromium.launch({ headless: true }); const context = await browser.newContext({ viewport: MOBILE_VIEWPORT }); const page = await context.newPage(); try { console.log('๐Ÿงช Testing Mobile Accordion and Modal Centering\n'); console.log(`๐Ÿ“ฑ Mobile Viewport: ${MOBILE_VIEWPORT.width}x${MOBILE_VIEWPORT.height}`); // Navigate to extended view await page.goto('http://localhost:1999/?lang=en&view=extended'); await page.waitForLoadState('networkidle'); console.log('โœ… Extended view loaded\n'); // ===== TEST 1: SIDEBAR ACCORDION ===== console.log('๐Ÿ” TEST 1: Sidebar Accordion Structure\n'); // Check for accordion elements const accordionDetails = await page.locator('.sidebar-accordion').first(); const accordionSummary = await page.locator('.sidebar-accordion-header').first(); const accordionContent = await page.locator('.sidebar-accordion-content').first(); const detailsCount = await page.locator('.sidebar-accordion').count(); const summaryCount = await page.locator('.sidebar-accordion-header').count(); const contentCount = await page.locator('.sidebar-accordion-content').count(); console.log(`๐Ÿ“Š Accordion Structure:`); console.log(` โ€ข Details elements: ${detailsCount}`); console.log(` โ€ข Summary elements: ${summaryCount}`); console.log(` โ€ข Content elements: ${contentCount}`); // Check if accordion is initially closed (should be closed on mobile) const isOpen = await accordionDetails.evaluate(el => el.hasAttribute('open')); console.log(` โ€ข Initially closed: ${!isOpen ? 'โœ… YES' : 'โŒ NO (should be closed)'}`); console.log(` โ€ข Initially open: ${isOpen ? 'โŒ YES (should be closed)' : 'โœ… NO'}`); // Check if summary is visible on mobile const summaryDisplay = await accordionSummary.evaluate(el => { const style = window.getComputedStyle(el); return style.display; }); console.log(` โ€ข Summary display: ${summaryDisplay}`); console.log(` โ€ข Summary visible: ${summaryDisplay !== 'none' ? 'โœ… YES' : 'โŒ NO'}`); // Check if content is initially hidden (since accordion starts closed) const initialContentHidden = await accordionContent.evaluate(el => { const style = window.getComputedStyle(el); return style.maxHeight === '0px' || style.opacity === '0'; }); console.log(` โ€ข Content initially hidden: ${initialContentHidden ? 'โœ… YES' : 'โŒ NO'}`); // Test accordion toggle if (detailsCount > 0) { console.log('\n๐Ÿ–ฑ๏ธ Testing Accordion Toggle...'); // Click to OPEN (since it starts closed) await accordionSummary.click(); await page.waitForTimeout(500); const isOpenedAfterClick = await accordionDetails.evaluate(el => el.hasAttribute('open')); console.log(` โ€ข Opened after click: ${isOpenedAfterClick ? 'โœ… YES' : 'โŒ NO'}`); // Check if content is now visible const contentVisible = await accordionContent.evaluate(el => { const style = window.getComputedStyle(el); return style.opacity === '1'; }); console.log(` โ€ข Content visible: ${contentVisible ? 'โœ… YES' : 'โŒ NO'}`); // Click to close again await accordionSummary.click(); await page.waitForTimeout(500); const isClosedAgain = await accordionDetails.evaluate(el => !el.hasAttribute('open')); console.log(` โ€ข Closed after second click: ${isClosedAgain ? 'โœ… YES' : 'โŒ NO'}`); // Verify content is hidden again const contentHiddenAgain = await accordionContent.evaluate(el => { const style = window.getComputedStyle(el); return style.maxHeight === '0px' || style.opacity === '0'; }); console.log(` โ€ข Content hidden again: ${contentHiddenAgain ? 'โœ… YES' : 'โŒ NO'}`); } // ===== TEST 2: MODAL CENTERING ===== console.log('\n๐Ÿ” TEST 2: Modal Centering\n'); // Open the PDF modal await page.click('#download-button'); await page.waitForTimeout(500); const modal = await page.locator('#pdf-modal'); const isModalOpen = await modal.evaluate(el => el.hasAttribute('open')); console.log(`๐Ÿ“ฆ Modal Status:`); console.log(` โ€ข Modal open: ${isModalOpen ? 'โœ… YES' : 'โŒ NO'}`); if (isModalOpen) { // Get modal bounding box const modalBox = await modal.boundingBox(); console.log(`\n๐Ÿ“ Modal Position:`); console.log(` โ€ข X position: ${modalBox.x.toFixed(2)}px`); console.log(` โ€ข Y position: ${modalBox.y.toFixed(2)}px`); console.log(` โ€ข Width: ${modalBox.width.toFixed(2)}px`); console.log(` โ€ข Height: ${modalBox.height.toFixed(2)}px`); // Calculate centers const modalCenterX = modalBox.x + modalBox.width / 2; const modalCenterY = modalBox.y + modalBox.height / 2; const viewportCenterX = MOBILE_VIEWPORT.width / 2; const viewportCenterY = MOBILE_VIEWPORT.height / 2; console.log(`\n๐ŸŽฏ Centering Analysis:`); console.log(` โ€ข Modal center X: ${modalCenterX.toFixed(2)}px`); console.log(` โ€ข Viewport center X: ${viewportCenterX.toFixed(2)}px`); console.log(` โ€ข Modal center Y: ${modalCenterY.toFixed(2)}px`); console.log(` โ€ข Viewport center Y: ${viewportCenterY.toFixed(2)}px`); // Check if centered (10px tolerance) const horizontalOffset = Math.abs(modalCenterX - viewportCenterX); const verticalOffset = Math.abs(modalCenterY - viewportCenterY); const TOLERANCE = 10; console.log(`\n๐Ÿ“ Offset Analysis:`); console.log(` โ€ข Horizontal offset: ${horizontalOffset.toFixed(2)}px`); console.log(` โ€ข Vertical offset: ${verticalOffset.toFixed(2)}px`); console.log(` โ€ข Tolerance: ${TOLERANCE}px`); const isHorizontallyCentered = horizontalOffset <= TOLERANCE; const isVerticallyCentered = verticalOffset <= TOLERANCE; console.log(`\nโœ… Centering Results:`); console.log(` โ€ข Horizontally centered: ${isHorizontallyCentered ? 'โœ… YES' : 'โŒ NO'}`); console.log(` โ€ข Vertically centered: ${isVerticallyCentered ? 'โœ… YES' : 'โŒ NO'}`); // Get CSS properties const cssProps = await modal.evaluate(el => { const style = window.getComputedStyle(el); return { position: style.position, top: style.top, left: style.left, transform: style.transform }; }); console.log(`\n๐ŸŽจ CSS Properties:`); console.log(` โ€ข position: ${cssProps.position}`); console.log(` โ€ข top: ${cssProps.top}`); console.log(` โ€ข left: ${cssProps.left}`); console.log(` โ€ข transform: ${cssProps.transform}`); // Overall test results console.log(`\n๐Ÿ“Š OVERALL RESULTS:`); if (isHorizontallyCentered && isVerticallyCentered) { console.log('โœ… Modal is PROPERLY CENTERED on mobile!'); } else { console.log('โŒ Modal is NOT centered on mobile'); console.log(` Needs adjustment: ${!isHorizontallyCentered ? 'horizontal' : ''} ${!isVerticallyCentered ? 'vertical' : ''}`); } } console.log('\nโœ… Test completed successfully!\n'); } catch (error) { console.error('โŒ Test failed:', error.message); console.error(error.stack); process.exit(1); } finally { await browser.close(); } })();