#!/usr/bin/env bun /** * Mobile Accordion Test * ====================== * Tests the sidebar accordion functionality on mobile devices in the extended CV view. * * What this test verifies: * - Accordion headers are visible on mobile (hidden on desktop) * - Accordion opens and closes when clicked * - Content is properly shown/hidden * - Chevron icon rotates correctly * - Both left and right sidebars work */ import { chromium } from 'playwright'; const BASE_URL = 'http://localhost:1999'; const MOBILE_VIEWPORT = { width: 375, height: 667 }; // iPhone SE size async function testMobileAccordion() { console.log('๐Ÿงช Starting Mobile Accordion Test...\n'); const browser = await chromium.launch({ headless: true }); const context = await browser.newContext({ viewport: MOBILE_VIEWPORT, userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15' }); const page = await context.newPage(); let allTestsPassed = true; try { // Navigate to page with extended CV (lang param and let localStorage handle length) console.log('๐Ÿ“ฑ Loading page in mobile viewport (375x667)...'); // First, set localStorage for extended CV await page.goto(BASE_URL); await page.evaluate(() => { localStorage.setItem('cv-length', 'long'); }); // Reload with the extended CV setting await page.goto(BASE_URL, { waitUntil: 'networkidle' }); await page.waitForTimeout(1500); // Test Left Sidebar Accordion console.log('\n๐Ÿ” Testing LEFT sidebar accordion...'); const leftAccordion = await page.locator('.cv-sidebar-left .sidebar-accordion').first(); const leftHeader = await page.locator('.cv-sidebar-left .sidebar-accordion-header').first(); const leftContent = await page.locator('.cv-sidebar-left .sidebar-accordion-content').first(); const leftChevron = await page.locator('.cv-sidebar-left .sidebar-accordion-header .chevron').first(); // Check header is visible on mobile const leftHeaderVisible = await leftHeader.isVisible(); console.log(` โœ“ Left accordion header visible: ${leftHeaderVisible ? 'โœ… YES' : 'โŒ NO'}`); if (!leftHeaderVisible) allTestsPassed = false; // Check if accordion is initially open const leftInitiallyOpen = await leftAccordion.getAttribute('open'); console.log(` โœ“ Left accordion initially open: ${leftInitiallyOpen !== null ? 'โœ… YES' : 'โŒ NO'}`); // Check content is visible when open const leftContentVisible = await leftContent.isVisible(); console.log(` โœ“ Left content visible when open: ${leftContentVisible ? 'โœ… YES' : 'โŒ NO'}`); if (!leftContentVisible && leftInitiallyOpen) allTestsPassed = false; // Close the accordion console.log('\n ๐Ÿ–ฑ๏ธ Clicking left accordion to close...'); await leftHeader.click(); await page.waitForTimeout(500); // Wait for animation // Check accordion is closed const leftNowClosed = await leftAccordion.getAttribute('open'); console.log(` โœ“ Left accordion closed: ${leftNowClosed === null ? 'โœ… YES' : 'โŒ NO'}`); if (leftNowClosed !== null) allTestsPassed = false; // Check content is hidden when closed const leftContentHidden = !(await leftContent.isVisible()); console.log(` โœ“ Left content hidden when closed: ${leftContentHidden ? 'โœ… YES' : 'โŒ NO'}`); if (!leftContentHidden) allTestsPassed = false; // Open the accordion again console.log('\n ๐Ÿ–ฑ๏ธ Clicking left accordion to re-open...'); await leftHeader.click(); await page.waitForTimeout(500); // Wait for animation // Check accordion is open again const leftReopened = await leftAccordion.getAttribute('open'); console.log(` โœ“ Left accordion re-opened: ${leftReopened !== null ? 'โœ… YES' : 'โŒ NO'}`); if (leftReopened === null) allTestsPassed = false; // Check content is visible again const leftContentVisibleAgain = await leftContent.isVisible(); console.log(` โœ“ Left content visible again: ${leftContentVisibleAgain ? 'โœ… YES' : 'โŒ NO'}`); if (!leftContentVisibleAgain) allTestsPassed = false; // Test Right Sidebar Accordion console.log('\n๐Ÿ” Testing RIGHT sidebar accordion...'); const rightAccordion = await page.locator('.cv-sidebar-right .sidebar-accordion').first(); const rightHeader = await page.locator('.cv-sidebar-right .sidebar-accordion-header').first(); const rightContent = await page.locator('.cv-sidebar-right .sidebar-accordion-content').first(); const rightChevron = await page.locator('.cv-sidebar-right .sidebar-accordion-header .chevron').first(); // Check header is visible on mobile const rightHeaderVisible = await rightHeader.isVisible(); console.log(` โœ“ Right accordion header visible: ${rightHeaderVisible ? 'โœ… YES' : 'โŒ NO'}`); if (!rightHeaderVisible) allTestsPassed = false; // Close and re-open right accordion console.log('\n ๐Ÿ–ฑ๏ธ Clicking right accordion to close...'); await rightHeader.click(); await page.waitForTimeout(500); const rightClosed = await rightAccordion.getAttribute('open'); console.log(` โœ“ Right accordion closed: ${rightClosed === null ? 'โœ… YES' : 'โŒ NO'}`); if (rightClosed !== null) allTestsPassed = false; console.log('\n ๐Ÿ–ฑ๏ธ Clicking right accordion to re-open...'); await rightHeader.click(); await page.waitForTimeout(500); const rightReopened = await rightAccordion.getAttribute('open'); console.log(` โœ“ Right accordion re-opened: ${rightReopened !== null ? 'โœ… YES' : 'โŒ NO'}`); if (rightReopened === null) allTestsPassed = false; // Test styling console.log('\n๐ŸŽจ Testing accordion styling...'); const leftHeaderStyles = await leftHeader.evaluate(el => { const styles = window.getComputedStyle(el); return { display: styles.display, background: styles.backgroundColor, padding: styles.padding, cursor: styles.cursor, borderRadius: styles.borderRadius }; }); console.log(` โœ“ Header display: ${leftHeaderStyles.display === 'flex' ? 'โœ… flex' : 'โŒ ' + leftHeaderStyles.display}`); console.log(` โœ“ Header background: ${leftHeaderStyles.background}`); console.log(` โœ“ Header cursor: ${leftHeaderStyles.cursor === 'pointer' ? 'โœ… pointer' : 'โŒ ' + leftHeaderStyles.cursor}`); if (leftHeaderStyles.display !== 'flex' || leftHeaderStyles.cursor !== 'pointer') { allTestsPassed = false; } // Take screenshot console.log('\n๐Ÿ“ธ Taking screenshot...'); await page.screenshot({ path: 'tests/screenshots/mobile-accordion-extended.png', fullPage: true }); console.log(' Saved: tests/screenshots/mobile-accordion-extended.png'); } catch (error) { console.error('\nโŒ Test failed with error:', error); allTestsPassed = false; } finally { await browser.close(); } // Final result console.log('\n' + '='.repeat(50)); if (allTestsPassed) { console.log('โœ… ALL MOBILE ACCORDION TESTS PASSED!'); console.log('='.repeat(50)); process.exit(0); } else { console.log('โŒ SOME MOBILE ACCORDION TESTS FAILED'); console.log('='.repeat(50)); process.exit(1); } } // Run test testMobileAccordion();