mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-09 23:12:06 -03:30
Parallelize client scope tests for the admin console (#43675)
Closes #43379 Signed-off-by: Jon Koops <jonkoops@gmail.com>
This commit is contained in:
parent
84a3c29f2b
commit
ee29c72ed6
@ -1,11 +1,11 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import adminClient from "../utils/AdminClient.ts";
|
||||
import { toClientScopes } from "../../src/client-scopes/routes/ClientScopes.tsx";
|
||||
import { toNewClientScope } from "../../src/client-scopes/routes/NewClientScope.tsx";
|
||||
import { createTestBed } from "../support/testbed.ts";
|
||||
import { assertSaveButtonIsDisabled, clickSaveButton } from "../utils/form.ts";
|
||||
import { login } from "../utils/login.ts";
|
||||
import { login, navigateTo } from "../utils/login.ts";
|
||||
import { assertNotificationMessage } from "../utils/masthead.ts";
|
||||
import { confirmModal } from "../utils/modal.ts";
|
||||
import { goToClientScopes } from "../utils/sidebar.ts";
|
||||
import {
|
||||
assertRowExists,
|
||||
assertTableRowsLength,
|
||||
@ -21,7 +21,6 @@ import {
|
||||
fillClientScopeData,
|
||||
getTableAssignedTypeColumn,
|
||||
getTableProtocolColumn,
|
||||
goToCreateItem,
|
||||
selectChangeType,
|
||||
selectClientScopeFilter,
|
||||
selectSecondaryFilterAssignedType,
|
||||
@ -42,193 +41,178 @@ const FilterProtocol = {
|
||||
OpenID: "OpenID Connect",
|
||||
};
|
||||
|
||||
test.describe.serial("Client Scopes test", () => {
|
||||
const clientScopeName = "client-scope-test";
|
||||
const itemId = `client-scope-test-${uuidv4()}`;
|
||||
const clientScope = {
|
||||
name: clientScopeName,
|
||||
description: "",
|
||||
protocol: "openid-connect",
|
||||
attributes: {
|
||||
"include.in.token.scope": "true",
|
||||
"display.on.consent.screen": "true",
|
||||
"gui.order": "1",
|
||||
"consent.screen.text": "",
|
||||
},
|
||||
};
|
||||
const placeHolder = "Search for client scope";
|
||||
const tableName = "Client scopes";
|
||||
const placeHolder = "Search for client scope";
|
||||
const tableName = "Client scopes";
|
||||
|
||||
test.beforeAll(async () => {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
clientScope.name = clientScopeName + i;
|
||||
await adminClient.createClientScope(clientScope);
|
||||
}
|
||||
test.describe("Client scopes filtering", () => {
|
||||
test("filters item by name", async ({ page }) => {
|
||||
await using testBed = await createTestBed({
|
||||
clientScopes: [{ name: "test-scope" }],
|
||||
});
|
||||
|
||||
await login(page, { to: toClientScopes({ realm: testBed.realm }) });
|
||||
|
||||
await searchItem(page, placeHolder, "test-scope");
|
||||
await assertRowExists(page, "test-scope");
|
||||
await assertTableRowsLength(page, tableName, 1);
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
if (await adminClient.existsClientScope(clientScopeName + i)) {
|
||||
await adminClient.deleteClientScope(clientScopeName + i);
|
||||
}
|
||||
}
|
||||
test("filters items by assigned type 'default'", async ({ page }) => {
|
||||
await using testBed = await createTestBed();
|
||||
|
||||
await login(page, { to: toClientScopes({ realm: testBed.realm }) });
|
||||
|
||||
await selectClientScopeFilter(page, "Assigned type");
|
||||
await selectSecondaryFilterAssignedType(page, FilterAssignedType.Default);
|
||||
|
||||
const assignedTypes = await getTableAssignedTypeColumn(page, tableName);
|
||||
|
||||
expect(assignedTypes).toContain(FilterAssignedType.Default);
|
||||
expect(assignedTypes).not.toContain(FilterAssignedType.Optional);
|
||||
expect(assignedTypes).not.toContain(FilterAssignedType.None);
|
||||
});
|
||||
|
||||
test.describe.serial("Client Scope filter list items", () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await login(page);
|
||||
await goToClientScopes(page);
|
||||
});
|
||||
test("filters items by assigned type 'optional'", async ({ page }) => {
|
||||
await using testBed = await createTestBed();
|
||||
|
||||
test("should filter item by name", async ({ page }) => {
|
||||
const itemName = clientScopeName + "0";
|
||||
await searchItem(page, placeHolder, itemName);
|
||||
await assertRowExists(page, itemName);
|
||||
await assertTableRowsLength(page, tableName, 1);
|
||||
});
|
||||
await login(page, { to: toClientScopes({ realm: testBed.realm }) });
|
||||
|
||||
test("should filter items by Assigned type Default", async ({ page }) => {
|
||||
await selectClientScopeFilter(page, "Assigned type");
|
||||
await selectSecondaryFilterAssignedType(page, FilterAssignedType.Default);
|
||||
await selectClientScopeFilter(page, "Assigned type");
|
||||
await selectSecondaryFilterAssignedType(page, FilterAssignedType.Optional);
|
||||
|
||||
const assignedTypes = await getTableAssignedTypeColumn(page, tableName);
|
||||
const assignedTypes = await getTableAssignedTypeColumn(page, tableName);
|
||||
|
||||
expect(assignedTypes).toContain(FilterAssignedType.Default);
|
||||
expect(assignedTypes).not.toContain(FilterAssignedType.Optional);
|
||||
expect(assignedTypes).not.toContain(FilterAssignedType.None);
|
||||
});
|
||||
|
||||
test("should filter items by Assigned type Optional", async ({ page }) => {
|
||||
await selectClientScopeFilter(page, "Assigned type");
|
||||
await selectSecondaryFilterAssignedType(
|
||||
page,
|
||||
FilterAssignedType.Optional,
|
||||
);
|
||||
|
||||
const assignedTypes = await getTableAssignedTypeColumn(page, tableName);
|
||||
|
||||
expect(assignedTypes).not.toContain(FilterAssignedType.Default);
|
||||
expect(assignedTypes).not.toContain(FilterAssignedType.None);
|
||||
expect(assignedTypes).toContain(FilterAssignedType.Optional);
|
||||
});
|
||||
|
||||
test("should filter items by Assigned type All", async ({ page }) => {
|
||||
await selectClientScopeFilter(page, "Assigned type");
|
||||
await selectSecondaryFilterAssignedType(
|
||||
page,
|
||||
FilterAssignedType.AllTypes,
|
||||
);
|
||||
|
||||
const assignedTypes = await getTableAssignedTypeColumn(page, tableName);
|
||||
|
||||
expect(assignedTypes).toContain(FilterAssignedType.Default);
|
||||
expect(assignedTypes).toContain(FilterAssignedType.Optional);
|
||||
expect(assignedTypes).toContain(FilterAssignedType.None);
|
||||
});
|
||||
|
||||
test("should filter items by Protocol OpenID", async ({ page }) => {
|
||||
await selectClientScopeFilter(page, "Protocol");
|
||||
await selectSecondaryFilterProtocol(page, FilterProtocol.OpenID);
|
||||
|
||||
const protocols = await getTableProtocolColumn(page, tableName);
|
||||
|
||||
expect(protocols).not.toContain(FilterProtocol.SAML);
|
||||
expect(protocols).toContain(FilterProtocol.OpenID);
|
||||
});
|
||||
|
||||
test("should filter items by Protocol SAML", async ({ page }) => {
|
||||
await selectClientScopeFilter(page, "Protocol");
|
||||
await selectSecondaryFilterProtocol(page, FilterProtocol.SAML);
|
||||
|
||||
const protocols = await getTableProtocolColumn(page, tableName);
|
||||
|
||||
expect(protocols).toContain(FilterProtocol.SAML);
|
||||
expect(protocols).not.toContain(FilterProtocol.OpenID);
|
||||
});
|
||||
|
||||
test("should show items on next page are more than 11", async ({
|
||||
page,
|
||||
}) => {
|
||||
await clickNextPageButton(page);
|
||||
const rows = await getTableData(page, tableName);
|
||||
expect(rows.length).toBeGreaterThan(1);
|
||||
});
|
||||
expect(assignedTypes).not.toContain(FilterAssignedType.Default);
|
||||
expect(assignedTypes).not.toContain(FilterAssignedType.None);
|
||||
expect(assignedTypes).toContain(FilterAssignedType.Optional);
|
||||
});
|
||||
|
||||
test.describe.serial("Client Scope modify list items", () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await login(page);
|
||||
await goToClientScopes(page);
|
||||
});
|
||||
test("filters items by assigned type 'all'", async ({ page }) => {
|
||||
await using testBed = await createTestBed();
|
||||
|
||||
test("should modify selected item type to Default", async ({ page }) => {
|
||||
const itemName = clientScopeName + "0";
|
||||
await clickSelectRow(page, tableName, itemName);
|
||||
await selectChangeType(page, FilterAssignedType.Default);
|
||||
await assertNotificationMessage(page, "Scope mapping updated");
|
||||
await login(page, { to: toClientScopes({ realm: testBed.realm }) });
|
||||
|
||||
const rows = await getTableData(page, tableName);
|
||||
const itemRow = rows.find((r) => r.includes(itemName));
|
||||
expect(itemRow).toContain(FilterAssignedType.Default);
|
||||
});
|
||||
await selectClientScopeFilter(page, "Assigned type");
|
||||
await selectSecondaryFilterAssignedType(page, FilterAssignedType.AllTypes);
|
||||
|
||||
const assignedTypes = await getTableAssignedTypeColumn(page, tableName);
|
||||
|
||||
expect(assignedTypes).toContain(FilterAssignedType.Default);
|
||||
expect(assignedTypes).toContain(FilterAssignedType.Optional);
|
||||
});
|
||||
|
||||
test.describe.serial("Client Scope creation", () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await login(page);
|
||||
await goToClientScopes(page);
|
||||
});
|
||||
test("filters items by protocol 'openid'", async ({ page }) => {
|
||||
await using testBed = await createTestBed();
|
||||
|
||||
test("should fail creating client scope", async ({ page }) => {
|
||||
await goToCreateItem(page);
|
||||
await assertSaveButtonIsDisabled(page);
|
||||
await login(page, { to: toClientScopes({ realm: testBed.realm }) });
|
||||
|
||||
await fillClientScopeData(page, "address");
|
||||
await page.getByTestId("save").click();
|
||||
await selectClientScopeFilter(page, "Protocol");
|
||||
await selectSecondaryFilterProtocol(page, FilterProtocol.OpenID);
|
||||
|
||||
await assertNotificationMessage(
|
||||
page,
|
||||
"Could not create client scope: 'Client Scope address already exists'",
|
||||
);
|
||||
const protocols = await getTableProtocolColumn(page, tableName);
|
||||
|
||||
await fillClientScopeData(page, "");
|
||||
await expect(page.getByTestId("save")).toBeDisabled();
|
||||
});
|
||||
expect(protocols).not.toContain(FilterProtocol.SAML);
|
||||
expect(protocols).toContain(FilterProtocol.OpenID);
|
||||
});
|
||||
|
||||
test("hides 'consent text' field when 'display consent' switch is disabled", async ({
|
||||
page,
|
||||
}) => {
|
||||
await goToCreateItem(page);
|
||||
test("filters items by protocol 'saml'", async ({ page }) => {
|
||||
await using testBed = await createTestBed();
|
||||
|
||||
await assertSwitchDisplayOnConsentScreenIsChecked(page);
|
||||
await assertConsentInputIsVisible(page);
|
||||
await login(page, { to: toClientScopes({ realm: testBed.realm }) });
|
||||
|
||||
await switchOffDisplayOnConsentScreen(page);
|
||||
await selectClientScopeFilter(page, "Protocol");
|
||||
await selectSecondaryFilterProtocol(page, FilterProtocol.SAML);
|
||||
|
||||
await assertConsentInputIsVisible(page, true);
|
||||
});
|
||||
const protocols = await getTableProtocolColumn(page, tableName);
|
||||
|
||||
test("Client scope CRUD test", async ({ page }) => {
|
||||
await assertRowExists(page, itemId, false);
|
||||
await goToCreateItem(page);
|
||||
expect(protocols).toContain(FilterProtocol.SAML);
|
||||
expect(protocols).not.toContain(FilterProtocol.OpenID);
|
||||
});
|
||||
|
||||
await fillClientScopeData(page, itemId);
|
||||
await clickSaveButton(page);
|
||||
test("shows items on next page are more than 11", async ({ page }) => {
|
||||
await using testBed = await createTestBed();
|
||||
|
||||
await assertNotificationMessage(page, "Client scope created");
|
||||
await login(page, { to: toClientScopes({ realm: testBed.realm }) });
|
||||
|
||||
await goToClientScopes(page);
|
||||
|
||||
await searchItem(page, placeHolder, itemId);
|
||||
await assertRowExists(page, itemId);
|
||||
await clickRowKebabItem(page, itemId, "Delete");
|
||||
|
||||
await confirmModal(page);
|
||||
await assertNotificationMessage(
|
||||
page,
|
||||
"The client scope has been deleted",
|
||||
);
|
||||
await assertRowExists(page, itemId, false);
|
||||
});
|
||||
await clickNextPageButton(page);
|
||||
const rows = await getTableData(page, tableName);
|
||||
expect(rows.length).toBeGreaterThan(1);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Client scopes modification", () => {
|
||||
test("modifies selected item type to 'default'", async ({ page }) => {
|
||||
await using testBed = await createTestBed({
|
||||
clientScopes: [{ name: "test-scope" }],
|
||||
});
|
||||
|
||||
await login(page, { to: toClientScopes({ realm: testBed.realm }) });
|
||||
|
||||
await clickSelectRow(page, tableName, "test-scope");
|
||||
await selectChangeType(page, FilterAssignedType.Default);
|
||||
await assertNotificationMessage(page, "Scope mapping updated");
|
||||
|
||||
const rows = await getTableData(page, tableName);
|
||||
const itemRow = rows.find((r) => r.includes("test-scope"));
|
||||
expect(itemRow).toContain(FilterAssignedType.Default);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Client scopes creation", () => {
|
||||
test("fails creating client scope with an existing name", async ({
|
||||
page,
|
||||
}) => {
|
||||
await using testBed = await createTestBed();
|
||||
|
||||
await login(page, { to: toNewClientScope({ realm: testBed.realm }) });
|
||||
|
||||
await assertSaveButtonIsDisabled(page);
|
||||
|
||||
await fillClientScopeData(page, "address");
|
||||
await page.getByTestId("save").click();
|
||||
|
||||
await assertNotificationMessage(
|
||||
page,
|
||||
"Could not create client scope: 'Client Scope address already exists'",
|
||||
);
|
||||
|
||||
await fillClientScopeData(page, "");
|
||||
await expect(page.getByTestId("save")).toBeDisabled();
|
||||
});
|
||||
|
||||
test("hides 'consent text' field when 'display consent' switch is disabled", async ({
|
||||
page,
|
||||
}) => {
|
||||
await using testBed = await createTestBed();
|
||||
|
||||
await login(page, { to: toNewClientScope({ realm: testBed.realm }) });
|
||||
|
||||
await assertSwitchDisplayOnConsentScreenIsChecked(page);
|
||||
await assertConsentInputIsVisible(page);
|
||||
|
||||
await switchOffDisplayOnConsentScreen(page);
|
||||
|
||||
await assertConsentInputIsVisible(page, true);
|
||||
});
|
||||
|
||||
test("creates and deletes a client scope", async ({ page }) => {
|
||||
const itemId = "test-scope";
|
||||
await using testBed = await createTestBed();
|
||||
|
||||
await login(page, { to: toNewClientScope({ realm: testBed.realm }) });
|
||||
await fillClientScopeData(page, itemId);
|
||||
await clickSaveButton(page);
|
||||
|
||||
await assertNotificationMessage(page, "Client scope created");
|
||||
|
||||
await navigateTo(page, toClientScopes({ realm: testBed.realm }));
|
||||
|
||||
await searchItem(page, placeHolder, itemId);
|
||||
await assertRowExists(page, itemId);
|
||||
await clickRowKebabItem(page, itemId, "Delete");
|
||||
|
||||
await confirmModal(page);
|
||||
await assertNotificationMessage(page, "The client scope has been deleted");
|
||||
await assertRowExists(page, itemId, false);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation.js";
|
||||
import { test } from "@playwright/test";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { toClientScopes } from "../../src/client-scopes/routes/ClientScopes.tsx";
|
||||
import { createTestBed } from "../support/testbed.ts";
|
||||
import { clickCancelButton, clickSaveButton } from "../utils/form.ts";
|
||||
import { login } from "../utils/login.ts";
|
||||
import { login, navigateTo } from "../utils/login.ts";
|
||||
import { assertNotificationMessage } from "../utils/masthead.ts";
|
||||
import { goToClientScopes } from "../utils/sidebar.ts";
|
||||
import {
|
||||
assertRowExists,
|
||||
clickTableRowItem,
|
||||
@ -18,40 +19,37 @@ import {
|
||||
goToMappersTab,
|
||||
removeMappers,
|
||||
} from "./mappers.ts";
|
||||
import adminClient from "../utils/AdminClient.ts";
|
||||
|
||||
test.describe.serial("Mappers tab test", () => {
|
||||
test.describe("Mappers tab", () => {
|
||||
const placeHolderClientScope = "Search for client scope";
|
||||
const placeHolder = "Search for mapper";
|
||||
const testBedData: RealmRepresentation = {
|
||||
clientScopes: [
|
||||
{
|
||||
name: "test-scope",
|
||||
protocol: "openid-connect",
|
||||
protocolMappers: [
|
||||
{
|
||||
name: "test-mapper",
|
||||
protocol: "openid-connect",
|
||||
protocolMapper: "oidc-hardcoded-claim-mapper",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const scopeName = `client-scope-mapper-${uuidv4()}`;
|
||||
|
||||
test.beforeAll(async () => {
|
||||
const { id } = await adminClient.createClientScope({
|
||||
name: scopeName,
|
||||
description: "",
|
||||
protocol: "openid-connect",
|
||||
});
|
||||
await adminClient.addMapping(id, {
|
||||
name: "test",
|
||||
protocol: "openid-connect",
|
||||
protocolMapper: "oidc-hardcoded-claim-mapper",
|
||||
});
|
||||
});
|
||||
|
||||
test.afterAll(() => adminClient.deleteClientScope(scopeName));
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await login(page);
|
||||
await goToClientScopes(page);
|
||||
await searchItem(page, placeHolderClientScope, scopeName);
|
||||
await clickTableRowItem(page, scopeName);
|
||||
await goToMappersTab(page);
|
||||
});
|
||||
|
||||
test("CRUD predefined mappers", async ({ page }) => {
|
||||
test("updates a predefined mapper", async ({ page }) => {
|
||||
const placeHolder = "Search for mapper";
|
||||
const mappers = ["birthdate", "email", "family name"];
|
||||
|
||||
await using testBed = await createTestBed(testBedData);
|
||||
|
||||
await login(page, { to: toClientScopes({ realm: testBed.realm }) });
|
||||
|
||||
await searchItem(page, placeHolderClientScope, "test-scope");
|
||||
await clickTableRowItem(page, "test-scope");
|
||||
await goToMappersTab(page);
|
||||
|
||||
await addPredefinedMappers(page, mappers);
|
||||
|
||||
// Configure first mapper
|
||||
@ -67,9 +65,9 @@ test.describe.serial("Mappers tab test", () => {
|
||||
await clickSaveButton(page);
|
||||
await assertNotificationMessage(page, "Mapping successfully updated");
|
||||
|
||||
await goToClientScopes(page);
|
||||
await searchItem(page, placeHolderClientScope, scopeName);
|
||||
await clickTableRowItem(page, scopeName);
|
||||
await navigateTo(page, toClientScopes({ realm: testBed.realm }));
|
||||
await searchItem(page, placeHolderClientScope, "test-scope");
|
||||
await clickTableRowItem(page, "test-scope");
|
||||
await goToMappersTab(page);
|
||||
await searchItem(page, placeHolder, mappers[0]);
|
||||
await clickTableRowItem(page, mappers[0]);
|
||||
@ -84,8 +82,17 @@ test.describe.serial("Mappers tab test", () => {
|
||||
await clickCancelButton(page);
|
||||
});
|
||||
|
||||
test("crud mappers by configuration", async ({ page }) => {
|
||||
test("creates and removes mappers by configuration", async ({ page }) => {
|
||||
const mapperNames = ["Pairwise subject identifier", "Allowed Web Origins"];
|
||||
|
||||
await using testBed = await createTestBed(testBedData);
|
||||
|
||||
await login(page, { to: toClientScopes({ realm: testBed.realm }) });
|
||||
|
||||
await searchItem(page, placeHolderClientScope, "test-scope");
|
||||
await clickTableRowItem(page, "test-scope");
|
||||
await goToMappersTab(page);
|
||||
|
||||
await addMappersByConfiguration(page, mapperNames);
|
||||
|
||||
await assertRowExists(page, mapperNames[0]);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import adminClient from "../utils/AdminClient.ts";
|
||||
import { toClientScopes } from "../../src/client-scopes/routes/ClientScopes.tsx";
|
||||
import { createTestBed } from "../support/testbed.ts";
|
||||
import { login } from "../utils/login.ts";
|
||||
import { assertNotificationMessage } from "../utils/masthead.ts";
|
||||
import { assertModalTitle, confirmModal } from "../utils/modal.ts";
|
||||
@ -11,7 +11,6 @@ import {
|
||||
confirmModalAssign,
|
||||
pickRole,
|
||||
} from "../utils/roles.ts";
|
||||
import { goToClientScopes } from "../utils/sidebar.ts";
|
||||
import {
|
||||
assertEmptyTable,
|
||||
assertRowExists,
|
||||
@ -22,30 +21,37 @@ import {
|
||||
} from "../utils/table.ts";
|
||||
import { goToScopeTab } from "./scope.ts";
|
||||
|
||||
test.describe.serial("Scope tab test", () => {
|
||||
const scopeName = `client-scope-mapper-${uuidv4()}`;
|
||||
test.describe("Scope tab", () => {
|
||||
const tableName = "Role list";
|
||||
|
||||
test.beforeAll(async () =>
|
||||
adminClient.createClientScope({
|
||||
name: scopeName,
|
||||
description: "",
|
||||
protocol: "openid-connect",
|
||||
}),
|
||||
);
|
||||
test("assigns and unassigns role", async ({ page }) => {
|
||||
await using testBed = await createTestBed({
|
||||
clientScopes: [
|
||||
{
|
||||
name: "test-scope",
|
||||
protocol: "openid-connect",
|
||||
},
|
||||
],
|
||||
roles: {
|
||||
realm: [
|
||||
{
|
||||
name: "composite-role",
|
||||
composite: true,
|
||||
composites: {
|
||||
realm: ["offline_access"],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
test.afterAll(() => adminClient.deleteClientScope(scopeName));
|
||||
const role = "composite-role";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await login(page);
|
||||
await goToClientScopes(page);
|
||||
await searchItem(page, "Search for client scope", scopeName);
|
||||
await clickTableRowItem(page, scopeName);
|
||||
await login(page, { to: toClientScopes({ realm: testBed.realm }) });
|
||||
|
||||
await searchItem(page, "Search for client scope", "test-scope");
|
||||
await clickTableRowItem(page, "test-scope");
|
||||
await goToScopeTab(page);
|
||||
});
|
||||
|
||||
test("Assign and unassign role", async ({ page }) => {
|
||||
const role = "admin";
|
||||
|
||||
await pickRoleType(page, "roles");
|
||||
await pickRole(page, role, true);
|
||||
@ -55,9 +61,16 @@ test.describe.serial("Scope tab test", () => {
|
||||
|
||||
await assertRowExists(page, role);
|
||||
|
||||
// Initially, only directly assigned roles are shown (inherited roles are hidden by default)
|
||||
const directRolesOnly = await getTableData(page, tableName);
|
||||
expect(directRolesOnly.length).toBe(1); // Only composite-role is directly assigned
|
||||
|
||||
// Click to show inherited roles (the toggle reveals inherited roles from composite)
|
||||
await clickHideInheritedRoles(page);
|
||||
const data = await getTableData(page, tableName);
|
||||
expect(data.length).toBeGreaterThan(1);
|
||||
const allRoles = await getTableData(page, tableName);
|
||||
expect(allRoles.length).toBe(2); // composite-role + offline_access (inherited from composite)
|
||||
|
||||
// Click again to hide inherited roles
|
||||
await clickHideInheritedRoles(page);
|
||||
|
||||
await clickSelectRow(page, tableName, role);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Page, expect } from "@playwright/test";
|
||||
import { goToRealm, goToRealms } from "../utils/sidebar";
|
||||
import { type Page, expect } from "@playwright/test";
|
||||
import { goToRealm, goToRealms } from "../utils/sidebar.ts";
|
||||
|
||||
function getCurrentRealmItem(page: Page) {
|
||||
return page.getByTestId("currentRealm");
|
||||
|
||||
@ -4,14 +4,12 @@ import type ClientScopeRepresentation from "@keycloak/keycloak-admin-client/lib/
|
||||
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation.js";
|
||||
import type OrganizationRepresentation from "@keycloak/keycloak-admin-client/lib/defs/organizationRepresentation.js";
|
||||
import type PolicyRepresentation from "@keycloak/keycloak-admin-client/lib/defs/policyRepresentation.js";
|
||||
import type ProtocolMapperRepresentation from "@keycloak/keycloak-admin-client/lib/defs/protocolMapperRepresentation.js";
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation.js";
|
||||
import type RoleRepresentation from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation.js";
|
||||
import type { RoleMappingPayload } from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation.js";
|
||||
import type { UserProfileConfig } from "@keycloak/keycloak-admin-client/lib/defs/userProfileMetadata.js";
|
||||
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation.js";
|
||||
import type { Credentials } from "@keycloak/keycloak-admin-client/lib/utils/auth.js";
|
||||
import { merge } from "lodash-es";
|
||||
|
||||
class AdminClient {
|
||||
readonly #client = new KeycloakAdminClient({
|
||||
@ -137,42 +135,11 @@ class AdminClient {
|
||||
);
|
||||
}
|
||||
|
||||
async getAdminUser() {
|
||||
await this.#login();
|
||||
const [user] = await this.#client.users.find({ username: "admin" });
|
||||
return user;
|
||||
}
|
||||
|
||||
async addUserToGroup(userId: string, groupId: string) {
|
||||
await this.#login();
|
||||
await this.#client.users.addToGroup({ id: userId, groupId });
|
||||
}
|
||||
|
||||
async createUserInGroup(username: string, groupId: string) {
|
||||
await this.#login();
|
||||
const user = await this.createUser({ username, enabled: true });
|
||||
await this.#client.users.addToGroup({ id: user.id!, groupId });
|
||||
}
|
||||
|
||||
async addRealmRoleToUser(
|
||||
userId: string,
|
||||
roleName: string,
|
||||
realmName: string = this.#client.realmName,
|
||||
) {
|
||||
await this.#login();
|
||||
|
||||
const realmRole = await this.#client.roles.findOneByName({
|
||||
name: roleName,
|
||||
realm: realmName,
|
||||
});
|
||||
|
||||
await this.#client.users.addRealmRoleMappings({
|
||||
id: userId,
|
||||
roles: [realmRole as RoleMappingPayload],
|
||||
realm: realmName,
|
||||
});
|
||||
}
|
||||
|
||||
async addClientRoleToUser(
|
||||
userId: string,
|
||||
clientId: string,
|
||||
@ -247,28 +214,6 @@ class AdminClient {
|
||||
return await this.#client.clientScopes.create(scope);
|
||||
}
|
||||
|
||||
async addMapping(id: string, mapping: ProtocolMapperRepresentation) {
|
||||
await this.#login();
|
||||
return this.#client.clientScopes.addProtocolMapper({ id }, mapping);
|
||||
}
|
||||
|
||||
async deleteClientScope(clientScopeName: string) {
|
||||
await this.#login();
|
||||
const clientScope = await this.#client.clientScopes.findOneByName({
|
||||
name: clientScopeName,
|
||||
});
|
||||
return await this.#client.clientScopes.del({ id: clientScope?.id! });
|
||||
}
|
||||
|
||||
async existsClientScope(clientScopeName: string) {
|
||||
await this.#login();
|
||||
return (await this.#client.clientScopes.findOneByName({
|
||||
name: clientScopeName,
|
||||
})) == undefined
|
||||
? false
|
||||
: true;
|
||||
}
|
||||
|
||||
async addDefaultClientScopeInClient(
|
||||
clientScopeName: string,
|
||||
clientId: string,
|
||||
@ -290,27 +235,6 @@ class AdminClient {
|
||||
});
|
||||
}
|
||||
|
||||
async removeDefaultClientScopeInClient(
|
||||
clientScopeName: string,
|
||||
clientId: string,
|
||||
) {
|
||||
await this.#login();
|
||||
const scope = await this.#client.clientScopes.findOneByName({
|
||||
name: clientScopeName,
|
||||
});
|
||||
const client = await this.#client.clients.find({ clientId: clientId });
|
||||
return await this.#client.clients.delDefaultClientScope({
|
||||
id: client[0]?.id!,
|
||||
clientScopeId: scope?.id!,
|
||||
});
|
||||
}
|
||||
|
||||
async getUserProfile(realm: string) {
|
||||
await this.#login();
|
||||
|
||||
return await this.#client.users.getProfile({ realm });
|
||||
}
|
||||
|
||||
async addUserProfile(realm: string, userProfile: UserProfileConfig) {
|
||||
await this.#login();
|
||||
const currentProfile = await this.#client.users.getProfile({ realm });
|
||||
@ -324,24 +248,6 @@ class AdminClient {
|
||||
});
|
||||
}
|
||||
|
||||
async updateUserProfile(realm: string, userProfile: UserProfileConfig) {
|
||||
await this.#login();
|
||||
|
||||
await this.#client.users.updateProfile(merge(userProfile, { realm }));
|
||||
}
|
||||
|
||||
async addGroupToProfile(realm: string, groupName: string) {
|
||||
await this.#login();
|
||||
|
||||
const currentProfile = await this.#client.users.getProfile({ realm });
|
||||
|
||||
await this.#client.users.updateProfile({
|
||||
...currentProfile,
|
||||
realm,
|
||||
...{ groups: [...currentProfile.groups!, { name: groupName }] },
|
||||
});
|
||||
}
|
||||
|
||||
async createRealmRole(payload: RoleRepresentation & { realm?: string }) {
|
||||
await this.#login();
|
||||
|
||||
@ -433,39 +339,6 @@ class AdminClient {
|
||||
});
|
||||
}
|
||||
|
||||
async unlinkAccountIdentityProvider(
|
||||
username: string,
|
||||
idpDisplayName: string,
|
||||
) {
|
||||
await this.#login();
|
||||
const user = await this.#client.users.find({ username });
|
||||
const identityProviders =
|
||||
(await this.#client.serverInfo.find()).identityProviders || [];
|
||||
const idp = identityProviders.find(({ name }) => name === idpDisplayName);
|
||||
await this.#client.users.delFromFederatedIdentity({
|
||||
id: user[0].id!,
|
||||
federatedIdentityId: idp?.id!,
|
||||
});
|
||||
}
|
||||
|
||||
async linkAccountIdentityProvider(username: string, idpDisplayName: string) {
|
||||
await this.#login();
|
||||
const user = await this.#client.users.find({ username });
|
||||
const identityProviders =
|
||||
(await this.#client.serverInfo.find()).identityProviders || [];
|
||||
const idp = identityProviders.find(({ name }) => name === idpDisplayName);
|
||||
const fedIdentity = {
|
||||
identityProvider: idp?.id,
|
||||
userId: "testUserIdApi",
|
||||
userName: "testUserNameApi",
|
||||
};
|
||||
await this.#client.users.addToFederatedIdentity({
|
||||
id: user[0].id!,
|
||||
federatedIdentityId: idp?.id!,
|
||||
federatedIdentity: fedIdentity,
|
||||
});
|
||||
}
|
||||
|
||||
async addLocalizationText(
|
||||
locale: string,
|
||||
key: string,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { clickSelectRow } from "./table";
|
||||
import { clickSelectRow } from "./table.ts";
|
||||
|
||||
export type RoleType = "client" | "roles";
|
||||
const rolePickTableName = "Role list";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { clickTableRowItem } from "./table";
|
||||
import { clickTableRowItem } from "./table.ts";
|
||||
|
||||
export async function goToRealm(page: Page, realmName: string) {
|
||||
const currentRealm = await page.getByTestId("currentRealm").textContent();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user