Add user profile tests for Checks that attribute with select annotation (#26899)

Closes #26898

Signed-off-by: Daniel Fesenmeyer <daniel.fesenmeyer@bosch.com>
This commit is contained in:
Daniel Fesenmeyer 2024-02-09 17:34:55 +01:00 committed by GitHub
parent 5f0ee7b0f7
commit 20e535a3f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 582 additions and 299 deletions

View file

@ -9,6 +9,7 @@ import { keycloakBefore } from "../support/util/keycloak_hooks";
import ModalUtils from "../support/util/ModalUtils"; import ModalUtils from "../support/util/ModalUtils";
import RealmSettingsPage from "../support/pages/admin-ui/manage/realm_settings/RealmSettingsPage"; import RealmSettingsPage from "../support/pages/admin-ui/manage/realm_settings/RealmSettingsPage";
import CreateUserPage from "../support/pages/admin-ui/manage/users/CreateUserPage"; import CreateUserPage from "../support/pages/admin-ui/manage/users/CreateUserPage";
import { UserProfileConfig } from "@keycloak/keycloak-admin-client/lib/defs/userProfileMetadata";
const loginPage = new LoginPage(); const loginPage = new LoginPage();
const sidebarPage = new SidebarPage(); const sidebarPage = new SidebarPage();
@ -24,45 +25,58 @@ const getUserProfileTab = () => userProfileTab.goToTab();
const getAttributesTab = () => userProfileTab.goToAttributesTab(); const getAttributesTab = () => userProfileTab.goToAttributesTab();
const getAttributesGroupTab = () => userProfileTab.goToAttributesGroupTab(); const getAttributesGroupTab = () => userProfileTab.goToAttributesGroupTab();
const getJsonEditorTab = () => userProfileTab.goToJsonEditorTab(); const getJsonEditorTab = () => userProfileTab.goToJsonEditorTab();
const clickCreateAttributeButton = () =>
userProfileTab.createAttributeButtonClick(); const usernameAttributeName = "username";
const emailAttributeName = "email";
let defaultUserProfile: UserProfileConfig;
describe("User profile tabs", () => { describe("User profile tabs", () => {
const realmName = "Realm_" + uuid(); const realmName = "Realm_" + uuid();
const attributeName = "Test"; const attributeName = "Test";
const attributeDisplayName = "Test display name";
before(() => adminClient.createRealm(realmName)); before(() => {
after(() => adminClient.deleteRealm(realmName)); cy.wrap(null).then(async () => {
await adminClient.createRealm(realmName);
defaultUserProfile = await adminClient.getUserProfile(realmName);
});
});
after(() =>
cy.wrap(null).then(async () => await adminClient.deleteRealm(realmName)),
);
beforeEach(() => { beforeEach(() => {
loginPage.logIn(); loginPage.logIn();
keycloakBefore(); keycloakBefore();
cy.wrap(null).then(async () => {
await adminClient.updateUserProfile(realmName, defaultUserProfile);
await adminClient.updateRealm(realmName, {
registrationEmailAsUsername: false,
editUsernameAllowed: false,
});
});
sidebarPage.goToRealm(realmName); sidebarPage.goToRealm(realmName);
sidebarPage.goToRealmSettings(); sidebarPage.goToRealmSettings();
}); });
afterEach(() => {
sidebarPage.goToRealmSettings();
sidebarPage.waitForPageLoad();
realmSettingsPage.goToLoginTab();
cy.wait(1000);
cy.findByTestId("email-as-username-switch").uncheck({ force: true });
cy.findByTestId("edit-username-switch").uncheck({ force: true });
});
describe("Attributes sub tab tests", () => { describe("Attributes sub tab tests", () => {
it("Goes to create attribute page", () => { it("Goes to create attribute page", () => {
getUserProfileTab(); getUserProfileTab();
getAttributesTab(); getAttributesTab();
clickCreateAttributeButton(); userProfileTab.clickOnCreateAttributeButton();
}); });
it("Completes new attribute form and performs cancel", () => { it("Completes new attribute form and performs cancel", () => {
getUserProfileTab(); getUserProfileTab();
getAttributesTab(); getAttributesTab();
clickCreateAttributeButton();
userProfileTab userProfileTab
.createAttribute(attributeName, "Test display name") .clickOnCreateAttributeButton()
.setAttributeNames(attributeName, attributeDisplayName)
.cancelAttributeCreation() .cancelAttributeCreation()
.checkElementNotInList(attributeName); .checkElementNotInList(attributeName);
}); });
@ -70,33 +84,35 @@ describe("User profile tabs", () => {
it("Completes new attribute form and performs submit", () => { it("Completes new attribute form and performs submit", () => {
getUserProfileTab(); getUserProfileTab();
getAttributesTab(); getAttributesTab();
clickCreateAttributeButton();
userProfileTab userProfileTab
.createAttribute(attributeName, "Display name") .clickOnCreateAttributeButton()
.saveAttributeCreation(); .setAttributeNames(attributeName, attributeDisplayName)
masthead.checkNotificationMessage( .saveAttributeCreation()
"Success! User Profile configuration has been saved.", .assertNotificationSaved();
);
}); });
it("Modifies existing attribute and performs save", () => { it("Modifies existing attribute and performs save", () => {
getUserProfileTab(); getUserProfileTab();
getAttributesTab(); createAttributeDefinition(attributeName);
userProfileTab userProfileTab
.selectElementInList(attributeName) .selectElementInList(attributeName)
.editAttribute("Edited display name") .editAttribute("Edited display name")
.saveAttributeCreation(); .saveAttributeCreation()
masthead.checkNotificationMessage( .assertNotificationSaved();
"Success! User Profile configuration has been saved.",
);
}); });
it("Adds and removes validator to/from existing attribute and performs save", () => { it("Adds and removes validator to/from existing attribute and performs save", () => {
getUserProfileTab(); getUserProfileTab();
getAttributesTab(); createAttributeDefinition(attributeName);
userProfileTab.selectElementInList(attributeName).cancelAddingValidator();
userProfileTab.addValidator(); userProfileTab
cy.get('tbody [data-label="Validator name"]').contains("email"); .selectElementInList(attributeName)
.cancelAddingValidator(emailAttributeName);
userProfileTab.addValidator(emailAttributeName);
cy.get('tbody [data-label="Validator name"]').contains(
emailAttributeName,
);
userProfileTab.cancelRemovingValidator(); userProfileTab.cancelRemovingValidator();
userProfileTab.removeValidator(); userProfileTab.removeValidator();
@ -106,15 +122,16 @@ describe("User profile tabs", () => {
describe("Attribute groups sub tab tests", () => { describe("Attribute groups sub tab tests", () => {
it("Deletes an attributes group", () => { it("Deletes an attributes group", () => {
const group = "Test";
cy.wrap(null).then(() => cy.wrap(null).then(() =>
adminClient.patchUserProfile(realmName, { adminClient.patchUserProfile(realmName, {
groups: [{ name: "Test" }], groups: [{ name: group }],
}), }),
); );
getUserProfileTab(); getUserProfileTab();
getAttributesGroupTab(); getAttributesGroupTab();
listingPage.deleteItem("Test"); listingPage.deleteItem(group);
modalUtils.confirmModal(); modalUtils.confirmModal();
listingPage.checkEmptyList(); listingPage.checkEmptyList();
}); });
@ -126,9 +143,9 @@ describe("User profile tabs", () => {
{ {
"attributes": [ "attributes": [
{ {
"name": "email"{downArrow}, "name": "${emailAttributeName}"{downArrow},
{ {
"name": "username", "name": "${usernameAttributeName}",
"validations": { "validations": {
"length": { "length": {
"min": 3, "min": 3,
@ -146,274 +163,281 @@ describe("User profile tabs", () => {
}); });
}); });
describe("Check attribute presence when creating a user based on email as username and edit username configs enabled/disabled", () => { describe("Check attributes are displayed and editable on user create/edit", () => {
it("Checks that not required attribute is not present when user is created with email as username and edit username set to disabled", () => { it("Checks that not required attribute is not present when user is created with email as username and edit username set to disabled", () => {
const attrName = "newAttribute1";
getUserProfileTab(); getUserProfileTab();
getAttributesTab(); createAttributeDefinition(attrName, (attrConfigurer) =>
clickCreateAttributeButton(); attrConfigurer.setNoAttributePermissions(),
userProfileTab
.createAttributeNotRequiredWithoutPermissions(
"newAttribute1",
"newAttribute1",
)
.saveAttributeCreation();
masthead.checkNotificationMessage(
"Success! User Profile configuration has been saved.",
); );
sidebarPage.goToRealmSettings(); sidebarPage.goToRealmSettings();
realmSettingsPage.goToLoginTab(); realmSettingsPage.goToLoginTab();
cy.wait(1000); cy.wait(1000);
cy.findByTestId("email-as-username-switch").should("have.value", "off"); realmSettingsPage
cy.findByTestId("edit-username-switch").should("have.value", "off"); .assertSwitch(realmSettingsPage.emailAsUsernameSwitch, false)
.assertSwitch(realmSettingsPage.editUsernameSwitch, false);
// Create user // Create user
sidebarPage.goToUsers(); sidebarPage.goToUsers();
cy.wait(1000); cy.wait(1000);
createUserPage.goToCreateUser(); createUserPage
cy.findByTestId("username").type("testuser7"); .goToCreateUser()
cy.findByTestId("create-user").click(); .assertAttributeFieldExists(attrName, false)
masthead.checkNotificationMessage("The user has been created"); .setUsername("testuser7")
cy.get(".pf-c-form__label-text") .create()
.contains("newAttribute1") .assertNotificationCreated()
.should("not.exist"); .assertAttributeFieldExists(attrName, false);
sidebarPage.goToRealmSettings(); sidebarPage.goToRealmSettings();
getUserProfileTab(); getUserProfileTab();
getAttributesTab(); getAttributesTab();
listingPage.deleteItem("newAttribute1"); listingPage.deleteItem(attrName);
modalUtils.confirmModal(); modalUtils.confirmModal();
masthead.checkNotificationMessage("Attribute deleted"); masthead.checkNotificationMessage("Attribute deleted");
}); });
it("Checks that not required attribute is not present when user is created/edited with email as username enabled", () => { it("Checks that not required attribute is not present when user is created/edited with email as username enabled", () => {
const attrName = "newAttribute2";
getUserProfileTab(); getUserProfileTab();
getAttributesTab(); createAttributeDefinition(attrName, (attrConfigurer) =>
clickCreateAttributeButton(); attrConfigurer.setNoAttributePermissions(),
userProfileTab
.createAttributeNotRequiredWithoutPermissions(
"newAttribute2",
"newAttribute2",
)
.saveAttributeCreation();
masthead.checkNotificationMessage(
"Success! User Profile configuration has been saved.",
); );
sidebarPage.goToRealmSettings(); sidebarPage.goToRealmSettings();
realmSettingsPage.goToLoginTab(); realmSettingsPage.goToLoginTab();
cy.wait(1000); cy.wait(1000);
cy.findByTestId("email-as-username-switch").check({ force: true }); realmSettingsPage
cy.findByTestId("email-as-username-switch").should("have.value", "on"); .setSwitch(realmSettingsPage.emailAsUsernameSwitch, true)
cy.findByTestId("edit-username-switch").should("have.value", "off"); .assertSwitch(realmSettingsPage.emailAsUsernameSwitch, true)
.assertSwitch(realmSettingsPage.editUsernameSwitch, false);
// Create user // Create user
sidebarPage.goToUsers(); sidebarPage.goToUsers();
createUserPage.goToCreateUser(); createUserPage
cy.findByTestId("email").type("testuser8@gmail.com"); .goToCreateUser()
cy.get(".pf-c-form__label-text") .setAttributeValue(emailAttributeName, "testuser8@gmail.com")
.contains("newAttribute2") .assertAttributeFieldExists(attrName, false)
.should("not.exist"); .create()
cy.findByTestId("create-user").click(); .assertNotificationCreated();
masthead.checkNotificationMessage("The user has been created");
// Edit user // Edit user
cy.get(".pf-c-form__label-text") createUserPage
.contains("newAttribute2") .assertAttributeFieldExists(attrName, false)
.should("not.exist"); .setAttributeValue(emailAttributeName, "testuser9@gmail.com")
cy.findByTestId("email").clear(); .update()
cy.findByTestId("email").type("testuser9@gmail.com"); .assertNotificationUpdated();
cy.findByTestId("save-user").click();
masthead.checkNotificationMessage("The user has been saved");
sidebarPage.goToRealmSettings();
getUserProfileTab();
getAttributesTab();
listingPage.deleteItem("newAttribute2");
modalUtils.confirmModal();
masthead.checkNotificationMessage("Attribute deleted");
}); });
it("Checks that not required attribute with permissions to view/edit is present when user is created", () => { it("Checks that not required attribute with permissions to view/edit is present when user is created", () => {
const attrName = "newAttribute3";
getUserProfileTab(); getUserProfileTab();
getAttributesTab(); createAttributeDefinition(attrName, (attrConfigurer) =>
clickCreateAttributeButton(); attrConfigurer.setAllAttributePermissions(),
userProfileTab
.createAttributeNotRequiredWithPermissions(
"newAttribute3",
"newAttribute3",
)
.saveAttributeCreation();
masthead.checkNotificationMessage(
"Success! User Profile configuration has been saved.",
); );
sidebarPage.goToRealmSettings(); sidebarPage.goToRealmSettings();
realmSettingsPage.goToLoginTab(); realmSettingsPage.goToLoginTab();
cy.wait(1000); cy.wait(1000);
cy.findByTestId("email-as-username-switch").should("have.value", "off"); realmSettingsPage
cy.findByTestId("edit-username-switch").should("have.value", "off"); .assertSwitch(realmSettingsPage.emailAsUsernameSwitch, false)
.assertSwitch(realmSettingsPage.editUsernameSwitch, false);
// Create user // Create user
sidebarPage.goToUsers(); sidebarPage.goToUsers();
createUserPage.goToCreateUser(); createUserPage
cy.findByTestId("username").type("testuser10"); .goToCreateUser()
cy.findByTestId("create-user").click(); .assertAttributeFieldExists(attrName, true)
masthead.checkNotificationMessage("The user has been created"); .setUsername("testuser10")
cy.get(".pf-c-form__label-text") .create()
.contains("newAttribute3") .assertNotificationCreated()
.should("exist"); .assertAttributeFieldExists(attrName, true);
sidebarPage.goToRealmSettings();
getUserProfileTab();
getAttributesTab();
listingPage.deleteItem("newAttribute3");
modalUtils.confirmModal();
masthead.checkNotificationMessage("Attribute deleted");
}); });
//TODO this test doesn't seem to pass on CI
it.skip("Checks that required attribute with permissions to view/edit is present and required when user is created", () => { it("Checks that required attribute with permissions to view/edit is present and required when user is created", () => {
const attrName = "newAttribute4";
getUserProfileTab(); getUserProfileTab();
getAttributesTab(); createAttributeDefinition(attrName, (attrConfigurer) =>
clickCreateAttributeButton(); attrConfigurer.setAllAttributePermissions().setAttributeRequired(),
userProfileTab
.createAttributeRequiredWithPermissions(
"newAttribute4",
"newAttribute4",
)
.saveAttributeCreation();
masthead.checkNotificationMessage(
"Success! User Profile configuration has been saved.",
); );
// Create user // Create user
sidebarPage.goToUsers(); sidebarPage.goToUsers();
createUserPage.goToCreateUser(); createUserPage
cy.findByTestId("username").type("testuser11"); .goToCreateUser()
cy.get(".pf-c-form__label-text") .assertAttributeLabel(attrName, attrName)
.contains("newAttribute4") .setUsername("testuser11")
.should("exist"); .create()
cy.findByTestId("create-user").click(); .assertValidationErrorRequired(attrName);
masthead.checkNotificationMessage(
"Could not create user: Please specify attribute newAttribute4.", createUserPage
); .setAttributeValue(attrName, "MyAttribute")
sidebarPage.goToRealmSettings(); .create()
getUserProfileTab(); .assertNotificationCreated();
getAttributesTab();
listingPage.deleteItem("newAttribute4");
modalUtils.confirmModal();
masthead.checkNotificationMessage("Attribute deleted");
}); });
it("Checks that required attribute with permissions to view/edit is accepted when user is created", () => { it("Checks that required attribute with permissions to view/edit is accepted when user is created", () => {
const attrName = "newAttribute5";
getUserProfileTab(); getUserProfileTab();
getAttributesTab(); createAttributeDefinition(attrName, (attrConfigurer) =>
clickCreateAttributeButton(); attrConfigurer.setAllAttributePermissions().setAttributeRequired(),
userProfileTab
.createAttributeRequiredWithPermissions(
"newAttribute5",
"newAttribute5",
)
.saveAttributeCreation();
masthead.checkNotificationMessage(
"Success! User Profile configuration has been saved.",
); );
// Create user // Create user
sidebarPage.goToUsers(); sidebarPage.goToUsers();
createUserPage.goToCreateUser(); createUserPage
cy.findByTestId("username").type("testuser12"); .goToCreateUser()
cy.get(".pf-c-form__label-text") .assertAttributeLabel(attrName, attrName)
.contains("newAttribute5") .setUsername("testuser12")
.should("exist"); .setAttributeValue(attrName, "MyAttribute")
cy.findByTestId("newAttribute5").type("MyAttribute"); .create()
cy.findByTestId("create-user").click(); .assertNotificationCreated();
masthead.checkNotificationMessage("The user has been created");
sidebarPage.goToRealmSettings();
getUserProfileTab();
getAttributesTab();
listingPage.deleteItem("newAttribute5");
modalUtils.confirmModal();
masthead.checkNotificationMessage("Attribute deleted");
}); });
it("Checks that attribute group is visible when user with existing attribute is created", () => { it("Checks that attribute group is visible when user with existing attribute is created", () => {
const group = "personalInfo";
getUserProfileTab(); getUserProfileTab();
getAttributesGroupTab(); getAttributesGroupTab()
cy.findAllByTestId("no-attributes-groups-empty-action").click(); .clickOnCreatesAttributesGroupButton()
userProfileTab.createAttributeGroup("personalInfo", "personalInfo"); .createAttributeGroup(group, group)
userProfileTab.saveAttributesGroupCreation(); .saveAttributesGroupCreation();
getAttributesTab(); getAttributesTab();
userProfileTab.selectElementInList("username"); userProfileTab
cy.get("#kc-attributeGroup").click(); .selectElementInList(usernameAttributeName)
cy.get("button.pf-c-select__menu-item").contains("personalInfo").click(); .setAttributeGroup(group)
userProfileTab.saveAttributeCreation(); .saveAttributeCreation()
masthead.checkNotificationMessage( .assertNotificationSaved();
"Success! User Profile configuration has been saved.",
);
// Create user // Create user
sidebarPage.goToUsers(); sidebarPage.goToUsers();
createUserPage.goToCreateUser(); createUserPage
cy.findByTestId("username").type("testuser14"); .goToCreateUser()
cy.get("h1#personalinfo").should("have.text", "personalInfo"); .assertGroupDisplayName(group, group)
cy.findByTestId("create-user").click(); .setUsername("testuser14")
masthead.checkNotificationMessage("The user has been created"); .create()
.assertNotificationCreated();
sidebarPage.goToRealmSettings(); sidebarPage.goToRealmSettings();
getUserProfileTab(); getUserProfileTab();
getAttributesTab(); getAttributesTab();
userProfileTab.selectElementInList("username"); userProfileTab
cy.get("#kc-attributeGroup").click(); .selectElementInList(usernameAttributeName)
cy.get("button.pf-c-select__menu-item").contains("None").click(); .resetAttributeGroup()
userProfileTab.saveAttributeCreation(); .saveAttributeCreation()
masthead.checkNotificationMessage( .assertNotificationSaved();
"Success! User Profile configuration has been saved.", });
it("Checks that attribute group is visible when user with a new attribute is created", () => {
const group = "contact";
const attrName = "address";
getUserProfileTab();
getAttributesGroupTab()
.clickOnCreatesAttributesGroupButton()
.createAttributeGroup(group, group)
.saveAttributesGroupCreation();
createAttributeDefinition(attrName, (attrConfigurer) =>
attrConfigurer.setAllAttributePermissions(),
); );
getAttributesGroupTab();
listingPage.deleteItem("personalInfo");
modalUtils.confirmModal();
listingPage.checkEmptyList();
});
it("Checks that attribute group is visible when user with a new attribute is created", () => {
getUserProfileTab();
getAttributesGroupTab();
cy.findAllByTestId("no-attributes-groups-empty-action").click();
userProfileTab.createAttributeGroup("contact", "contact");
userProfileTab.saveAttributesGroupCreation();
getAttributesTab();
clickCreateAttributeButton();
userProfileTab userProfileTab
.createAttributeNotRequiredWithPermissions("address", "address") .selectElementInList(attrName)
.saveAttributeCreation(); .setAttributeGroup(group)
masthead.checkNotificationMessage( .saveAttributeCreation()
"Success! User Profile configuration has been saved.", .assertNotificationSaved();
);
userProfileTab.selectElementInList("address");
cy.get("#kc-attributeGroup").click();
cy.get("button.pf-c-select__menu-item").contains("contact").click();
userProfileTab.saveAttributeCreation();
masthead.checkNotificationMessage(
"Success! User Profile configuration has been saved.",
);
// Create user // Create user
sidebarPage.goToUsers(); sidebarPage.goToUsers();
createUserPage.goToCreateUser(); const initialAttrValue = "MyNewAddress1";
cy.findByTestId("username").type("testuser13"); createUserPage
cy.get("h1#contact").should("have.text", "contact"); .goToCreateUser()
cy.get(".pf-c-form__label-text").contains("address").should("exist"); .assertGroupDisplayName(group, group)
cy.findByTestId("address").type("MyNewAddress1"); .assertAttributeLabel(attrName, attrName)
cy.findByTestId("create-user").click(); .setUsername("testuser13")
masthead.checkNotificationMessage("The user has been created"); .setAttributeValue(attrName, initialAttrValue)
cy.findByTestId("address").should("have.value", "MyNewAddress1"); .create()
.assertNotificationCreated()
.assertAttributeValue(attrName, initialAttrValue);
// Edit attribute // Edit attribute
cy.findByTestId("address").clear(); const newAttrValue = "MyNewAddress2";
cy.findByTestId("address").type("MyNewAddress2"); createUserPage
cy.findByTestId("save-user").click(); .setAttributeValue(attrName, newAttrValue)
masthead.checkNotificationMessage("The user has been saved"); .update()
cy.findByTestId("address").should("have.value", "MyNewAddress2"); .assertNotificationUpdated()
.assertAttributeValue(attrName, newAttrValue);
sidebarPage.goToRealmSettings(); sidebarPage.goToRealmSettings();
getUserProfileTab(); getUserProfileTab();
getAttributesTab(); getAttributesTab();
userProfileTab.selectElementInList("address"); userProfileTab
cy.get("#kc-attributeGroup").click(); .selectElementInList(attrName)
cy.get("button.pf-c-select__menu-item").contains("None").click(); .resetAttributeGroup()
userProfileTab.saveAttributeCreation(); .saveAttributeCreation()
masthead.checkNotificationMessage( .assertNotificationSaved();
"Success! User Profile configuration has been saved.", });
it("Checks that attribute with select-annotation is displayed and editable when user is created/edited", () => {
const userName = "select-test-user";
const attrName = "select-test-attr";
const opt1 = "opt1";
const opt2 = "opt2";
const supportedOptions = [opt1, opt2];
getUserProfileTab();
createAttributeDefinition(attrName, (attrConfigurer) =>
attrConfigurer
.setAllAttributePermissions()
.clickAddValidator()
.selectValidatorType("options")
.setListFieldValues("options", supportedOptions)
.clickSave(),
); );
getAttributesGroupTab(); // Create user
listingPage.deleteItem("contact"); sidebarPage.goToUsers();
modalUtils.confirmModal(); createUserPage
listingPage.checkEmptyList(); .goToCreateUser()
.assertAttributeLabel(attrName, attrName)
.assertAttributeSelect(attrName, supportedOptions, "")
.setUsername(userName)
.setAttributeValueOnSelect(attrName, opt1)
.create()
.assertNotificationCreated()
.assertAttributeLabel(attrName, attrName)
.assertAttributeSelect(attrName, supportedOptions, opt1);
// Edit attribute
createUserPage
.setAttributeValueOnSelect(attrName, opt2)
.update()
.assertNotificationUpdated()
.assertAttributeLabel(attrName, attrName)
.assertAttributeSelect(attrName, supportedOptions, opt2);
}); });
}); });
function createAttributeDefinition(
attrName: string,
attrConfigurer?: (attrConfigurer: UserProfile) => void,
) {
userProfileTab
.goToAttributesTab()
.clickOnCreateAttributeButton()
.setAttributeNames(attrName, attrName);
if (attrConfigurer) {
attrConfigurer(userProfileTab);
}
userProfileTab.saveAttributeCreation().assertNotificationSaved();
}
}); });

View file

@ -73,7 +73,7 @@ describe("User creation", () => {
createUserPage.createUser(itemId); createUserPage.createUser(itemId);
createUserPage.save(); createUserPage.create();
masthead.checkNotificationMessage("The user has been created"); masthead.checkNotificationMessage("The user has been created");
}); });
@ -95,7 +95,7 @@ describe("User creation", () => {
createUserPage.joinGroups(); createUserPage.joinGroups();
createUserPage.save(); createUserPage.create();
masthead.checkNotificationMessage("The user has been created"); masthead.checkNotificationMessage("The user has been created");
}); });
@ -109,7 +109,7 @@ describe("User creation", () => {
createUserPage.createUser(itemIdWithCred); createUserPage.createUser(itemIdWithCred);
userDetailsPage.fillUserData(); userDetailsPage.fillUserData();
createUserPage.save(); createUserPage.create();
masthead.checkNotificationMessage("The user has been created"); masthead.checkNotificationMessage("The user has been created");
sidebarPage.waitForPageLoad(); sidebarPage.waitForPageLoad();
@ -493,7 +493,7 @@ describe("User creation", () => {
createUserPage.goToCreateUser(); createUserPage.goToCreateUser();
createUserPage.createUser(a11yUser); createUserPage.createUser(a11yUser);
userDetailsPage.fillUserData(); userDetailsPage.fillUserData();
createUserPage.save(); createUserPage.create();
cy.checkA11y(); cy.checkA11y();
}); });

View file

@ -1,26 +1,27 @@
export default class FormValidation { export default class FormValidation {
static assertRequired(chain: Cypress.Chainable<JQuery<HTMLElement>>) { static assertRequired(chain: Cypress.Chainable<JQuery<HTMLElement>>) {
return this.#getHelperText(chain).should("have.text", "Required field"); return this.assertMessage(chain, "Required field");
}
static assertMessage(
chain: Cypress.Chainable<JQuery<HTMLElement>>,
expectedMessage: string,
) {
return this.#getHelperText(chain).should("have.text", expectedMessage);
} }
static assertMinValue( static assertMinValue(
chain: Cypress.Chainable<JQuery<HTMLElement>>, chain: Cypress.Chainable<JQuery<HTMLElement>>,
minValue: number, minValue: number,
) { ) {
this.#getHelperText(chain).should( this.assertMessage(chain, `Must be greater than ${minValue}`);
"have.text",
`Must be greater than ${minValue}`,
);
} }
static assertMaxValue( static assertMaxValue(
chain: Cypress.Chainable<JQuery<HTMLElement>>, chain: Cypress.Chainable<JQuery<HTMLElement>>,
maxValue: number, maxValue: number,
) { ) {
this.#getHelperText(chain).should( this.assertMessage(chain, `Must be less than ${maxValue}`);
"have.text",
`Must be less than ${maxValue}`,
);
} }
static #getHelperText(chain: Cypress.Chainable<JQuery<HTMLElement>>) { static #getHelperText(chain: Cypress.Chainable<JQuery<HTMLElement>>) {

View file

@ -71,6 +71,7 @@ export default class RealmSettingsPage extends CommonPage {
forgotPwdSwitch = "forgot-pw-switch"; forgotPwdSwitch = "forgot-pw-switch";
rememberMeSwitch = "remember-me-switch"; rememberMeSwitch = "remember-me-switch";
emailAsUsernameSwitch = "email-as-username-switch"; emailAsUsernameSwitch = "email-as-username-switch";
editUsernameSwitch = "edit-username-switch";
loginWithEmailSwitch = "login-with-email-switch"; loginWithEmailSwitch = "login-with-email-switch";
duplicateEmailsSwitch = "duplicate-emails-switch"; duplicateEmailsSwitch = "duplicate-emails-switch";
verifyEmailSwitch = "verify-email-switch"; verifyEmailSwitch = "verify-email-switch";
@ -448,6 +449,22 @@ export default class RealmSettingsPage extends CommonPage {
return this; return this;
} }
assertSwitch(switchName: string, on: boolean) {
cy.findByTestId(switchName).should("have.value", on ? "on" : "off");
return this;
}
setSwitch(switchName: string, on: boolean) {
if (on) {
cy.findByTestId(switchName).check({ force: true });
} else {
cy.findByTestId(switchName).uncheck({ force: true });
}
return this;
}
toggleCheck(switchName: string) { toggleCheck(switchName: string) {
cy.findByTestId(switchName).click(); cy.findByTestId(switchName).click();

View file

@ -1,6 +1,10 @@
import Select from "../../../../forms/Select"; import Masthead from "../../Masthead";
import ValidatorConfigDialogue from "./ValidatorConfigDialogue";
export default class UserProfile { export default class UserProfile {
readonly masthead = new Masthead();
readonly validatorConfigDialogue = new ValidatorConfigDialogue(this);
#userProfileTab = "rs-user-profile-tab"; #userProfileTab = "rs-user-profile-tab";
#attributesTab = "attributesTab"; #attributesTab = "attributesTab";
#attributesGroupTab = "attributesGroupTab"; #attributesGroupTab = "attributesGroupTab";
@ -13,25 +17,22 @@ export default class UserProfile {
#newAttributeNameInput = "attribute-name"; #newAttributeNameInput = "attribute-name";
#newAttributeDisplayNameInput = "attribute-display-name"; #newAttributeDisplayNameInput = "attribute-display-name";
#newAttributeEnabledWhen = 'input[name="enabledWhen"]'; #newAttributeEnabledWhen = 'input[name="enabledWhen"]';
#newAttributeRequiredWhen = 'input[name="requiredWhen"]';
#newAttributeEmptyValidators = ".kc-emptyValidators"; #newAttributeEmptyValidators = ".kc-emptyValidators";
#newAttributeAnnotationBtn = "annotations-add-row"; #newAttributeAnnotationBtn = "annotations-add-row";
#newAttributeAnnotationKey = "annotations.0.key"; #newAttributeAnnotationKey = "annotations.0.key";
#newAttributeAnnotationValue = "annotations.0.value"; #newAttributeAnnotationValue = "annotations.0.value";
#validatorRolesList = "#validator";
#validatorsList = 'tbody [data-label="name"]'; #validatorsList = 'tbody [data-label="name"]';
#saveNewAttributeBtn = "attribute-create"; #saveNewAttributeBtn = "attribute-create";
#addValidatorBtn = "addValidator"; #addValidatorBtn = "addValidator";
#saveValidatorBtn = "save-validator-role-button";
#removeValidatorBtn = "deleteValidator"; #removeValidatorBtn = "deleteValidator";
#deleteValidatorBtn = "confirm"; #deleteValidatorBtn = "confirm";
#cancelAddingValidatorBtn = "cancel-validator-role-button";
#cancelRemovingValidatorBtn = "cancel"; #cancelRemovingValidatorBtn = "cancel";
#newAttributeRequiredField = "input#kc-required.pf-c-switch__input"; #newAttributeRequiredField = "input#kc-required.pf-c-switch__input";
#newAttributeUserEdit = "user-edit"; #newAttributeUserEdit = "user-edit";
#newAttributeAdminEdit = "admin-edit"; #newAttributeAdminEdit = "admin-edit";
#newAttributeUserView = "user-view"; #newAttributeUserView = "user-view";
#newAttributeAdminView = "admin-view"; #newAttributeAdminView = "admin-view";
#createAttributesGroupButton = "create-attributes-groups-action";
#newAttributesGroupNameInput = "input#kc-name"; #newAttributesGroupNameInput = "input#kc-name";
#newAttributesGroupDisplayNameInput = 'input[name="displayHeader"]'; #newAttributesGroupDisplayNameInput = 'input[name="displayHeader"]';
#saveNewAttributesGroupBtn = "saveGroupBtn"; #saveNewAttributesGroupBtn = "saveGroupBtn";
@ -56,7 +57,7 @@ export default class UserProfile {
return this; return this;
} }
createAttributeButtonClick() { clickOnCreateAttributeButton() {
cy.findByTestId(this.#createAttributeButton).click(); cy.findByTestId(this.#createAttributeButton).click();
return this; return this;
} }
@ -81,7 +82,7 @@ export default class UserProfile {
return this; return this;
} }
createAttribute(name: string, displayName: string) { setAttributeNames(name: string, displayName: string) {
cy.findByTestId(this.#newAttributeNameInput).type(name); cy.findByTestId(this.#newAttributeNameInput).type(name);
cy.findByTestId(this.#newAttributeDisplayNameInput).type(displayName); cy.findByTestId(this.#newAttributeDisplayNameInput).type(displayName);
return this; return this;
@ -97,23 +98,21 @@ export default class UserProfile {
return this; return this;
} }
createAttributeNotRequiredWithPermissions(name: string, displayName: string) { setAttributeRequired() {
cy.findByTestId(this.#newAttributeNameInput).type(name); cy.get(this.#newAttributeRequiredField).first().check({ force: true });
cy.findByTestId(this.#newAttributeDisplayNameInput).type(displayName);
cy.get(this.#newAttributeEnabledWhen).first().check();
cy.findByTestId(this.#newAttributeUserEdit).first().check({ force: true });
cy.findByTestId(this.#newAttributeUserView).first().check({ force: true });
cy.findByTestId(this.#newAttributeAdminView).first().check({ force: true });
return this; return this;
} }
createAttributeNotRequiredWithoutPermissions( setAllAttributePermissions() {
name: string, cy.findByTestId(this.#newAttributeUserEdit).first().check({ force: true });
displayName: string, cy.findByTestId(this.#newAttributeUserView).first().check({ force: true });
) { cy.findByTestId(this.#newAttributeAdminView).first().check({ force: true });
cy.findByTestId(this.#newAttributeNameInput).type(name);
cy.findByTestId(this.#newAttributeDisplayNameInput).type(displayName); return this;
cy.get(this.#newAttributeEnabledWhen).first().check(); }
setNoAttributePermissions() {
cy.findByTestId(this.#newAttributeAdminEdit) cy.findByTestId(this.#newAttributeAdminEdit)
.first() .first()
.uncheck({ force: true }); .uncheck({ force: true });
@ -121,15 +120,8 @@ export default class UserProfile {
return this; return this;
} }
createAttributeRequiredWithPermissions(name: string, displayName: string) { clickOnCreatesAttributesGroupButton() {
cy.findByTestId(this.#newAttributeNameInput).type(name); cy.findByTestId(this.#createAttributesGroupButton).click();
cy.findByTestId(this.#newAttributeDisplayNameInput).type(displayName);
cy.get(this.#newAttributeEnabledWhen).first().check();
cy.get(this.#newAttributeRequiredField).first().check({ force: true });
cy.get(this.#newAttributeRequiredWhen).first().check({ force: true });
cy.findByTestId(this.#newAttributeUserEdit).first().check({ force: true });
cy.findByTestId(this.#newAttributeUserView).first().check({ force: true });
cy.findByTestId(this.#newAttributeAdminView).first().check({ force: true });
return this; return this;
} }
@ -149,6 +141,17 @@ export default class UserProfile {
return this; return this;
} }
setAttributeGroup(group: string) {
cy.get("#kc-attributeGroup").click();
cy.get("button.pf-c-select__menu-item").contains(group).click();
return this;
}
resetAttributeGroup() {
return this.setAttributeGroup("None");
}
editAttribute(displayName: string) { editAttribute(displayName: string) {
cy.findByTestId(this.#newAttributeDisplayNameInput) cy.findByTestId(this.#newAttributeDisplayNameInput)
.click() .click()
@ -162,10 +165,9 @@ export default class UserProfile {
return this; return this;
} }
addValidator() { addValidator(type: string) {
cy.findByTestId(this.#addValidatorBtn).click(); this.clickAddValidator().selectValidatorType(type).clickSave();
Select.selectItem(cy.get(this.#validatorRolesList), "email");
cy.findByTestId(this.#saveValidatorBtn).click();
return this; return this;
} }
@ -175,13 +177,18 @@ export default class UserProfile {
return this; return this;
} }
cancelAddingValidator() { cancelAddingValidator(type: string) {
cy.findByTestId(this.#addValidatorBtn).click(); this.clickAddValidator().selectValidatorType(type).clickCancel();
Select.selectItem(cy.get(this.#validatorRolesList), "email");
cy.findByTestId(this.#cancelAddingValidatorBtn).click();
return this; return this;
} }
clickAddValidator() {
cy.findByTestId(this.#addValidatorBtn).click();
return this.validatorConfigDialogue;
}
cancelRemovingValidator() { cancelRemovingValidator() {
cy.findByTestId(this.#removeValidatorBtn).click(); cy.findByTestId(this.#removeValidatorBtn).click();
cy.findByTestId(this.#cancelRemovingValidatorBtn).click(); cy.findByTestId(this.#cancelRemovingValidatorBtn).click();
@ -201,6 +208,14 @@ export default class UserProfile {
return this; return this;
} }
assertNotificationSaved() {
this.masthead.checkNotificationMessage(
"Success! User Profile configuration has been saved.",
);
return this;
}
shouldHaveText(text: string) { shouldHaveText(text: string) {
this.#getText().should("have.text", text); this.#getText().should("have.text", text);
return this; return this;

View file

@ -0,0 +1,46 @@
import UserProfile from "./UserProfile";
import Select from "../../../../forms/Select";
export default class ValidatorConfigDialogue {
readonly #validatorSelector = "#validator";
readonly #saveValidatorButton = "save-validator-role-button";
readonly #cancelValidatorButton = "cancel-validator-role-button";
readonly #addValue = "addValue";
readonly userProfile: UserProfile;
constructor(userProfile: UserProfile) {
this.userProfile = userProfile;
}
clickSave() {
cy.findByTestId(this.#saveValidatorButton).click();
return this.userProfile;
}
selectValidatorType(type: string) {
Select.selectItem(cy.get(this.#validatorSelector), type);
return this;
}
setListFieldValues(fieldName: string, values: string[]) {
for (let i = 0; i < values.length; i++) {
if (i != 0) {
cy.findByTestId(this.#addValue).click();
}
const testId = `config.options${i}`;
cy.findByTestId(testId).clear().type(values[i]);
}
return this;
}
clickCancel() {
cy.findByTestId(this.#cancelValidatorButton).click();
return this.userProfile;
}
}

View file

@ -1,34 +1,33 @@
import Masthead from "../../Masthead";
import FormValidation from "../../../../forms/FormValidation";
export default class CreateUserPage { export default class CreateUserPage {
usernameInput: string; readonly masthead = new Masthead();
readonly emptyOptionValue = "Choose...";
usersEmptyState: string; usersEmptyState: string;
emptyStateCreateUserBtn: string; emptyStateCreateUserBtn: string;
addUserBtn: string; addUserBtn: string;
joinGroupsBtn: string; joinGroupsBtn: string;
joinBtn: string; joinBtn: string;
createBtn: string;
saveBtn: string; saveBtn: string;
cancelBtn: string; cancelBtn: string;
constructor() { constructor() {
this.usernameInput = "#username";
this.usersEmptyState = "empty-state"; this.usersEmptyState = "empty-state";
this.emptyStateCreateUserBtn = "no-users-found-empty-action"; this.emptyStateCreateUserBtn = "no-users-found-empty-action";
this.addUserBtn = "add-user"; this.addUserBtn = "add-user";
this.joinGroupsBtn = "join-groups-button"; this.joinGroupsBtn = "join-groups-button";
this.joinBtn = "join-button"; this.joinBtn = "join-button";
this.saveBtn = "create-user"; this.createBtn = "create-user";
this.saveBtn = "save-user";
this.cancelBtn = "cancel-create-user"; this.cancelBtn = "cancel-create-user";
} }
//#region General Settings //#region General Settings
createUser(username: string) { createUser(username: string) {
cy.get(this.usernameInput).clear(); return this.setUsername(username);
if (username) {
cy.get(this.usernameInput).type(username);
}
return this;
} }
goToCreateUser() { goToCreateUser() {
@ -55,12 +54,177 @@ export default class CreateUserPage {
return this; return this;
} }
save() { create() {
cy.findByTestId(this.createBtn).click();
return this;
}
update() {
cy.findByTestId(this.saveBtn).click(); cy.findByTestId(this.saveBtn).click();
return this; return this;
} }
assertAttributeValue(attrName: string, expectedValue: string) {
cy.findByTestId(attrName).should("have.value", expectedValue);
return this;
}
assertAttributeFieldExists(attrName: string, shouldExist: boolean) {
const chainer = shouldExist ? "exist" : "not.exist";
cy.findByTestId(attrName).should(chainer);
return this;
}
assertAttributeSelect(
attrName: string,
expectedOptionsWithoutEmptyOption: string[],
expectedValue: string,
) {
this.#getSelectFieldButton(attrName).should(
"have.class",
"pf-c-select__toggle",
);
const valueToCheck = expectedValue ? expectedValue : this.emptyOptionValue;
this.#getSelectFieldButton(attrName)
.find(".pf-c-select__toggle-text")
.invoke("text")
.should("eq", valueToCheck);
const expectedOptions = [this.emptyOptionValue].concat(
expectedOptionsWithoutEmptyOption,
);
this.#withSelectExpanded(attrName, () => {
this.#getSelectOptions(attrName)
.should("have.length", expectedOptions.length)
.each(($option, index) =>
cy.wrap($option).should("have.text", expectedOptions[index]),
);
});
return this;
}
#getSelectFieldButton(attrName: string) {
const attrSelector = `#${attrName}`;
return cy.get(attrSelector);
}
#getSelectOptions(attrName: string) {
return this.#getSelectFieldButton(attrName)
.parent()
.find(".pf-c-select__menu-item");
}
#toggleSelectField(
attrName: string,
toggleCondition?: (currentlyExpanded: boolean) => boolean,
) {
return this.#getSelectFieldButton(attrName).then(($selectField) => {
const currentlyExpanded = $selectField.attr("aria-expanded") === "true";
if (!toggleCondition || toggleCondition(currentlyExpanded)) {
cy.wrap($selectField).click();
}
});
}
/**
* Runs the given function in the context of an expanded select field.
*
* This method makes sure that the initial expanded/collapsed state is preserved:
* The select field will be expanded before running the function, if it is not already expanded.
* It will be collapsed after running the function, when it was not expanded before running the function.
*
* @param attrName the attribute name of the select field
* @param func the function to be applied
* @private
*/
#withSelectExpanded(attrName: string, func: () => any) {
let wasInitiallyExpanded = false;
this.#toggleSelectField(attrName, (currentlyExpanded) => {
wasInitiallyExpanded = currentlyExpanded;
return !currentlyExpanded;
})
.then(() => func())
.then(() =>
// click again on the dropdown to hide the values list, when necessary
this.#toggleSelectField(
attrName,
(currentlyExpanded) => currentlyExpanded && !wasInitiallyExpanded,
),
);
}
assertAttributeLabel(attrName: string, expectedText: string) {
cy.get(`.pf-c-form__label[for='${attrName}'] .pf-c-form__label-text`)
.contains(expectedText)
.should("exist");
return this;
}
assertValidationErrorRequired(attrName: string) {
FormValidation.assertMessage(
cy.findByTestId(attrName),
`Please specify '${attrName}'.`,
);
return this;
}
assertGroupDisplayName(group: string, expectedDisplayName: string) {
cy.get(`h1#${group.toLowerCase()}`).should(
"have.text",
expectedDisplayName,
);
return this;
}
setAttributeValue(attrName: string, value: string) {
cy.findByTestId(attrName).clear().type(value);
return this;
}
setAttributeValueOnSelect(attrName: string, value: string) {
this.#withSelectExpanded(attrName, () => {
this.#getSelectOptions(attrName).contains(value).click();
});
return this;
}
setUsername(value: string) {
this.#getUsernameField().clear();
if (value) {
this.#getUsernameField().type(value);
}
return this;
}
#getUsernameField() {
return cy.findByTestId("username");
}
assertNotificationCreated() {
this.masthead.checkNotificationMessage("The user has been created");
return this;
}
assertNotificationUpdated() {
this.masthead.checkNotificationMessage("The user has been saved");
return this;
}
cancel() { cancel() {
cy.findByTestId(this.cancelBtn).click(); cy.findByTestId(this.cancelBtn).click();

View file

@ -245,6 +245,18 @@ class AdminClient {
}); });
} }
async getUserProfile(realm: string) {
await this.#login();
return await this.#client.users.getProfile({ realm });
}
async updateUserProfile(realm: string, userProfile: UserProfileConfig) {
await this.#login();
await this.#client.users.updateProfile(merge(userProfile, { realm }));
}
async patchUserProfile(realm: string, payload: UserProfileConfig) { async patchUserProfile(realm: string, payload: UserProfileConfig) {
await this.#login(); await this.#login();

View file

@ -75,7 +75,11 @@ export const AttributesGroupTab = () => {
<ToolbarItem> <ToolbarItem>
<Button <Button
component={(props) => ( component={(props) => (
<Link {...props} to={toNewAttributesGroup({ realm })} /> <Link
data-testid="create-attributes-groups-action"
{...props}
to={toNewAttributesGroup({ realm })}
/>
)} )}
> >
{t("createGroupText")} {t("createGroupText")}