/** * BOM Screen - Restoration Verification * Screen 4168 - verify split panel, BOM list, and tree with child items */ import { chromium } from 'playwright'; import { mkdirSync, existsSync } from 'fs'; import { join } from 'path'; const SCREENSHOT_DIR = join(process.cwd(), 'bom-detail-test-screenshots'); async function ensureDir(dir) { if (!existsSync(dir)) mkdirSync(dir, { recursive: true }); } async function screenshot(page, name) { ensureDir(SCREENSHOT_DIR); await page.screenshot({ path: join(SCREENSHOT_DIR, `${name}.png`), fullPage: true }); console.log(` [Screenshot] ${name}.png`); } async function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); } async function main() { const browser = await chromium.launch({ headless: true }); const page = await browser.newPage({ viewport: { width: 1400, height: 900 } }); try { console.log('\n--- Step 1-2: Login ---'); await page.goto('http://localhost:9771/login', { waitUntil: 'load', timeout: 45000 }); await page.locator('input[type="text"], input[placeholder*="ID"]').first().fill('topseal_admin'); await page.locator('input[type="password"]').first().fill('qlalfqjsgh11'); await Promise.all([ page.waitForNavigation({ waitUntil: 'domcontentloaded', timeout: 20000 }).catch(() => {}), page.locator('button:has-text("로그인")').first().click(), ]); await sleep(3000); console.log('\n--- Step 4-5: Navigate to screen 4168 ---'); await page.goto('http://localhost:9771/screens/4168', { waitUntil: 'load', timeout: 45000 }); await sleep(5000); console.log('\n--- Step 6: Screenshot after load ---'); await screenshot(page, '10-bom-4168-initial'); const hasBomList = (await page.locator('text="BOM 목록"').count()) > 0; const hasSplitPanel = (await page.locator('text="BOM 상세정보"').count()) > 0 || hasBomList; const rowCount = await page.locator('table tbody tr').count(); const hasBomRows = rowCount > 0; console.log('\n========== INITIAL STATE (Step 7) =========='); console.log('BOM management screen loaded:', hasBomList || hasSplitPanel ? 'YES' : 'CHECK'); console.log('Split panel (BOM list left):', hasSplitPanel ? 'YES' : 'NO'); console.log('BOM data rows visible:', hasBomRows ? `YES (${rowCount} rows)` : 'NO'); if (hasBomRows) { console.log('\n--- Step 8-9: Click first row ---'); await page.locator('table tbody tr').first().click(); await sleep(5000); console.log('\n--- Step 10: Screenshot after row click ---'); await screenshot(page, '11-bom-4168-after-click'); const noDataMsg = (await page.locator('text="등록된 하위 품목이 없습니다"').count()) > 0; const treeArea = page.locator('div:has-text("BOM 구성"), div:has-text("BOM 상세정보")').first(); const treeText = (await treeArea.textContent().catch(() => '') || '').substring(0, 600); const hasChildItems = !noDataMsg && (treeText.includes('품번') || treeText.includes('레벨') || treeText.length > 150); console.log('\n========== AFTER ROW CLICK (Step 11) =========='); console.log('BOM tree shows child items:', hasChildItems ? 'YES' : noDataMsg ? 'NO (empty message)' : 'CHECK'); console.log('Tree preview:', treeText.substring(0, 300) + (treeText.length > 300 ? '...' : '')); } else { console.log('\n--- No BOM rows to click ---'); } } catch (err) { console.error('Error:', err.message); try { await page.screenshot({ path: join(SCREENSHOT_DIR, '99-error.png'), fullPage: true }); } catch (e) {} } finally { await browser.close(); } } main();