152 lines
5.1 KiB
JavaScript
152 lines
5.1 KiB
JavaScript
|
|
/**
|
||
|
|
* 결재 템플릿 관리 및 결재함 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);
|
||
|
|
});
|