188 lines
5.9 KiB
JavaScript
188 lines
5.9 KiB
JavaScript
|
|
#!/usr/bin/env node
|
||
|
|
/**
|
||
|
|
* Test: Button Hover Full Opacity + Footer Interaction
|
||
|
|
*
|
||
|
|
* Verifies on mobile view (max-width: 900px):
|
||
|
|
* 1. All buttons become 100% opaque (alpha = 1.0) on hover
|
||
|
|
* 2. Buttons become semi-transparent (opacity 0.2) when hovering footer
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { chromium } from 'playwright';
|
||
|
|
|
||
|
|
const TEST_URL = 'http://localhost:1999';
|
||
|
|
const VIEWPORT_WIDTH = 375; // Mobile width
|
||
|
|
const VIEWPORT_HEIGHT = 812; // iPhone X height
|
||
|
|
|
||
|
|
// Helper to extract RGB values from background color
|
||
|
|
function parseRGB(colorString) {
|
||
|
|
const match = colorString.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
|
||
|
|
if (!match) return null;
|
||
|
|
return {
|
||
|
|
r: parseInt(match[1]),
|
||
|
|
g: parseInt(match[2]),
|
||
|
|
b: parseInt(match[3]),
|
||
|
|
a: match[4] ? parseFloat(match[4]) : 1
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
async function testButtonHoverAndFooter() {
|
||
|
|
console.log('🧪 Testing Button Hover Opacity + Footer Interaction');
|
||
|
|
console.log('='.repeat(70));
|
||
|
|
|
||
|
|
const browser = await chromium.launch({ headless: true });
|
||
|
|
const context = await browser.newContext({
|
||
|
|
viewport: { width: VIEWPORT_WIDTH, height: VIEWPORT_HEIGHT },
|
||
|
|
deviceScaleFactor: 2,
|
||
|
|
});
|
||
|
|
const page = await context.newPage();
|
||
|
|
|
||
|
|
// Disable cache
|
||
|
|
await page.route('**/*', (route) => {
|
||
|
|
route.continue({
|
||
|
|
headers: {
|
||
|
|
...route.request().headers(),
|
||
|
|
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
||
|
|
},
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
try {
|
||
|
|
await page.goto(TEST_URL, { waitUntil: 'networkidle' });
|
||
|
|
console.log(`✅ Navigated to ${TEST_URL}`);
|
||
|
|
await page.waitForTimeout(1500);
|
||
|
|
|
||
|
|
const buttons = [
|
||
|
|
{ selector: '.download-btn', name: 'Download' },
|
||
|
|
{ selector: '.print-friendly-btn', name: 'Print' },
|
||
|
|
{ selector: '.shortcuts-btn', name: 'Shortcuts' },
|
||
|
|
{ selector: '.color-theme-switcher', name: 'Theme' },
|
||
|
|
{ selector: '.info-button', name: 'Info' },
|
||
|
|
{ selector: '.back-to-top', name: 'Back to Top' },
|
||
|
|
];
|
||
|
|
|
||
|
|
let allTestsPassed = true;
|
||
|
|
|
||
|
|
// TEST 1: All buttons reach 100% opacity on hover
|
||
|
|
console.log('\n📊 TEST 1: Button Hover - Full Opacity (100%)');
|
||
|
|
console.log('-'.repeat(70));
|
||
|
|
|
||
|
|
for (const button of buttons) {
|
||
|
|
try {
|
||
|
|
const buttonElement = await page.$(button.selector);
|
||
|
|
if (!buttonElement) {
|
||
|
|
console.log(`❌ ${button.name}: Button not found`);
|
||
|
|
allTestsPassed = false;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Hover over the button
|
||
|
|
await buttonElement.hover();
|
||
|
|
await page.waitForTimeout(500);
|
||
|
|
|
||
|
|
// Get hover background color
|
||
|
|
const hoverBg = await page.evaluate((sel) => {
|
||
|
|
const btn = document.querySelector(sel);
|
||
|
|
return btn ? window.getComputedStyle(btn).backgroundColor : null;
|
||
|
|
}, button.selector);
|
||
|
|
|
||
|
|
const hoverColor = parseRGB(hoverBg);
|
||
|
|
|
||
|
|
if (hoverColor) {
|
||
|
|
const alphaIs100 = Math.abs(hoverColor.a - 1.0) < 0.1;
|
||
|
|
|
||
|
|
if (alphaIs100) {
|
||
|
|
console.log(`✅ ${button.name}: Hover opacity = ${hoverColor.a.toFixed(2)} (100%) ✓`);
|
||
|
|
} else {
|
||
|
|
console.log(`❌ ${button.name}: Hover opacity = ${hoverColor.a.toFixed(2)} (Expected 1.0)`);
|
||
|
|
allTestsPassed = false;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
console.log(`❌ ${button.name}: Could not parse hover background color`);
|
||
|
|
allTestsPassed = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Move mouse away
|
||
|
|
await page.mouse.move(0, 0);
|
||
|
|
await page.waitForTimeout(300);
|
||
|
|
|
||
|
|
} catch (error) {
|
||
|
|
console.log(`❌ ${button.name}: Error - ${error.message}`);
|
||
|
|
allTestsPassed = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// TEST 2: Footer hover makes buttons semi-transparent
|
||
|
|
console.log('\n📊 TEST 2: Footer Hover - Buttons Become Transparent (20%)');
|
||
|
|
console.log('-'.repeat(70));
|
||
|
|
|
||
|
|
try {
|
||
|
|
// Scroll to footer
|
||
|
|
await page.evaluate(() => {
|
||
|
|
window.scrollTo(0, document.body.scrollHeight);
|
||
|
|
});
|
||
|
|
await page.waitForTimeout(500);
|
||
|
|
|
||
|
|
// Find footer element
|
||
|
|
const footer = await page.$('footer.no-print');
|
||
|
|
if (!footer) {
|
||
|
|
console.log('❌ Footer element not found');
|
||
|
|
allTestsPassed = false;
|
||
|
|
} else {
|
||
|
|
// Hover over footer
|
||
|
|
await footer.hover();
|
||
|
|
await page.waitForTimeout(500);
|
||
|
|
|
||
|
|
// Check if buttons have footer-hovered class and opacity 0.2
|
||
|
|
for (const button of buttons) {
|
||
|
|
const buttonData = await page.evaluate((sel) => {
|
||
|
|
const btn = document.querySelector(sel);
|
||
|
|
if (!btn) return null;
|
||
|
|
return {
|
||
|
|
hasClass: btn.classList.contains('footer-hovered'),
|
||
|
|
opacity: window.getComputedStyle(btn).opacity
|
||
|
|
};
|
||
|
|
}, button.selector);
|
||
|
|
|
||
|
|
if (buttonData) {
|
||
|
|
const opacityValue = parseFloat(buttonData.opacity);
|
||
|
|
const opacityCorrect = Math.abs(opacityValue - 0.2) < 0.05;
|
||
|
|
|
||
|
|
if (buttonData.hasClass && opacityCorrect) {
|
||
|
|
console.log(`✅ ${button.name}: Footer hover opacity = ${opacityValue.toFixed(2)} ✓`);
|
||
|
|
} else {
|
||
|
|
console.log(`❌ ${button.name}: Footer hover opacity = ${opacityValue.toFixed(2)} (Expected 0.2), Class: ${buttonData.hasClass}`);
|
||
|
|
allTestsPassed = false;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
console.log(`❌ ${button.name}: Could not check footer hover state`);
|
||
|
|
allTestsPassed = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.log(`❌ Footer hover test error: ${error.message}`);
|
||
|
|
allTestsPassed = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log('-'.repeat(70));
|
||
|
|
|
||
|
|
if (allTestsPassed) {
|
||
|
|
console.log('\n✅ ALL TESTS PASSED!');
|
||
|
|
console.log(' • All buttons reach 100% opacity on hover');
|
||
|
|
console.log(' • Buttons become 20% opacity when hovering footer');
|
||
|
|
} else {
|
||
|
|
console.log('\n❌ SOME TESTS FAILED - Check output above');
|
||
|
|
}
|
||
|
|
|
||
|
|
await browser.close();
|
||
|
|
process.exit(allTestsPassed ? 0 : 1);
|
||
|
|
|
||
|
|
} catch (error) {
|
||
|
|
console.error('\n❌ Test error:', error);
|
||
|
|
await browser.close();
|
||
|
|
process.exit(1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
testButtonHoverAndFooter();
|