forked from baron/baron-sso
366 lines
9.8 KiB
TypeScript
366 lines
9.8 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import {
|
|
type ClientRelation,
|
|
type Consent,
|
|
installDevApiMock,
|
|
makeClient,
|
|
seedAuth,
|
|
} from "./helpers/devfront-fixtures";
|
|
import { installDevFrontStaticRoutes } from "./helpers/static-devfront";
|
|
|
|
const editRelations = [
|
|
{
|
|
relation: "config_editor",
|
|
subject: "User:playwright-user",
|
|
subjectType: "User",
|
|
subjectId: "playwright-user",
|
|
},
|
|
{
|
|
relation: "admins",
|
|
subject: "User:playwright-user",
|
|
subjectType: "User",
|
|
subjectId: "playwright-user",
|
|
},
|
|
{
|
|
relation: "config_editor",
|
|
subject: "User:admin-user",
|
|
subjectType: "User",
|
|
subjectId: "admin-user",
|
|
},
|
|
{
|
|
relation: "config_editor",
|
|
subject: "User:undefined",
|
|
subjectType: "User",
|
|
subjectId: "undefined",
|
|
},
|
|
{
|
|
relation: "config_editor",
|
|
subject: "User:",
|
|
subjectType: "User",
|
|
subjectId: "",
|
|
},
|
|
] satisfies ClientRelation[];
|
|
|
|
test.describe("DevFront RP claim cache", () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await installDevFrontStaticRoutes(page);
|
|
await seedAuth(page, "super_admin");
|
|
});
|
|
|
|
test("keeps saved RP claim value visible after saving", async ({ page }) => {
|
|
const state = {
|
|
clients: [
|
|
makeClient("client-claims", {
|
|
name: "Claims app",
|
|
metadata: {
|
|
id_token_claims: [
|
|
{
|
|
namespace: "rp_claims",
|
|
key: "old_claim",
|
|
value: "A",
|
|
valueType: "text",
|
|
readPermission: "admin_only",
|
|
writePermission: "admin_only",
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
consents: [] as Consent[],
|
|
relations: {
|
|
"client-claims": editRelations,
|
|
},
|
|
auditLogsByCursor: undefined,
|
|
mockRole: "super_admin",
|
|
};
|
|
await installDevApiMock(page, state);
|
|
|
|
await page.goto("http://devfront.test/clients/client-claims/settings");
|
|
|
|
const claimKeyInput = page
|
|
.getByPlaceholder(/e\.g\. locale|예: locale/i)
|
|
.first();
|
|
await expect(claimKeyInput).toHaveValue("old_claim");
|
|
await expect(claimKeyInput).toBeEnabled();
|
|
|
|
await claimKeyInput.fill("new_claim");
|
|
await page.getByRole("button", { name: /^저장$|^Save$/i }).click();
|
|
|
|
await expect
|
|
.poll(
|
|
() =>
|
|
(
|
|
state.clients[0]?.metadata?.id_token_claims as
|
|
| Array<{ key?: string }>
|
|
| undefined
|
|
)?.[0]?.key,
|
|
)
|
|
.toBe("new_claim");
|
|
await expect(claimKeyInput).toHaveValue("new_claim");
|
|
});
|
|
|
|
test("adds supported scopes and custom claim keys from the scope picker including offline_access", async ({
|
|
page,
|
|
}) => {
|
|
const state = {
|
|
clients: [
|
|
makeClient("client-claims", {
|
|
name: "Claims app",
|
|
metadata: {
|
|
structured_scopes: [
|
|
{
|
|
id: "scope-openid",
|
|
name: "openid",
|
|
description: "OIDC",
|
|
mandatory: true,
|
|
},
|
|
],
|
|
id_token_claims: [
|
|
{
|
|
namespace: "rp_claims",
|
|
key: "employee_code",
|
|
value: "E001",
|
|
valueType: "text",
|
|
readPermission: "admin_only",
|
|
writePermission: "admin_only",
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
consents: [] as Consent[],
|
|
relations: {
|
|
"client-claims": editRelations,
|
|
},
|
|
auditLogsByCursor: undefined,
|
|
mockRole: "super_admin",
|
|
};
|
|
await installDevApiMock(page, state);
|
|
|
|
await page.goto("http://devfront.test/clients/client-claims/settings");
|
|
await page
|
|
.getByRole("button", { name: /스코프 추가|Scope 추가|Add Scope/i })
|
|
.click();
|
|
|
|
await expect(
|
|
page.getByText("offline_access", { exact: true }),
|
|
).toBeVisible();
|
|
await expect(
|
|
page.getByRole("button", { name: /employee_code/ }),
|
|
).toBeVisible();
|
|
|
|
await page.getByRole("button", { name: /employee_code/ }).click();
|
|
await page.getByRole("button", { name: /^저장$|^Save$/i }).click();
|
|
|
|
await expect
|
|
.poll(() =>
|
|
(
|
|
state.clients[0]?.metadata?.structured_scopes as
|
|
| Array<{ name?: string }>
|
|
| undefined
|
|
)?.some((scope) => scope.name === "employee_code"),
|
|
)
|
|
.toBe(true);
|
|
});
|
|
|
|
test("forces read permission on when write permission is enabled", async ({
|
|
page,
|
|
}) => {
|
|
const state = {
|
|
clients: [
|
|
makeClient("client-claims", {
|
|
name: "Claims app",
|
|
metadata: {
|
|
id_token_claims: [
|
|
{
|
|
namespace: "rp_claims",
|
|
key: "locale",
|
|
value: "ko",
|
|
valueType: "text",
|
|
readPermission: "admin_only",
|
|
writePermission: "admin_only",
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
consents: [] as Consent[],
|
|
relations: {
|
|
"client-claims": editRelations,
|
|
},
|
|
auditLogsByCursor: undefined,
|
|
mockRole: "super_admin",
|
|
};
|
|
await installDevApiMock(page, state);
|
|
|
|
await page.goto("http://devfront.test/clients/client-claims/settings");
|
|
|
|
const readSwitch = page
|
|
.getByRole("switch", { name: /사용자 읽기|Allow user read/i })
|
|
.first();
|
|
const writeSwitch = page
|
|
.getByRole("switch", { name: /사용자 쓰기|Allow user write/i })
|
|
.first();
|
|
|
|
await expect(readSwitch).toHaveAttribute("aria-checked", "false");
|
|
await expect(writeSwitch).toHaveAttribute("aria-checked", "false");
|
|
await expect(readSwitch).toBeEnabled();
|
|
await expect(writeSwitch).toBeEnabled();
|
|
|
|
await writeSwitch.click();
|
|
|
|
await expect(readSwitch).toHaveAttribute("aria-checked", "true");
|
|
await expect(writeSwitch).toHaveAttribute("aria-checked", "true");
|
|
|
|
await page.getByRole("button", { name: /^저장$|^Save$/i }).click();
|
|
|
|
await expect
|
|
.poll(
|
|
() =>
|
|
(
|
|
state.clients[0]?.metadata?.id_token_claims as
|
|
| Array<{
|
|
readPermission?: string;
|
|
writePermission?: string;
|
|
}>
|
|
| undefined
|
|
)?.[0],
|
|
)
|
|
.toMatchObject({
|
|
readPermission: "user_and_admin",
|
|
writePermission: "user_and_admin",
|
|
});
|
|
});
|
|
|
|
test("blocks saving an RP claim default value that does not match the selected value type", async ({
|
|
page,
|
|
}) => {
|
|
const state = {
|
|
clients: [
|
|
makeClient("client-claims", {
|
|
name: "Claims app",
|
|
metadata: {
|
|
id_token_claims: [
|
|
{
|
|
namespace: "rp_claims",
|
|
key: "profile",
|
|
value: "{}",
|
|
valueType: "text",
|
|
readPermission: "admin_only",
|
|
writePermission: "admin_only",
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
consents: [] as Consent[],
|
|
relations: {
|
|
"client-claims": editRelations,
|
|
},
|
|
auditLogsByCursor: undefined,
|
|
mockRole: "super_admin",
|
|
};
|
|
await installDevApiMock(page, state);
|
|
|
|
await page.goto("http://devfront.test/clients/client-claims/settings");
|
|
|
|
await page
|
|
.getByLabel(/Claim 값 타입|Claim value type/i)
|
|
.first()
|
|
.selectOption("object");
|
|
await page
|
|
.locator('textarea[placeholder="{\\"key\\": \\"value\\"}"]')
|
|
.fill("not-json");
|
|
|
|
await expect(
|
|
page.getByRole("button", { name: /^저장$|^Save$/i }),
|
|
).toBeDisabled();
|
|
|
|
expect(
|
|
(
|
|
state.clients[0]?.metadata?.id_token_claims as
|
|
| Array<{ valueType?: string; value?: string }>
|
|
| undefined
|
|
)?.[0],
|
|
).toMatchObject({
|
|
value: "{}",
|
|
valueType: "text",
|
|
});
|
|
});
|
|
|
|
test("saves a float RP claim default value and blocks decimal values for integer number claims", async ({
|
|
page,
|
|
}) => {
|
|
const state = {
|
|
clients: [
|
|
makeClient("client-claims", {
|
|
name: "Claims app",
|
|
metadata: {
|
|
id_token_claims: [
|
|
{
|
|
namespace: "rp_claims",
|
|
key: "ratio",
|
|
value: "0",
|
|
valueType: "text",
|
|
readPermission: "admin_only",
|
|
writePermission: "admin_only",
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
consents: [] as Consent[],
|
|
relations: {
|
|
"client-claims": editRelations,
|
|
},
|
|
auditLogsByCursor: undefined,
|
|
mockRole: "super_admin",
|
|
};
|
|
await installDevApiMock(page, state);
|
|
|
|
await page.goto("http://devfront.test/clients/client-claims/settings");
|
|
|
|
await page
|
|
.getByLabel(/Claim 값 타입|Claim value type/i)
|
|
.first()
|
|
.selectOption("float");
|
|
await page
|
|
.getByPlaceholder(/기본값을 입력하세요|Enter the default value/i)
|
|
.first()
|
|
.fill("3.14");
|
|
await page.getByRole("button", { name: /^저장$|^Save$/i }).click();
|
|
|
|
await expect
|
|
.poll(
|
|
() =>
|
|
(
|
|
state.clients[0]?.metadata?.id_token_claims as
|
|
| Array<{ valueType?: string; value?: string }>
|
|
| undefined
|
|
)?.[0],
|
|
)
|
|
.toMatchObject({
|
|
value: "3.14",
|
|
valueType: "float",
|
|
});
|
|
|
|
const valueTypeSelect = page
|
|
.getByLabel(/Claim 값 타입|Claim value type/i)
|
|
.first();
|
|
await expect(valueTypeSelect).toHaveValue("float");
|
|
await expect(
|
|
page.getByRole("button", { name: /^저장$|^Save$/i }),
|
|
).toBeEnabled();
|
|
|
|
await valueTypeSelect.selectOption("number");
|
|
await expect(valueTypeSelect).toHaveValue("number");
|
|
const defaultValueInput = page
|
|
.getByPlaceholder(/기본값을 입력하세요|Enter the default value/i)
|
|
.first();
|
|
await defaultValueInput.fill("3.14");
|
|
await expect(
|
|
page.getByRole("button", { name: /^저장$|^Save$/i }),
|
|
).toBeDisabled();
|
|
});
|
|
});
|