updated and fixed user test (#1956)

* updated and fixed user test

* Update cypress/integration/users_test.spec.ts

* fixed the confirm button test id

* fixed tests

* fix

* removed unused refresh

Co-authored-by: Jenny <32821331+jenny-s51@users.noreply.github.com>
This commit is contained in:
Erik Jan de Wit 2022-02-02 12:44:52 +01:00 committed by GitHub
parent b9224862de
commit 6a970e6cb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 289 additions and 287 deletions

View file

@ -4,7 +4,10 @@ import ListingPage from "../support/pages/admin_console/ListingPage";
import SidebarPage from "../support/pages/admin_console/SidebarPage"; import SidebarPage from "../support/pages/admin_console/SidebarPage";
import ModalUtils from "../support/util/ModalUtils"; import ModalUtils from "../support/util/ModalUtils";
import AdminClient from "../support/util/AdminClient"; import AdminClient from "../support/util/AdminClient";
import { keycloakBefore } from "../support/util/keycloak_hooks"; import {
keycloakBefore,
keycloakBeforeEach,
} from "../support/util/keycloak_hooks";
const loginPage = new LoginPage(); const loginPage = new LoginPage();
const masthead = new Masthead(); const masthead = new Masthead();
@ -22,6 +25,8 @@ describe("Clients SAML tests", () => {
clientId: samlClientName, clientId: samlClientName,
publicClient: false, publicClient: false,
}); });
keycloakBefore();
loginPage.logIn();
}); });
after(() => { after(() => {
@ -29,8 +34,7 @@ describe("Clients SAML tests", () => {
}); });
beforeEach(() => { beforeEach(() => {
keycloakBefore(); keycloakBeforeEach();
loginPage.logIn();
sidebarPage.goToClients(); sidebarPage.goToClients();
listingPage.searchItem(samlClientName).goToItemDetails(samlClientName); listingPage.searchItem(samlClientName).goToItemDetails(samlClientName);
}); });
@ -62,6 +66,8 @@ describe("Clients SAML tests", () => {
clientId, clientId,
protocol: "saml", protocol: "saml",
}); });
keycloakBefore();
loginPage.logIn();
}); });
after(() => { after(() => {
@ -69,8 +75,7 @@ describe("Clients SAML tests", () => {
}); });
beforeEach(() => { beforeEach(() => {
keycloakBefore(); keycloakBeforeEach();
loginPage.logIn();
sidebarPage.goToClients(); sidebarPage.goToClients();
listingPage.searchItem(clientId).goToItemDetails(clientId); listingPage.searchItem(clientId).goToItemDetails(clientId);
cy.findByTestId("keysTab").click(); cy.findByTestId("keysTab").click();
@ -87,7 +92,11 @@ describe("Clients SAML tests", () => {
}); });
it("disable client signature", () => { it("disable client signature", () => {
cy.intercept(
"auth/admin/realms/master/clients/*/certificates/saml.signing"
).as("load");
cy.findByTestId("clientSignature").click({ force: true }); cy.findByTestId("clientSignature").click({ force: true });
cy.waitFor("@load");
modalUtils modalUtils
.checkModalTitle('Disable "Client signature required"') .checkModalTitle('Disable "Client signature required"')

View file

@ -282,7 +282,7 @@ describe("Clients test", () => {
cy.findByTestId("mappersTab").click(); cy.findByTestId("mappersTab").click();
cy.findByText("Add predefined mapper").click(); cy.findByText("Add predefined mapper").click();
cy.get("table input").first().click(); cy.get("table input").first().click();
cy.findByTestId("modalConfirm").click(); cy.findByTestId("confirm").click();
masthead.checkNotificationMessage("Mapping successfully created"); masthead.checkNotificationMessage("Mapping successfully created");
}); });
}); });

View file

@ -128,7 +128,7 @@ describe("Identity provider test", () => {
listingPage.goToItemDetails("facebook"); listingPage.goToItemDetails("facebook");
addMapperPage.goToMappersTab(); addMapperPage.goToMappersTab();
listingPage.deleteItem("facebook attribute importer"); listingPage.deleteItem("facebook attribute importer");
cy.findByTestId("modalConfirm").click(); cy.findByTestId("confirm").click();
}); });
it("clean up providers", () => { it("clean up providers", () => {

View file

@ -17,6 +17,7 @@ describe("Partial import test", () => {
beforeEach(() => { beforeEach(() => {
keycloakBefore(); keycloakBefore();
loginPage.logIn(); loginPage.logIn();
sidebarPage.waitForPageLoad();
// doing this from the UI has the added bonus of putting you in the test realm // doing this from the UI has the added bonus of putting you in the test realm
sidebarPage.goToCreateRealm(); sidebarPage.goToCreateRealm();

View file

@ -6,8 +6,10 @@ import ListingPage from "../support/pages/admin_console/ListingPage";
import UserDetailsPage from "../support/pages/admin_console/manage/users/UserDetailsPage"; import UserDetailsPage from "../support/pages/admin_console/manage/users/UserDetailsPage";
import AttributesTab from "../support/pages/admin_console/manage/AttributesTab"; import AttributesTab from "../support/pages/admin_console/manage/AttributesTab";
import ModalUtils from "../support/util/ModalUtils"; import ModalUtils from "../support/util/ModalUtils";
import { keycloakBefore } from "../support/util/keycloak_hooks"; import {
import GroupModal from "../support/pages/admin_console/manage/groups/GroupModal"; keycloakBefore,
keycloakBeforeEach,
} from "../support/util/keycloak_hooks";
import UserGroupsPage from "../support/pages/admin_console/manage/users/UserGroupsPage"; import UserGroupsPage from "../support/pages/admin_console/manage/users/UserGroupsPage";
import AdminClient from "../support/util/AdminClient"; import AdminClient from "../support/util/AdminClient";
import CredentialsPage from "../support/pages/admin_console/manage/users/CredentialsPage"; import CredentialsPage from "../support/pages/admin_console/manage/users/CredentialsPage";
@ -15,38 +17,7 @@ import CredentialsPage from "../support/pages/admin_console/manage/users/Credent
let groupName = "group"; let groupName = "group";
let groupsList: string[] = []; let groupsList: string[] = [];
describe("Group creation", () => { describe("User creation", () => {
const loginPage = new LoginPage();
const masthead = new Masthead();
const sidebarPage = new SidebarPage();
const groupModal = new GroupModal();
beforeEach(() => {
keycloakBefore();
loginPage.logIn();
sidebarPage.goToGroups();
});
function createNewGroup() {
groupName += "_" + (Math.random() + 1).toString(36).substring(7);
sidebarPage.waitForPageLoad();
groupModal.open().fillGroupForm(groupName).clickCreate();
groupsList = [...groupsList, groupName];
masthead.checkNotificationMessage("Group created");
sidebarPage.goToGroups();
}
it("Add groups to be joined", () => {
for (let i = 0; i <= 2; i++) {
createNewGroup();
}
});
});
describe("Users test", () => {
const loginPage = new LoginPage(); const loginPage = new LoginPage();
const sidebarPage = new SidebarPage(); const sidebarPage = new SidebarPage();
const createUserPage = new CreateUserPage(); const createUserPage = new CreateUserPage();
@ -60,217 +31,208 @@ describe("Users test", () => {
let itemId = "user_crud"; let itemId = "user_crud";
let itemIdWithCred = "user_crud_cred"; let itemIdWithCred = "user_crud_cred";
const adminClient = new AdminClient();
describe("User creation", () => { before(() => {
beforeEach(() => { for (let i = 0; i <= 2; i++) {
keycloakBefore(); groupName += "_" + (Math.random() + 1).toString(36).substring(7);
loginPage.logIn(); adminClient.createGroup(groupName);
cy.intercept( groupsList = [...groupsList, groupName];
"/auth/admin/realms/master/components?type=org.keycloak.storage.UserStorageProvider" }
).as("brute-force");
sidebarPage.goToUsers(); keycloakBefore();
loginPage.logIn();
});
beforeEach(() => {
keycloakBeforeEach();
sidebarPage.goToUsers();
});
after(() => {
adminClient.deleteGroups();
});
it("Go to create User page", () => {
createUserPage.goToCreateUser();
cy.url().should("include", "users/add-user");
// Verify Cancel button works
createUserPage.cancel();
cy.url().should("not.include", "/add-user");
});
it("Create user test", () => {
itemId += "_" + (Math.random() + 1).toString(36).substring(7);
// Create
createUserPage.goToCreateUser();
createUserPage.createUser(itemId);
createUserPage.toggleAddGroupModal();
const groupsListCopy = groupsList.slice(0, 1);
groupsListCopy.forEach((element) => {
cy.findByTestId(`${element}-check`).click();
}); });
after(async () => { createUserPage.joinGroups();
await new AdminClient().deleteGroups();
});
it("Go to create User page", () => { createUserPage.save();
createUserPage.goToCreateUser();
cy.url().should("include", "users/add-user");
// Verify Cancel button works masthead.checkNotificationMessage("The user has been created");
createUserPage.cancel(); });
cy.url().should("not.include", "/add-user");
});
it("Create user test", () => { it("Create user with credentials test", () => {
itemId += "_" + (Math.random() + 1).toString(36).substring(7); itemIdWithCred += "_" + (Math.random() + 1).toString(36).substring(7);
// Create createUserPage.goToCreateUser();
createUserPage.goToCreateUser();
createUserPage.createUser(itemId); createUserPage.createUser(itemIdWithCred);
createUserPage.toggleAddGroupModal(); userDetailsPage.fillUserData();
createUserPage.save();
masthead.checkNotificationMessage("The user has been created");
sidebarPage.waitForPageLoad();
const groupsListCopy = groupsList.slice(0, 1); credentialsPage
.goToCredentialsTab()
.clickEmptyStatePasswordBtn()
.fillPasswordForm()
.clickConfirmationBtn()
.clickSetPasswordBtn();
});
groupsListCopy.forEach((element) => { it("User details test", () => {
cy.findByTestId(`${element}-check`).click(); sidebarPage.waitForPageLoad();
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId);
userDetailsPage.fillUserData().save();
masthead.checkNotificationMessage("The user has been saved");
sidebarPage.waitForPageLoad();
sidebarPage.goToUsers();
listingPage.searchItem(itemId).itemExist(itemId);
});
it("User attributes test", () => {
listingPage.goToItemDetails(itemId);
attributesTab
.goToAttributesTab()
.fillLastRow("key", "value")
.saveAttribute();
masthead.checkNotificationMessage("The user has been saved");
});
it("User attributes with multiple values test", () => {
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId);
cy.intercept("PUT", `/auth/admin/realms/master/users/*`).as("save-user");
const attributeKey = "key-multiple";
attributesTab
.goToAttributesTab()
.fillLastRow(attributeKey, "other value")
.saveAttribute();
cy.wait("@save-user").should(({ request, response }) => {
expect(response?.statusCode).to.equal(204);
expect(request?.body.attributes, "response body").deep.equal({
key: ["value"],
"key-multiple": ["other value"],
}); });
createUserPage.joinGroups();
createUserPage.save();
masthead.checkNotificationMessage("The user has been created");
sidebarPage.goToUsers();
}); });
it("Create user with credentials test", () => { masthead.checkNotificationMessage("The user has been saved");
itemIdWithCred += "_" + (Math.random() + 1).toString(36).substring(7); });
createUserPage.goToCreateUser(); it("Add user to groups test", () => {
// Go to user groups
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId);
createUserPage.createUser(itemIdWithCred); userGroupsPage.goToGroupsTab();
userGroupsPage.toggleAddGroupModal();
createUserPage.save(); const groupsListCopy = groupsList.slice(1, 2);
masthead.checkNotificationMessage("The user has been created"); groupsListCopy.forEach((element) => {
cy.findByTestId(`${element}-check`).click();
sidebarPage.goToUsers();
listingPage.goToItemDetails(itemIdWithCred);
userDetailsPage.fillUserData().save();
masthead.checkNotificationMessage("The user has been saved");
credentialsPage
.goToCredentialsTab()
.clickEmptyStatePasswordBtn()
.fillPasswordForm()
.clickConfirmationBtn()
.clickSetPasswordBtn();
sidebarPage.goToUsers();
}); });
it("User details test", () => { userGroupsPage.joinGroups();
cy.wait("@brute-force"); });
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId); it("Leave group test", () => {
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId);
// Go to user groups
userGroupsPage.goToGroupsTab();
cy.findByTestId(`leave-${groupsList[0]}`).click();
cy.findByTestId("confirm").click();
});
userDetailsPage.fillUserData().save(); it("Go to user consents test", () => {
listingPage.searchItem(itemId).itemExist(itemId);
masthead.checkNotificationMessage("The user has been saved"); sidebarPage.waitForPageLoad();
listingPage.goToItemDetails(itemId);
sidebarPage.goToUsers(); cy.findByTestId("user-consents-tab").click();
cy.wait("@brute-force"); cy.findByTestId("empty-state").contains("No consents");
listingPage.searchItem(itemId).itemExist(itemId); });
});
it("User attributes test", () => { it("Reset credential of User with empty state", () => {
cy.wait("@brute-force"); listingPage.goToItemDetails(itemId);
listingPage.searchItem(itemId).itemExist(itemId); credentialsPage
.goToCredentialsTab()
.clickEmptyStateResetBtn()
.fillResetCredentialForm();
masthead.checkNotificationMessage("Failed to send email to user.");
modalUtils.cancelModal();
});
listingPage.goToItemDetails(itemId); it("Reset credential of User with existing credentials", () => {
listingPage.goToItemDetails(itemIdWithCred);
credentialsPage
.goToCredentialsTab()
.clickResetBtn()
.fillResetCredentialForm();
attributesTab masthead.checkNotificationMessage("Failed to send email to user.");
.goToAttributesTab() modalUtils.cancelModal();
.fillLastRow("key", "value") });
.saveAttribute();
masthead.checkNotificationMessage("The user has been saved"); it("Delete user test", () => {
}); // Delete
listingPage.deleteItem(itemId);
it("User attributes with multiple values test", () => { modalUtils.checkModalTitle("Delete user?").confirmModal();
cy.wait("@brute-force");
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId); masthead.checkNotificationMessage("The user has been deleted");
sidebarPage.waitForPageLoad();
cy.intercept("PUT", `/auth/admin/realms/master/users/*`).as("save-user"); listingPage.itemExist(itemId, false);
});
const attributeKey = "key-multiple"; it("Delete user with credential test", () => {
attributesTab // Delete
.goToAttributesTab() listingPage.deleteItem(itemIdWithCred);
.fillLastRow(attributeKey, "other value")
.saveAttribute();
cy.wait("@save-user").should(({ request, response }) => { modalUtils.checkModalTitle("Delete user?").confirmModal();
expect(response?.statusCode).to.equal(204);
expect(request?.body.attributes, "response body").deep.equal({ masthead.checkNotificationMessage("The user has been deleted");
key: ["value"], sidebarPage.waitForPageLoad();
"key-multiple": ["other value"],
});
});
masthead.checkNotificationMessage("The user has been saved"); listingPage.itemExist(itemIdWithCred, false);
});
it("Add user to groups test", () => {
cy.wait("@brute-force");
// Go to user groups
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId);
userGroupsPage.goToGroupsTab();
userGroupsPage.toggleAddGroupModal();
const groupsListCopy = groupsList.slice(1, 2);
groupsListCopy.forEach((element) => {
cy.findByTestId(`${element}-check`).click();
});
userGroupsPage.joinGroups();
});
it("Leave group test", () => {
cy.wait("@brute-force");
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId);
// Go to user groups
userGroupsPage.goToGroupsTab();
cy.findByTestId(`leave-${groupsList[0]}`).click();
cy.findByTestId("modalConfirm").click();
});
it("Go to user consents test", () => {
cy.wait("@brute-force");
listingPage.searchItem(itemId).itemExist(itemId);
listingPage.goToItemDetails(itemId);
cy.findByTestId("user-consents-tab").click();
cy.findByTestId("empty-state").contains("No consents");
});
it("Reset credential of User with empty state", () => {
cy.wait("@brute-force");
listingPage.goToItemDetails(itemId);
credentialsPage
.goToCredentialsTab()
.clickEmptyStateResetBtn()
.fillResetCredentialForm();
masthead.checkNotificationMessage("Failed to send email to user.");
});
it("Reset credential of User with existing credentials", () => {
cy.wait("@brute-force");
listingPage.goToItemDetails(itemIdWithCred);
credentialsPage
.goToCredentialsTab()
.clickResetBtn()
.fillResetCredentialForm();
masthead.checkNotificationMessage("Failed to send email to user.");
});
it("Delete user test", () => {
// Delete
listingPage.deleteItem(itemId);
modalUtils.checkModalTitle("Delete user?").confirmModal();
masthead.checkNotificationMessage("The user has been deleted");
listingPage.itemExist(itemId, false);
});
it("Delete user with credential test", () => {
// Delete
listingPage.deleteItem(itemIdWithCred);
modalUtils.checkModalTitle("Delete user?").confirmModal();
masthead.checkNotificationMessage("The user has been deleted");
listingPage.itemExist(itemIdWithCred, false);
});
}); });
}); });

View file

@ -24,10 +24,9 @@ export default class SidebarPage {
goToRealm(realmName: string) { goToRealm(realmName: string) {
cy.findByTestId(this.realmsList).scrollIntoView().click(); cy.findByTestId(this.realmsList).scrollIntoView().click();
cy.findByTestId(this.realmsList) cy.findByTestId(this.realmsList).within(() => {
.get("ul") cy.get("ul").contains(capitalize(realmName)).click();
.contains(capitalize(realmName)) });
.click();
return this; return this;
} }

View file

@ -9,7 +9,6 @@ export default class RoleMappingTab {
private hideInheritedRolesBtn = "#hideInheritedRoles"; private hideInheritedRolesBtn = "#hideInheritedRoles";
private assignedRolesTable = "assigned-roles"; private assignedRolesTable = "assigned-roles";
private namesColumn = 'td[data-label="Name"]:visible'; private namesColumn = 'td[data-label="Name"]:visible';
private confirmModalBtn = "modalConfirm";
goToServiceAccountTab() { goToServiceAccountTab() {
cy.findByTestId(this.tab).click(); cy.findByTestId(this.tab).click();

View file

@ -85,7 +85,7 @@ export default class RealmSettingsPage {
keyInput = "key-input"; keyInput = "key-input";
valueInput = "value-input"; valueInput = "value-input";
deleteAction = "delete-action"; deleteAction = "delete-action";
modalConfirm = "modalConfirm"; modalConfirm = "confirm";
ssoSessionIdleInput = "sso-session-idle-input"; ssoSessionIdleInput = "sso-session-idle-input";
ssoSessionMaxInput = "sso-session-max-input"; ssoSessionMaxInput = "sso-session-max-input";
ssoSessionIdleRememberMeInput = "sso-session-idle-remember-me-input"; ssoSessionIdleRememberMeInput = "sso-session-idle-remember-me-input";
@ -625,7 +625,7 @@ export default class RealmSettingsPage {
cy.get(this.deleteDialogBodyText).contains( cy.get(this.deleteDialogBodyText).contains(
"This action will permanently delete the policy Test. This cannot be undone." "This action will permanently delete the policy Test. This cannot be undone."
); );
cy.findByTestId("modalConfirm").contains("Delete"); cy.findByTestId(this.modalConfirm).contains("Delete");
cy.get(this.deleteDialogCancelBtn).contains("Cancel").click(); cy.get(this.deleteDialogCancelBtn).contains("Cancel").click();
cy.get("table").should("be.visible").contains("td", "Test"); cy.get("table").should("be.visible").contains("td", "Test");
} }
@ -633,7 +633,8 @@ export default class RealmSettingsPage {
shouldDeleteClientProfileDialog() { shouldDeleteClientProfileDialog() {
this.listingPage.searchItem("Test", false); this.listingPage.searchItem("Test", false);
this.listingPage.clickRowDetails("Test").clickDetailMenu("Delete"); this.listingPage.clickRowDetails("Test").clickDetailMenu("Delete");
cy.findByTestId("modalConfirm").contains("Delete").click(); cy.findByTestId(this.modalConfirm).contains("Delete");
cy.findByTestId(this.modalConfirm).click();
cy.get(this.alertMessage).should("be.visible", "Client profile deleted"); cy.get(this.alertMessage).should("be.visible", "Client profile deleted");
cy.get("table").should("not.have.text", "Test"); cy.get("table").should("not.have.text", "Test");
} }
@ -755,7 +756,7 @@ export default class RealmSettingsPage {
cy.get(this.deleteDialogBodyText).contains( cy.get(this.deleteDialogBodyText).contains(
"The action will permanently delete secure-ciba-signed-authn-req. This cannot be undone." "The action will permanently delete secure-ciba-signed-authn-req. This cannot be undone."
); );
cy.findByTestId("modalConfirm").contains("Delete"); cy.findByTestId(this.modalConfirm).contains("Delete");
cy.get(this.deleteDialogCancelBtn).contains("Cancel").click(); cy.get(this.deleteDialogCancelBtn).contains("Cancel").click();
cy.get('ul[class*="pf-c-data-list"]').should( cy.get('ul[class*="pf-c-data-list"]').should(
"have.text", "have.text",
@ -802,7 +803,8 @@ export default class RealmSettingsPage {
cy.get(this.deleteDialogBodyText).contains( cy.get(this.deleteDialogBodyText).contains(
"The action will permanently delete secure-ciba-signed-authn-req. This cannot be undone." "The action will permanently delete secure-ciba-signed-authn-req. This cannot be undone."
); );
cy.findByTestId("modalConfirm").contains("Delete").click(); cy.findByTestId(this.modalConfirm).contains("Delete");
cy.findByTestId(this.modalConfirm).click();
cy.get('h6[class*="kc-emptyExecutors"]').should( cy.get('h6[class*="kc-emptyExecutors"]').should(
"have.text", "have.text",
"No executors configured" "No executors configured"
@ -813,12 +815,12 @@ export default class RealmSettingsPage {
cy.get('[data-label="Name"]') cy.get('[data-label="Name"]')
.contains("Edit") .contains("Edit")
.parentsUntil("tbody") .parentsUntil("tbody")
.get(this.moreDrpDwn) .within(() => {
.last() cy.get(this.moreDrpDwn).click();
.click() });
.get(this.moreDrpDwnItems) cy.get(this.moreDrpDwnItems).click();
.click(); cy.findByTestId(this.modalConfirm).contains("Delete");
cy.findByTestId("modalConfirm").contains("Delete").click(); cy.findByTestId(this.modalConfirm).click();
cy.get(this.alertMessage).should("be.visible", "Client profile deleted"); cy.get(this.alertMessage).should("be.visible", "Client profile deleted");
cy.get("table").should("not.have.text", "Edit"); cy.get("table").should("not.have.text", "Edit");
} }
@ -843,7 +845,8 @@ export default class RealmSettingsPage {
); );
cy.get(this.createClientDrpDwn).contains("Action").click(); cy.get(this.createClientDrpDwn).contains("Action").click();
cy.findByTestId("deleteClientProfileDropdown").click(); cy.findByTestId("deleteClientProfileDropdown").click();
cy.findByTestId("modalConfirm").contains("Delete").click(); cy.findByTestId(this.modalConfirm).contains("Delete");
cy.findByTestId(this.modalConfirm).click();
cy.get(this.alertMessage).should("be.visible", "Client profile deleted"); cy.get(this.alertMessage).should("be.visible", "Client profile deleted");
cy.get("table").should("not.have.text", "Test Again Description"); cy.get("table").should("not.have.text", "Test Again Description");
} }
@ -956,7 +959,7 @@ export default class RealmSettingsPage {
cy.get(this.deleteDialogBodyText).contains( cy.get(this.deleteDialogBodyText).contains(
"This action will permanently delete the profile Test. This cannot be undone." "This action will permanently delete the profile Test. This cannot be undone."
); );
cy.findByTestId("modalConfirm").contains("Delete"); cy.findByTestId(this.modalConfirm).contains("Delete");
cy.get(this.deleteDialogCancelBtn).contains("Cancel").click(); cy.get(this.deleteDialogCancelBtn).contains("Cancel").click();
cy.get("table").should("be.visible").contains("td", "Test"); cy.get("table").should("be.visible").contains("td", "Test");
} }
@ -1008,11 +1011,11 @@ export default class RealmSettingsPage {
addClientScopes() { addClientScopes() {
cy.findByTestId(this.selectScopeButton).click(); cy.findByTestId(this.selectScopeButton).click();
cy.get(".pf-c-table__check > label > input[name=checkrow0]").click(); cy.get(".pf-c-table__check > input[name=checkrow0]").click();
cy.get(".pf-c-table__check > label > input[name=checkrow1]").click(); cy.get(".pf-c-table__check > input[name=checkrow1]").click();
cy.get(".pf-c-table__check > label > input[name=checkrow2]").click(); cy.get(".pf-c-table__check > input[name=checkrow2]").click();
cy.findByTestId("modalConfirm").contains("Add").click(); cy.findByTestId(this.modalConfirm).contains("Add").click();
} }
shouldAddClientScopesCondition() { shouldAddClientScopesCondition() {
@ -1079,8 +1082,9 @@ export default class RealmSettingsPage {
cy.get(this.deleteDialogBodyText).contains( cy.get(this.deleteDialogBodyText).contains(
"This action will permanently delete client-roles. This cannot be undone." "This action will permanently delete client-roles. This cannot be undone."
); );
cy.findByTestId("modalConfirm").contains("Delete"); cy.findByTestId(this.modalConfirm).contains("Delete");
cy.get(this.deleteDialogCancelBtn).contains("Cancel").click(); cy.get(this.deleteDialogCancelBtn).contains("Cancel");
cy.get(this.deleteDialogCancelBtn).click();
cy.get('ul[class*="pf-c-data-list"]').contains("client-roles"); cy.get('ul[class*="pf-c-data-list"]').contains("client-roles");
} }
@ -1091,7 +1095,8 @@ export default class RealmSettingsPage {
cy.get(this.deleteDialogBodyText).contains( cy.get(this.deleteDialogBodyText).contains(
"This action will permanently delete client-roles. This cannot be undone." "This action will permanently delete client-roles. This cannot be undone."
); );
cy.findByTestId("modalConfirm").contains("Delete").click(); cy.findByTestId(this.modalConfirm).contains("Delete");
cy.findByTestId(this.modalConfirm).click();
cy.get('ul[class*="pf-c-data-list"]').contains("client-scopes"); cy.get('ul[class*="pf-c-data-list"]').contains("client-scopes");
} }
@ -1102,7 +1107,8 @@ export default class RealmSettingsPage {
cy.get(this.deleteDialogBodyText).contains( cy.get(this.deleteDialogBodyText).contains(
"This action will permanently delete client-scopes. This cannot be undone." "This action will permanently delete client-scopes. This cannot be undone."
); );
cy.findByTestId("modalConfirm").contains("Delete").click(); cy.findByTestId(this.modalConfirm).contains("Delete");
cy.findByTestId(this.modalConfirm).click();
cy.get('h6[class*="kc-emptyConditions"]').should( cy.get('h6[class*="kc-emptyConditions"]').should(
"have.text", "have.text",
"No conditions configured" "No conditions configured"
@ -1112,7 +1118,7 @@ export default class RealmSettingsPage {
shouldDeleteClientPolicyDialog() { shouldDeleteClientPolicyDialog() {
this.listingPage.searchItem("Test", false); this.listingPage.searchItem("Test", false);
this.listingPage.clickRowDetails("Test").clickDetailMenu("Delete"); this.listingPage.clickRowDetails("Test").clickDetailMenu("Delete");
cy.findByTestId("modalConfirm").contains("Delete").click(); cy.findByTestId(this.modalConfirm).contains("Delete").click();
cy.get(this.alertMessage).should("be.visible", "Client profile deleted"); cy.get(this.alertMessage).should("be.visible", "Client profile deleted");
cy.get("table").should("not.have.text", "Test"); cy.get("table").should("not.have.text", "Test");
} }
@ -1135,7 +1141,7 @@ export default class RealmSettingsPage {
cy.findByTestId(this.clientPolicyDrpDwn).contains("Action").click(); cy.findByTestId(this.clientPolicyDrpDwn).contains("Action").click();
cy.findByTestId("deleteClientPolicyDropdown").click(); cy.findByTestId("deleteClientPolicyDropdown").click();
cy.findByTestId("modalConfirm").contains("Delete").click(); cy.findByTestId(this.modalConfirm).contains("Delete").click();
cy.get(this.alertMessage).should("be.visible", "Client profile deleted"); cy.get(this.alertMessage).should("be.visible", "Client profile deleted");
cy.findByTestId(this.createPolicyEmptyStateBtn).should("exist"); cy.findByTestId(this.createPolicyEmptyStateBtn).should("exist");
} }

View file

@ -52,6 +52,11 @@ export default class AdminClient {
await this.client.clients.del({ id: client.id! }); await this.client.clients.del({ id: client.id! });
} }
async createGroup(groupName: string) {
await this.login();
return await this.client.groups.create({ name: groupName });
}
async createSubGroups(groups: string[]) { async createSubGroups(groups: string[]) {
await this.login(); await this.login();
let parentGroup = undefined; let parentGroup = undefined;

View file

@ -2,18 +2,18 @@ export default class ModalUtils {
private modalTitle = ".pf-c-modal-box .pf-c-modal-box__title-text"; private modalTitle = ".pf-c-modal-box .pf-c-modal-box__title-text";
private modalMessage = ".pf-c-modal-box .pf-c-modal-box__body"; private modalMessage = ".pf-c-modal-box .pf-c-modal-box__body";
private confirmModalBtn = "#modal-confirm"; private confirmModalBtn = "confirm";
private cancelModalBtn = "#modal-cancel"; private cancelModalBtn = "cancel";
private closeModalBtn = ".pf-c-modal-box .pf-m-plain"; private closeModalBtn = ".pf-c-modal-box .pf-m-plain";
confirmModal(force = false) { confirmModal(force = false) {
cy.get(this.confirmModalBtn).click({ force }); cy.findByTestId(this.confirmModalBtn).click({ force });
return this; return this;
} }
cancelModal() { cancelModal() {
cy.get(this.cancelModalBtn).click(); cy.findByTestId(this.cancelModalBtn).click();
return this; return this;
} }

View file

@ -43,7 +43,7 @@ describe("MapperDialog", () => {
fireEvent.click(screen.getByText("Show")); fireEvent.click(screen.getByText("Show"));
expect(screen.getByTestId("modalConfirm")).toHaveClass("pf-m-disabled"); expect(screen.getByTestId("confirm")).toHaveClass("pf-m-disabled");
}); });
it("returns array with selected build in protocol mapping", () => { it("returns array with selected build in protocol mapping", () => {
@ -55,7 +55,7 @@ describe("MapperDialog", () => {
fireEvent.click(screen.getByText("Show")); fireEvent.click(screen.getByText("Show"));
fireEvent.click(screen.getByLabelText("Select row 0")); fireEvent.click(screen.getByLabelText("Select row 0"));
fireEvent.click(screen.getByLabelText("Select row 1")); fireEvent.click(screen.getByLabelText("Select row 1"));
fireEvent.click(screen.getByTestId("modalConfirm")); fireEvent.click(screen.getByTestId("confirm"));
expect(onConfirm).toBeCalledWith([ expect(onConfirm).toBeCalledWith([
serverInfo.builtinProtocolMappers[protocol][0], serverInfo.builtinProtocolMappers[protocol][0],

View file

@ -107,7 +107,7 @@ export const AddMapperDialog = (props: AddMapperDialogProps) => {
? [ ? [
<Button <Button
id="modal-confirm" id="modal-confirm"
data-testid="modalConfirm" data-testid="confirm"
key="confirm" key="confirm"
isDisabled={rows.length === 0 || selectedRows.length === 0} isDisabled={rows.length === 0 || selectedRows.length === 0}
onClick={() => { onClick={() => {
@ -119,6 +119,7 @@ export const AddMapperDialog = (props: AddMapperDialogProps) => {
</Button>, </Button>,
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={() => { onClick={() => {

View file

@ -61,6 +61,7 @@ export const ImportKeyDialog = ({
actions={[ actions={[
<Button <Button
id="modal-confirm" id="modal-confirm"
data-testid="confirm"
key="confirm" key="confirm"
onClick={() => { onClick={() => {
handleSubmit((importFile) => { handleSubmit((importFile) => {
@ -73,6 +74,7 @@ export const ImportKeyDialog = ({
</Button>, </Button>,
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={() => { onClick={() => {

View file

@ -147,7 +147,7 @@ export const AddScopeDialog = ({
? [ ? [
<Button <Button
id="modal-add" id="modal-add"
data-testid="modalConfirm" data-testid="confirm"
key="add" key="add"
variant={ButtonVariant.primary} variant={ButtonVariant.primary}
onClick={() => { onClick={() => {
@ -160,6 +160,7 @@ export const AddScopeDialog = ({
</Button>, </Button>,
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={() => { onClick={() => {

View file

@ -30,7 +30,7 @@ describe("ConfirmDialog", () => {
render(<Test />); render(<Test />);
fireEvent.click(screen.getByTestId("show")); fireEvent.click(screen.getByTestId("show"));
const confirmButton = screen.getByTestId("modalConfirm"); const confirmButton = screen.getByTestId("confirm");
expect(confirmButton).toBeInTheDocument(); expect(confirmButton).toBeInTheDocument();
fireEvent.click(confirmButton); fireEvent.click(confirmButton);

View file

@ -71,7 +71,7 @@ export const ConfirmDialogModal = ({
actions={[ actions={[
<Button <Button
id="modal-confirm" id="modal-confirm"
data-testid="modalConfirm" data-testid="confirm"
key="confirm" key="confirm"
isDisabled={confirmButtonDisabled} isDisabled={confirmButtonDisabled}
variant={continueButtonVariant || ButtonVariant.primary} variant={continueButtonVariant || ButtonVariant.primary}
@ -85,6 +85,7 @@ export const ConfirmDialogModal = ({
!noCancelButton && ( !noCancelButton && (
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={() => { onClick={() => {

View file

@ -78,6 +78,7 @@ export const GroupsModal = ({
</Button>, </Button>,
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={() => { onClick={() => {

View file

@ -67,6 +67,7 @@ export const ManageOderDialog = ({
actions={[ actions={[
<Button <Button
id="modal-confirm" id="modal-confirm"
data-testid="confirm"
key="confirm" key="confirm"
onClick={() => { onClick={() => {
order.map(async (alias, index) => { order.map(async (alias, index) => {
@ -87,6 +88,7 @@ export const ManageOderDialog = ({
</Button>, </Button>,
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={onClose} onClick={onClose}

View file

@ -50,6 +50,7 @@ export const AddMessageBundleModal = ({
</Button>, </Button>,
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={() => { onClick={() => {

View file

@ -62,6 +62,7 @@ export const AddUserEmailModal = ({ callback }: AddUserEmailModalProps) => {
</Button>, </Button>,
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={cancel} onClick={cancel}

View file

@ -84,6 +84,7 @@ JavaKeystoreModalProps) => {
</Button>, </Button>,
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={() => { onClick={() => {

View file

@ -92,9 +92,6 @@ export default function NewClientPolicyForm() {
const form = useForm<ClientPolicyRepresentation>({ mode: "onChange" }); const form = useForm<ClientPolicyRepresentation>({ mode: "onChange" });
const { handleSubmit } = form; const { handleSubmit } = form;
const [key, setKey] = useState(0);
const refresh = () => setKey(new Date().getTime());
const formValues = form.getValues(); const formValues = form.getValues();
type ClientPoliciesHeaderProps = { type ClientPoliciesHeaderProps = {
@ -102,7 +99,6 @@ export default function NewClientPolicyForm() {
value: boolean; value: boolean;
save: () => void; save: () => void;
realmName: string; realmName: string;
refresh: () => void;
}; };
const ClientPoliciesHeader = ({ const ClientPoliciesHeader = ({
@ -192,7 +188,7 @@ export default function NewClientPolicyForm() {
setShowAddConditionsAndProfilesForm(true); setShowAddConditionsAndProfilesForm(true);
} }
}, },
[key] []
); );
const setupForm = (policy: ClientPolicyRepresentation) => { const setupForm = (policy: ClientPolicyRepresentation) => {
@ -252,7 +248,6 @@ export default function NewClientPolicyForm() {
`/${realm}/realm-settings/clientPolicies/${createdForm.name}/edit-policy` `/${realm}/realm-settings/clientPolicies/${createdForm.name}/edit-policy`
); );
setShowAddConditionsAndProfilesForm(true); setShowAddConditionsAndProfilesForm(true);
refresh();
} catch (error) { } catch (error) {
addError("realm-settings:createClientPolicyError", error); addError("realm-settings:createClientPolicyError", error);
} }
@ -306,7 +301,6 @@ export default function NewClientPolicyForm() {
history.push( history.push(
`/${realm}/realm-settings/clientPolicies/${formValues.name}/edit-policy` `/${realm}/realm-settings/clientPolicies/${formValues.name}/edit-policy`
); );
refresh();
} catch (error) { } catch (error) {
addError(t("deleteConditionError"), error); addError(t("deleteConditionError"), error);
} }
@ -383,10 +377,6 @@ export default function NewClientPolicyForm() {
form.setValue("description", currentPolicy?.description); form.setValue("description", currentPolicy?.description);
}; };
const refreshHeader = () => {
setKey(new Date().getTime());
};
const toggleModal = () => { const toggleModal = () => {
setProfilesModalOpen(!profilesModalOpen); setProfilesModalOpen(!profilesModalOpen);
}; };
@ -450,7 +440,6 @@ export default function NewClientPolicyForm() {
value={value} value={value}
onChange={onChange} onChange={onChange}
realmName={realm} realmName={realm}
refresh={refreshHeader}
save={save} save={save}
/> />
)} )}

View file

@ -83,6 +83,7 @@ export const RSAGeneratedModal = ({
</Button>, </Button>,
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={() => { onClick={() => {

View file

@ -102,6 +102,7 @@ export const RSAModal = ({
</Button>, </Button>,
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={() => { onClick={() => {

View file

@ -55,6 +55,7 @@ export const LogoutAllSessionsModal = ({
</Button>, </Button>,
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={() => { onClick={() => {

View file

@ -169,6 +169,7 @@ export const RevocationModal = ({
</Button>, </Button>,
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={() => { onClick={() => {

View file

@ -494,7 +494,7 @@ export const UserCredentials = ({ user }: UserCredentialsProps) => {
{t("save")} {t("save")}
</Button>, </Button>,
<Button <Button
data-testid="cancelBtn" data-testid="cancel"
key={`cancelBtn-${user.id}`} key={`cancelBtn-${user.id}`}
variant="link" variant="link"
form="userCredentials-form" form="userCredentials-form"
@ -606,7 +606,7 @@ export const UserCredentials = ({ user }: UserCredentialsProps) => {
{isResetPassword ? t("resetPassword") : t("savePassword")} {isResetPassword ? t("resetPassword") : t("savePassword")}
</Button>, </Button>,
<Button <Button
data-testid="cancelSetPasswordBtn" data-testid="cancel"
key={`cancelConfirmBtn-${user.id}`} key={`cancelConfirmBtn-${user.id}`}
variant="link" variant="link"
form="userCredentials-form" form="userCredentials-form"
@ -653,7 +653,7 @@ export const UserCredentials = ({ user }: UserCredentialsProps) => {
{t("credentialResetConfirm")} {t("credentialResetConfirm")}
</Button>, </Button>,
<Button <Button
data-testid="cancelBtn" data-testid="cancel"
key={`cancelBtn-${user.id}`} key={`cancelBtn-${user.id}`}
variant="link" variant="link"
form="userCredentialsReset-form" form="userCredentialsReset-form"

View file

@ -77,6 +77,7 @@ export const UserIdpModal = ({
</Button>, </Button>,
<Button <Button
id="modal-cancel" id="modal-cancel"
data-testid="cancel"
key="cancel" key="cancel"
variant={ButtonVariant.link} variant={ButtonVariant.link}
onClick={() => { onClick={() => {

View file

@ -39,9 +39,10 @@ import { useRealm } from "../context/realm-context/RealmContext";
import { emptyFormatter } from "../util"; import { emptyFormatter } from "../util";
import { toUser } from "./routes/User"; import { toUser } from "./routes/User";
import { toAddUser } from "./routes/AddUser"; import { toAddUser } from "./routes/AddUser";
import helpUrls from "../help-urls";
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
import "./user-section.css"; import "./user-section.css";
import helpUrls from "../help-urls";
type BruteUser = UserRepresentation & { type BruteUser = UserRepresentation & {
brute?: Record<string, object>; brute?: Record<string, object>;
@ -53,7 +54,7 @@ export default function UsersSection() {
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const { realm: realmName } = useRealm(); const { realm: realmName } = useRealm();
const history = useHistory(); const history = useHistory();
const [listUsers, setListUsers] = useState(false); const [userStorage, setUserStorage] = useState<ComponentRepresentation[]>();
const [searchUser, setSearchUser] = useState<string>(); const [searchUser, setSearchUser] = useState<string>();
const [realm, setRealm] = useState<RealmRepresentation | undefined>(); const [realm, setRealm] = useState<RealmRepresentation | undefined>();
const [kebabOpen, setKebabOpen] = useState(false); const [kebabOpen, setKebabOpen] = useState(false);
@ -63,27 +64,26 @@ export default function UsersSection() {
const refresh = () => setKey(`${new Date().getTime()}`); const refresh = () => setKey(`${new Date().getTime()}`);
useFetch( useFetch(
() => { async () => {
const testParams = { const testParams = {
type: "org.keycloak.storage.UserStorageProvider", type: "org.keycloak.storage.UserStorageProvider",
}; };
return Promise.all([ try {
adminClient.components.find(testParams), return await Promise.all([
adminClient.realms.findOne({ realm: realmName }), adminClient.components.find(testParams),
]).catch( adminClient.realms.findOne({ realm: realmName }),
() => ]);
[[], undefined] as [ } catch {
ComponentRepresentation[], return [[], undefined] as [
RealmRepresentation | undefined ComponentRepresentation[],
] RealmRepresentation | undefined
); ];
}
}, },
([storageProviders, realm]) => { ([storageProviders, realm]) => {
//should *only* list users when no user federation is configured setUserStorage(storageProviders);
setListUsers(!(storageProviders.length > 0));
setRealm(realm); setRealm(realm);
refresh();
}, },
[] []
); );
@ -204,6 +204,13 @@ export default function UsersSection() {
const goToCreate = () => history.push(toAddUser({ realm: realmName })); const goToCreate = () => history.push(toAddUser({ realm: realmName }));
if (!userStorage) {
return <KeycloakSpinner />;
}
//should *only* list users when no user federation is configured
const listUsers = !(userStorage.length > 0);
const toolbar = ( const toolbar = (
<> <>
<ToolbarItem> <ToolbarItem>
@ -257,6 +264,10 @@ export default function UsersSection() {
</> </>
); );
if (!realm) {
return <KeycloakSpinner />;
}
return ( return (
<> <>
<DeleteConfirm /> <DeleteConfirm />

View file

@ -29,6 +29,7 @@ import { UserRoleMapping } from "./UserRoleMapping";
import { UserAttributes } from "./UserAttributes"; import { UserAttributes } from "./UserAttributes";
import { UserCredentials } from "./UserCredentials"; import { UserCredentials } from "./UserCredentials";
import { useAccess } from "../context/access/Access"; import { useAccess } from "../context/access/Access";
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
const UsersTabs = () => { const UsersTabs = () => {
const { t } = useTranslation("users"); const { t } = useTranslation("users");
@ -142,6 +143,10 @@ const UsersTabs = () => {
}, },
}); });
if (id && !user) {
return <KeycloakSpinner />;
}
return ( return (
<> <>
<ImpersonateConfirm /> <ImpersonateConfirm />