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 Button const requestBtn = page.getByRole('button', { name: /개발자 등록 신청/ }); await requestBtn.waitFor({ state: 'visible' }); await requestBtn.click(); // Fill Form (using direct selectors for reliability) await page.locator("#org").fill("QA Team"); await page.locator("#reason").fill("Need to test OIDC integration"); // Submit await page.getByRole('button', { name: /신청하기|Submit/ }).click(); // 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, "rp_admin"); 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.locator("input[placeholder*='Awesome']"); await nameInput.fill("E2E Test RP"); await nameInput.press('Tab'); const uriInput = page.locator("textarea.font-mono"); 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.locator("h1")).toContainText(/설정|Settings/); }); });