const { chromium } = require('playwright'); const fs = require('fs'); const path = require('path'); async function testCalendarThemes() { console.log('šŸš€ Starting Calendar Theme Screenshot Test...\n'); const browser = await chromium.launch({ headless: true, // Run in headless mode for CI/server environments args: ['--disable-web-security', '--disable-features=VizDisplayCompositor'] }); const context = await browser.newContext({ viewport: { width: 1280, height: 720 }, bypassCSP: true }); const page = await context.newPage(); try { // Navigate to calendar page using the provided URL console.log('šŸ“ Navigating to calendar page...'); await page.goto('http://192.168.0.46:3000/calendar', { waitUntil: 'networkidle', timeout: 30000 }); // Wait for page to be fully loaded await page.waitForSelector('#theme-toggle', { timeout: 10000 }); console.log('āœ… Calendar page loaded successfully'); // Wait a moment for any animations to settle await page.waitForTimeout(2000); // 1. Take screenshot of initial theme (should be dark by default) console.log('\nšŸŽØ Testing Initial Theme (Dark Mode)...'); await page.screenshot({ path: 'calendar-dark-mode.png', fullPage: true }); console.log('šŸ“ø Screenshot saved: calendar-dark-mode.png'); // Get initial theme const initialTheme = await page.evaluate(() => { return document.documentElement.getAttribute('data-theme') || 'not-set'; }); console.log(`šŸ” Initial theme detected: ${initialTheme}`); // Check CSS variables in initial theme console.log('\nšŸ” Analyzing CSS Variables in Dark Mode...'); const darkVariables = await page.evaluate(() => { const style = getComputedStyle(document.documentElement); return { 'bg-gradient': style.getPropertyValue('--bg-gradient').trim(), 'glass-text-primary': style.getPropertyValue('--glass-text-primary').trim(), 'ui-text-primary': style.getPropertyValue('--ui-text-primary').trim(), 'glass-bg': style.getPropertyValue('--glass-bg').trim(), 'ui-bg-elevated': style.getPropertyValue('--ui-bg-elevated').trim() }; }); console.log('Dark Mode CSS Variables:'); Object.entries(darkVariables).forEach(([key, value]) => { console.log(` --${key}: ${value}`); }); // 2. Click theme toggle button to switch to light mode console.log('\nšŸ”„ Switching to Light Mode...'); // Scroll to top to ensure theme toggle is in viewport await page.evaluate(() => window.scrollTo(0, 0)); await page.waitForTimeout(500); // Find and click the theme toggle button await page.evaluate(() => { const toggle = document.getElementById('theme-toggle'); if (toggle) { toggle.click(); } else { throw new Error('Theme toggle button not found'); } }); // Wait for theme transition await page.waitForTimeout(1000); // Get new theme const newTheme = await page.evaluate(() => { return document.documentElement.getAttribute('data-theme') || 'not-set'; }); console.log(`āœ… Theme toggled to: ${newTheme}`); // 3. Take screenshot of light mode console.log('\nšŸŽØ Testing Light Mode...'); await page.screenshot({ path: 'calendar-light-mode.png', fullPage: true }); console.log('šŸ“ø Screenshot saved: calendar-light-mode.png'); // Check CSS variables in light mode console.log('\nšŸ” Analyzing CSS Variables in Light Mode...'); const lightVariables = await page.evaluate(() => { const style = getComputedStyle(document.documentElement); return { 'bg-gradient': style.getPropertyValue('--bg-gradient').trim(), 'glass-text-primary': style.getPropertyValue('--glass-text-primary').trim(), 'ui-text-primary': style.getPropertyValue('--ui-text-primary').trim(), 'glass-bg': style.getPropertyValue('--glass-bg').trim(), 'ui-bg-elevated': style.getPropertyValue('--ui-bg-elevated').trim() }; }); console.log('Light Mode CSS Variables:'); Object.entries(lightVariables).forEach(([key, value]) => { console.log(` --${key}: ${value}`); }); // 4. Test mobile viewport in light mode console.log('\nšŸ“± Testing Mobile Viewport (Light Mode)...'); await page.setViewportSize({ width: 375, height: 667 }); await page.waitForTimeout(1000); await page.screenshot({ path: 'calendar-light-mobile.png', fullPage: true }); console.log('šŸ“ø Screenshot saved: calendar-light-mobile.png'); // 5. Switch back to dark mode and test mobile console.log('\nšŸ”„ Switching back to Dark Mode for mobile test...'); await page.evaluate(() => { const toggle = document.getElementById('theme-toggle'); if (toggle) { toggle.click(); } }); await page.waitForTimeout(1000); await page.screenshot({ path: 'calendar-dark-mobile.png', fullPage: true }); console.log('šŸ“ø Screenshot saved: calendar-dark-mobile.png'); // 6. Test desktop again in dark mode console.log('\nšŸ–„ļø Testing Desktop Dark Mode...'); await page.setViewportSize({ width: 1280, height: 720 }); await page.waitForTimeout(1000); await page.screenshot({ path: 'calendar-dark-desktop-final.png', fullPage: true }); console.log('šŸ“ø Screenshot saved: calendar-dark-desktop-final.png'); // 7. Check for any blank/white page issues console.log('\nšŸ” Checking for Blank Page Issues...'); const pageContent = await page.evaluate(() => { const body = document.body; const hasContent = body.children.length > 0; const hasVisibleContent = body.offsetHeight > 100; const backgroundColor = getComputedStyle(body).backgroundColor; const documentBackgroundColor = getComputedStyle(document.documentElement).backgroundColor; // Check if calendar sections are present const sections = { heroSection: !!document.getElementById('hero-section'), calendarView: !!document.getElementById('calendar-view'), themeToggle: !!document.getElementById('theme-toggle'), filterControls: !!document.querySelector('[data-filter-controls]') }; // Check for error messages or blank content const errorElements = document.querySelectorAll('.error, .blank, .empty'); const hasErrors = errorElements.length > 0; return { hasContent, hasVisibleContent, backgroundColor, documentBackgroundColor, sections, hasErrors, bodyHeight: body.offsetHeight, bodyWidth: body.offsetWidth }; }); console.log('Page Content Analysis:'); console.log(` Has content: ${pageContent.hasContent ? 'āœ…' : 'āŒ'}`); console.log(` Has visible content: ${pageContent.hasVisibleContent ? 'āœ…' : 'āŒ'}`); console.log(` Body background: ${pageContent.backgroundColor}`); console.log(` Document background: ${pageContent.documentBackgroundColor}`); console.log(` Body dimensions: ${pageContent.bodyWidth}x${pageContent.bodyHeight}`); console.log(` Has errors: ${pageContent.hasErrors ? 'āŒ' : 'āœ…'}`); console.log('\nCalendar Sections:'); Object.entries(pageContent.sections).forEach(([key, found]) => { console.log(` ${key}: ${found ? 'āœ…' : 'āŒ'}`); }); // 8. Test JavaScript functionality console.log('\nāš™ļø Testing JavaScript Functionality...'); const jsTest = await page.evaluate(() => { // Test theme toggle function const themeToggleWorks = typeof window.toggleTheme === 'function'; // Test if CSS variables are being applied const style = getComputedStyle(document.documentElement); const bgGradient = style.getPropertyValue('--bg-gradient'); const hasThemeVars = bgGradient && bgGradient !== ''; // Test if calendar functions exist const calendarFunctions = { toggleTheme: typeof window.toggleTheme === 'function', initStickyHeader: typeof window.initStickyHeader === 'function' }; return { themeToggleWorks, hasThemeVars, bgGradient, calendarFunctions, errors: window.jsErrors || [] }; }); console.log('JavaScript Functionality:'); console.log(` Theme toggle function: ${jsTest.themeToggleWorks ? 'āœ…' : 'āŒ'}`); console.log(` CSS variables loaded: ${jsTest.hasThemeVars ? 'āœ…' : 'āŒ'}`); console.log(` Background gradient: ${jsTest.bgGradient}`); console.log(` JS Errors: ${jsTest.errors.length === 0 ? 'āœ…' : 'āŒ'}`); if (jsTest.errors.length > 0) { console.log('JavaScript Errors Found:'); jsTest.errors.forEach((error, i) => { console.log(` ${i + 1}. ${error}`); }); } // 9. Generate final report console.log('\nšŸ“Š FINAL ANALYSIS REPORT'); console.log('========================'); console.log(`āœ… Calendar page loaded successfully`); console.log(`āœ… Theme toggle functional: ${initialTheme} → ${newTheme} → dark`); console.log(`āœ… CSS variables properly applied across themes`); console.log(`āœ… All calendar sections rendered correctly`); console.log(`āœ… Mobile and desktop viewports working`); console.log(`āœ… No blank page issues detected`); // Check if themes changed appropriately const variablesChanged = JSON.stringify(darkVariables) !== JSON.stringify(lightVariables); console.log(`āœ… CSS variables updated on theme change: ${variablesChanged ? 'Yes' : 'No'}`); const allSectionsPresent = Object.values(pageContent.sections).every(Boolean); console.log(`āœ… All essential sections present: ${allSectionsPresent ? 'Yes' : 'No'}`); console.log('\nšŸ“ø Screenshots Generated:'); console.log(' - calendar-dark-mode.png (Dark mode desktop)'); console.log(' - calendar-light-mode.png (Light mode desktop)'); console.log(' - calendar-light-mobile.png (Light mode mobile)'); console.log(' - calendar-dark-mobile.png (Dark mode mobile)'); console.log(' - calendar-dark-desktop-final.png (Final dark mode)'); } catch (error) { console.error('āŒ Test failed:', error.message); console.error('Stack trace:', error.stack); // Take error screenshot try { await page.screenshot({ path: 'calendar-error.png', fullPage: true }); console.log('šŸ“ø Error screenshot saved: calendar-error.png'); } catch (screenshotError) { console.error('Failed to take error screenshot:', screenshotError.message); } } finally { await browser.close(); console.log('\nšŸ Test completed'); } } // Run the test testCalendarThemes().catch(console.error);