/** * 반응형 렌더링 검증: 화면 1053, 2089, 156, 4155 * 로그인: admin / wace1234! */ import { chromium } from "playwright"; import * as path from "path"; import * as fs from "fs"; const BASE_URL = "http://localhost:9771"; const SCREENSHOT_DIR = path.join(__dirname, "../verification-screenshots"); async function main() { const browser = await chromium.launch({ headless: true }); const context = await browser.newContext({ viewport: { width: 1280, height: 900 } }); const page = await context.newPage(); const report: Record = {}; try { // 1-3: Login await page.goto(`${BASE_URL}/login`, { waitUntil: "load", timeout: 30000 }); await page.waitForTimeout(1500); await page.fill("#userId", "admin"); await page.fill("#password", "wace1234!"); await page.locator('button[type="submit"]').first().click(); await page.waitForTimeout(3000); if (page.url().includes("/login")) { await page.fill("#userId", "wace"); await page.fill("#password", "qlalfqjsgh11"); await page.locator('button[type="submit"]').first().click(); await page.waitForTimeout(3000); } await page.waitForURL((u: URL) => !u.includes("/login"), { timeout: 15000 }).catch(() => {}); await page.waitForTimeout(2000); await page.getByText("로딩중", { exact: false }).waitFor({ state: "hidden", timeout: 10000 }).catch(() => {}); async function captureAndVerify(screenId: number, screenName: string) { await page.goto(`${BASE_URL}/screens/${screenId}`, { waitUntil: "domcontentloaded", timeout: 45000 }); await page.waitForTimeout(2000); if (page.url().includes("/login")) { await page.fill("#userId", "wace"); await page.fill("#password", "qlalfqjsgh11"); await page.locator('button[type="submit"]').first().click(); await page.waitForURL((u: URL) => !u.includes("/login"), { timeout: 15000 }).catch(() => {}); await page.waitForTimeout(2000); await page.goto(`${BASE_URL}/screens/${screenId}`, { waitUntil: "domcontentloaded", timeout: 45000 }); await page.waitForTimeout(2000); } await page.getByText("로딩중", { exact: false }).waitFor({ state: "hidden", timeout: 10000 }).catch(() => {}); await page.getByText("화면을 불러오는 중", { exact: false }).waitFor({ state: "hidden", timeout: 25000 }).catch(() => {}); await page.waitForTimeout(2000); const info = await page.evaluate(() => { const buttons = Array.from(document.querySelectorAll("button")); const btnWithText = buttons.filter((b) => (b as HTMLElement).innerText?.trim().length > 0); const splitPanel = document.querySelector("[class*='split'], [class*='Split'], [class*='border-r']"); const leftPanel = document.querySelector("[class*='border-r']"); const table = document.querySelector("table"); const thead = document.querySelector("thead"); const tbody = document.querySelector("tbody"); const pagination = document.body.innerText.includes("표시") || document.body.innerText.includes("1/"); const bodyText = document.body.innerText; const hasOverlap = bodyText.includes("화면을 찾을 수 없습니다") ? false : null; const btnDetails = btnWithText.slice(0, 5).map((b) => ({ text: (b as HTMLElement).innerText?.trim().substring(0, 30), rect: (b as HTMLElement).getBoundingClientRect(), })); return { pageLoadsWithoutErrors: !bodyText.includes("화면을 찾을 수 없습니다"), buttonsVisible: btnWithText.length > 0, buttonsCount: btnWithText.length, buttonDetails: btnDetails, splitPanelVisible: !!splitPanel, leftPanelVisible: !!leftPanel, tableVisible: !!table && !!thead && !!tbody, paginationVisible: !!pagination, bodyScrollWidth: document.body.scrollWidth, viewportWidth: window.innerWidth, viewportHeight: window.innerHeight, hasHorizontalOverflow: document.body.scrollWidth > window.innerWidth, }; }); await page.screenshot({ path: path.join(SCREENSHOT_DIR, `responsive-${screenId}.png`), fullPage: true, }); console.log(`responsive-${screenId}.png saved`); return { screenId, screenName, ...info }; } // 4: Screen 1053 - 거래처관리 report.screen1053 = await captureAndVerify(1053, "거래처관리 - split panel custom mode"); // 5: Screen 2089 - BOM관리 report.screen2089 = await captureAndVerify(2089, "BOM관리 - split panel"); // 6: Screen 156 - 수주관리 report.screen156 = await captureAndVerify(156, "수주관리 - regular screen"); // 7: Screen 4155 - 작업지시 report.screen4155 = await captureAndVerify(4155, "작업지시 - buttons at bottom"); fs.writeFileSync( path.join(SCREENSHOT_DIR, "responsive-report.json"), JSON.stringify(report, null, 2) ); console.log("\n=== Report ==="); console.log(JSON.stringify(report, null, 2)); } catch (error: any) { console.error("Error:", error.message); report.error = error.message; await page.screenshot({ path: path.join(SCREENSHOT_DIR, "responsive-error.png"), fullPage: true, }).catch(() => {}); } finally { await browser.close(); } } main();