const { chromium } = require('playwright'); async function testContainerControls() { console.log('🚀 Starting Playwright test for container controls...\n'); const browser = await chromium.launch({ headless: true }); const context = await browser.newContext({ ignoreHTTPSErrors: true, }); const page = await context.newPage(); // Capture console messages const consoleMessages = []; page.on('console', msg => { consoleMessages.push(`[${msg.type()}] ${msg.text()}`); }); // Capture network errors const networkErrors = []; page.on('requestfailed', request => { networkErrors.push({ url: request.url(), failure: request.failure().errorText }); }); try { console.log('📍 Navigating to https://admin-panel.habland.orb.local/'); await page.goto('https://admin-panel.habland.orb.local/', { waitUntil: 'networkidle', timeout: 10000 }); console.log('✅ Page loaded successfully\n'); // Wait for container cards to load (they have the bg-[#24253a] class) console.log('⏳ Waiting for container cards to load...'); await page.waitForSelector('.bg-\\[\\#24253a\\]', { timeout: 5000 }); const containerCards = await page.locator('.rounded-3xl.bg-\\[\\#24253a\\]').all(); const containerCount = containerCards.length; console.log(`✅ Found ${containerCount} container cards\n`); if (containerCount === 0) { console.log('❌ No containers found on the page'); return; } // Analyze all containers console.log('📊 Container Status Overview:'); for (let i = 0; i < Math.min(containerCount, 5); i++) { const card = containerCards[i]; const title = await card.locator('h3').textContent(); const statusBadge = await card.locator('.absolute.left-4.top-4').textContent(); // Check which buttons are available const hasRestart = await card.locator('button[title="Restart"]').count() > 0; const hasStop = await card.locator('button[title="Stop"]').count() > 0; const hasStart = await card.locator('button:has-text("Start Server")').count() > 0; console.log(`\n${i + 1}. ${title}`); console.log(` Status: ${statusBadge.trim()}`); console.log(` Controls: ${hasStart ? 'Start' : ''}${hasRestart ? ' Restart' : ''}${hasStop ? ' Stop' : ''}`); } // Find a container with restart button (running container) let testContainer = null; let testContainerName = null; for (const card of containerCards) { const hasRestart = await card.locator('button[title="Restart"]').count() > 0; if (hasRestart) { testContainer = card; testContainerName = await card.locator('h3').textContent(); break; } } if (!testContainer) { console.log('\n⚠️ No running containers found to test controls'); // Try to find a stopped container to start for (const card of containerCards) { const hasStart = await card.locator('button:has-text("Start Server")').count() > 0; if (hasStart) { testContainer = card; testContainerName = await card.locator('h3').textContent(); console.log(`\n🎯 Found stopped container to test: ${testContainerName}`); break; } } } if (!testContainer) { console.log('\n❌ No containers available for testing'); return; } console.log(`\n🎯 Testing controls for: ${testContainerName}`); // Set up API call monitoring BEFORE clicking const apiCalls = []; const apiResponses = []; page.on('request', request => { if (request.url().includes('/api/control')) { apiCalls.push({ method: request.method(), url: request.url(), postData: request.postData() }); } }); page.on('response', async response => { if (response.url().includes('/api/control')) { const status = response.status(); let body = null; try { body = await response.json(); } catch (e) { try { body = await response.text(); } catch (e2) { body = 'Unable to parse response'; } } apiResponses.push({ status, body }); } }); // Click the appropriate button const hasRestart = await testContainer.locator('button[title="Restart"]').count() > 0; const hasStart = await testContainer.locator('button:has-text("Start Server")').count() > 0; if (hasRestart) { console.log('\n🖱️ Clicking Restart button...'); await testContainer.locator('button[title="Restart"]').click(); } else if (hasStart) { console.log('\n🖱️ Clicking Start Server button...'); await testContainer.locator('button:has-text("Start Server")').click(); } // Wait for API call to complete await page.waitForTimeout(3000); console.log(`\n📊 API Results:`); console.log(` Calls made: ${apiCalls.length}`); if (apiCalls.length > 0) { apiCalls.forEach((call, i) => { console.log(`\n Call ${i + 1}:`); console.log(` Method: ${call.method}`); console.log(` URL: ${call.url}`); if (call.postData) { console.log(` Body: ${call.postData}`); } }); } if (apiResponses.length > 0) { apiResponses.forEach((resp, i) => { console.log(`\n Response ${i + 1}:`); console.log(` Status: ${resp.status}`); console.log(` Body:`, typeof resp.body === 'object' ? JSON.stringify(resp.body, null, 6) : resp.body); }); } // Take screenshot await page.screenshot({ path: '/Users/matt/DEV/habland/admin-panel/container-controls-test.png', fullPage: true }); console.log('\n📸 Screenshot saved: container-controls-test.png'); // Report console errors const errors = consoleMessages.filter(msg => msg.startsWith('[error]')); if (errors.length > 0) { console.log('\n⚠️ Console Errors:'); errors.forEach(err => console.log(` ${err}`)); } // Report network errors if (networkErrors.length > 0) { console.log('\n⚠️ Network Errors:'); networkErrors.forEach(err => { console.log(` ${err.url}: ${err.failure}`); }); } } catch (error) { console.error('\n❌ Test failed:', error.message); await page.screenshot({ path: '/Users/matt/DEV/habland/admin-panel/error-screenshot.png' }); console.log('📸 Error screenshot saved: error-screenshot.png'); } finally { await browser.close(); console.log('\n✅ Test completed'); } } testContainerControls().catch(console.error);