Files
cv-site/tests/mjs/43-info-modal-mobile-font-test.mjs
T

176 lines
7.7 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
/**
* Test: Info Modal Mobile Font Sizes
* Purpose: Verify that all font sizes in the info modal are appropriately sized for mobile
* Date: 2025-11-27
*/
import { launch } from 'puppeteer';
const BASE_URL = process.env.CV_TEST_URL || 'http://localhost:1999';
const MOBILE_WIDTH = 375; // iPhone SE width
const MOBILE_HEIGHT = 667; // iPhone SE height
async function testInfoModalMobileFonts() {
console.log('🧪 Testing Info Modal Mobile Font Sizes...\n');
const browser = await launch({
headless: false, // Show browser for visual verification
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
// Set mobile viewport
await page.setViewport({
width: MOBILE_WIDTH,
height: MOBILE_HEIGHT,
isMobile: true,
hasTouch: true
});
try {
// Navigate to the CV page
console.log(`📱 Navigating to ${BASE_URL}?lang=en (Mobile: ${MOBILE_WIDTH}x${MOBILE_HEIGHT})`);
await page.goto(`${BASE_URL}?lang=en`, { waitUntil: 'networkidle0' });
// Wait for info button to be visible
await page.waitForSelector('#info-button', { visible: true });
console.log('✅ Info button found');
// Click the info button to open modal
console.log('🖱️ Opening info modal...');
await page.click('#info-button');
// Wait for modal to appear
await page.waitForSelector('#info-modal[open]', { visible: true, timeout: 3000 });
console.log('✅ Info modal opened');
// Wait a bit for animation
await new Promise(resolve => setTimeout(resolve, 500));
// Take screenshot of the modal
await page.screenshot({
path: '/Users/txeo/Git/yo/cv/tests/screenshots/info-modal-mobile-fonts.png',
fullPage: false
});
console.log('📸 Screenshot saved: tests/screenshots/info-modal-mobile-fonts.png');
// Check font sizes of key elements
const fontSizes = await page.evaluate(() => {
const getComputedFontSize = (selector) => {
const element = document.querySelector(selector);
if (!element) return null;
return window.getComputedStyle(element).fontSize;
};
return {
title: getComputedFontSize('.info-modal-header h2'),
cvTitle: getComputedFontSize('.info-modal-cv-title'),
description: getComputedFontSize('.info-modal-description'),
techItem: getComputedFontSize('.info-tech-item span'),
githubButton: getComputedFontSize('.info-modal-github'),
githubSubtext: getComputedFontSize('.info-modal-github-subtext'),
bracket: getComputedFontSize('.photo-bracket-wrapper::before') ||
getComputedFontSize('.photo-bracket-wrapper'),
closeButton: (() => {
const btn = document.querySelector('.info-modal-close');
if (!btn) return null;
return `${btn.offsetWidth}x${btn.offsetHeight}`;
})()
};
});
console.log('\n📏 Font Sizes on Mobile:');
console.log(' • Title (h2):', fontSizes.title, '(expected: ~17.6px / 1.1rem)');
console.log(' • CV Title:', fontSizes.cvTitle, '(expected: 16px / 1rem)');
console.log(' • Description:', fontSizes.description, '(expected: ~13.6px / 0.85rem)');
console.log(' • Tech Items:', fontSizes.techItem, '(expected: ~12.8px / 0.8rem)');
console.log(' • GitHub Button:', fontSizes.githubButton, '(expected: 14px / 0.875rem)');
console.log(' • GitHub Subtext:', fontSizes.githubSubtext, '(expected: ~12.8px / 0.8rem)');
console.log(' • Close Button Size:', fontSizes.closeButton, '(expected: 32x32)');
// Check modal dimensions
const modalDimensions = await page.evaluate(() => {
const modal = document.querySelector('#info-modal');
const content = document.querySelector('.info-modal-content');
if (!modal || !content) return null;
const modalRect = modal.getBoundingClientRect();
const contentRect = content.getBoundingClientRect();
return {
modal: {
width: Math.round(modalRect.width),
height: Math.round(modalRect.height),
top: Math.round(modalRect.top),
left: Math.round(modalRect.left)
},
content: {
width: Math.round(contentRect.width),
height: Math.round(contentRect.height),
padding: window.getComputedStyle(content).padding
}
};
});
console.log('\n📐 Modal Dimensions:');
console.log(' • Modal:', `${modalDimensions.modal.width}x${modalDimensions.modal.height}px`);
console.log(' • Position:', `top: ${modalDimensions.modal.top}px, left: ${modalDimensions.modal.left}px`);
console.log(' • Content:', `${modalDimensions.content.width}x${modalDimensions.content.height}px`);
console.log(' • Content Padding:', modalDimensions.content.padding);
console.log(' • Viewport:', `${MOBILE_WIDTH}x${MOBILE_HEIGHT}px`);
// Check if modal fits within viewport
const fitsInViewport =
modalDimensions.modal.width <= MOBILE_WIDTH &&
modalDimensions.modal.height <= MOBILE_HEIGHT;
console.log('\n🎯 Modal Fit Test:');
if (fitsInViewport) {
console.log(' ✅ Modal fits within mobile viewport');
} else {
console.log(' ❌ Modal DOES NOT fit within viewport!');
console.log(` Width: ${modalDimensions.modal.width} > ${MOBILE_WIDTH} = ${modalDimensions.modal.width > MOBILE_WIDTH}`);
console.log(` Height: ${modalDimensions.modal.height} > ${MOBILE_HEIGHT} = ${modalDimensions.modal.height > MOBILE_HEIGHT}`);
}
// Check for overflow
const hasOverflow = await page.evaluate(() => {
const content = document.querySelector('.info-modal-content');
if (!content) return false;
return content.scrollHeight > content.clientHeight;
});
console.log(' • Content Overflow:', hasOverflow ? '⚠️ Yes (scrollable)' : '✅ No');
// Parse font sizes and validate they're smaller than desktop
const parsePx = (sizeStr) => parseFloat(sizeStr);
const titlePx = parsePx(fontSizes.title);
const cvTitlePx = parsePx(fontSizes.cvTitle);
const descriptionPx = parsePx(fontSizes.description);
const techItemPx = parsePx(fontSizes.techItem);
console.log('\n✅ Validation:');
console.log(' • Title < 20px:', titlePx < 20 ? '✅' : '❌', `(${titlePx.toFixed(1)}px)`);
console.log(' • CV Title ≈ 16px:', Math.abs(cvTitlePx - 16) < 2 ? '✅' : '❌', `(${cvTitlePx.toFixed(1)}px)`);
console.log(' • Description < 15px:', descriptionPx < 15 ? '✅' : '❌', `(${descriptionPx.toFixed(1)}px)`);
console.log(' • Tech Items ≈ 12.8px:', Math.abs(techItemPx - 12.8) < 2 ? '✅' : '❌', `(${techItemPx.toFixed(1)}px)`);
// Keep browser open for manual inspection
console.log('\n👀 Browser kept open for visual inspection...');
console.log(' Press Ctrl+C to close when done.\n');
// Wait indefinitely
await new Promise(() => {});
} catch (error) {
console.error('❌ Test failed:', error.message);
await browser.close();
process.exit(1);
}
}
testInfoModalMobileFonts();