forked from baron/baron-sso
170 lines
5.0 KiB
TypeScript
170 lines
5.0 KiB
TypeScript
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.getByRole("button", { name: "신청하기", exact: true }).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.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();
|
|
});
|
|
});
|