/** * /screens/29 화면 렌더링 E2E 테스트 * 실행: node scripts/run-screens-29-test.js */ const { chromium } = require("playwright"); const BASE_URL = "http://localhost:9771"; const SCREENSHOT_PATH = ".agent-pipeline/browser-tests/result.png"; async function runTest() { const browser = await chromium.launch({ headless: true }); const context = await browser.newContext({ viewport: { width: 1280, height: 720 }, }); const page = await context.newPage(); const results = []; let allPassed = true; function pass(name) { results.push(`PASS: ${name}`); } function fail(name, reason) { allPassed = false; results.push(`FAIL: ${name} - ${reason}`); } try { // 로그인 await page.goto(`${BASE_URL}/login`); await page.waitForLoadState("networkidle"); await page.getByPlaceholder("사용자 ID를 입력하세요").fill("wace"); await page.getByPlaceholder("비밀번호를 입력하세요").fill("qlalfqjsgh11"); await Promise.all([ page.waitForURL((url) => !url.toString().includes("/login"), { timeout: 30000, }), page.getByRole("button", { name: "로그인" }).click(), ]); await page.waitForLoadState("networkidle"); const loginUrl = page.url(); if (loginUrl.includes("/login")) { fail("로그인", "/login 페이지에 머무름"); } else { pass(`로그인 성공 (URL: ${loginUrl})`); } // /screens/29 접속 await page.goto(`${BASE_URL}/screens/29`); await page.waitForLoadState("domcontentloaded"); await page.waitForTimeout(3000); const screenUrl = page.url(); results.push(`INFO: screens/29 접속 URL = ${screenUrl}`); // 에러 오버레이 체크 const hasError = await page .locator('[id="__next"] .nextjs-container-errors-body') .isVisible() .catch(() => false); if (hasError) { fail("에러 오버레이 확인", "에러 오버레이가 표시됨"); } else { pass("에러 오버레이 없음"); } // 화면 렌더링 확인 const bodyVisible = await page .locator("body") .isVisible({ timeout: 10000 }) .catch(() => false); if (!bodyVisible) { fail("화면 렌더링", "body 요소가 보이지 않음"); } else { pass("화면 렌더링 확인"); } // 버튼 존재 확인 await page.waitForTimeout(2000); const buttonCount = await page.locator("button").count(); if (buttonCount === 0) { fail("버튼 확인", "버튼이 하나도 없음"); } else { pass(`버튼 ${buttonCount}개 확인`); } // 테이블/그리드 요소 확인 const tableCount = await page .locator('table, [role="grid"], [role="table"]') .count(); const gridLikeCount = await page .locator( 'tbody, thead, .ag-root, [class*="table"], [class*="grid"], [class*="Table"], [class*="Grid"]' ) .count(); if (tableCount > 0) { pass(`테이블/그리드 ${tableCount}개 확인`); } else if (gridLikeCount > 0) { pass(`그리드 유사 요소 ${gridLikeCount}개 확인`); } else { // 스크린샷 찍고 경고 (HTML 구조 파악용) results.push("WARN: 표준 테이블/그리드 요소 없음 - 스크린샷으로 확인 필요"); } // 스크린샷 저장 await page.screenshot({ path: SCREENSHOT_PATH, fullPage: true }); pass("스크린샷 저장 완료"); } catch (err) { allPassed = false; results.push(`ERROR: ${err.message}`); await page .screenshot({ path: SCREENSHOT_PATH, fullPage: true }) .catch(() => {}); } finally { await browser.close(); } console.log("\n=== 테스트 결과 ==="); results.forEach((r) => console.log(r)); console.log("==================\n"); if (allPassed) { console.log("BROWSER_TEST_RESULT: PASS"); process.exit(0); } else { const failItems = results.filter((r) => r.startsWith("FAIL:") || r.startsWith("ERROR:")); console.log(`BROWSER_TEST_RESULT: FAIL - ${failItems[0] || "알 수 없는 오류"}`); process.exit(1); } } runTest().catch((err) => { console.error("실행 오류:", err); console.log(`BROWSER_TEST_RESULT: FAIL - ${err.message}`); process.exit(1); });