Files
cv-site/tests/mjs/67-button-colors-and-visibility-test.mjs
juanatsap 566ec1431c fix: Update zoom button to preferred purple shade #5c59b6
Changed zoom button color from #9b59b6 to #5c59b6 for better visual appeal.
The new shade is more blue-tinted, creating a vibrant indigo/periwinkle appearance
that remains distinct from the info button blue.

Changes:
- Updated zoom-toggle-btn background: rgba(92, 89, 182, 0.7)
- Updated hover state: #5c59b6
- Updated at-bottom state: #5c59b6
- Updated test output to reflect correct hex code

Test verified: All buttons visible and colors distinct at all viewports.
2025-11-25 06:49:24 +00:00

280 lines
11 KiB
JavaScript
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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);
})();