Files
cv-site/tests/mjs/76-cmd-k-lazy-loading.test.mjs
juanatsap 2d3d3de8cd feat: lazy load ninja-keys + HTML Invoker Commands API
- Lazy load ninja-keys only on CMD+K press (0 requests on initial load)
- Use esm.sh bundled module (3 requests vs ~81 previously)
- Add esm.sh to CSP whitelist
- Implement HTML Invoker Commands API for modals:
  - commandfor="modal-id" + command="show-modal" for opening
  - commandfor="modal-id" + command="close" for closing
  - Removes need for onclick handlers on modal buttons
- Refactor index.html into layout partials (head, body-scripts)
- Add comprehensive tests for both features
2025-12-02 08:29:54 +00:00

257 lines
10 KiB
JavaScript

#!/usr/bin/env bun
/**
* CMD+K LAZY LOADING TEST
* =======================
* Tests that ninja-keys is lazy-loaded only when needed:
* - No ninja-keys element on initial page load
* - No esm.sh/ninja-keys loaded initially
* - CMD+K triggers dynamic import
* - ninja-keys element created and opened
* - Subsequent uses don't reload
*
* This optimization reduces initial page load by ~15 module requests
*/
import { chromium } from 'playwright';
const URL = "http://localhost:1999";
async function testCmdKLazyLoading() {
console.log('🚀 CMD+K LAZY LOADING TEST\n');
console.log('='.repeat(70));
const browser = await chromium.launch({ headless: process.env.HEADLESS === 'true' });
const context = await browser.newContext({ viewport: { width: 1920, height: 1080 } });
const page = await context.newPage();
const testResults = [];
const networkRequests = [];
// Monitor network requests
page.on('request', request => {
const url = request.url();
if (url.includes('ninja-keys') || url.includes('esm.sh')) {
networkRequests.push({
url,
timestamp: Date.now(),
type: request.resourceType()
});
}
});
await page.goto(URL);
await page.waitForTimeout(2000);
const initialRequestCount = networkRequests.length;
console.log(` Initial ninja-keys/esm.sh requests: ${initialRequestCount}`);
// ========================================================================
// TEST 1: No ninja-keys element on initial load
// ========================================================================
console.log('\n1️⃣ Testing no ninja-keys on initial load...');
const ninjaKeysOnLoad = await page.evaluate(() => {
const nk = document.getElementById('cmd-k-bar');
return {
exists: !!nk,
tagName: nk?.tagName || 'N/A'
};
});
console.log(` ninja-keys element exists: ${ninjaKeysOnLoad.exists}`);
const noInitialElement = !ninjaKeysOnLoad.exists;
console.log(` ${noInitialElement ? '✅ PASS' : '❌ FAIL'} - No ninja-keys element on initial load`);
testResults.push({ test: 'No ninja-keys element on initial load', passed: noInitialElement });
// ========================================================================
// TEST 2: No esm.sh requests on initial load
// ========================================================================
console.log('\n2️⃣ Testing no esm.sh requests on initial load...');
const noInitialRequests = initialRequestCount === 0;
console.log(` esm.sh requests before interaction: ${initialRequestCount}`);
console.log(` ${noInitialRequests ? '✅ PASS' : '❌ FAIL'} - No ninja-keys loaded initially`);
testResults.push({ test: 'No esm.sh requests on initial load', passed: noInitialRequests });
// ========================================================================
// TEST 3: Container element exists for lazy loading
// ========================================================================
console.log('\n3️⃣ Testing container element exists...');
const containerExists = await page.evaluate(() => {
const container = document.getElementById('cmd-k-container');
return !!container;
});
console.log(` cmd-k-container exists: ${containerExists}`);
console.log(` ${containerExists ? '✅ PASS' : '❌ FAIL'} - Container ready for lazy loading`);
testResults.push({ test: 'Container element exists', passed: containerExists });
// ========================================================================
// TEST 4: CMD+K triggers lazy load
// ========================================================================
console.log('\n4️⃣ Testing CMD+K triggers lazy load...');
const requestsBeforeCmdK = networkRequests.length;
// Press CMD+K (Mac) or Ctrl+K (Windows/Linux)
await page.keyboard.press('Meta+k');
await page.waitForTimeout(3000); // Wait for module to load and custom element to register
const requestsAfterCmdK = networkRequests.length;
const newRequests = requestsAfterCmdK - requestsBeforeCmdK;
console.log(` Requests before CMD+K: ${requestsBeforeCmdK}`);
console.log(` Requests after CMD+K: ${requestsAfterCmdK}`);
console.log(` New esm.sh requests: ${newRequests}`);
const lazyLoadTriggered = newRequests > 0;
console.log(` ${lazyLoadTriggered ? '✅ PASS' : '❌ FAIL'} - CMD+K triggers module load`);
testResults.push({ test: 'CMD+K triggers lazy load', passed: lazyLoadTriggered });
// ========================================================================
// TEST 5: ninja-keys element created after CMD+K
// ========================================================================
console.log('\n5️⃣ Testing ninja-keys element created...');
const ninjaKeysAfterCmdK = await page.evaluate(() => {
const nk = document.getElementById('cmd-k-bar');
if (!nk) return { exists: false, tagName: 'N/A', isOpen: false };
// ninja-keys uses shadow DOM with .modal.visible class
const shadow = nk.shadowRoot;
const modal = shadow?.querySelector('.modal');
return {
exists: true,
tagName: nk.tagName,
isOpen: modal?.classList?.contains('visible') || false
};
});
console.log(` ninja-keys exists: ${ninjaKeysAfterCmdK.exists}`);
console.log(` ninja-keys tag: ${ninjaKeysAfterCmdK.tagName}`);
console.log(` ninja-keys open: ${ninjaKeysAfterCmdK.isOpen}`);
const elementCreated = ninjaKeysAfterCmdK.exists && ninjaKeysAfterCmdK.tagName === 'NINJA-KEYS';
console.log(` ${elementCreated ? '✅ PASS' : '❌ FAIL'} - ninja-keys element created`);
testResults.push({ test: 'ninja-keys element created', passed: elementCreated });
// Close ninja-keys
await page.keyboard.press('Escape');
await page.waitForTimeout(300);
// ========================================================================
// TEST 6: Subsequent CMD+K doesn't reload module
// ========================================================================
console.log('\n6️⃣ Testing subsequent CMD+K doesn\'t reload...');
const requestsBeforeSecond = networkRequests.length;
// Press CMD+K again
await page.keyboard.press('Meta+k');
await page.waitForTimeout(500);
const requestsAfterSecond = networkRequests.length;
const additionalRequests = requestsAfterSecond - requestsBeforeSecond;
console.log(` Requests before 2nd CMD+K: ${requestsBeforeSecond}`);
console.log(` Requests after 2nd CMD+K: ${requestsAfterSecond}`);
console.log(` Additional requests: ${additionalRequests}`);
const noReload = additionalRequests === 0;
console.log(` ${noReload ? '✅ PASS' : '❌ FAIL'} - No module reload on subsequent use`);
testResults.push({ test: 'No module reload on subsequent use', passed: noReload });
// Close ninja-keys
await page.keyboard.press('Escape');
await page.waitForTimeout(300);
// ========================================================================
// TEST 7: Button click also triggers lazy load
// ========================================================================
console.log('\n7️⃣ Testing button click works with lazy-loaded ninja-keys...');
const cmdKButton = await page.$('#cmd-k-button');
if (cmdKButton) {
await cmdKButton.click();
await page.waitForTimeout(1000);
const openAfterClick = await page.evaluate(() => {
const nk = document.getElementById('cmd-k-bar');
if (!nk) return false;
// ninja-keys uses shadow DOM with .modal.visible class
const shadow = nk.shadowRoot;
const modal = shadow?.querySelector('.modal');
return modal?.classList?.contains('visible') || false;
});
console.log(` ninja-keys opened via button: ${openAfterClick}`);
console.log(` ${openAfterClick ? '✅ PASS' : '❌ FAIL'} - Button click opens ninja-keys`);
testResults.push({ test: 'Button click opens ninja-keys', passed: openAfterClick });
await page.keyboard.press('Escape');
} else {
console.log(' ⚠️ CMD+K button not found');
testResults.push({ test: 'Button click opens ninja-keys', passed: false });
}
// ========================================================================
// TEST 8: esm.sh used instead of unpkg (no redirect chains)
// ========================================================================
console.log('\n8️⃣ Testing esm.sh CDN used (no 302 redirects)...');
const esmShRequests = networkRequests.filter(r => r.url.includes('esm.sh'));
const unpkgRequests = networkRequests.filter(r => r.url.includes('unpkg.com/ninja-keys'));
console.log(` esm.sh requests: ${esmShRequests.length}`);
console.log(` unpkg ninja-keys requests: ${unpkgRequests.length}`);
const usesEsmSh = esmShRequests.length > 0 && unpkgRequests.length === 0;
console.log(` ${usesEsmSh ? '✅ PASS' : '❌ FAIL'} - Uses esm.sh CDN (pre-bundled)`);
testResults.push({ test: 'Uses esm.sh CDN (no redirects)', passed: usesEsmSh });
// ========================================================================
// 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`);
// Show all network requests for debugging
if (networkRequests.length > 0) {
console.log('\n Network requests (ninja-keys/esm.sh):');
networkRequests.forEach((r, i) => {
console.log(` ${i + 1}. ${r.url.substring(0, 80)}...`);
});
}
console.log("=".repeat(70) + "\n");
if (failedTests === 0) {
console.log("🎉 ALL CMD+K LAZY LOADING TESTS PASSED!");
console.log(" Initial page load has NO ninja-keys overhead!");
} 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 testCmdKLazyLoading();