Files
cv-site/tests/mjs/66-comprehensive-all-viewports-test.mjs
T
juanatsap 76d80edd7e fix: Remove unused cookie helper functions and fix desktop sidebar visibility
1. Removed unused getPreferenceCookie and setPreferenceCookie functions
   - These were flagged by golangci-lint as unused
   - Cookie preferences now handled client-side via localStorage
   - Removed unused net/http import

2. Fixed desktop sidebar accordion auto-opening
   - Updated handleLandscapeAccordions() to open accordions in desktop view (≥769px)
   - Sidebars now show content in desktop, landscape mobile, and portrait mobile
   - Only keep accordions collapsed in portrait mobile for space saving

3. Created comprehensive multi-viewport test (66-comprehensive-all-viewports-test.mjs)
   - Tests desktop (1278px), portrait mobile (375×667), landscape mobile (667×375)
   - Validates sidebars, accordion state, content visibility, AND all buttons
   - Checks button backdrop visibility in mobile views
   - Every feature now has corresponding test coverage

Fixes golangci-lint errors:
- internal/handlers/cv_helpers.go:366: func getPreferenceCookie is unused
- internal/handlers/cv_helpers.go:375: func setPreferenceCookie is unused
- internal/handlers/cv_helpers.go:7: net/http imported and not used
2025-11-25 06:00:39 +00:00

215 lines
10 KiB
JavaScript
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');
if (!results.buttons.backToTop.visible) issues.push('Back to top button not visible');
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);
})();