import { expect, test } from "@playwright/test"; import { type DeveloperRequest, installDevApiMock, seedAuth, } from "./helpers/devfront-fixtures"; import { captureEvidence } from "./helpers/evidence"; test.describe("DevFront developer request and management", () => { test.afterEach(async ({ page }, testInfo) => { if (testInfo.status === "passed") { await captureEvidence(page, testInfo, testInfo.title); } }); test.beforeEach(async ({ page }) => { page.on("dialog", async (dialog) => { await dialog.accept(); }); }); test("user can request developer access when no RP exists", async ({ page, }) => { const state = { clients: [], consents: [], developerRequests: [], }; await seedAuth(page, "user"); await installDevApiMock(page, state); await page.goto("/clients"); // Click request link and open the request modal on the dedicated page const requestBtn = page.getByRole("button", { name: /개발자 등록 신청하기|개발자 등록 신청/, }); await requestBtn.waitFor({ state: "visible" }); await requestBtn.click(); await expect(page).toHaveURL(/\/developer-requests$/); const openRequestBtn = page.getByRole("button", { name: /신규 신청하기|Request|Apply/, }); await openRequestBtn.click(); // Fill Form (organization is read-only and comes from the active tenant) await page.locator("#reason").fill("Need to test OIDC integration"); // Submit await page .locator("form") .filter({ has: page.locator("#reason") }) .evaluate((form) => { (form as HTMLFormElement).requestSubmit(); }); // Verify Status - Look for "Pending" or "대기" anywhere await expect(page.locator("body")).toContainText(/대기|Pending/); }); test("super admin can approve, reject and cancel developer requests", async ({ page, }) => { const request: DeveloperRequest = { id: "req-admin-test", userId: "user-1", userName: "Requester User", name: "Requester User", userEmail: "user1@example.com", organization: "Dev Team", reason: "API Test", status: "pending", createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; const state = { clients: [], consents: [], developerRequests: [request], }; await seedAuth(page, "super_admin"); await installDevApiMock(page, state); await page.goto("/developer-requests"); // Wait for data to load await page.waitForLoadState("networkidle"); await expect(page.locator("table")).toContainText("Requester User", { timeout: 10000, }); // Approve const approveBtn = page.getByRole("button", { name: "승인" }).first(); await approveBtn.click(); await expect(page.locator("table")).toContainText(/승인됨|Approved/); // Cancel approval (Requires notes) await page.locator("input.h-8").first().fill("Cancellation reason"); await page.getByRole("button", { name: "승인 취소" }).click(); await expect(page.locator("table")).toContainText(/대기|Pending/); // Reject (Requires notes) await page.locator("input.h-8").first().fill("Rejection reason"); await page.getByRole("button", { name: "반려" }).click(); await expect(page.locator("table")).toContainText(/반려됨|Rejected/); }); test("approved user can see 'Add App' guidance and create RP", async ({ page, }) => { const request: DeveloperRequest = { id: "req-approved", userId: "playwright-user", userName: "Playwright User", name: "Playwright User", userEmail: "playwright@example.com", organization: "QA", reason: "Test", status: "approved", createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), approvedAt: new Date().toISOString(), }; const state = { clients: [], consents: [], developerRequests: [request], }; await seedAuth(page, "user"); await installDevApiMock(page, state); await page.goto("/clients"); // Click Add App const createBtn = page .getByRole("button", { name: /연동 앱 추가/ }) .first(); await createBtn.click(); // Fill Form (Must fill all mandatory fields to enable Submit) await expect(page).toHaveURL(/\/clients\/new$/); const nameInput = page.getByPlaceholder( /My Awesome Application|예: 멋진 애플리케이션/, ); await nameInput.fill("E2E Test RP"); await nameInput.press("Tab"); const uriInput = page.getByRole("textbox", { name: /Redirect URIs|인증 콜백 URL|Callback/i, }); await uriInput.fill("https://example.com/callback"); await uriInput.press("Tab"); // Submit const submitBtn = page .getByRole("button", { name: /생성/ }) .filter({ hasNotText: "취소" }); await expect(submitBtn).toBeEnabled({ timeout: 10000 }); await submitBtn.click(); // Verification await expect(page).toHaveURL(/\/clients\/client-\d+\/settings$/); await expect( page.getByRole("heading", { name: /연동 앱 설정|Settings/ }), ).toBeVisible(); }); });