diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html index 4237f7dce4b..04c2339238e 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-mappers-add.html @@ -37,7 +37,7 @@ {{mapper.name}} {{mapperTypes[mapper.protocolMapper].category}} {{mapperTypes[mapper.protocolMapper].name}} - + {{:: 'no-mappers-available' | translate}} diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/required-actions.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/required-actions.html index 0161a3011eb..8a81237f4d1 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/required-actions.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/required-actions.html @@ -20,8 +20,8 @@ {{requiredAction.name}} - - + + No required actions configured diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/authentication/RequiredActions.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/authentication/RequiredActions.java index 0ea6af2b514..b6f182a5b4c 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/authentication/RequiredActions.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/authentication/RequiredActions.java @@ -7,11 +7,17 @@ import org.openqa.selenium.support.FindBy; /** * @author tkyjovsk * @author mhajas + * @author Vaclav Muzikar */ public class RequiredActions extends Authentication { - public final static String ENABLED = "enabled"; - public final static String DEFAULT_ACTION = "defaultAction"; + public final static String ENABLED = ".enabled"; + public final static String DEFAULT = ".defaultAction"; + public final static String CONFIGURE_TOTP = "CONFIGURE_TOTP"; + public final static String UPDATE_PROFILE = "UPDATE_PROFILE"; + public final static String TERMS_AND_CONDITIONS = "terms_and_conditions"; + public final static String UPDATE_PASSWORD = "UPDATE_PASSWORD"; + public final static String VERIFY_EMAIL = "VERIFY_EMAIL"; @FindBy(tagName = "table") private WebElement requiredActionTable; @@ -21,51 +27,59 @@ public class RequiredActions extends Authentication { return super.getUriFragment() + "/required-actions"; } - private void setRequiredActionValue(String row, String column, boolean value) { - WebElement checkbox = requiredActionTable.findElement(By.xpath("//td[text()='" + row + "']/..//input[@ng-model='requiredAction." + column + "']")); + private void setRequiredActionValue(String id, boolean value) { + WebElement checkbox = requiredActionTable.findElement(By.id(id)); if (checkbox.isSelected() != value) { checkbox.click(); } } + private void setRequiredActionEnabledValue(String id, boolean value) { + setRequiredActionValue(id + ENABLED, value); + } + + private void setRequiredActionDefaultValue(String id, boolean value) { + setRequiredActionValue(id + DEFAULT, value); + } + public void setTermsAndConditionEnabled(boolean value) { - setRequiredActionValue("Terms and Conditions", ENABLED, value); + setRequiredActionEnabledValue(TERMS_AND_CONDITIONS, value); } public void setTermsAndConditionDefaultAction(boolean value) { - setRequiredActionValue("Terms and Conditions", DEFAULT_ACTION, value); + setRequiredActionDefaultValue(TERMS_AND_CONDITIONS, value); } public void setVerifyEmailEnabled(boolean value) { - setRequiredActionValue("Verify Email", ENABLED, value); + setRequiredActionEnabledValue(VERIFY_EMAIL, value); } public void setVerifyEmailDefaultAction(boolean value) { - setRequiredActionValue("Verify Email", DEFAULT_ACTION, value); + setRequiredActionDefaultValue(VERIFY_EMAIL, value); } public void setUpdatePasswordEnabled(boolean value) { - setRequiredActionValue("Update Password", ENABLED, value); + setRequiredActionEnabledValue(UPDATE_PASSWORD, value); } public void setUpdatePasswordDefaultAction(boolean value) { - setRequiredActionValue("Update Password", DEFAULT_ACTION, value); + setRequiredActionDefaultValue(UPDATE_PASSWORD, value); } public void setConfigureTotpEnabled(boolean value) { - setRequiredActionValue("Configure Totp", ENABLED, value); + setRequiredActionEnabledValue(CONFIGURE_TOTP, value); } public void setConfigureTotpDefaultAction(boolean value) { - setRequiredActionValue("Configure Totp", DEFAULT_ACTION, value); + setRequiredActionDefaultValue(CONFIGURE_TOTP, value); } public void setUpdateProfileEnabled(boolean value) { - setRequiredActionValue("Update Profile", ENABLED, value); + setRequiredActionEnabledValue(UPDATE_PROFILE, value); } public void setUpdateProfileDefaultAction(boolean value) { - setRequiredActionValue("Update Profile", DEFAULT_ACTION, value); + setRequiredActionDefaultValue(UPDATE_PROFILE, value); } } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/ClientMappers.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/ClientMappers.java index d56dca5482c..10fb7e5f897 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/ClientMappers.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/ClientMappers.java @@ -1,14 +1,112 @@ package org.keycloak.testsuite.console.page.clients; +import org.keycloak.representations.idm.ProtocolMapperRepresentation; +import org.keycloak.testsuite.console.page.fragment.DataTable; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; + +import java.util.ArrayList; +import java.util.List; + /** * * @author tkyjovsk + * @author Vaclav Muzikar */ public class ClientMappers extends Client { + public static final String ADD_BUILTIN = "Add Builtin"; + + @FindBy(tagName = "table") + private ClientMapperTable table; + @Override public String getUriFragment() { return super.getUriFragment() + "/mappers"; } + public ClientMapperTable mapperTable() { + return table; + } + + public class ClientMapperTable extends DataTable { + + public List searchMappings(String searchPattern) { + search(searchPattern); + return getMappingsFromRows(); + } + + public void createMapper() { + waitAjaxForBody(); + clickHeaderLink(CREATE); + } + + public void addBuiltin() { + waitAjaxForBody(); + clickHeaderLink(ADD_BUILTIN); + } + + public void clickMapper(String mapperName) { + waitAjaxForBody(); + body().findElement(By.linkText(mapperName)).click(); + } + + public void clickMapper(ProtocolMapperRepresentation mapper) { + clickMapper(mapper.getName()); + } + + private void clickMapperActionButton(String mapperName, String buttonText) { + waitAjaxForBody(); + clickRowActionButton(getRowByLinkText(mapperName), buttonText); + } + + private void clickMapperActionButton(ProtocolMapperRepresentation mapper, String buttonName) { + clickMapperActionButton(mapper.getName(), buttonName); + } + + public void editMapper(String mapperName) { + clickMapperActionButton(mapperName, EDIT); + } + + public void editMapper(ProtocolMapperRepresentation mapper) { + clickMapperActionButton(mapper, EDIT); + } + + public void deleteMapper(String mapperName) { + clickMapperActionButton(mapperName, DELETE); + } + + public void deleteMapper(ProtocolMapperRepresentation mapper) { + clickMapperActionButton(mapper, DELETE); + } + + public ProtocolMapperRepresentation getMappingFromRow(WebElement row) { + if (!row.isDisplayed()) {return null;} // Is that necessary? + + ProtocolMapperRepresentation mappingsRepresentation = new ProtocolMapperRepresentation(); + List cols = row.findElements(By.tagName("td")); + + + mappingsRepresentation.setName(cols.get(0).getText()); + //mappingsRepresentation.setProtocol(cols.get(1).getText()); + mappingsRepresentation.setProtocolMapper(cols.get(2).getText()); + + return mappingsRepresentation; + } + + public List getMappingsFromRows() { + List mappings = new ArrayList(); + + for (WebElement row : rows()) { + ProtocolMapperRepresentation mapperRepresentation = getMappingFromRow(row); + if (mapperRepresentation != null) { + mappings.add(mapperRepresentation); + } + } + + return mappings; + } + } + } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientMappers.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientMappers.java new file mode 100644 index 00000000000..962e7a51a18 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientMappers.java @@ -0,0 +1,21 @@ +package org.keycloak.testsuite.console.page.clients; + +import org.jboss.arquillian.graphene.page.Page; +import org.keycloak.testsuite.console.page.AdminConsoleCreate; + +/** + * @author Vaclav Muzikar + */ +public class CreateClientMappers extends AdminConsoleCreate { + + @Page + private CreateClientMappersForm form; + + public CreateClientMappers() { + setEntity("mappers"); + } + + public CreateClientMappersForm form() { + return form; + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientMappersForm.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientMappersForm.java new file mode 100644 index 00000000000..900b4d207a6 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientMappersForm.java @@ -0,0 +1,187 @@ +package org.keycloak.testsuite.console.page.clients; + +import org.jboss.arquillian.test.api.ArquillianResource; +import org.keycloak.testsuite.console.page.fragment.OnOffSwitch; +import org.keycloak.testsuite.page.Form; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.ui.Select; + +import java.util.List; + +/** + * @author Vaclav Muzikar + * + * TODO: SAML + */ +public class CreateClientMappersForm extends Form { + + // Mappers types + public static final String HARDCODED_ROLE = "Hardcoded Role"; + public static final String HARDCODED_CLAIM = "Hardcoded claim"; + public static final String USER_SESSION_NOTE = "User Session Note"; + public static final String ROLE_NAME_MAPPER = "Role Name Mapper"; + public static final String USER_ADDRESS = "User Address"; + public static final String USERS_FULL_NAME = "User's full name"; + public static final String USER_ATTRIBUTE = "User Attribute"; + public static final String USER_PROPERTY = "User Property"; + + @FindBy(id = "name") + private WebElement nameElement; + + @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='consentRequired']]") + private OnOffSwitch consentRequiredSwitch; + + @FindBy(id = "consentText") + private WebElement consentTextElement; + + @FindBy(id = "mapperTypeCreate") + private Select mapperTypeSelect; + + @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Property']//following-sibling::node()//input[@type='text']") + private WebElement propertyInput; + + @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='User Attribute']//following-sibling::node()//input[@type='text']") + private WebElement userAttributeInput; + + @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='User Session Note']//following-sibling::node()//input[@type='text']") + private WebElement userSessionNoteInput; + + @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Multivalued']//following-sibling::node()//div[@class='onoffswitch']") + private OnOffSwitch multivaluedInput; + + @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Role']//following-sibling::node()//input[@type='text']") + private WebElement roleInput; + + @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='New Role Name']//following-sibling::node()//input[@type='text']") + private WebElement newRoleInput; + + @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Token Claim Name']//following-sibling::node()//input[@type='text']") + private WebElement tokenClaimNameInput; + + @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Claim value']//following-sibling::node()//input[@type='text']") + private WebElement tokenClaimValueInput; + + @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Claim JSON Type']//following-sibling::node()//select") + private Select claimJSONTypeInput; + + @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Add to ID token']//following-sibling::node()//div[@class='onoffswitch']") + private OnOffSwitch addToIDTokenInput; + + @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Add to access token']//following-sibling::node()//div[@class='onoffswitch']") + private OnOffSwitch addToAccessTokenInput; + + public boolean isConsentRequired() { + return consentRequiredSwitch.isOn(); + } + + public void setConsentRequired(boolean consentRequired) { + consentRequiredSwitch.setOn(consentRequired); + } + + public String getConsentText() { + return getInputValue(consentTextElement); + } + + public void setConsentText(String consentText) { + setInputValue(consentTextElement, consentText); + } + + public String getMapperType() { + return mapperTypeSelect.getFirstSelectedOption().getText(); + } + + public void setMapperType(String type) { + mapperTypeSelect.selectByVisibleText(type); + } + + public String getProperty() { + return getInputValue(propertyInput); + } + + public void setProperty(String value) { + setInputValue(propertyInput, value); + } + + public String getUserAttribute() { + return getInputValue(userAttributeInput); + } + + public void setUserAttribute(String value) { + setInputValue(userAttributeInput, value); + } + + public String getUserSessionNote() { + return getInputValue(userSessionNoteInput); + } + + public void setUserSessionNote(String value) { + setInputValue(userSessionNoteInput, value); + } + + public boolean isMultivalued() { + return multivaluedInput.isOn(); + } + + public void setMultivalued(boolean value) { + multivaluedInput.setOn(value); + } + + public String getRole() { + return getInputValue(roleInput); + } + + public void setRole(String value) { + setInputValue(roleInput, value); + } + + public String getNewRole() { + return getInputValue(newRoleInput); + } + + public void setNewRole(String value) { + setInputValue(newRoleInput, value); + } + + public String getTokenClaimName() { + return getInputValue(tokenClaimNameInput); + } + + public void setTokenClaimName(String value) { + setInputValue(tokenClaimNameInput, value); + } + + public String getTokenClaimValue() { + return getInputValue(tokenClaimValueInput); + } + + public void setTokenClaimValue(String value) { + setInputValue(tokenClaimValueInput, value); + } + + public String getClaimJSONType() { + return claimJSONTypeInput.getFirstSelectedOption().getText(); + } + + public void setClaimJSONType(String value) { + claimJSONTypeInput.selectByVisibleText(value); + } + + public boolean isAddToIDToken() { + return addToIDTokenInput.isOn(); + } + + public void setAddToIDToken(boolean value) { + addToIDTokenInput.setOn(value); + } + + public boolean isAddToAccessToken() { + return addToAccessTokenInput.isOn(); + } + + public void setAddToAccessToken(boolean value) { + addToAccessTokenInput.setOn(value); + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/OnOffSwitch.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/OnOffSwitch.java index 6319c4c8207..118e0586318 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/OnOffSwitch.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/OnOffSwitch.java @@ -36,6 +36,14 @@ public class OnOffSwitch { @ArquillianResource private Actions actions; + public OnOffSwitch() { + } + + public OnOffSwitch(WebElement root, Actions actions) { + this.root = root; + this.actions = actions; + } + public boolean isOn() { waitAjaxForElement(root); return root.findElement(By.tagName("input")).isSelected();