/** * 회사 선택 → 메뉴 → 수주/구매관리 화면 검증 * 1. 로그인 (topseal7 또는 wace) * 2. 회사 선택 → 탑씰 * 3. 영업관리 > 수주관리 또는 구매관리 * 4. 데이터 화면 스크린샷 * 5. 테이블 가로 스크롤 확인 */ 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 steps: string[] = []; try { // Step 1: 로그인 페이지 console.log("Step 1: 로그인 페이지 접속..."); await page.goto(`${BASE_URL}/login`, { waitUntil: "domcontentloaded", timeout: 15000 }); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-01-login-page.png"), fullPage: true }); steps.push("01-login-page"); // Step 2: 로그인 시도 (topseal7 먼저) console.log("Step 2: 로그인 (topseal7 시도)..."); await page.fill("#userId", "topseal7"); await page.fill("#password", "qlalfqjsgh11"); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-02-login-topseal7.png"), fullPage: true }); await page.locator('button[type="submit"]').first().click(); await page.waitForTimeout(3000); const urlAfterLogin = page.url(); const isStillLogin = urlAfterLogin.includes("/login"); if (isStillLogin) { console.log("topseal7 로그인 실패, wace 시도..."); await page.fill("#userId", "wace"); await page.fill("#password", "qlalfqjsgh11"); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-02b-login-wace.png"), fullPage: true }); await page.locator('button[type="submit"]').first().click(); await page.waitForTimeout(3000); } await page.waitForURL((url) => !url.includes("/login"), { timeout: 15000 }).catch(() => {}); await page.waitForTimeout(3000); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-03-after-login.png"), fullPage: true }); steps.push("03-after-login"); // Step 3: 회사 선택 → 탑씰 (SUPER_ADMIN만 보임, 메인 앱 로드 대기) console.log("Step 3: 회사 선택 클릭..."); await page.getByText("현재 관리 회사").waitFor({ timeout: 8000 }).catch(() => {}); await page.waitForTimeout(1000); const companyBtn = page.getByText("회사 선택").first(); if ((await companyBtn.count()) > 0) { await companyBtn.click(); await page.waitForTimeout(1500); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-04-company-dropdown.png"), fullPage: true }); const tapsealOption = page.getByText("탑씰", { exact: true }).first(); if ((await tapsealOption.count()) > 0) { await tapsealOption.click(); await page.waitForTimeout(2000); console.log("탑씰 선택됨"); } else { console.log("탑씰 옵션 없음 - 스킵"); } await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-05-after-company.png"), fullPage: true }); } else { console.log("회사 선택 버튼 없음"); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-05-no-company-btn.png"), fullPage: true }); } steps.push("05-after-company"); // Step 4: 영업관리 > 수주관리 또는 구매관리 console.log("Step 4: 메뉴 클릭 (영업관리 > 수주관리)..."); const salesMgmt = page.getByText("영업관리").first(); if ((await salesMgmt.count()) > 0) { await salesMgmt.click(); await page.waitForTimeout(1000); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-06-sales-expanded.png"), fullPage: true }); const orderMgmt = page.getByText("수주관리").first(); if ((await orderMgmt.count()) > 0) { await orderMgmt.click(); await page.waitForTimeout(3000); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-07-order-screen.png"), fullPage: true }); } else { const purchaseMgmt = page.getByText("구매관리").first(); if ((await purchaseMgmt.count()) > 0) { await purchaseMgmt.click(); await page.waitForTimeout(3000); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-07-purchase-screen.png"), fullPage: true }); } } } else { const purchaseMgmt = page.getByText("구매관리").first(); if ((await purchaseMgmt.count()) > 0) { await purchaseMgmt.click(); await page.waitForTimeout(3000); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-07-purchase-direct.png"), fullPage: true }); } } steps.push("07-menu-screen"); // Step 5: /screens/1244 직접 접속 시도 console.log("Step 5: /screens/1244 직접 접속..."); await page.goto(`${BASE_URL}/screens/1244`, { waitUntil: "domcontentloaded", timeout: 15000 }); await page.waitForTimeout(5000); await page.getByText("로딩중", { exact: false }).waitFor({ state: "hidden", timeout: 10000 }).catch(() => {}); await page.waitForTimeout(2000); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-08-screen-1244.png"), fullPage: true }); steps.push("08-screen-1244"); // Step 6: 테이블 가로 스크롤 확인 console.log("Step 6: 테이블 가로 스크롤 확인..."); const tableContainer = page.locator("table").locator("..").first(); const table = page.locator("table").first(); if ((await table.count()) > 0) { const tableBox = await table.boundingBox(); const hasOverflowX = await table.evaluate((el) => { const parent = el.closest("[style*='overflow'], [class*='overflow']"); return parent ? getComputedStyle(parent as Element).overflowX !== "visible" : false; }).catch(() => false); const scrollWidth = await table.evaluate((el) => el.scrollWidth); const clientWidth = await table.evaluate((el) => el.clientWidth); const canScroll = scrollWidth > clientWidth; console.log(`테이블: scrollWidth=${scrollWidth}, clientWidth=${clientWidth}, 가로스크롤가능=${canScroll}`); } await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-09-table-scroll-check.png"), fullPage: true }); steps.push("09-table-scroll"); // Step 7: 최종 스크린샷 console.log("Step 7: 최종 스크린샷..."); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-10-final.png"), fullPage: true }); steps.push("10-final"); fs.writeFileSync( path.join(SCREENSHOT_DIR, "flow-result.json"), JSON.stringify({ steps, timestamp: new Date().toISOString() }, null, 2) ); console.log("\n완료. 스크린샷:", SCREENSHOT_DIR); } catch (error: any) { console.error("오류:", error.message); await page.screenshot({ path: path.join(SCREENSHOT_DIR, "flow-99-error.png"), fullPage: true }).catch(() => {}); } finally { await browser.close(); } } main();