ERP-node/frontend/scripts/verify-screen-156.ts

112 lines
4.3 KiB
TypeScript

/**
* 화면 156 검증: 로드, 버튼, 테이블, 페이지네이션, 레이아웃
*/
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<string, any> = {};
try {
await page.goto(`${BASE_URL}/screens/156`, { waitUntil: "load", timeout: 30000 });
await page.waitForTimeout(2000);
const url = page.url();
if (url.includes("/login")) {
report.loginRequired = true;
await page.screenshot({ path: path.join(SCREENSHOT_DIR, "screen-156-login.png"), fullPage: true });
console.log("Login page - logging in with wace...");
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/156`, { waitUntil: "load", timeout: 30000 });
await page.waitForTimeout(2000);
}
const currentUrl = page.url();
report.loginRequired = currentUrl.includes("/login");
if (!currentUrl.includes("/login")) {
await page.getByText("로딩중", { exact: false }).waitFor({ state: "hidden", timeout: 10000 }).catch(() => {});
await page.waitForTimeout(2000);
const hasError = (await page.locator('text="화면을 찾을 수 없습니다"').count()) > 0;
report.pageLoadsWithoutErrors = !hasError;
const buttonCount = await page.locator("button").count();
const buttonsBetween = await page.evaluate(() => {
const searchWidget = document.querySelector("[class*='search'], [class*='filter']");
const table = document.querySelector("table");
const buttons = document.querySelectorAll("button");
let between = 0;
buttons.forEach((btn) => {
const rect = btn.getBoundingClientRect();
if (searchWidget && table) {
const sRect = searchWidget.getBoundingClientRect();
const tRect = table.getBoundingClientRect();
if (rect.top > sRect.bottom && rect.top < tRect.top) between++;
}
});
return between;
});
report.buttonsVisible = buttonCount > 0;
report.buttonsBetweenSearchAndTable = buttonsBetween;
const table = page.locator("table").first();
const tableVisible = (await table.count()) > 0;
report.tableVisible = tableVisible;
let tableOverflow = false;
if (tableVisible) {
const dims = await table.evaluate((el) => ({
scrollWidth: el.scrollWidth,
clientWidth: el.clientWidth,
}));
tableOverflow = dims.scrollWidth > dims.clientWidth;
report.tableScrollWidth = dims.scrollWidth;
report.tableClientWidth = dims.clientWidth;
}
report.tableOverflowsHorizontally = tableOverflow;
const paginationVisible = (await page.getByText("표시", { exact: false }).count()) > 0 ||
(await page.getByText("1/", { exact: false }).count()) > 0;
report.paginationBarVisible = paginationVisible;
const bodyScrollWidth = await page.evaluate(() => document.body.scrollWidth);
const viewportWidth = 1280;
report.bodyScrollWidth = bodyScrollWidth;
report.hasHorizontalScrollbar = bodyScrollWidth > viewportWidth;
report.layoutResponsive = !report.hasHorizontalScrollbar;
await page.screenshot({ path: path.join(SCREENSHOT_DIR, "screen-156-snapshot.png"), fullPage: true });
console.log("screen-156-snapshot.png saved");
}
console.log("\n=== Report ===");
console.log(JSON.stringify(report, null, 2));
fs.writeFileSync(
path.join(SCREENSHOT_DIR, "screen-156-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-156-error.png"), fullPage: true }).catch(() => {});
} finally {
await browser.close();
}
}
main();