// test_modal_click.js // Playwright test to debug modal click functionality const { chromium } = require('playwright'); const TARGET_URL = 'http://192.168.254.12:8000'; (async () => { const browser = await chromium.launch({ headless: true }); const context = await browser.newContext(); const page = await context.newPage(); // Log console messages page.on('console', msg => console.log(`[CONSOLE] ${msg.type()}: ${msg.text()}`)); page.on('pageerror', exc => console.log(`[PAGE ERROR] ${exc.message}`)); try { console.log(`\nšŸ” [TEST] Navigating to ${TARGET_URL}...`); await page.goto(TARGET_URL, { waitUntil: 'networkidle' }); console.log('āœ… Page loaded'); console.log('[WAIT] Waiting for models container to populate...'); try { await page.waitForSelector('[data-model-key]', { timeout: 5000 }); console.log('āœ… [SUCCESS] Models loaded - found cards with data-model-key attribute'); } catch (e) { console.log(`āŒ [FAILURE] No models found: ${e.message}`); const content = await page.content(); console.log('\nšŸ“‹ Page content (first 1000 chars):'); console.log(content.substring(0, 1000)); await browser.close(); return; } // Get all model cards const cards = await page.locator('[data-model-key]').all(); console.log(`\nšŸ“Š Found ${cards.length} model cards`); if (cards.length === 0) { console.log('āŒ No cards found'); await browser.close(); return; } // Get first card info const firstCard = cards[0]; const modelKey = await firstCard.getAttribute('data-model-key'); console.log(`\nšŸŽÆ [TARGET] First card data-model-key: ${modelKey}`); // Get modal state BEFORE click const modalElement = page.locator('#model-details-modal'); const modalExists = await modalElement.count() > 0; if (!modalExists) { console.log('\nāŒ [ERROR] Modal element #model-details-modal not found!'); await browser.close(); return; } const classAttributeBefore = await modalElement.getAttribute('class'); const isHiddenBefore = classAttributeBefore && classAttributeBefore.includes('hidden'); console.log(`\nšŸ“ [BEFORE CLICK] Modal HTML class: '${classAttributeBefore}'`); console.log(` Is hidden: ${isHiddenBefore}`); // Check if app is initialized const appExists = await page.evaluate(() => typeof window.llmMonitorApp !== 'undefined'); console.log(` App initialized: ${appExists}`); // Check localStorage const localStorage = await page.evaluate(() => JSON.stringify(Object.fromEntries(Object.entries(window.localStorage)))); const lsData = JSON.parse(localStorage); console.log(` localStorage keys: ${Object.keys(lsData).join(', ')}`); // PERFORM CLICK console.log(`\nšŸ–±ļø [CLICK] Clicking on model card...`); await firstCard.click(); // Brief pause for DOM update await page.waitForTimeout(500); // Get modal state AFTER click const classAttributeAfter = await modalElement.getAttribute('class'); const isHiddenAfter = classAttributeAfter && classAttributeAfter.includes('hidden'); console.log(`\nšŸ“ [AFTER CLICK] Modal HTML class: '${classAttributeAfter}'`); console.log(` Is hidden: ${isHiddenAfter}`); // Evaluate if modal is visible const modalState = await page.evaluate(() => { const modal = document.getElementById('model-details-modal'); if (!modal) return 'NOT_FOUND'; const isHidden = modal.classList.contains('hidden'); const computedStyle = window.getComputedStyle(modal); return { hasHiddenClass: isHidden, display: computedStyle.display, visibility: computedStyle.visibility, opacity: computedStyle.opacity, zIndex: computedStyle.zIndex }; }); console.log(`\nšŸ’» [DOM CHECK] Modal computed state:`); console.log(JSON.stringify(modalState, null, 3)); // Check for event listeners and app methods const appState = await page.evaluate(() => { const card = document.querySelector('[data-model-key]'); if (!card) return 'NO_CARDS'; if (window.llmMonitorApp && typeof window.llmMonitorApp.showModelDetails === 'function') { return 'APP_METHOD_EXISTS'; } return 'NO_APP_METHOD'; }); console.log(`\nšŸ”— [LISTENERS] Event handler state: ${appState}`); // Take screenshot const screenshotPath = '/tmp/modal-test-after-click.png'; await page.screenshot({ path: screenshotPath }); console.log(`\nšŸ“ø Screenshot saved: ${screenshotPath}`); // Final verdict console.log('\n' + '='.repeat(70)); if (isHiddenBefore !== undefined && isHiddenAfter !== undefined) { if (isHiddenBefore && !isHiddenAfter) { console.log('āœ… [PASS] Modal successfully opened on click!'); } else if (isHiddenBefore && isHiddenAfter) { console.log('āŒ [FAIL] Modal still has "hidden" class after click'); console.log(' → Event handler may not be attached'); console.log(' → app.js may not be loaded/initialized'); } else { console.log('āš ļø [UNCLEAR] Unexpected modal state'); } } else { console.log('āŒ [ERROR] Could not compare modal states'); } console.log('='.repeat(70)); } catch (error) { console.error('Test error:', error.message); } finally { await browser.close(); } })();