1
0
forked from baron/baron-sso

feat(devfront): show client creators and headless filter

This commit is contained in:
2026-06-17 22:03:15 +09:00
parent 69e1e32fd4
commit 5f3167a503
7 changed files with 311 additions and 9 deletions

View File

@@ -1,4 +1,4 @@
import { expect, test } from "@playwright/test";
import { expect, type Page, test } from "@playwright/test";
import {
type AuditLog,
type Consent,
@@ -15,6 +15,42 @@ test.afterEach(async ({ page }, testInfo) => {
}
});
async function mockAdminUserLookup(page: Page) {
await page.route("**/api/v1/admin/users/*", async (route) => {
const url = new URL(route.request().url());
const userId = url.pathname.split("/").pop();
const users: Record<string, DevAssignableUser> = {
"creator-headless": {
id: "creator-headless",
name: "Headless Creator",
email: "headless.creator@example.com",
},
"creator-plain": {
id: "creator-plain",
name: "Plain Creator",
email: "plain.creator@example.com",
},
};
const found = userId ? users[userId] : undefined;
await route.fulfill({
status: found ? 200 : 404,
contentType: "application/json",
body: JSON.stringify(
found
? {
...found,
role: "user",
status: "active",
createdAt: "2026-03-03T00:00:00.000Z",
updatedAt: "2026-03-03T00:00:00.000Z",
}
: { error: "not found" },
),
});
});
}
test("clients page loads correctly", async ({ page }) => {
await seedAuth(page, "super_admin");
await installDevApiMock(page, {
@@ -87,6 +123,66 @@ test("clients page shows Tenant-limited only for tenant access restricted RP", a
await expect(page.getByText("Tenant-scoped")).toHaveCount(0);
});
test("clients page resolves creator and filters Headless Login clients", async ({
page,
}) => {
await seedAuth(page, "super_admin");
await installDevApiMock(page, {
clients: [
makeClient("client-plain", {
name: "Plain Server App",
createdAt: "2026-05-01T00:00:00.000Z",
creatorId: "creator-plain",
}),
makeClient("client-headless", {
name: "Headless Login App",
createdAt: "2026-05-02T00:00:00.000Z",
creatorId: "creator-headless",
metadata: {
headless_login_enabled: true,
},
}),
],
users: [
{
id: "creator-headless",
name: "Headless Creator",
email: "headless.creator@example.com",
},
{
id: "creator-plain",
name: "Plain Creator",
email: "plain.creator@example.com",
},
] as DevAssignableUser[],
consents: [] as Consent[],
auditLogsByCursor: undefined,
});
await mockAdminUserLookup(page);
await page.goto("/clients");
const headlessRow = page.locator("tbody tr", {
hasText: "Headless Login App",
});
await expect(headlessRow).toContainText("Headless Creator");
await expect(headlessRow).toContainText("headless.creator@example.com");
await page
.getByRole("button", { name: /Advanced Filters|고급 필터/ })
.click();
await page
.locator('select:has(option[value="headless"])')
.selectOption("headless");
await expect(
page.locator("tbody tr", { hasText: "Headless Login App" }),
).toBeVisible();
await expect(
page.locator("tbody tr", { hasText: "Plain Server App" }),
).toHaveCount(0);
});
test("overview page shows recent RP changes", async ({ page }) => {
await seedAuth(page, "super_admin");
await installDevApiMock(page, {

View File

@@ -8,6 +8,7 @@ export type Client = {
name: string;
type: ClientType;
status: ClientStatus;
creatorId?: string;
redirectUris: string[];
scopes: string[];
createdAt: string;
@@ -594,6 +595,7 @@ export async function installDevApiMock(page: Page, state: DevApiMockState) {
name: client.name,
type: client.type,
status: client.status,
creatorId: client.creatorId,
createdAt: client.createdAt,
redirectUris: client.redirectUris,
scopes: client.scopes,