mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-16 11:19:11 +00:00
242 lines
No EOL
7.6 KiB
JavaScript
242 lines
No EOL
7.6 KiB
JavaScript
const { chromium, devices } = require('@playwright/test');
|
|
const fs = require('fs').promises;
|
|
const path = require('path');
|
|
|
|
const PULSE_URL = process.env.PULSE_URL || 'http://localhost:7655';
|
|
const OUTPUT_DIR = path.join(__dirname, '..', 'docs', 'images');
|
|
|
|
async function ensureOutputDir() {
|
|
try {
|
|
await fs.mkdir(OUTPUT_DIR, { recursive: true });
|
|
} catch (error) {
|
|
console.error('Error creating output directory:', error);
|
|
}
|
|
}
|
|
|
|
async function wait(ms) {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
async function takeScreenshot(page, name, options = {}) {
|
|
const { selector = null, fullPage = false } = options;
|
|
|
|
await wait(1500); // Wait for animations
|
|
|
|
let screenshotOptions = {
|
|
type: 'png',
|
|
path: path.join(OUTPUT_DIR, `${name}.png`)
|
|
};
|
|
|
|
if (selector) {
|
|
const element = await page.locator(selector).first();
|
|
await element.waitFor({ state: 'visible', timeout: 10000 });
|
|
screenshotOptions = {
|
|
...screenshotOptions,
|
|
clip: await element.boundingBox()
|
|
};
|
|
} else if (fullPage) {
|
|
screenshotOptions.fullPage = true;
|
|
}
|
|
|
|
await page.screenshot(screenshotOptions);
|
|
console.log(`✅ Saved ${name}.png`);
|
|
}
|
|
|
|
async function clickAndWait(page, selector, waitTime = 1000) {
|
|
try {
|
|
const element = page.locator(selector).first();
|
|
if (await element.count() > 0) {
|
|
await element.click();
|
|
await wait(waitTime);
|
|
return true;
|
|
}
|
|
} catch (e) {
|
|
console.log(`Could not click ${selector}: ${e.message}`);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
async function forceDarkMode(page) {
|
|
// First, inject dark mode styles and classes before page load
|
|
await page.addInitScript(() => {
|
|
// Force dark mode via localStorage
|
|
localStorage.setItem('theme', 'dark');
|
|
localStorage.setItem('pulse-theme', 'dark');
|
|
localStorage.setItem('color-theme', 'dark');
|
|
|
|
// Add dark class to html element
|
|
document.documentElement.classList.add('dark');
|
|
document.documentElement.classList.remove('light');
|
|
|
|
// Override any light mode styles
|
|
const style = document.createElement('style');
|
|
style.textContent = `
|
|
html, body {
|
|
background-color: #111827 !important; /* gray-900 */
|
|
color: #f3f4f6 !important; /* gray-100 */
|
|
}
|
|
html.dark {
|
|
color-scheme: dark !important;
|
|
}
|
|
/* Force dark backgrounds on main containers */
|
|
.bg-white {
|
|
background-color: #1f2937 !important; /* gray-800 */
|
|
}
|
|
.bg-gray-50 {
|
|
background-color: #374151 !important; /* gray-700 */
|
|
}
|
|
/* Ensure the main app background is dark */
|
|
#root > div:first-child {
|
|
background-color: #111827 !important;
|
|
}
|
|
`;
|
|
document.head.appendChild(style);
|
|
});
|
|
}
|
|
|
|
async function ensureDarkThemeAfterLoad(page) {
|
|
await page.evaluate(() => {
|
|
// Double-check and force dark mode after page load
|
|
document.documentElement.classList.add('dark');
|
|
document.documentElement.classList.remove('light');
|
|
|
|
// Force dark background on body
|
|
document.body.style.backgroundColor = '#111827';
|
|
|
|
// Find any light backgrounds and make them dark
|
|
const lightElements = document.querySelectorAll('[class*="bg-white"], [class*="bg-gray-50"]');
|
|
lightElements.forEach(el => {
|
|
el.style.backgroundColor = '#1f2937';
|
|
});
|
|
});
|
|
}
|
|
|
|
async function main() {
|
|
await ensureOutputDir();
|
|
|
|
const browser = await chromium.launch({
|
|
headless: true
|
|
});
|
|
|
|
// Desktop screenshots with dark mode forced
|
|
const desktopContext = await browser.newContext({
|
|
viewport: { width: 1440, height: 900 },
|
|
colorScheme: 'dark' // Force dark color scheme
|
|
});
|
|
|
|
const page = await desktopContext.newPage();
|
|
|
|
// Force dark mode before navigation
|
|
await forceDarkMode(page);
|
|
|
|
try {
|
|
console.log(`📸 Starting screenshot capture for ${PULSE_URL}`);
|
|
|
|
// Navigate to Pulse
|
|
await page.goto(PULSE_URL, { waitUntil: 'networkidle' });
|
|
await wait(2000);
|
|
|
|
// Ensure dark theme after page load
|
|
await ensureDarkThemeAfterLoad(page);
|
|
await wait(1000);
|
|
|
|
// 1. Dashboard Screenshot
|
|
console.log('📸 Capturing dashboard...');
|
|
await takeScreenshot(page, '01-dashboard');
|
|
|
|
// 2. Storage View
|
|
console.log('📸 Capturing storage view...');
|
|
const storageClicked = await clickAndWait(page, 'button:has-text("Storage"), a:has-text("Storage"), [role="tab"]:has-text("Storage")', 2000);
|
|
if (storageClicked) {
|
|
await ensureDarkThemeAfterLoad(page);
|
|
await takeScreenshot(page, '02-storage');
|
|
}
|
|
|
|
// 3. Backups View
|
|
console.log('📸 Capturing backups view...');
|
|
const backupsClicked = await clickAndWait(page, 'button:has-text("Backups"), a:has-text("Backups"), [role="tab"]:has-text("Backups")', 2000);
|
|
if (backupsClicked) {
|
|
await ensureDarkThemeAfterLoad(page);
|
|
await takeScreenshot(page, '03-backups');
|
|
}
|
|
|
|
// 4. Alerts View
|
|
console.log('📸 Capturing alerts view...');
|
|
const alertsClicked = await clickAndWait(page, 'button:has-text("Alerts"), a:has-text("Alerts"), [role="tab"]:has-text("Alerts")', 2000);
|
|
if (alertsClicked) {
|
|
await ensureDarkThemeAfterLoad(page);
|
|
await takeScreenshot(page, '04-alerts');
|
|
|
|
// 5. Alert History
|
|
console.log('📸 Looking for alert history...');
|
|
const historyClicked = await clickAndWait(page, 'button:has-text("History"), button:has-text("Alert History"), [role="tab"]:has-text("History")', 2000);
|
|
if (historyClicked) {
|
|
await ensureDarkThemeAfterLoad(page);
|
|
await takeScreenshot(page, '05-alert-history');
|
|
} else {
|
|
await fs.copyFile(
|
|
path.join(OUTPUT_DIR, '04-alerts.png'),
|
|
path.join(OUTPUT_DIR, '05-alert-history.png')
|
|
);
|
|
console.log('✅ Used alerts view for alert history');
|
|
}
|
|
}
|
|
|
|
// 6. Settings View
|
|
console.log('📸 Capturing settings view...');
|
|
const settingsClicked = await clickAndWait(page, 'button:has-text("Settings"), a:has-text("Settings"), [aria-label="Settings"], .settings-icon', 2000);
|
|
if (settingsClicked) {
|
|
await ensureDarkThemeAfterLoad(page);
|
|
await takeScreenshot(page, '06-settings');
|
|
} else {
|
|
await clickAndWait(page, 'svg[class*="settings"], svg[class*="gear"], button:has(svg[class*="settings"])', 2000);
|
|
await ensureDarkThemeAfterLoad(page);
|
|
await takeScreenshot(page, '06-settings');
|
|
}
|
|
|
|
// 7. Dark Mode Screenshot
|
|
console.log('📸 Capturing dark mode view...');
|
|
await clickAndWait(page, 'button:has-text("Dashboard"), a:has-text("Dashboard"), [role="tab"]:has-text("Dashboard")', 2000);
|
|
await ensureDarkThemeAfterLoad(page);
|
|
await wait(1000);
|
|
await takeScreenshot(page, '07-dark-mode');
|
|
|
|
// Close desktop context
|
|
await desktopContext.close();
|
|
|
|
// 8. Mobile Screenshot with dark mode
|
|
console.log('📸 Capturing mobile view...');
|
|
const mobileContext = await browser.newContext({
|
|
...devices['iPhone 12'],
|
|
viewport: { width: 390, height: 844 },
|
|
colorScheme: 'dark'
|
|
});
|
|
|
|
const mobilePage = await mobileContext.newPage();
|
|
await forceDarkMode(mobilePage);
|
|
|
|
await mobilePage.goto(PULSE_URL, { waitUntil: 'networkidle' });
|
|
await wait(2000);
|
|
|
|
await ensureDarkThemeAfterLoad(mobilePage);
|
|
await wait(1000);
|
|
|
|
await takeScreenshot(mobilePage, '08-mobile');
|
|
|
|
await mobileContext.close();
|
|
|
|
console.log('✨ Screenshot capture complete!');
|
|
console.log(`📁 Screenshots saved to: ${OUTPUT_DIR}`);
|
|
|
|
} catch (error) {
|
|
console.error('❌ Error during screenshot capture:', error);
|
|
|
|
// Take error screenshot
|
|
await takeScreenshot(page, 'error-state');
|
|
} finally {
|
|
await browser.close();
|
|
}
|
|
}
|
|
|
|
// Run the script
|
|
main().catch(console.error); |