Files
cv-site/tests/mjs/66-comprehensive-all-viewports-test.mjs
T
juanatsap 015863d426 test: Update comprehensive test to handle back-to-top button behavior
The back-to-top button is intentionally hidden on page load and only
appears after scrolling down. This is expected behavior, not a bug.
Updated test to not flag this as an issue.
2025-11-25 06:02:09 +00:00

216 lines
10 KiB
JavaScript
Executable File
Raw 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';
const VIEWPORTS = {
desktop: { width: 1278, height: 800, name: 'Desktop (1278px)' },
portraitMobile: { width: 375, height: 667, name: 'Portrait Mobile (375×667)' },
landscapeMobile: { width: 667, height: 375, name: 'Landscape Mobile (667×375)' }
};
async function testViewport(browser, viewport) {
const context = await browser.newContext({
viewport,
userAgent: viewport.width < 768 ? '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' : undefined,
hasTouch: viewport.width < 768
});
const page = await context.newPage();
await page.goto('http://localhost:1999/?lang=en&view=extended');
await page.waitForLoadState('networkidle');
const results = await page.evaluate(() => {
// Page 1 - Left Sidebar
const sidebarLeft = document.querySelector('.cv-sidebar-left');
const accordionLeft = sidebarLeft?.querySelector('.sidebar-accordion');
const accordionContentLeft = sidebarLeft?.querySelector('.sidebar-accordion-content');
// Page 2 - Right Sidebar (scroll to it first)
document.querySelector('.page-2')?.scrollIntoView();
const sidebarRight = document.querySelector('.cv-sidebar-right');
const accordionRight = sidebarRight?.querySelector('.sidebar-accordion');
const accordionContentRight = sidebarRight?.querySelector('.sidebar-accordion-content');
// Buttons
const downloadBtn = document.querySelector('.download-btn');
const printBtn = document.querySelector('.print-friendly-btn');
const infoBtn = document.querySelector('.info-button');
const backToTop = document.querySelector('.back-to-top');
const themeSwitcher = document.querySelector('.color-theme-switcher');
const backdrop = document.querySelector('.fixed-buttons-backdrop');
const sidebarLeftRect = sidebarLeft?.getBoundingClientRect();
const sidebarRightRect = sidebarRight?.getBoundingClientRect();
return {
viewport: {
width: window.innerWidth,
height: window.innerHeight,
isPortrait: window.innerHeight > window.innerWidth,
isLandscape: window.innerWidth > window.innerHeight
},
mediaQueries: {
desktop: window.matchMedia('(min-width: 769px)').matches,
mobile: window.matchMedia('(max-width: 768px)').matches,
landscape: window.matchMedia('(max-width: 915px) and (orientation: landscape)').matches,
},
leftSidebar: {
exists: !!sidebarLeft,
visible: sidebarLeft && window.getComputedStyle(sidebarLeft).display !== 'none',
height: sidebarLeftRect ? Math.round(sidebarLeftRect.height) : 0,
accordionOpen: accordionLeft?.hasAttribute('open'),
contentHeight: accordionContentLeft ? Math.round(accordionContentLeft.getBoundingClientRect().height) : 0,
},
rightSidebar: {
exists: !!sidebarRight,
visible: sidebarRight && window.getComputedStyle(sidebarRight).display !== 'none',
height: sidebarRightRect ? Math.round(sidebarRightRect.height) : 0,
accordionOpen: accordionRight?.hasAttribute('open'),
contentHeight: accordionContentRight ? Math.round(accordionContentRight.getBoundingClientRect().height) : 0,
},
buttons: {
downloadBtn: {
exists: !!downloadBtn,
visible: downloadBtn && window.getComputedStyle(downloadBtn).display !== 'none',
bottom: downloadBtn ? window.getComputedStyle(downloadBtn).bottom : 'N/A',
zIndex: downloadBtn ? window.getComputedStyle(downloadBtn).zIndex : 'N/A',
},
printBtn: {
exists: !!printBtn,
visible: printBtn && window.getComputedStyle(printBtn).display !== 'none',
},
infoBtn: {
exists: !!infoBtn,
visible: infoBtn && window.getComputedStyle(infoBtn).display !== 'none',
},
backToTop: {
exists: !!backToTop,
visible: backToTop && window.getComputedStyle(backToTop).display !== 'none',
},
themeSwitcher: {
exists: !!themeSwitcher,
visible: themeSwitcher && window.getComputedStyle(themeSwitcher).display !== 'none',
opacity: themeSwitcher ? window.getComputedStyle(themeSwitcher).opacity : 'N/A',
},
backdrop: {
exists: !!backdrop,
visible: backdrop && window.getComputedStyle(backdrop).display !== 'none',
height: backdrop ? window.getComputedStyle(backdrop).height : 'N/A',
},
}
};
});
await page.screenshot({
path: `tests/screenshots/comprehensive-${viewport.name.toLowerCase().replace(/[^a-z0-9]/g, '-')}.png`,
fullPage: true
});
await context.close();
return results;
}
(async () => {
const browser = await chromium.launch({ headless: true });
console.log('🧪 Comprehensive Multi-Viewport Test\n');
console.log('Testing: Sidebars, Accordions, and Buttons\n');
const allResults = {};
const failures = [];
for (const [key, viewport] of Object.entries(VIEWPORTS)) {
console.log(`📱 Testing: ${viewport.name}`);
console.log('='.repeat(50));
const results = await testViewport(browser, viewport);
allResults[key] = results;
// Print results
console.log(`\nViewport: ${results.viewport.width}×${results.viewport.height}`);
console.log(`Orientation: ${results.viewport.isLandscape ? 'Landscape' : 'Portrait'}\n`);
console.log('Left Sidebar:');
console.log(` • Exists: ${results.leftSidebar.exists ? '✅' : '❌'}`);
console.log(` • Visible: ${results.leftSidebar.visible ? '✅' : '❌'}`);
console.log(` • Height: ${results.leftSidebar.height}px`);
console.log(` • Accordion open: ${results.leftSidebar.accordionOpen ? '✅' : '❌'}`);
console.log(` • Content height: ${results.leftSidebar.contentHeight}px\n`);
console.log('Right Sidebar:');
console.log(` • Exists: ${results.rightSidebar.exists ? '✅' : '❌'}`);
console.log(` • Visible: ${results.rightSidebar.visible ? '✅' : '❌'}`);
console.log(` • Height: ${results.rightSidebar.height}px`);
console.log(` • Accordion open: ${results.rightSidebar.accordionOpen ? '✅' : '❌'}`);
console.log(` • Content height: ${results.rightSidebar.contentHeight}px\n`);
console.log('Buttons:');
console.log(` • Download button: ${results.buttons.downloadBtn.exists && results.buttons.downloadBtn.visible ? '✅' : '❌'}`);
console.log(` • Print button: ${results.buttons.printBtn.exists && results.buttons.printBtn.visible ? '✅' : '❌'}`);
console.log(` • Info button: ${results.buttons.infoBtn.exists && results.buttons.infoBtn.visible ? '✅' : '❌'}`);
console.log(` • Back to top: ${results.buttons.backToTop.exists && results.buttons.backToTop.visible ? '✅' : '❌'}`);
console.log(` • Theme switcher: ${results.buttons.themeSwitcher.exists && results.buttons.themeSwitcher.visible ? '✅' : '❌'}`);
console.log(` • Backdrop: ${results.buttons.backdrop.exists && results.buttons.backdrop.visible ? '✅' : '❌'}\n`);
// Validation rules
const issues = [];
// Desktop: Sidebars should be open with content
if (results.mediaQueries.desktop) {
if (!results.leftSidebar.accordionOpen) issues.push('Desktop: Left sidebar accordion should be open');
if (!results.rightSidebar.accordionOpen) issues.push('Desktop: Right sidebar accordion should be open');
if (results.leftSidebar.contentHeight < 100) issues.push('Desktop: Left sidebar has no content');
if (results.rightSidebar.contentHeight < 100) issues.push('Desktop: Right sidebar has no content');
}
// Landscape mobile: Sidebars should be open
if (results.mediaQueries.landscape) {
if (!results.leftSidebar.accordionOpen) issues.push('Landscape: Left sidebar accordion should be open');
if (!results.rightSidebar.accordionOpen) issues.push('Landscape: Right sidebar accordion should be open');
if (results.leftSidebar.contentHeight < 100) issues.push('Landscape: Left sidebar has no content');
}
// All viewports: Buttons should be visible
if (!results.buttons.downloadBtn.visible) issues.push('Download button not visible');
if (!results.buttons.printBtn.visible) issues.push('Print button not visible');
if (!results.buttons.infoBtn.visible) issues.push('Info button not visible');
// Note: Back to top button may not be visible on page load (only shows after scrolling)
// This is expected behavior, so we don't flag it as an issue
if (!results.buttons.themeSwitcher.visible) issues.push('Theme switcher not visible');
// Mobile: Backdrop should be visible
if (results.mediaQueries.mobile || results.mediaQueries.landscape) {
if (!results.buttons.backdrop.visible) issues.push('Mobile: Button backdrop not visible');
}
if (issues.length > 0) {
console.log('❌ ISSUES FOUND:');
issues.forEach(issue => {
console.log(` - ${issue}`);
failures.push(`${viewport.name}: ${issue}`);
});
} else {
console.log('✅ All checks passed');
}
console.log('\n');
}
// Final summary
console.log('='.repeat(50));
console.log('FINAL SUMMARY\n');
if (failures.length === 0) {
console.log('✅ ALL VIEWPORTS PASSED ALL CHECKS\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);
})();