#!/usr/bin/env bun /** * COLOR THEME SWITCHER TEST * ========================== * Tests color theme switcher functionality with dynamic colors * - Verifies button positioning (Download PDF and Print Friendly at top) * - Tests theme cycling (auto โ†’ light โ†’ dark โ†’ auto) * - Validates dynamic button colors per theme mode * - Confirms icon changes per theme * - Tests localStorage persistence */ import { chromium } from 'playwright'; const URL = "http://localhost:1999"; async function testColorThemeSwitcher() { console.log('๐Ÿงช COLOR THEME SWITCHER TEST\n'); console.log('='.repeat(70)); const browser = await chromium.launch({ headless: false }); const page = await browser.newPage({ viewport: { width: 1920, height: 1080 } }); const errors = []; const testResults = []; page.on('console', msg => { const text = msg.text(); if (msg.type() === 'error') { errors.push(text); console.log(`โŒ ERROR: ${text}`); } }); page.on('pageerror', err => { errors.push(err.message); console.log(`โŒ PAGE ERROR: ${err.message}`); }); console.log("\n1๏ธโƒฃ Loading page..."); await page.goto(URL); await page.waitForTimeout(2000); // ======================================================================== // TEST 1: Button Positioning // ======================================================================== console.log("\n2๏ธโƒฃ Testing button positioning..."); const themeBtn = page.locator('#color-theme-switcher'); const downloadBtn = page.locator('.download-btn'); const printBtn = page.locator('.print-friendly-btn'); const shortcutsBtn = page.locator('.shortcuts-btn'); const backToTopBtn = page.locator('.back-to-top'); const positions = {}; const buttons = [ { name: 'Download PDF', locator: downloadBtn }, { name: 'Print Friendly', locator: printBtn }, { name: 'Theme Switcher', locator: themeBtn }, { name: 'Shortcuts', locator: shortcutsBtn }, { name: 'Back to Top', locator: backToTopBtn } ]; for (const btn of buttons) { const box = await btn.locator.boundingBox(); if (box) { positions[btn.name] = box.y; } } // Verify order: smaller bottom value = higher on screen const expectedOrder = ['Download PDF', 'Print Friendly', 'Theme Switcher', 'Shortcuts', 'Back to Top']; let positionsCorrect = true; for (let i = 0; i < expectedOrder.length - 1; i++) { const current = positions[expectedOrder[i]]; const next = positions[expectedOrder[i + 1]]; if (current && next) { const isCorrect = current < next; if (!isCorrect) { positionsCorrect = false; console.log(` โŒ ${expectedOrder[i]} should be above ${expectedOrder[i + 1]}`); } } } testResults.push({ test: 'Button Positioning', passed: positionsCorrect, message: positionsCorrect ? 'Buttons in correct order (top to bottom)' : 'Button order incorrect' }); console.log(` ${positionsCorrect ? 'โœ…' : 'โŒ'} Button positioning: ${positionsCorrect ? 'CORRECT' : 'INCORRECT'}`); // ======================================================================== // TEST 2: Theme Cycling and Dynamic Colors // ======================================================================== console.log("\n3๏ธโƒฃ Testing theme cycling and dynamic colors..."); const themes = [ { name: 'auto', color: 'rgb(155, 89, 182)', icon: 'mdi:theme-light-dark' }, { name: 'light', color: 'rgb(243, 156, 18)', icon: 'mdi:white-balance-sunny' }, { name: 'dark', color: 'rgb(52, 152, 219)', icon: 'mdi:moon-waning-crescent' }, { name: 'auto', color: 'rgb(155, 89, 182)', icon: 'mdi:theme-light-dark' } // Cycle back ]; let themeTestsPassed = true; for (let i = 0; i < themes.length; i++) { const theme = themes[i]; if (i > 0) { await themeBtn.click(); await page.waitForTimeout(500); } // Get current theme mode from document const currentMode = await page.evaluate(() => document.documentElement.getAttribute('data-color-theme') ); // Get button background color const bgColor = await themeBtn.evaluate(el => window.getComputedStyle(el).backgroundColor ); // Get button data attribute const dataMode = await themeBtn.getAttribute('data-theme-mode'); // Get icon const iconName = await page.locator('#themeIcon').getAttribute('icon'); const modeMatch = currentMode === theme.name; const colorMatch = bgColor === theme.color; const dataMatch = dataMode === theme.name; const iconMatch = iconName === theme.icon; const allMatch = modeMatch && colorMatch && dataMatch && iconMatch; console.log(` ${i + 1}. Theme: ${theme.name.toUpperCase()}`); console.log(` Document mode: ${currentMode} ${modeMatch ? 'โœ“' : 'โœ—'}`); console.log(` Button data: ${dataMode} ${dataMatch ? 'โœ“' : 'โœ—'}`); console.log(` Icon: ${iconName} ${iconMatch ? 'โœ“' : 'โœ—'}`); console.log(` Color: ${bgColor} ${colorMatch ? 'โœ“' : 'โœ—'}`); console.log(` Status: ${allMatch ? 'โœ… PASS' : 'โŒ FAIL'}`); if (!allMatch) themeTestsPassed = false; } testResults.push({ test: 'Theme Cycling', passed: themeTestsPassed, message: themeTestsPassed ? 'All theme modes cycle correctly' : 'Theme cycling failed' }); testResults.push({ test: 'Dynamic Colors', passed: themeTestsPassed, message: themeTestsPassed ? 'Button colors change per theme mode' : 'Dynamic colors failed' }); // ======================================================================== // TEST 3: localStorage Persistence // ======================================================================== console.log("\n4๏ธโƒฃ Testing localStorage persistence..."); // Set to light mode await themeBtn.click(); await page.waitForTimeout(300); const storedTheme = await page.evaluate(() => localStorage.getItem('color-theme-mode') ); const persistenceWorks = storedTheme === 'light'; testResults.push({ test: 'localStorage Persistence', passed: persistenceWorks, message: persistenceWorks ? `Theme '${storedTheme}' saved to localStorage` : 'localStorage not saving theme' }); console.log(` ${persistenceWorks ? 'โœ…' : 'โŒ'} localStorage: ${persistenceWorks ? `'${storedTheme}' saved correctly` : 'FAILED'}`); // ======================================================================== // TEST SUMMARY // ======================================================================== console.log('\n' + '='.repeat(70)); console.log('๐Ÿ“Š TEST RESULTS'); console.log('='.repeat(70) + '\n'); const allPassed = testResults.every(r => r.passed); testResults.forEach(r => { console.log(` ${r.passed ? 'โœ…' : 'โŒ'} ${r.test}: ${r.message}`); }); console.log('\n' + '='.repeat(70)); if (allPassed && errors.length === 0) { console.log('\n๐ŸŽ‰ ALL COLOR THEME TESTS PASSED!\n'); await browser.close(); process.exit(0); } else { console.log('\nโŒ SOME TESTS FAILED\n'); if (errors.length > 0) { console.log(`Browser errors: ${errors.length}`); } console.log("\nBrowser will stay open for manual inspection."); console.log("Press Ctrl+C when done.\n"); await new Promise(() => {}); // Keep browser open } } await testColorThemeSwitcher();