1
0
forked from baron/baron-sso
Files
baron-sso/devfront/tests/devfront-role-switch-report.spec.ts

240 lines
7.4 KiB
TypeScript

import { expect, test } from "@playwright/test";
import {
type AuditLog,
type Consent,
installDevApiMock,
makeClient,
seedAuth,
} from "./helpers/devfront-fixtures";
import { captureEvidence } from "./helpers/evidence";
const appNamePlaceholder = /My Awesome Application|예: 멋진 애플리케이션/i;
test.describe("DevFront role report", () => {
test.beforeEach(async ({ page }) => {
page.on("dialog", async (dialog) => {
await dialog.accept();
});
});
test("user can enter and sees empty RP list", async ({
page,
}, testInfo) => {
await seedAuth(page, "user");
await installDevApiMock(page, {
clients: [],
consents: [] as Consent[],
auditLogs: [] as AuditLog[],
});
await page.goto("/clients");
await expect(
page.getByText(/조회 가능한 RP가 없습니다|No RPs are available/i),
).toBeVisible();
await expect(
page.getByRole("heading", {
name: /^연동 앱$|^Connected Application$/i,
}),
).toBeVisible();
await captureEvidence(page, testInfo, "role-user-empty-rps");
});
test("user sees developer request entry point on overview", async ({
page,
}, testInfo) => {
await seedAuth(page, "user");
await installDevApiMock(page, {
clients: [],
consents: [] as Consent[],
auditLogs: [] as AuditLog[],
auditLogsByCursor: undefined,
developerRequests: [],
});
await page.goto("/");
await expect(
page.getByText(
/대시보드는 개발자 권한이 있어야 볼 수 있습니다|개발자 권한 신청을 검토 중입니다./,
),
).toBeVisible();
const requestBtn = page.getByRole("button", {
name: /개발자 권한 신청/,
});
await expect(requestBtn).toBeVisible();
await requestBtn.click();
await expect(page).toHaveURL(/\/developer-requests$/);
await captureEvidence(page, testInfo, "role-user-overview-request-entry");
});
test("user with approved developer request sees overview without CTA", async ({
page,
}, testInfo) => {
await seedAuth(page, "user");
await installDevApiMock(page, {
clients: [],
consents: [] as Consent[],
auditLogs: [] as AuditLog[],
auditLogsByCursor: undefined,
developerRequests: [
{
id: "req-approved",
userId: "playwright-user",
userName: "Playwright User",
name: "Playwright User",
userEmail: "playwright@example.com",
organization: "Tenant A",
reason: "Need access",
status: "approved",
createdAt: "2026-05-29T00:00:00.000Z",
updatedAt: "2026-05-29T00:00:00.000Z",
approvedAt: "2026-05-29T00:10:00.000Z",
},
],
});
await page.goto("/");
await expect(page.getByRole("heading", { name: /운영 현황/ })).toBeVisible();
await expect(
page.getByRole("button", { name: /개발자 권한 신청/ }),
).toHaveCount(0);
await captureEvidence(page, testInfo, "role-user-overview-approved");
});
test("rp_admin sees only assigned Gitea app and its logs", async ({
page,
}, testInfo) => {
await seedAuth(page, "rp_admin");
const state = {
clients: [makeClient("gitea-client", { name: "Gitea" })],
consents: [] as Consent[],
auditLogs: [
{
event_id: "evt-rp-1",
timestamp: "2026-03-04T01:00:00.000Z",
user_id: "rp-admin-user",
event_type: "CLIENT_UPDATE",
status: "success" as const,
ip_address: "127.0.0.1",
user_agent: "playwright",
details: JSON.stringify({
action: "UPDATE_CLIENT",
target_id: "gitea-client",
tenant_id: "tenant-a",
}),
},
] as AuditLog[],
};
await installDevApiMock(page, state);
await page.goto("/clients");
await expect(
page.getByRole("link", { name: "Gitea", exact: true }),
).toBeVisible();
await expect(
page.getByRole("cell", { name: "gitea-client" }),
).toBeVisible();
await captureEvidence(page, testInfo, "role-rp-admin-clients");
await page.goto("/audit-logs");
await expect(page.getByText("UPDATE_CLIENT")).toBeVisible();
await expect(page.getByText("gitea-client")).toBeVisible();
await captureEvidence(page, testInfo, "role-rp-admin-audit");
});
test("tenant_admin can manage tenant apps and see tenant logs", async ({
page,
}, testInfo) => {
await seedAuth(page, "tenant_admin");
const state = {
clients: [
makeClient("tenant-a-app-1", { name: "Tenant A CRM" }),
makeClient("tenant-a-app-2", { name: "Tenant A ERP" }),
],
consents: [] as Consent[],
auditLogs: [] as AuditLog[],
auditLogsByCursor: undefined,
};
await installDevApiMock(page, state);
await page.goto("/clients");
await expect(page.getByText("Tenant A CRM")).toBeVisible();
await expect(page.getByText("Tenant A ERP")).toBeVisible();
await captureEvidence(page, testInfo, "role-tenant-admin-clients");
await page.goto("/clients/tenant-a-app-1/settings");
await page
.getByPlaceholder(appNamePlaceholder)
.fill("Tenant A CRM Updated");
const updatePromise = page.waitForResponse(
(r) =>
r.url().includes("/api/v1/dev/clients") &&
r.request().method() === "PUT",
);
await page.getByRole("button", { name: /^저장$|^Save$/i }).click();
await updatePromise;
await page.goto("/audit-logs");
await expect(page.getByText("UPDATE_CLIENT")).toBeVisible({
timeout: 30000,
});
await expect(page.getByText("tenant-a-app-1")).toBeVisible();
await captureEvidence(page, testInfo, "role-tenant-admin-audit");
});
test("super_admin sees all and can generate log entries", async ({
page,
}, testInfo) => {
await seedAuth(page, "super_admin");
const state = {
clients: [
makeClient("tenant-a-app", { name: "Tenant A App" }),
makeClient("tenant-b-app", { name: "Tenant B App" }),
],
consents: [] as Consent[],
auditLogs: [] as AuditLog[],
auditLogsByCursor: undefined,
};
await installDevApiMock(page, state);
await page.goto("/clients");
await expect(page.getByText("Tenant A App")).toBeVisible();
await expect(page.getByText("Tenant B App")).toBeVisible();
await captureEvidence(page, testInfo, "role-super-admin-clients");
await page.goto("/clients/new");
await page
.getByPlaceholder(appNamePlaceholder)
.fill("Super Admin Created App");
await page
.getByPlaceholder(/https:\/\/app\.example\.com\/callback/i)
.fill("https://super-admin.example.com/callback");
const createPromise = page.waitForResponse(
(r) =>
r.url().includes("/api/v1/dev/clients") &&
r.request().method() === "POST",
);
await page.getByRole("button", { name: /앱 생성|Create/i }).click();
await createPromise;
await expect(page).toHaveURL(/\/clients\/client-\d+\/settings$/);
await expect
.poll(() =>
state.auditLogs.some((item) => {
try {
return JSON.parse(item.details)?.action === "CREATE_CLIENT";
} catch {
return false;
}
}),
)
.toBe(true);
await page.goto("/audit-logs");
await expect(page.getByText("CREATE_CLIENT")).toBeVisible({
timeout: 30000,
});
await captureEvidence(page, testInfo, "role-super-admin-audit");
});
});