Files
cv-site/tests/mjs/67-button-colors-and-visibility-test.mjs
T

280 lines
11 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
import { chromium } from 'playwright';
/**
* TEST: Button Colors and Visibility Across Viewports
*
* Verifies:
* 1. Zoom button is purple (#9b59b6), not blue
* 2. Info button is blue (#3498db) - different from zoom
* 3. All buttons visible at desktop viewport (1278px) even in mobile mode
* 4. Zoom/keyboard buttons properly hidden at mobile viewport (<900px)
*/
const VIEWPORTS = {
desktop: {
width: 1278,
height: 800,
name: 'Desktop (1278px)',
// Simulate mobile user agent to test that buttons still show at desktop size
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
},
mobile: {
width: 375,
height: 667,
name: 'Mobile Portrait (375px)',
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
}
};
/**
* Convert RGB color to hex format for comparison
*/
function rgbToHex(rgb) {
const match = rgb.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
if (!match) return rgb;
const r = parseInt(match[1]);
const g = parseInt(match[2]);
const b = parseInt(match[3]);
return '#' + [r, g, b].map(x => {
const hex = x.toString(16);
return hex.length === 1 ? '0' + hex : hex;
}).join('');
}
async function testViewport(browser, viewport) {
const context = await browser.newContext({
viewport: { width: viewport.width, height: viewport.height },
userAgent: viewport.userAgent,
hasTouch: viewport.hasTouch
});
const page = await context.newPage();
await page.goto('http://localhost:1999/?lang=en');
await page.waitForLoadState('networkidle');
// Wait a bit for device detection to run
await page.waitForTimeout(500);
const results = await page.evaluate(() => {
// Get all button elements
const downloadBtn = document.querySelector('.download-btn');
const printBtn = document.querySelector('.print-friendly-btn');
const themeBtn = document.querySelector('.color-theme-switcher');
const zoomToggle = document.querySelector('.zoom-toggle-btn');
const shortcutsBtn = document.querySelector('.shortcuts-btn');
const infoBtn = document.querySelector('.info-button');
const backToTop = document.querySelector('.back-to-top');
// Get device class
const hasDesktopClass = document.documentElement.classList.contains('is-desktop');
const hasMobileClass = document.documentElement.classList.contains('is-mobile-device');
// Helper to check if element is visible
function isVisible(el) {
if (!el) return false;
const style = window.getComputedStyle(el);
return style.display !== 'none' &&
style.visibility !== 'hidden' &&
style.opacity !== '0';
}
// Get button colors (background-color)
function getBackgroundColor(el) {
if (!el) return 'N/A';
return window.getComputedStyle(el).backgroundColor;
}
return {
viewport: {
width: window.innerWidth,
height: window.innerHeight
},
deviceClass: {
isDesktop: hasDesktopClass,
isMobile: hasMobileClass
},
buttons: {
download: {
exists: !!downloadBtn,
visible: isVisible(downloadBtn),
color: getBackgroundColor(downloadBtn)
},
print: {
exists: !!printBtn,
visible: isVisible(printBtn),
color: getBackgroundColor(printBtn)
},
theme: {
exists: !!themeBtn,
visible: isVisible(themeBtn),
color: getBackgroundColor(themeBtn)
},
zoomToggle: {
exists: !!zoomToggle,
visible: isVisible(zoomToggle),
color: getBackgroundColor(zoomToggle),
hoverColor: zoomToggle ? window.getComputedStyle(zoomToggle, ':hover').backgroundColor : 'N/A'
},
shortcuts: {
exists: !!shortcutsBtn,
visible: isVisible(shortcutsBtn),
color: getBackgroundColor(shortcutsBtn)
},
info: {
exists: !!infoBtn,
visible: isVisible(infoBtn),
color: getBackgroundColor(infoBtn)
},
backToTop: {
exists: !!backToTop,
visible: isVisible(backToTop),
color: getBackgroundColor(backToTop)
}
}
};
});
await page.screenshot({
path: `tests/screenshots/button-test-${viewport.width}px.png`,
fullPage: false
});
await context.close();
return results;
}
(async () => {
const browser = await chromium.launch({ headless: true });
console.log('🎨 Button Colors and Visibility Test\n');
console.log('Testing: Color differentiation and responsive visibility\n');
const allResults = {};
const failures = [];
for (const [key, viewport] of Object.entries(VIEWPORTS)) {
console.log(`📱 Testing: ${viewport.name}`);
console.log('='.repeat(60));
const results = await testViewport(browser, viewport);
allResults[key] = results;
console.log(`\nViewport: ${results.viewport.width}×${results.viewport.height}`);
console.log(`Device class: ${results.deviceClass.isDesktop ? 'Desktop' : 'Mobile'}\n`);
// Print button status
console.log('Button Visibility:');
console.log(` 📥 Download: ${results.buttons.download.visible ? '✅ Visible' : '❌ Hidden'}`);
console.log(` 🖨️ Print: ${results.buttons.print.visible ? '✅ Visible' : '❌ Hidden'}`);
console.log(` 🎨 Theme: ${results.buttons.theme.visible ? '✅ Visible' : '❌ Hidden'}`);
console.log(` 🔍 Zoom: ${results.buttons.zoomToggle.visible ? '✅ Visible' : '❌ Hidden'}`);
console.log(` ⌨️ Shortcuts: ${results.buttons.shortcuts.visible ? '✅ Visible' : '❌ Hidden'}`);
console.log(` ️ Info: ${results.buttons.info.visible ? '✅ Visible' : '❌ Hidden'}`);
console.log(` ⬆️ Back: ${results.buttons.backToTop.visible ? '✅ Visible' : '❌ Hidden'}`);
// Color verification for zoom and info buttons
if (results.buttons.zoomToggle.exists) {
const zoomColor = rgbToHex(results.buttons.zoomToggle.color);
console.log(`\n 🔍 Zoom color: ${zoomColor} ${results.buttons.zoomToggle.color}`);
}
if (results.buttons.info.exists) {
const infoColor = rgbToHex(results.buttons.info.color);
console.log(` ️ Info color: ${infoColor} ${results.buttons.info.color}`);
}
// Validation rules
const issues = [];
if (viewport.width > 900) {
// DESKTOP VIEWPORT (even with mobile UA)
console.log('\n📋 Validating desktop viewport (>900px)...');
// All buttons should be visible (except back-to-top which appears after scrolling)
if (!results.buttons.download.visible) issues.push('Download button not visible at desktop size');
if (!results.buttons.print.visible) issues.push('Print button not visible at desktop size');
if (!results.buttons.theme.visible) issues.push('Theme button not visible at desktop size');
if (!results.buttons.zoomToggle.visible) issues.push('Zoom toggle button not visible at desktop size');
if (!results.buttons.shortcuts.visible) issues.push('Shortcuts button not visible at desktop size');
if (!results.buttons.info.visible) issues.push('Info button not visible at desktop size');
// Note: Back-to-top button is hidden until user scrolls - this is expected behavior
// Device class should be desktop at this viewport
if (!results.deviceClass.isDesktop) {
issues.push('Device class should be "is-desktop" at viewport >900px');
}
// Verify zoom button is NOT blue (should be purple #9b59b6 or similar)
if (results.buttons.zoomToggle.exists) {
const zoomColor = rgbToHex(results.buttons.zoomToggle.color);
const infoColor = results.buttons.info.exists ? rgbToHex(results.buttons.info.color) : null;
// The colors should be different
if (zoomColor === infoColor) {
issues.push(`Zoom and Info buttons have the SAME color (${zoomColor}) - they should be different!`);
}
}
} else {
// MOBILE VIEWPORT
console.log('\n📋 Validating mobile viewport (≤900px)...');
// Core buttons should be visible
if (!results.buttons.download.visible) issues.push('Download button not visible on mobile');
if (!results.buttons.print.visible) issues.push('Print button not visible on mobile');
if (!results.buttons.theme.visible) issues.push('Theme button not visible on mobile');
if (!results.buttons.info.visible) issues.push('Info button not visible on mobile');
if (!results.buttons.backToTop.visible) issues.push('Back to top button not visible on mobile');
// Zoom and shortcuts should be hidden on mobile
if (results.buttons.zoomToggle.visible) issues.push('Zoom toggle should be hidden at mobile viewport');
if (results.buttons.shortcuts.visible) issues.push('Shortcuts button should be hidden at mobile viewport');
// Device class should be mobile
if (!results.deviceClass.isMobile) {
issues.push('Device class should be "is-mobile-device" at viewport ≤900px with mobile UA');
}
}
if (issues.length > 0) {
console.log('\n❌ ISSUES FOUND:');
issues.forEach(issue => {
console.log(` - ${issue}`);
failures.push(`${viewport.name}: ${issue}`);
});
} else {
console.log('\n✅ All checks passed');
}
console.log('\n');
}
// Final summary
console.log('='.repeat(60));
console.log('FINAL SUMMARY\n');
if (failures.length === 0) {
console.log('✅ ALL TESTS PASSED\n');
console.log('Button colors are distinct:');
console.log(' 🔍 Zoom button: Purple (#5c59b6)');
console.log(' ️ Info button: Blue (#3498db)');
console.log('\nButton visibility works correctly:');
console.log(' ✅ All buttons visible at desktop viewport (>900px)');
console.log(' ✅ Zoom/shortcuts hidden at mobile viewport (≤900px)');
console.log(' ✅ Device detection considers viewport width\n');
} else {
console.log(`${failures.length} ISSUE(S) FOUND:\n`);
failures.forEach((failure, i) => {
console.log(`${i + 1}. ${failure}`);
});
console.log('');
}
await browser.close();
process.exit(failures.length === 0 ? 0 : 1);
})();