#!/usr/bin/env node import { chromium } from 'playwright'; const MOBILE_VIEWPORT = { width: 375, height: 667 }; (async () => { const browser = await chromium.launch({ headless: true }); console.log('๐Ÿงช Testing Final Mobile Fixes\n'); // Test with iPhone user agent (real mobile device) const context = 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 page = await context.newPage(); await page.goto('http://localhost:1999/?lang=en&view=extended'); await page.waitForLoadState('networkidle'); // FIX 1: Check button reorganization (no gap from hidden shortcuts) console.log('๐Ÿ“ฑ FIX 1: Button Reorganization (5 buttons, no gap)\n'); const buttonPositions = await page.evaluate(() => { const buttons = { download: document.querySelector('.download-btn'), print: document.querySelector('.print-friendly-btn'), theme: document.querySelector('.color-theme-switcher'), info: document.querySelector('.info-button'), backToTop: document.querySelector('.back-to-top'), shortcuts: document.querySelector('.shortcuts-btn') }; const positions = {}; for (const [name, btn] of Object.entries(buttons)) { if (btn) { const rect = btn.getBoundingClientRect(); const computed = window.getComputedStyle(btn); positions[name] = { left: Math.round(rect.left), visible: computed.display !== 'none' }; } } return positions; }); console.log('Button Positions:'); Object.entries(buttonPositions).forEach(([name, pos]) => { console.log(` โ€ข ${name}: ${pos.visible ? 'VISIBLE' : 'HIDDEN'} at ${pos.left}px from left`); }); const shortcutsHidden = !buttonPositions.shortcuts.visible; const buttonsEvenlySpaced = Math.abs( (buttonPositions.print.left - buttonPositions.download.left) - 60 ) < 5; // Should be ~60px apart console.log(`\n Shortcuts hidden: ${shortcutsHidden ? 'โœ…' : 'โŒ'}`); console.log(` Buttons evenly spaced: ${buttonsEvenlySpaced ? 'โœ…' : 'โŒ'}\n`); // FIX 2: Check info button is BLUE (not green) console.log('๐ŸŽจ FIX 2: Info Button Color (Blue vs Green)\n'); const buttonColors = await page.evaluate(() => { const info = document.querySelector('.info-button'); const backToTop = document.querySelector('.back-to-top'); const infoStyles = window.getComputedStyle(info); const backToTopStyles = window.getComputedStyle(backToTop); return { info: { background: infoStyles.backgroundColor, opacity: infoStyles.opacity }, backToTop: { background: backToTopStyles.backgroundColor, opacity: backToTopStyles.opacity } }; }); console.log('Info Button:'); console.log(` โ€ข Background: ${buttonColors.info.background}`); console.log(` โ€ข Opacity: ${buttonColors.info.opacity}`); console.log(` โ€ข Expected: rgb(52, 152, 219) - Blue\n`); console.log('Back-to-Top Button:'); console.log(` โ€ข Background: ${buttonColors.backToTop.background}`); console.log(` โ€ข Opacity: ${buttonColors.backToTop.opacity}`); console.log(` โ€ข Expected: rgb(39, 174, 96) - Green\n`); const infoIsBlue = buttonColors.info.background.includes('52, 152, 219') || buttonColors.info.background.includes('52,152,219'); const backToTopIsGreen = buttonColors.backToTop.background.includes('39, 174, 96') || buttonColors.backToTop.background.includes('39,174,96'); const differentColors = buttonColors.info.background !== buttonColors.backToTop.background; console.log(` Info is blue: ${infoIsBlue ? 'โœ…' : 'โŒ'}`); console.log(` Back-to-top is green: ${backToTopIsGreen ? 'โœ…' : 'โŒ'}`); console.log(` Different colors: ${differentColors ? 'โœ…' : 'โŒ'}\n`); // FIX 3: Check theme button full opacity console.log('๐ŸŒˆ FIX 3: Theme Button Transparency\n'); const themeButtonStyles = await page.evaluate(() => { const theme = document.querySelector('.color-theme-switcher'); const computed = window.getComputedStyle(theme); const bg = computed.backgroundColor; // Extract rgba values const match = bg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/); const alpha = match && match[4] ? parseFloat(match[4]) : 1.0; return { background: bg, opacity: computed.opacity, alpha: alpha, themeMode: theme.getAttribute('data-theme-mode') }; }); console.log('Theme Button:'); console.log(` โ€ข Mode: ${themeButtonStyles.themeMode}`); console.log(` โ€ข Background: ${themeButtonStyles.background}`); console.log(` โ€ข Opacity: ${themeButtonStyles.opacity}`); console.log(` โ€ข Alpha: ${themeButtonStyles.alpha}`); const themeFullOpacity = parseFloat(themeButtonStyles.opacity) === 1.0 && themeButtonStyles.alpha === 1.0; console.log(` โ€ข Full opacity: ${themeFullOpacity ? 'โœ…' : 'โŒ'}\n`); // Take screenshot await page.screenshot({ path: 'tests/screenshots/final-mobile-fixes.png', fullPage: true }); console.log('๐Ÿ“ธ Screenshot: tests/screenshots/final-mobile-fixes.png\n'); const allPassed = shortcutsHidden && buttonsEvenlySpaced && infoIsBlue && differentColors && themeFullOpacity; console.log(`${allPassed ? 'โœ…' : 'โŒ'} Tests ${allPassed ? 'PASSED' : 'FAILED'}\n`); await browser.close(); process.exit(allPassed ? 0 : 1); })();