9a848e8c53
Implement a command palette accessible via CMD+K/Ctrl+K using the ninja-keys web component. Features include: - New /api/cmd-k endpoint serving dynamic CV entries (experiences, projects, courses) - Language-aware responses with 1-hour cache headers - Scroll-to-section functionality for quick navigation - Enhanced keyboard shortcuts modal with CMD+K documentation - Comprehensive test coverage for API and UI interactions Also includes cleanup of deprecated debug test files and various UI polish improvements to contact form, themes, and action bar components.
144 lines
6.0 KiB
JavaScript
144 lines
6.0 KiB
JavaScript
#!/usr/bin/env bun
|
|
/**
|
|
* CMD+K BUTTON FUNCTIONALITY TEST
|
|
* ================================
|
|
* Tests that the CMD+K button:
|
|
* - Has a distinct icon from zoom button
|
|
* - Click handler opens ninja-keys
|
|
* - At-bottom illumination works
|
|
* - Has distinct color from zoom button
|
|
*/
|
|
|
|
import { chromium } from 'playwright';
|
|
|
|
const URL = "http://localhost:1999";
|
|
|
|
async function testCmdKButton() {
|
|
console.log('🎯 CMD+K BUTTON FUNCTIONALITY TEST\n');
|
|
console.log('='.repeat(70));
|
|
|
|
const browser = await chromium.launch({ headless: process.env.HEADLESS === 'true' });
|
|
const page = await browser.newPage({ viewport: { width: 1920, height: 1080 } });
|
|
|
|
const testResults = [];
|
|
|
|
await page.goto(URL);
|
|
await page.waitForTimeout(2000);
|
|
|
|
// ========================================================================
|
|
// TEST 1: Button exists with distinct icon
|
|
// ========================================================================
|
|
console.log('\n1️⃣ Testing button exists with distinct icon...');
|
|
|
|
const cmdKButton = await page.$('#cmd-k-button');
|
|
const buttonExists = cmdKButton !== null;
|
|
console.log(` Button exists: ${buttonExists}`);
|
|
|
|
let iconsDistinct = false;
|
|
if (buttonExists) {
|
|
const cmdKIcon = await page.$eval('#cmd-k-button iconify-icon', el => el.getAttribute('icon'));
|
|
const zoomIcon = await page.$eval('#zoom-toggle-button iconify-icon', el => el.getAttribute('icon'));
|
|
|
|
console.log(` CMD+K icon: ${cmdKIcon}`);
|
|
console.log(` Zoom icon: ${zoomIcon}`);
|
|
iconsDistinct = cmdKIcon !== zoomIcon;
|
|
console.log(` ${iconsDistinct ? '✅ PASS' : '❌ FAIL'} - Icons are distinct`);
|
|
}
|
|
testResults.push({ test: 'Icons are distinct', passed: buttonExists && iconsDistinct });
|
|
|
|
// ========================================================================
|
|
// TEST 2: Button click opens ninja-keys
|
|
// ========================================================================
|
|
console.log('\n2️⃣ Testing button click opens ninja-keys...');
|
|
|
|
await page.click('#cmd-k-button');
|
|
await page.waitForTimeout(500);
|
|
|
|
const ninjaKeysOpen = await page.$eval('#cmd-k-bar', el => el.hasAttribute('open'));
|
|
console.log(` Ninja-keys open: ${ninjaKeysOpen}`);
|
|
console.log(` ${ninjaKeysOpen ? '✅ PASS' : '❌ FAIL'} - Click opens ninja-keys`);
|
|
testResults.push({ test: 'Click opens ninja-keys', passed: ninjaKeysOpen });
|
|
|
|
// Close ninja-keys
|
|
await page.keyboard.press('Escape');
|
|
await page.waitForTimeout(300);
|
|
|
|
// ========================================================================
|
|
// TEST 3: At-bottom illumination
|
|
// ========================================================================
|
|
console.log('\n3️⃣ Testing at-bottom illumination...');
|
|
|
|
// Scroll to very top - use scroll() which fires event naturally
|
|
await page.evaluate(() => window.scrollTo(0, 0));
|
|
await page.waitForTimeout(100);
|
|
// Trigger handleScroll manually via hyperscript's behavior
|
|
await page.evaluate(() => window.dispatchEvent(new Event('scroll')));
|
|
await page.waitForTimeout(300);
|
|
const atTopClass = await page.$eval('#cmd-k-button', el => el.classList.contains('at-bottom'));
|
|
console.log(` At top - has at-bottom class: ${atTopClass}`);
|
|
|
|
// Scroll to bottom using mouse wheel to trigger actual scroll
|
|
await page.mouse.wheel(0, 100000);
|
|
await page.waitForTimeout(1000);
|
|
const atBottomClass = await page.$eval('#cmd-k-button', el => el.classList.contains('at-bottom'));
|
|
const zoomAtBottomClass = await page.$eval('#zoom-toggle-button', el => el.classList.contains('at-bottom'));
|
|
const infoAtBottomClass = await page.$eval('#info-button', el => el.classList.contains('at-bottom'));
|
|
console.log(` At bottom - CMD+K has at-bottom: ${atBottomClass}`);
|
|
console.log(` At bottom - Zoom has at-bottom: ${zoomAtBottomClass}`);
|
|
console.log(` At bottom - Info has at-bottom: ${infoAtBottomClass}`);
|
|
|
|
const illuminationWorks = !atTopClass && atBottomClass;
|
|
console.log(` ${illuminationWorks ? '✅ PASS' : '❌ FAIL'} - At-bottom illumination works`);
|
|
testResults.push({ test: 'At-bottom illumination', passed: illuminationWorks });
|
|
|
|
// ========================================================================
|
|
// TEST 4: Distinct color from zoom button
|
|
// ========================================================================
|
|
console.log('\n4️⃣ Testing distinct color at bottom...');
|
|
|
|
const cmdKBgColor = await page.$eval('#cmd-k-button', el => window.getComputedStyle(el).backgroundColor);
|
|
const zoomBgColor = await page.$eval('#zoom-toggle-button', el => window.getComputedStyle(el).backgroundColor);
|
|
|
|
console.log(` CMD+K bg color: ${cmdKBgColor}`);
|
|
console.log(` Zoom bg color: ${zoomBgColor}`);
|
|
|
|
const colorsDistinct = cmdKBgColor !== zoomBgColor;
|
|
console.log(` ${colorsDistinct ? '✅ PASS' : '❌ FAIL'} - Colors are distinct`);
|
|
testResults.push({ test: 'Colors are distinct', passed: colorsDistinct });
|
|
|
|
// ========================================================================
|
|
// FINAL SUMMARY
|
|
// ========================================================================
|
|
console.log("\n" + "=".repeat(70));
|
|
console.log("📊 TEST SUMMARY\n");
|
|
|
|
const totalTests = testResults.length;
|
|
const passedTests = testResults.filter(r => r.passed).length;
|
|
const failedTests = totalTests - passedTests;
|
|
|
|
testResults.forEach(result => {
|
|
console.log(` ${result.passed ? '✅' : '❌'} ${result.test}`);
|
|
});
|
|
|
|
console.log(`\n Total: ${passedTests}/${totalTests} tests passed`);
|
|
console.log("=".repeat(70) + "\n");
|
|
|
|
if (failedTests === 0) {
|
|
console.log("🎉 ALL CMD+K BUTTON TESTS PASSED!");
|
|
} else {
|
|
console.log("⚠️ SOME TESTS FAILED - See details above");
|
|
}
|
|
|
|
// Auto-close after tests if HEADLESS env is set
|
|
if (process.env.HEADLESS === 'true') {
|
|
await browser.close();
|
|
process.exit(failedTests === 0 ? 0 : 1);
|
|
} else {
|
|
console.log("\nBrowser will stay open for manual inspection.");
|
|
console.log("Press Ctrl+C when done.\n");
|
|
await new Promise(() => {}); // Keep browser open
|
|
}
|
|
}
|
|
|
|
await testCmdKButton();
|