diff --git a/scripts/run-e2e-test.js b/scripts/run-e2e-test.js new file mode 100644 index 00000000..fc9566db --- /dev/null +++ b/scripts/run-e2e-test.js @@ -0,0 +1,151 @@ +/** + * 결재 템플릿 관리 및 결재함 E2E 테스트 + * 실행: node scripts/run-e2e-test.js + */ +const { chromium } = require("playwright"); + +const BASE_URL = "http://localhost:9771"; +const SCREENSHOT_DIR = ".agent-pipeline/browser-tests"; + +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({ name, status: "PASS" }); + console.log(`PASS: ${name}`); + } + + function fail(name, reason) { + results.push({ name, status: "FAIL", reason }); + console.log(`FAIL: ${name} - ${reason}`); + allPassed = false; + } + + 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"); + pass("로그인"); + + // ========================================================= + // 결재 템플릿 관리 페이지 + // ========================================================= + await page.goto(`${BASE_URL}/admin/approvalTemplate`); + await page.waitForLoadState("domcontentloaded"); + await page.waitForTimeout(3000); + + // 1. "결재 템플릿 관리" 제목 확인 + try { + await page.locator("h1").filter({ hasText: "결재 템플릿 관리" }).waitFor({ timeout: 10000 }); + pass("결재 템플릿 관리 - 제목 확인"); + } catch (e) { + fail("결재 템플릿 관리 - 제목 확인", e.message); + } + + // 2. "신규 등록" 버튼 확인 + try { + await page.getByRole("button", { name: "신규 등록" }).waitFor({ timeout: 10000 }); + pass("결재 템플릿 관리 - 신규 등록 버튼 확인"); + } catch (e) { + fail("결재 템플릿 관리 - 신규 등록 버튼 확인", e.message); + } + + // 3. 검색 입력란 확인 + try { + await page.getByPlaceholder("템플릿명 또는 설명 검색...").waitFor({ timeout: 10000 }); + pass("결재 템플릿 관리 - 검색 입력란 확인"); + } catch (e) { + // placeholder가 다를 수 있으므로 input으로 재시도 + try { + await page.locator("input[type='text']").first().waitFor({ timeout: 5000 }); + pass("결재 템플릿 관리 - 검색 입력란 확인 (input fallback)"); + } catch (e2) { + fail("결재 템플릿 관리 - 검색 입력란 확인", e.message); + } + } + + // 4. JS 에러 오버레이 확인 + const hasError1 = await page.locator('[id="__next"] .nextjs-container-errors-body').isVisible().catch(() => false); + if (!hasError1) { + pass("결재 템플릿 관리 - JS 에러 없음"); + } else { + fail("결재 템플릿 관리 - JS 에러 없음", "에러 오버레이 감지됨"); + } + + await page.screenshot({ path: `${SCREENSHOT_DIR}/result-template.png`, fullPage: true }); + + // ========================================================= + // 결재함 페이지 + // ========================================================= + await page.goto(`${BASE_URL}/admin/approvalBox`); + await page.waitForLoadState("domcontentloaded"); + await page.waitForTimeout(3000); + + // 1. 탭 확인 + try { + await page.getByRole("tab", { name: /수신함/ }).waitFor({ timeout: 10000 }); + pass("결재함 - 수신함 탭 확인"); + } catch (e) { + fail("결재함 - 수신함 탭 확인", e.message); + } + + try { + await page.getByRole("tab", { name: /상신함/ }).waitFor({ timeout: 10000 }); + pass("결재함 - 상신함 탭 확인"); + } catch (e) { + fail("결재함 - 상신함 탭 확인", e.message); + } + + // 2. JS 에러 오버레이 확인 + const hasError2 = await page.locator('[id="__next"] .nextjs-container-errors-body').isVisible().catch(() => false); + if (!hasError2) { + pass("결재함 - JS 에러 없음"); + } else { + fail("결재함 - JS 에러 없음", "에러 오버레이 감지됨"); + } + + await page.screenshot({ path: `${SCREENSHOT_DIR}/result-box.png`, fullPage: true }); + + } catch (e) { + fail("테스트 실행", e.message); + } finally { + await browser.close(); + } + + console.log("\n=== 테스트 결과 ==="); + results.forEach(r => { + const status = r.status === "PASS" ? "✓" : "✗"; + console.log(`${status} ${r.name}${r.reason ? `: ${r.reason}` : ""}`); + }); + + if (allPassed) { + console.log("\nBROWSER_TEST_RESULT: PASS"); + process.exit(0); + } else { + const failed = results.filter(r => r.status === "FAIL").map(r => r.name).join(", "); + console.log(`\nBROWSER_TEST_RESULT: FAIL - ${failed}`); + process.exit(1); + } +} + +runTest().catch(e => { + console.error("치명적 오류:", e); + console.log("BROWSER_TEST_RESULT: FAIL - 치명적 오류: " + e.message); + process.exit(1); +});