mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-09 23:12:06 -03:30
Fix unstable user tests for admin console (#42489)
Closes #42477 Signed-off-by: Jon Koops <jonkoops@gmail.com>
This commit is contained in:
parent
74511ddafd
commit
7634b42cc3
@ -205,7 +205,10 @@ test.describe
|
||||
});
|
||||
|
||||
test("Should view authorization tab", async ({ page }) => {
|
||||
await login(page, "test-view-authz-user", "password");
|
||||
await login(page, {
|
||||
username: "test-view-authz-user",
|
||||
password: "password",
|
||||
});
|
||||
|
||||
await goToRealm(page, "realm-view-authz");
|
||||
await page.reload();
|
||||
|
||||
@ -85,12 +85,11 @@ test.describe.serial("Events tests", () => {
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await login(
|
||||
page,
|
||||
eventsTestUser.userRepresentation.username,
|
||||
eventsTestUser.userRepresentation.credentials[0].value,
|
||||
realmName,
|
||||
);
|
||||
await login(page, {
|
||||
realm: realmName,
|
||||
username: eventsTestUser.userRepresentation.username,
|
||||
password: eventsTestUser.userRepresentation.credentials[0].value,
|
||||
});
|
||||
await goToEvents(page);
|
||||
});
|
||||
|
||||
|
||||
@ -87,7 +87,7 @@ test.describe.serial("Masthead tests", () => {
|
||||
|
||||
test("Login without privileges to see admin console", async ({ page }) => {
|
||||
await logout(page);
|
||||
await login(page, username, "test", realmName);
|
||||
await login(page, { realm: realmName, username, password: "test" });
|
||||
await expect(
|
||||
page.getByText(
|
||||
"You do not have permission to access this resource, sign in with a user that has permission, or contact your administrator.",
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { test } from "@playwright/test";
|
||||
import { v4 as uuid } from "uuid";
|
||||
import adminClient from "../utils/AdminClient.ts";
|
||||
import { DEFAULT_REALM } from "../utils/constants.ts";
|
||||
import { assertRequiredFieldError, switchOff } from "../utils/form.ts";
|
||||
import { login } from "../utils/login.ts";
|
||||
import {
|
||||
@ -46,7 +47,7 @@ test.describe.serial("Realm tests", () => {
|
||||
await page.getByTestId("create").click();
|
||||
await assertRequiredFieldError(page, "realm");
|
||||
|
||||
await fillRealmName(page, "master");
|
||||
await fillRealmName(page, DEFAULT_REALM);
|
||||
await clickCreateRealmForm(page);
|
||||
|
||||
await assertNotificationMessage(
|
||||
|
||||
@ -53,12 +53,11 @@ async function updateUserLocale(locale: string) {
|
||||
|
||||
async function goToPage(page: Page, locale: string) {
|
||||
await updateUserLocale(locale);
|
||||
await login(
|
||||
page,
|
||||
testConfig.username,
|
||||
testConfig.password,
|
||||
testConfig.realmName,
|
||||
);
|
||||
await login(page, {
|
||||
realm: testConfig.realmName,
|
||||
username: testConfig.username,
|
||||
password: testConfig.password,
|
||||
});
|
||||
await goToUserFederation(page);
|
||||
}
|
||||
|
||||
|
||||
12
js/apps/admin-ui/test/support/testbed.ts
Normal file
12
js/apps/admin-ui/test/support/testbed.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation.js";
|
||||
import adminClient from "../utils/AdminClient.ts";
|
||||
|
||||
export async function createTestBed(
|
||||
overrides?: RealmRepresentation,
|
||||
): Promise<string> {
|
||||
const { realmName } = await adminClient.createRealm(
|
||||
crypto.randomUUID(),
|
||||
overrides,
|
||||
);
|
||||
return realmName;
|
||||
}
|
||||
@ -1,5 +1,10 @@
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation.js";
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { v4 as uuid } from "uuid";
|
||||
import { toRealmSettings } from "../../src/realm-settings/routes/RealmSettings.tsx";
|
||||
import { toAddUser } from "../../src/user/routes/AddUser.tsx";
|
||||
import { toUser } from "../../src/user/routes/User.tsx";
|
||||
import { toUsers } from "../../src/user/routes/Users.tsx";
|
||||
import { createTestBed } from "../support/testbed.ts";
|
||||
import adminClient from "../utils/AdminClient.ts";
|
||||
import {
|
||||
assertAttributeLength,
|
||||
@ -7,11 +12,12 @@ import {
|
||||
fillAttributeData,
|
||||
goToAttributesTab,
|
||||
} from "../utils/attributes.ts";
|
||||
import { DEFAULT_REALM } from "../utils/constants.ts";
|
||||
import { selectItem } from "../utils/form.ts";
|
||||
import { login } from "../utils/login.ts";
|
||||
import { assertNotificationMessage } from "../utils/masthead.ts";
|
||||
import { confirmModal } from "../utils/modal.ts";
|
||||
import { goToRealm, goToRealmSettings, goToUsers } from "../utils/sidebar.ts";
|
||||
import { goToUsers } from "../utils/sidebar.ts";
|
||||
import {
|
||||
assertNoResults,
|
||||
assertRowExists,
|
||||
@ -23,42 +29,15 @@ import {
|
||||
clickCancelButton,
|
||||
clickSaveButton,
|
||||
fillUserForm,
|
||||
goToGroupTab,
|
||||
joinGroup,
|
||||
} from "./main.ts";
|
||||
|
||||
let groupName = "group";
|
||||
let groupsList: string[] = [];
|
||||
test.describe("User creation", () => {
|
||||
test("navigates to the create user page", async ({ page }) => {
|
||||
const realm = await createTestBed();
|
||||
|
||||
test.describe.serial("User creation", () => {
|
||||
const realmName = `users-${uuid()}`;
|
||||
await login(page, { to: toUsers({ realm }) });
|
||||
|
||||
const userId = `user_crud-${uuid()}`;
|
||||
|
||||
test.beforeAll(async () => {
|
||||
await adminClient.createRealm(realmName);
|
||||
|
||||
for (let i = 0; i <= 2; i++) {
|
||||
groupName += "_" + uuid();
|
||||
await adminClient.createGroup(groupName, realmName);
|
||||
groupsList = [...groupsList, groupName];
|
||||
}
|
||||
});
|
||||
|
||||
test.afterAll(() => adminClient.deleteRealm(realmName));
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await login(page);
|
||||
await goToRealm(page, realmName);
|
||||
await goToRealmSettings(page);
|
||||
await selectItem(page, "#unmanagedAttributePolicy", "Enabled");
|
||||
await page.getByTestId("realmSettingsGeneralTab-save").click();
|
||||
await goToUsers(page);
|
||||
});
|
||||
|
||||
test.afterEach(() => adminClient.deleteUser(userId, realmName, true));
|
||||
|
||||
test("Go to create User page", async ({ page }) => {
|
||||
await clickAddUserButton(page);
|
||||
await expect(page).toHaveURL(/.*users\/add-user/);
|
||||
|
||||
@ -66,42 +45,53 @@ test.describe.serial("User creation", () => {
|
||||
await expect(page).not.toHaveURL(/.*users\/add-user/);
|
||||
});
|
||||
|
||||
test("Create user test", async ({ page }) => {
|
||||
await clickAddUserButton(page);
|
||||
test("creates a new user", async ({ page }) => {
|
||||
const realm = await createTestBed();
|
||||
|
||||
await login(page, { to: toAddUser({ realm }) });
|
||||
|
||||
await fillUserForm(page, {
|
||||
username: userId,
|
||||
email: `example_${uuid()}@example.com`,
|
||||
username: "test-user",
|
||||
email: "test-user@example.com",
|
||||
});
|
||||
await clickSaveButton(page);
|
||||
await assertNotificationMessage(page, "The user has been created");
|
||||
});
|
||||
|
||||
test("Should check temporary admin user existence", async ({ page }) => {
|
||||
test("checks temporary admin user existence", async ({ page }) => {
|
||||
await login(page, { to: toUsers({ realm: DEFAULT_REALM }) });
|
||||
|
||||
// check banner visibility first
|
||||
await expect(page.locator(".pf-v5-c-banner")).toContainText(
|
||||
"You are logged in as a temporary admin user.",
|
||||
);
|
||||
|
||||
await goToRealm(page, "master");
|
||||
await goToUsers(page);
|
||||
await searchItem(page, "Search", "admin");
|
||||
await assertRowExists(page, "admin");
|
||||
await expect(page.locator("#temporary-admin-label")).toBeVisible();
|
||||
});
|
||||
|
||||
test("Create user with groups test", async ({ page }) => {
|
||||
await clickAddUserButton(page);
|
||||
await fillUserForm(page, { username: userId });
|
||||
await joinGroup(page, [groupsList[0]]);
|
||||
test("creates a user that joins a group", async ({ page }) => {
|
||||
const realm = await createTestBed({
|
||||
groups: [{ name: "test-group" }],
|
||||
});
|
||||
|
||||
await login(page, { to: toAddUser({ realm }) });
|
||||
|
||||
await fillUserForm(page, { username: "test-user" });
|
||||
await joinGroup(page, ["test-group"]);
|
||||
await clickSaveButton(page);
|
||||
await assertNotificationMessage(page, "The user has been created");
|
||||
});
|
||||
|
||||
test("Create user with credentials test", async ({ page }) => {
|
||||
await clickAddUserButton(page);
|
||||
test("creates a user with a password credential", async ({ page }) => {
|
||||
const realm = await createTestBed();
|
||||
|
||||
await login(page, { to: toAddUser({ realm }) });
|
||||
|
||||
await fillUserForm(page, {
|
||||
username: userId,
|
||||
email: `example_${uuid()}@example.com`,
|
||||
username: "test-user",
|
||||
email: "test-user@example.com",
|
||||
firstName: "firstname",
|
||||
lastName: "lastname",
|
||||
});
|
||||
@ -116,102 +106,114 @@ test.describe.serial("User creation", () => {
|
||||
await confirmModal(page);
|
||||
await confirmModal(page);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe.serial("Existing users", () => {
|
||||
const placeHolder = "Search user";
|
||||
const existingUserId = `existing_user-${uuid()}`;
|
||||
const existingUserId2 = `existing_user2-${uuid()}`;
|
||||
test.describe("Existing users", () => {
|
||||
const placeHolder = "Search user";
|
||||
const existingUserName = "existing-user";
|
||||
const overrides: RealmRepresentation = {
|
||||
users: [{ username: existingUserName }],
|
||||
};
|
||||
|
||||
test.beforeAll(() =>
|
||||
Promise.all([
|
||||
adminClient.createUser({
|
||||
realm: realmName,
|
||||
username: existingUserId,
|
||||
}),
|
||||
adminClient.createUser({
|
||||
realm: realmName,
|
||||
username: existingUserId2,
|
||||
}),
|
||||
]),
|
||||
test("searches for an existing user", async ({ page }) => {
|
||||
const realm = await createTestBed(overrides);
|
||||
|
||||
await login(page, { to: toUsers({ realm }) });
|
||||
|
||||
await searchItem(page, placeHolder, existingUserName);
|
||||
await assertRowExists(page, existingUserName);
|
||||
});
|
||||
|
||||
test("searches for a non-existing user", async ({ page }) => {
|
||||
const realm = await createTestBed(overrides);
|
||||
|
||||
await login(page, { to: toUsers({ realm }) });
|
||||
|
||||
await searchItem(page, "Search", "non-existing-user");
|
||||
await assertNoResults(page);
|
||||
});
|
||||
|
||||
test("edits a user", async ({ page }) => {
|
||||
const realm = await createTestBed(overrides);
|
||||
const user = await adminClient.findUserByUsername(realm, existingUserName);
|
||||
|
||||
await login(page, { to: toUser({ realm, id: user.id!, tab: "settings" }) });
|
||||
|
||||
await fillUserForm(page, {
|
||||
email: "test-user@example.com",
|
||||
firstName: "first",
|
||||
lastName: "last",
|
||||
});
|
||||
await clickSaveButton(page);
|
||||
await assertNotificationMessage(page, "The user has been saved");
|
||||
});
|
||||
|
||||
const attributesName = "unmanagedAttributes";
|
||||
|
||||
test("adds unmanaged attributes to a user", async ({ page }) => {
|
||||
const realm = await createTestBed(overrides);
|
||||
|
||||
await login(page, { to: toRealmSettings({ realm }) });
|
||||
|
||||
await selectItem(page, "#unmanagedAttributePolicy", "Enabled");
|
||||
await page.getByTestId("realmSettingsGeneralTab-save").click();
|
||||
|
||||
await goToUsers(page);
|
||||
await clickTableRowItem(page, existingUserName);
|
||||
await goToAttributesTab(page);
|
||||
|
||||
await fillAttributeData(page, "key_test", "value_test", attributesName);
|
||||
await clickAttributeSaveButton(page);
|
||||
await assertNotificationMessage(page, "The user has been saved");
|
||||
|
||||
await fillAttributeData(page, "LDAP_ID", "value_test", attributesName, 1);
|
||||
await fillAttributeData(
|
||||
page,
|
||||
"LDAP_ID",
|
||||
"another_value_test",
|
||||
attributesName,
|
||||
2,
|
||||
);
|
||||
await clickAttributeSaveButton(page);
|
||||
|
||||
test("Search existing user test", async ({ page }) => {
|
||||
await searchItem(page, placeHolder, existingUserId);
|
||||
await assertRowExists(page, existingUserId);
|
||||
await expect(page.getByText("Update of read-only attribute")).toHaveCount(
|
||||
2,
|
||||
);
|
||||
await assertNotificationMessage(page, "The user has not been saved: ");
|
||||
});
|
||||
|
||||
test("adds unmanaged attributes with multiple values to a user", async ({
|
||||
page,
|
||||
}) => {
|
||||
const realm = await createTestBed(overrides);
|
||||
|
||||
await login(page, { to: toRealmSettings({ realm }) });
|
||||
|
||||
await selectItem(page, "#unmanagedAttributePolicy", "Enabled");
|
||||
await page.getByTestId("realmSettingsGeneralTab-save").click();
|
||||
await goToUsers(page);
|
||||
await clickTableRowItem(page, existingUserName);
|
||||
await goToAttributesTab(page);
|
||||
|
||||
await fillAttributeData(page, "key-multiple", "value1", attributesName);
|
||||
await fillAttributeData(page, "key-multiple", "value2", attributesName, 1);
|
||||
await clickAttributeSaveButton(page);
|
||||
|
||||
await assertNotificationMessage(page, "The user has been saved");
|
||||
await assertAttributeLength(page, 2, attributesName);
|
||||
});
|
||||
|
||||
test("adds a user to a group", async ({ page }) => {
|
||||
const realm = await createTestBed({
|
||||
...overrides,
|
||||
groups: [{ name: "test-group" }],
|
||||
});
|
||||
const user = await adminClient.findUserByUsername(realm, existingUserName);
|
||||
|
||||
test("Search non-existing user test", async ({ page }) => {
|
||||
await searchItem(page, "Search", "user_DNE");
|
||||
await assertNoResults(page);
|
||||
});
|
||||
await login(page, { to: toUser({ realm, id: user.id!, tab: "groups" }) });
|
||||
|
||||
test("User details test", async ({ page }) => {
|
||||
await searchItem(page, placeHolder, existingUserId);
|
||||
await assertRowExists(page, existingUserId);
|
||||
await clickTableRowItem(page, existingUserId);
|
||||
|
||||
await fillUserForm(page, {
|
||||
email: `example_${uuid()}@example.com`,
|
||||
firstName: "first",
|
||||
lastName: "last",
|
||||
});
|
||||
await clickSaveButton(page);
|
||||
await assertNotificationMessage(page, "The user has been saved");
|
||||
|
||||
await goToUsers(page);
|
||||
await searchItem(page, placeHolder, existingUserId);
|
||||
await assertRowExists(page, existingUserId);
|
||||
});
|
||||
|
||||
const attributesName = "unmanagedAttributes";
|
||||
|
||||
test("Select Unmanaged attributes", async ({ page }) => {
|
||||
await clickTableRowItem(page, existingUserId);
|
||||
|
||||
await goToAttributesTab(page);
|
||||
await fillAttributeData(page, "key_test", "value_test", attributesName);
|
||||
await clickAttributeSaveButton(page);
|
||||
await assertNotificationMessage(page, "The user has been saved");
|
||||
|
||||
await fillAttributeData(page, "LDAP_ID", "value_test", attributesName, 1);
|
||||
await fillAttributeData(
|
||||
page,
|
||||
"LDAP_ID",
|
||||
"another_value_test",
|
||||
attributesName,
|
||||
2,
|
||||
);
|
||||
await clickAttributeSaveButton(page);
|
||||
await expect(page.getByText("Update of read-only attribute")).toHaveCount(
|
||||
2,
|
||||
);
|
||||
await assertNotificationMessage(page, "The user has not been saved: ");
|
||||
});
|
||||
|
||||
test("User attributes with multiple values test", async ({ page }) => {
|
||||
await clickTableRowItem(page, existingUserId2);
|
||||
|
||||
await goToAttributesTab(page);
|
||||
await fillAttributeData(page, "key-multiple", "value1", attributesName);
|
||||
await fillAttributeData(
|
||||
page,
|
||||
"key-multiple",
|
||||
"value2",
|
||||
attributesName,
|
||||
1,
|
||||
);
|
||||
await clickAttributeSaveButton(page);
|
||||
await assertNotificationMessage(page, "The user has been saved");
|
||||
await assertAttributeLength(page, 2, attributesName);
|
||||
});
|
||||
|
||||
test("Add user to groups test", async ({ page }) => {
|
||||
await clickTableRowItem(page, existingUserId);
|
||||
|
||||
await goToGroupTab(page);
|
||||
await joinGroup(page, groupsList, true);
|
||||
await assertNotificationMessage(page, "Added group membership");
|
||||
await assertRowExists(page, groupsList[2]);
|
||||
});
|
||||
await joinGroup(page, ["test-group"], true);
|
||||
await assertNotificationMessage(page, "Added group membership");
|
||||
await assertRowExists(page, "test-group");
|
||||
});
|
||||
});
|
||||
|
||||
@ -43,7 +43,7 @@ class AdminClient {
|
||||
|
||||
async createRealm(realm: string, payload?: RealmRepresentation) {
|
||||
await this.#login();
|
||||
await this.#client.realms.create({ realm, ...payload });
|
||||
return await this.#client.realms.create({ realm, ...payload });
|
||||
}
|
||||
|
||||
async updateRealm(realm: string, payload: RealmRepresentation) {
|
||||
@ -667,6 +667,22 @@ class AdminClient {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async findUserByUsername(
|
||||
realm: string,
|
||||
username: string,
|
||||
): Promise<UserRepresentation> {
|
||||
await this.#login();
|
||||
|
||||
const users = await this.#client.users.find({
|
||||
realm,
|
||||
username,
|
||||
exact: true,
|
||||
max: 1,
|
||||
});
|
||||
|
||||
return users[0];
|
||||
}
|
||||
}
|
||||
|
||||
const adminClient = new AdminClient();
|
||||
|
||||
@ -1,28 +1,50 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { generatePath, type Path } from "react-router-dom";
|
||||
|
||||
import {
|
||||
ADMIN_PASSWORD,
|
||||
ADMIN_USER,
|
||||
DEFAULT_REALM,
|
||||
SERVER_URL,
|
||||
ROOT_PATH,
|
||||
} from "./constants";
|
||||
SERVER_URL,
|
||||
} from "./constants.ts";
|
||||
|
||||
export const login = async (
|
||||
export type LoginOptions = {
|
||||
realm?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
to?: Partial<Path>;
|
||||
};
|
||||
|
||||
const DEFAULT_LOGIN_OPTIONS: Required<LoginOptions> = {
|
||||
realm: DEFAULT_REALM,
|
||||
username: ADMIN_USER,
|
||||
password: ADMIN_PASSWORD,
|
||||
to: {},
|
||||
};
|
||||
|
||||
export async function login(
|
||||
page: Page,
|
||||
username = ADMIN_USER,
|
||||
password = ADMIN_PASSWORD,
|
||||
realm = DEFAULT_REALM,
|
||||
) => {
|
||||
const rootPath = SERVER_URL + ROOT_PATH.replace(":realm", realm);
|
||||
options: LoginOptions = {},
|
||||
): Promise<void> {
|
||||
const { realm, username, password, to } = {
|
||||
...DEFAULT_LOGIN_OPTIONS,
|
||||
...options,
|
||||
};
|
||||
|
||||
await page.goto(rootPath);
|
||||
const url = new URL(generatePath(ROOT_PATH, { realm }), SERVER_URL);
|
||||
|
||||
if (to.pathname) {
|
||||
url.hash = to.pathname;
|
||||
}
|
||||
|
||||
await page.goto(url.toString());
|
||||
await page.getByLabel("Username").fill(username);
|
||||
await page.getByLabel("Password", { exact: true }).fill(password);
|
||||
await page.getByRole("button", { name: "Sign In" }).click();
|
||||
};
|
||||
}
|
||||
|
||||
export const logout = async (page: Page, username: string = "admin") => {
|
||||
export async function logout(page: Page, username = ADMIN_USER): Promise<void> {
|
||||
await page.getByRole("button", { name: username, exact: true }).click();
|
||||
await page.getByRole("menuitem", { name: "Sign out" }).click();
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user