/** * 화면 1244 검증: table-list 레이아웃 (데스크톱 + 모바일) */ 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 = { desktop: {}, mobile: {} }; try { await page.goto(`${BASE_URL}/screens/1244`, { waitUntil: "load", timeout: 30000 }); 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) => !u.includes("/login"), { timeout: 15000 }).catch(() => {}); await page.waitForTimeout(2000); await page.goto(`${BASE_URL}/screens/1244`, { waitUntil: "load", timeout: 30000 }); await page.waitForTimeout(2000); } await page.getByText("로딩중", { exact: false }).waitFor({ state: "hidden", timeout: 10000 }).catch(() => {}); await page.waitForTimeout(2000); report.desktop.pageLoadsWithoutErrors = (await page.locator('text="화면을 찾을 수 없습니다"').count()) === 0; const desktopInfo = await page.evaluate(() => { const table = document.querySelector("table"); const thead = document.querySelector("thead"); const tbody = document.querySelector("tbody"); const ths = document.querySelectorAll("thead th"); const buttons = document.querySelectorAll("button"); const searchInputs = document.querySelectorAll('input[type="text"], input[type="search"], select'); const pagination = document.body.innerText.includes("표시") || document.body.innerText.includes("1/") || document.body.innerText.includes("페이지") || document.querySelector("[class*='pagination'], [class*='Pagination']"); let buttonsBetweenSearchAndTable = 0; const searchY = searchInputs.length > 0 ? (searchInputs[0] as HTMLElement).getBoundingClientRect().bottom : 0; const tableY = table ? (table as HTMLElement).getBoundingClientRect().top : 0; buttons.forEach((btn) => { const rect = (btn as HTMLElement).getBoundingClientRect(); if (rect.top >= searchY - 20 && rect.top <= tableY + 100) buttonsBetweenSearchAndTable++; }); return { tableVisible: !!table && !!thead && !!tbody, columnCount: ths.length, buttonsVisible: buttons.length > 0, buttonsBetweenSearchAndTable, paginationVisible: !!pagination, bodyScrollWidth: document.body.scrollWidth, viewportWidth: window.innerWidth, hasHorizontalOverflow: document.body.scrollWidth > window.innerWidth, tableScrollWidth: table ? (table as HTMLElement).scrollWidth : 0, tableClientWidth: table ? (table as HTMLElement).clientWidth : 0, }; }); report.desktop.buttonsVisible = desktopInfo.buttonsVisible; report.desktop.buttonsBetweenSearchAndTable = desktopInfo.buttonsBetweenSearchAndTable; report.desktop.tableVisible = desktopInfo.tableVisible; report.desktop.columnCount = desktopInfo.columnCount; report.desktop.paginationVisible = desktopInfo.paginationVisible; report.desktop.noHorizontalOverflow = !desktopInfo.hasHorizontalOverflow; report.desktop.overflowDetails = { bodyScrollWidth: desktopInfo.bodyScrollWidth, viewportWidth: desktopInfo.viewportWidth, tableScrollWidth: desktopInfo.tableScrollWidth, tableClientWidth: desktopInfo.tableClientWidth, }; await page.screenshot({ path: path.join(SCREENSHOT_DIR, "screen-1244-desktop.png"), fullPage: true, }); console.log("screen-1244-desktop.png saved"); await page.setViewportSize({ width: 768, height: 900 }); await page.waitForTimeout(1500); const mobileInfo = await page.evaluate(() => { const table = document.querySelector("table"); const thead = document.querySelector("thead"); const tbody = document.querySelector("tbody"); const ths = document.querySelectorAll("thead th"); const buttons = document.querySelectorAll("button"); const pagination = document.body.innerText.includes("표시") || document.body.innerText.includes("1/") || document.body.innerText.includes("페이지") || document.querySelector("[class*='pagination'], [class*='Pagination']"); return { tableVisible: !!table && !!thead && !!tbody, columnCount: ths.length, buttonsVisible: buttons.length > 0, paginationVisible: !!pagination, bodyScrollWidth: document.body.scrollWidth, viewportWidth: window.innerWidth, hasHorizontalOverflow: document.body.scrollWidth > window.innerWidth, }; }); report.mobile.pageLoadsWithoutErrors = report.desktop.pageLoadsWithoutErrors; report.mobile.buttonsVisible = mobileInfo.buttonsVisible; report.mobile.tableVisible = mobileInfo.tableVisible; report.mobile.columnCount = mobileInfo.columnCount; report.mobile.paginationVisible = mobileInfo.paginationVisible; report.mobile.noHorizontalOverflow = !mobileInfo.hasHorizontalOverflow; report.mobile.overflowDetails = { bodyScrollWidth: mobileInfo.bodyScrollWidth, viewportWidth: mobileInfo.viewportWidth, }; await page.screenshot({ path: path.join(SCREENSHOT_DIR, "screen-1244-mobile-768.png"), fullPage: true, }); console.log("screen-1244-mobile-768.png saved"); console.log("\n=== Report ==="); console.log(JSON.stringify(report, null, 2)); fs.writeFileSync( path.join(SCREENSHOT_DIR, "screen-1244-layout-report.json"), 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, "screen-1244-error.png"), fullPage: true, }).catch(() => {}); } finally { await browser.close(); } } main();