import { chromium } from "playwright"; import * as fs from "fs"; import * as path from "path"; const BASE = "http://localhost:9771"; const OUT = path.join(__dirname); async function main() { const browser = await chromium.launch({ headless: true }); const ctx = await browser.newContext({ viewport: { width: 1920, height: 1080 } }); const page = await ctx.newPage(); const jsErrors: string[] = []; page.on("pageerror", (e) => jsErrors.push(e.message)); page.on("console", (msg) => { if (msg.type() === "error") jsErrors.push("[console.error] " + msg.text().substring(0, 200)); }); // 1) Login console.log("1) Logging in..."); await page.goto(`${BASE}/login`); await page.waitForLoadState("networkidle"); await page.waitForTimeout(3000); await page.fill('[placeholder="사용자 ID를 입력하세요"]', "wace"); await page.fill('[placeholder="비밀번호를 입력하세요"]', "qlalfqjsgh11"); await page.click('button:has-text("로그인")'); await page.waitForTimeout(6000); await page.screenshot({ path: path.join(OUT, "01-after-login.png") }); console.log(" URL after login:", page.url()); // 2) Open designer for screen 60 (has v2-input) console.log("\n2) Opening designer for screen 60..."); await page.evaluate(() => { sessionStorage.setItem("erp-tab-store", JSON.stringify({ state: { tabs: [{ id: "t", title: "화면관리", path: "/admin/screenMng/screenMngList", isActive: true, isPinned: false }], activeTabId: "t" }, version: 0, })); }); await page.goto(`${BASE}/admin/screenMng/screenMngList?openDesigner=60`, { waitUntil: "domcontentloaded", timeout: 60000 }); await page.waitForTimeout(12000); await page.screenshot({ path: path.join(OUT, "02-designer-loaded.png") }); // 3) Check DOM for components const domInfo = await page.evaluate(() => { const compWrappers = document.querySelectorAll("[data-component-id]"); const ids = Array.from(compWrappers).map(el => el.getAttribute("data-component-id")); const bodyText = document.body.innerText.substring(0, 500); const hasCanvas = !!document.querySelector('[class*="canvas"], [class*="designer-content"]'); const allClasses = Array.from(document.querySelectorAll("[class]")) .map(el => el.className) .filter(c => typeof c === "string" && (c.includes("canvas") || c.includes("designer") || c.includes("panel"))) .slice(0, 20); return { componentIds: ids, hasCanvas, bodyTextPreview: bodyText, relevantClasses: allClasses }; }); console.log(" Components in DOM:", domInfo.componentIds.length); console.log(" Component IDs:", domInfo.componentIds.slice(0, 10)); console.log(" Has canvas:", domInfo.hasCanvas); console.log(" Relevant classes:", domInfo.relevantClasses.slice(0, 5)); // 4) If components found, click the first one if (domInfo.componentIds.length > 0) { const firstId = domInfo.componentIds[0]; console.log(`\n3) Clicking component: ${firstId}`); try { await page.click(`[data-component-id="${firstId}"]`, { force: true, timeout: 5000 }); await page.waitForTimeout(3000); await page.screenshot({ path: path.join(OUT, "03-component-clicked.png") }); // Check right panel const panelInfo = await page.evaluate(() => { const labels = document.querySelectorAll("label"); const inputs = document.querySelectorAll("input"); const selects = document.querySelectorAll('[role="combobox"]'); const tabs = document.querySelectorAll('[role="tab"]'); const switches = document.querySelectorAll('[role="switch"]'); const rightPanel = document.querySelector('[class*="right"], [class*="sidebar"], [class*="properties"]'); return { labels: labels.length, inputs: inputs.length, selects: selects.length, tabs: tabs.length, switches: switches.length, hasRightPanel: !!rightPanel, rightPanelText: rightPanel?.textContent?.substring(0, 300) || "(no panel found)", errorTexts: Array.from(document.querySelectorAll('[class*="error"], [class*="destructive"]')) .map(el => (el as HTMLElement).innerText?.substring(0, 100)) .filter(t => t && t.length > 0), }; }); console.log(" Panel info:", JSON.stringify(panelInfo, null, 2)); } catch (e: any) { console.log(" Click failed:", e.message.substring(0, 100)); } } else { console.log("\n No components found in DOM - designer may not have loaded"); console.log(" Body preview:", domInfo.bodyTextPreview.substring(0, 200)); } // 5) Try clicking on different areas of the page to find components if (domInfo.componentIds.length === 0) { console.log("\n4) Trying to find canvas area by clicking..."); // Take full page screenshot to see what's there await page.screenshot({ path: path.join(OUT, "04-full-page.png"), fullPage: true }); // Get viewport-based content const pageStructure = await page.evaluate(() => { const allElements = document.querySelectorAll("div, section, main, aside"); const structure: string[] = []; allElements.forEach(el => { const rect = el.getBoundingClientRect(); if (rect.width > 100 && rect.height > 100) { const cls = el.className?.toString().substring(0, 50) || ""; const id = el.id || ""; structure.push(`${el.tagName}#${id}.${cls} [${Math.round(rect.x)},${Math.round(rect.y)} ${Math.round(rect.width)}x${Math.round(rect.height)}]`); } }); return structure.slice(0, 30); }); console.log(" Large elements:"); pageStructure.forEach(s => console.log(" " + s)); } // Summary console.log("\n\n=== SUMMARY ==="); console.log(`JS Errors: ${jsErrors.length}`); if (jsErrors.length > 0) { const unique = [...new Set(jsErrors)]; console.log("Unique errors:"); unique.slice(0, 20).forEach(e => console.log(" " + e.substring(0, 200))); } await browser.close(); console.log("\nScreenshots saved to:", OUT); } main().catch(console.error);