KEYCLOAK-4488 Fix Auth Flows Console UI tests

Signed-off-by: Peter Zaoral <pzaoral@redhat.com>
This commit is contained in:
Peter Zaoral 2017-03-21 11:16:08 +01:00
parent b30b96b9a1
commit 0a8ca19944
4 changed files with 255 additions and 100 deletions

View file

@ -28,20 +28,30 @@ import org.openqa.selenium.support.ui.Select;
/** /**
* *
* @author <a href="mailto:vramik@redhat.com">Vlastislav Ramik</a> * @author <a href="mailto:vramik@redhat.com">Vlastislav Ramik</a>
* @author <a href="mailto:pzaoral@redhat.com">Peter Zaoral</a>
*/ */
public class CreateExecutionForm extends Form { public class CreateExecutionForm extends Form {
public enum ProviderOption { public enum ProviderOption {
DIRECT_GRANT_VALIDATE_USERNAME("direct-grant-validate-username"), IDENTITY_PROVIDER_REDIRECTOR("Identity Provider Redirector"),
RESET_OTP("reset-otp"), USERNAME_VALIDATION("Username Validation"),
AUTH_COOKIE("auth-cookie"), RESET_OTP("Reset OTP"),
RESET_CREDENTIALS_CHOOSE_USER("reset-credentials-choose-user"), COOKIE("Cookie"),
DIRECT_GRANT_VALIDATE_PASSWORD("direct-grant-validate-password"), CHOOSE_USER("Choose User"),
AUTH_USERNAME_PASSWORD_FORM("auth-username-password-form"), PASSWORD("Password"),
AUTH_OTP_FORM("auth-otp-form"), REVIEW_PROFILE("Review Profile"),
AUTH_SPNEGO("auth-spnego"), CONFIRM_LINK_EXISTING_ACCOUNT("Confirm Link Existing Account"),
DIRECT_GRANT_VALIDATE_OPT("direct-grant-validate-otp"), CONDITIONAL_OTP("Conditional OTP"),
RESET_CREDENTIALS_EMAIL("reset-credential-email"), USERNAME_PASSWORD("Username Password"),
RESET_PASSWORD("reset-password"); KERBEROS("Kerberos"),
SEND_RESET_EMAIL("Send Reset Email"),
RESET_PASSWORD("Reset Password"),
HTTP_BASIC_AUTHETICATION("HTTP Basic Authentication"),
OTP_FORM("OTP Form"),
USERNAME_PASSWORD_FORM_FOR_IDENTITY_PROVIDER_REAUTH("Username Password For Identity Provider Reauthentication"),
VERIFY_EXISTING_ACCOUNT_BY_EMAIL("Verify Existing Account By Email"),
SCRIPT("Script"),
OTP("OTP"),
CREATE_USER_IF_UNIQUE("Create User If Unique");
private final String name; private final String name;

View file

@ -5,9 +5,13 @@ import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.ui.Select; import org.openqa.selenium.support.ui.Select;
import java.util.List;
import java.util.stream.Collectors;
/** /**
* @author tkyjovsk * @author tkyjovsk
* @author mhajas * @author mhajas
* @author pzaoral
*/ */
public class Flows extends Authentication { public class Flows extends Authentication {
@ -19,19 +23,19 @@ public class Flows extends Authentication {
@FindBy(tagName = "select") @FindBy(tagName = "select")
private Select flowSelect; private Select flowSelect;
@FindBy(xpath = "//button[text() = 'New']") @FindBy(xpath = ".//button[@data-ng-click='createFlow()']")
private WebElement newButton; private WebElement newButton;
@FindBy(xpath = "//button[text() = 'Copy']") @FindBy(xpath = ".//button[@data-ng-click='copyFlow()']")
private WebElement copyButton; private WebElement copyButton;
@FindBy(xpath = "//button[text() = 'Delete']") @FindBy(xpath = ".//button[@data-ng-click='deleteFlow()']")
private WebElement deleteButton; private WebElement deleteButton;
@FindBy(xpath = "//button[text() = 'Add Execution']") @FindBy(xpath = ".//button[@data-ng-click='addExecution()']")
private WebElement addExecutionButton; private WebElement addExecutionButton;
@FindBy(xpath = "//button[text() = 'Add Flow']") @FindBy(xpath = ".//button[@data-ng-click='addFlow()']")
private WebElement addFlowButton; private WebElement addFlowButton;
@FindBy(tagName = "table") @FindBy(tagName = "table")
@ -39,10 +43,10 @@ public class Flows extends Authentication {
public enum FlowOption { public enum FlowOption {
DIRECT_GRANT("Direct grant"), DIRECT_GRANT("Direct Grant"),
REGISTRATION("Registration"), REGISTRATION("Registration"),
BROWSER("Browser"), BROWSER("Browser"),
RESET_CREDENTIALS("Reset credentials"), RESET_CREDENTIALS("Reset Credentials"),
CLIENTS("Clients"); CLIENTS("Clients");
private final String name; private final String name;
@ -64,6 +68,10 @@ public class Flows extends Authentication {
return flowSelect.getFirstSelectedOption().getText(); return flowSelect.getFirstSelectedOption().getText();
} }
public List<String> getFlowAllValues() {
return flowSelect.getOptions().stream().map(WebElement::getText).collect(Collectors.toList());
}
public FlowsTable table() { public FlowsTable table() {
return flowsTable; return flowsTable;
} }

View file

@ -25,11 +25,16 @@ import org.openqa.selenium.By;
import org.openqa.selenium.WebElement; import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.FindBy;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
/** /**
* *
* @author <a href="mailto:vramik@redhat.com">Vlastislav Ramik</a> * @author <a href="mailto:vramik@redhat.com">Vlastislav Ramik</a>
* @author <a href="mailto:pzaoral@redhat.com">Peter Zaoral</a>
*/ */
public class FlowsTable { public class FlowsTable {
public enum RequirementOption { public enum RequirementOption {
@ -53,8 +58,8 @@ public class FlowsTable {
public enum Action { public enum Action {
DELETE("Delete"), DELETE("Delete"),
ADD_EXECUTION("Add Execution"), ADD_EXECUTION("Add execution"),
ADD_FLOW("Add Flow"); ADD_FLOW("Add flow");
private final String name; private final String name;
@ -69,26 +74,51 @@ public class FlowsTable {
@FindBy(tagName = "tbody") @FindBy(tagName = "tbody")
private WebElement tbody; private WebElement tbody;
private WebElement getRowByLabelText(String text) { private WebElement getRowByLabelText(String text) {
WebElement row = tbody.findElement(By.xpath("//span[text() = '" + text + "']/../..")); WebElement row = tbody.findElement(By.xpath("//span[text() = '" + text + "']/../.."));
//tbody.findElement(By.xpath("//span[contains(text(),\"" + text + "\")]/../.."));
waitUntilElement(row).is().present(); waitUntilElement(row).is().present();
return row; return row;
} }
public void clickLevelUpButton(String rowLabel) { public void clickLevelUpButton(String rowLabel) {
getRowByLabelText(rowLabel).findElement(By.xpath("//i[contains(@class, 'up')]/..")).click(); getRowByLabelText(rowLabel).findElement(By.xpath(".//button[@data-ng-click='raisePriority(execution)']")).click();
} }
public void clickLevelDownButton(String rowLabel) { public void clickLevelDownButton(String rowLabel) {
getRowByLabelText(rowLabel).findElement(By.xpath("//i[contains(@class, 'down')]/..")).click(); getRowByLabelText(rowLabel).findElement(By.xpath(".//button[@data-ng-click='lowerPriority(execution)']")).click();
} }
public void changeRequirement(String rowLabel, RequirementOption option) { public void changeRequirement(String rowLabel, RequirementOption option) {
getRowByLabelText(rowLabel).findElement(By.xpath("//input[@value = '" + option + "']")).click(); getRowByLabelText(rowLabel).findElement(By.xpath(".//input[@value = '" + option + "']")).click();
} }
public void performAction(String rowLabel, Action action) { public void performAction(String rowLabel, Action action) {
getRowByLabelText(rowLabel).findElement(
By.xpath(".//div[@class = 'dropdown']/a[@class='dropdown-toggle ng-binding']")).click();
WebElement currentAction = getRowByLabelText(rowLabel).findElement(
By.xpath("//div[@class = 'dropdown open']/ul[@class = 'dropdown-menu']/li/" +
"a[@class='ng-binding' and text()='" + action.getName() + "']"));
currentAction.click();
}
// Returns all aliases of flows (first "Auth Type" column in table) including the names of execution flows
// Each returned alias (key) has also the Requirement option (value) assigned in the Map
public Map<String, String> getFlowsAliasesWithRequirements(){
Map<String, String> flows = new LinkedHashMap<>();
List<WebElement> aliases = tbody.findElements(By.xpath("//span[@class='ng-binding']"));
for(WebElement alias : aliases)
{
List<WebElement> requirementsOptions = alias.findElements(By.xpath(".//../parent::*//input[@type='radio']"));
for (WebElement requirement : requirementsOptions) {
if (requirement.isSelected()) {
flows.put(alias.getText(), requirement.getAttribute("value"));
}
}
}
return flows;
} }
} }

View file

@ -21,10 +21,12 @@
*/ */
package org.keycloak.testsuite.console.authentication; package org.keycloak.testsuite.console.authentication;
import org.apache.commons.collections.CollectionUtils;
import org.jboss.arquillian.graphene.page.Page; import org.jboss.arquillian.graphene.page.Page;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation;
import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.testsuite.console.AbstractConsoleTest; import org.keycloak.testsuite.console.AbstractConsoleTest;
import org.keycloak.testsuite.console.page.authentication.flows.CreateExecution; import org.keycloak.testsuite.console.page.authentication.flows.CreateExecution;
import org.keycloak.testsuite.console.page.authentication.flows.CreateExecutionForm; import org.keycloak.testsuite.console.page.authentication.flows.CreateExecutionForm;
@ -33,18 +35,26 @@ import org.keycloak.testsuite.console.page.authentication.flows.CreateFlowForm;
import org.keycloak.testsuite.console.page.authentication.flows.Flows; import org.keycloak.testsuite.console.page.authentication.flows.Flows;
import org.keycloak.testsuite.console.page.authentication.flows.FlowsTable; import org.keycloak.testsuite.console.page.authentication.flows.FlowsTable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
* *
* @author <a href="mailto:vramik@redhat.com">Vlastislav Ramik</a> * @author <a href="mailto:vramik@redhat.com">Vlastislav Ramik</a>
* @author <a href="mailto:pzaoral@redhat.com">Peter Zaoral</a>
*/ */
@Ignore //waiting for KEYCLOAK-1967(KEYCLOAK-1966)
public class FlowsTest extends AbstractConsoleTest { public class FlowsTest extends AbstractConsoleTest {
@Page @Page
private Flows flowsPage; private Flows flowsPage;
@Page @Page
private CreateFlow createFlowPage; private CreateFlow createFlowPage;
@ -58,53 +68,72 @@ public class FlowsTest extends AbstractConsoleTest {
@Test @Test
public void createDeleteFlowTest() { public void createDeleteFlowTest() {
log.info("add new flow"); // Adding new flow
flowsPage.clickNew(); flowsPage.clickNew();
createFlowPage.form().setValues("testFlow", "testDesc", CreateFlowForm.FlowType.GENERIC); createFlowPage.form().setValues("testFlow", "testDesc", CreateFlowForm.FlowType.GENERIC);
assertEquals("Success! Flow Created.", createFlowPage.getSuccessMessage()); assertAlertSuccess();
log.debug("new flow created via UI");
// Checking if test flow is created via rest
AuthenticationFlowRepresentation testFlow = getLastFlowFromREST();
assertEquals("testFlow", testFlow.getAlias());
log.info("check if test flow is created via rest"); // Checking if testFlow is selected in UI
//rest: flow is present
log.debug("checked");
log.debug("check if testFlow is selected in UI");
assertEquals("TestFlow", flowsPage.getFlowSelectValue()); assertEquals("TestFlow", flowsPage.getFlowSelectValue());
log.info("add new execution flow within testFlow"); // Adding new execution flow within testFlow
flowsPage.clickAddFlow(); flowsPage.clickAddFlow();
createFlowPage.form().setValues("testExecutionFlow", "executionDesc", CreateFlowForm.FlowType.GENERIC); createFlowPage.form().setValues("testExecution", "executionDesc", CreateFlowForm.FlowType.GENERIC);
assertEquals("Success! Flow Created.", createFlowPage.getSuccessMessage()); assertAlertSuccess();
log.debug("new execution flow created via UI");
log.info("check if execution flow is created via rest"); // Checking if execution flow is created via rest
//rest: flow within nested flow is present testFlow = getLastFlowFromREST();
log.debug("checked"); assertEquals("testExecution", testFlow.getAuthenticationExecutions().get(0).getFlowAlias());
log.debug("check if testFlow is selected in UI"); // Checking if testFlow is selected in UI
assertEquals("TestFlow", flowsPage.getFlowSelectValue()); assertEquals("TestFlow", flowsPage.getFlowSelectValue());
log.info("delete test flow"); // Deleting test flow
flowsPage.clickDelete(); flowsPage.clickDelete();
assertEquals("Success! Flow removed", createFlowPage.getSuccessMessage()); modalDialog.confirmDeletion();
log.debug("test flow removed via UI"); assertAlertSuccess();
log.info("check if both test flow and execution flow is removed via rest"); // Checking if both test flow and execution flow is removed via UI
//rest assertEquals("Browser", flowsPage.getFlowSelectValue());
log.debug("checked"); assertThat(flowsPage.getFlowAllValues(), not(hasItem("TestFlow")));
// Checking if both test flow and execution flow is removed via rest
assertThat(testRealmResource().flows().getFlows(), not(hasItem(testFlow)));
} }
@Test
public void selectFlowOptionTest() {
flowsPage.selectFlowOption(Flows.FlowOption.DIRECT_GRANT);
assertEquals("Direct Grant", flowsPage.getFlowSelectValue());
flowsPage.selectFlowOption(Flows.FlowOption.BROWSER);
assertEquals("Browser", flowsPage.getFlowSelectValue());
flowsPage.selectFlowOption(Flows.FlowOption.CLIENTS);
assertEquals("Clients", flowsPage.getFlowSelectValue());
}
@Test @Test
public void createFlowWithEmptyAliasTest() { public void createFlowWithEmptyAliasTest() {
flowsPage.clickNew(); flowsPage.clickNew();
createFlowPage.form().setValues("", "testDesc", CreateFlowForm.FlowType.GENERIC); createFlowPage.form().setValues("", "testDesc", CreateFlowForm.FlowType.GENERIC);
assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", createFlowPage.getErrorMessage()); assertAlertDanger();
//rest:flow isn't present //rest:flow isn't present
//best-efford: check empty alias in nested flow
} }
@Test
public void createNestedFlowWithEmptyAliasTest() {
//best-effort: check empty alias in nested flow
flowsPage.clickNew();
createFlowPage.form().setValues("testFlow", "testDesc", CreateFlowForm.FlowType.GENERIC);
flowsPage.clickAddFlow();
createFlowPage.form().setValues("", "executionDesc", CreateFlowForm.FlowType.GENERIC);
assertAlertDanger();
}
@Test @Test
public void copyFlowTest() { public void copyFlowTest() {
flowsPage.selectFlowOption(Flows.FlowOption.BROWSER); flowsPage.selectFlowOption(Flows.FlowOption.BROWSER);
@ -112,86 +141,164 @@ public class FlowsTest extends AbstractConsoleTest {
modalDialog.setName("test copy of browser"); modalDialog.setName("test copy of browser");
modalDialog.ok(); modalDialog.ok();
assertEquals("Success! Flow copied.", createFlowPage.getSuccessMessage()); assertAlertSuccess();
//UI
assertEquals("Test Copy Of Browser", flowsPage.getFlowSelectValue());
assertTrue(flowsPage.table().getFlowsAliasesWithRequirements().containsKey("Test Copy Of Browser Forms"));
assertEquals(6,flowsPage.table().getFlowsAliasesWithRequirements().size());
//rest: copied flow present //rest: copied flow present
assertThat(testRealmResource().flows().getFlows().stream()
.map(AuthenticationFlowRepresentation::getAlias).
collect(Collectors.toList()), hasItem(getLastFlowFromREST().getAlias()));
} }
@Test @Test
public void createDeleteExecutionTest() { public void createDeleteExecutionTest() {
//rest: add new flow // Adding new execution within testFlow
log.info("add new execution within testFlow"); flowsPage.clickNew();
createFlowPage.form().setValues("testFlow", "testDesc", CreateFlowForm.FlowType.GENERIC);
flowsPage.clickAddExecution(); flowsPage.clickAddExecution();
createExecutionPage.form().selectProviderOption(CreateExecutionForm.ProviderOption.RESET_PASSWORD); createExecutionPage.form().selectProviderOption(CreateExecutionForm.ProviderOption.RESET_PASSWORD);
createExecutionPage.form().save(); createExecutionPage.form().save();
assertAlertSuccess();
assertEquals("Success! Execution Created.", createExecutionPage.getSuccessMessage()); // REST
log.debug("new execution flow created via UI"); assertEquals(1, getLastFlowFromREST().getAuthenticationExecutions().size());
assertEquals("reset-password", getLastFlowFromREST().getAuthenticationExecutions().get(0).getAuthenticator());
//rest:check new execution
// UI
log.debug("check if testFlow is selected in UI");
assertEquals("TestFlow", flowsPage.getFlowSelectValue()); assertEquals("TestFlow", flowsPage.getFlowSelectValue());
assertEquals(1,flowsPage.table().getFlowsAliasesWithRequirements().size());
log.info("delete test flow"); assertTrue(flowsPage.table().getFlowsAliasesWithRequirements().keySet().contains("Reset Password"));
// Deletion
flowsPage.clickDelete(); flowsPage.clickDelete();
assertEquals("Success! Flow removed", createFlowPage.getSuccessMessage()); modalDialog.confirmDeletion();
log.debug("test flow removed via UI"); assertAlertSuccess();
assertThat(flowsPage.getFlowAllValues(), not(hasItem("TestFlow")));
log.info("check if both test flow and execution flow is removed via rest");
//rest
log.debug("checked");
} }
@Test @Test
public void navigationTest() { public void navigationTest() {
//rest: add or copy flow to test navigation (browser) flowsPage.selectFlowOption(Flows.FlowOption.BROWSER);
flowsPage.clickCopy();
modalDialog.ok();
//rest: //init order
log.debug("check if there is expected structure of the flow");
//first should be Cookie //first should be Cookie
//second Kerberos //second Kerberos
//third Test Copy Of Browser Forms //third Identity provider redirector
//fourth Test Copy Of Browser Forms
//a) Username Password Form //a) Username Password Form
//b) OTP Form //b) OTP Form
flowsPage.table().clickLevelDownButton("Cookie"); flowsPage.table().clickLevelDownButton("Cookie");
assertEquals("Success! Priority lowered", flowsPage.getSuccessMessage()); assertAlertSuccess();
flowsPage.table().clickLevelUpButton("Test Copy Of Browser Forms"); flowsPage.table().clickLevelUpButton("Cookie");
assertEquals("Success! Priority raised", flowsPage.getSuccessMessage()); assertAlertSuccess();
flowsPage.table().clickLevelUpButton("OTP Forms"); flowsPage.table().clickLevelUpButton("Kerberos");
assertEquals("Success! Priority raised", flowsPage.getSuccessMessage()); assertAlertSuccess();
//rest:check if navigation was changed properly flowsPage.table().clickLevelDownButton("Identity Provider Redirector");
assertAlertSuccess();
flowsPage.table().clickLevelUpButton("OTP Form");
assertAlertSuccess();
List<String> expectedOrder = new ArrayList<>();
Collections.addAll(expectedOrder, "Kerberos", "Cookie", "Copy Of Browser Forms", "OTP Form",
"Username Password Form", "Identity Provider Redirector");
//UI
assertEquals(6,flowsPage.table().getFlowsAliasesWithRequirements().size());
assertTrue(expectedOrder.containsAll(flowsPage.table().getFlowsAliasesWithRequirements().keySet()));
//REST
assertEquals("auth-spnego", getLastFlowFromREST().getAuthenticationExecutions().get(0).getAuthenticator());
assertEquals("auth-cookie", getLastFlowFromREST().getAuthenticationExecutions().get(1).getAuthenticator());
assertEquals("Copy of browser forms", getLastFlowFromREST().getAuthenticationExecutions().get(2).getFlowAlias());
assertEquals("identity-provider-redirector", getLastFlowFromREST().getAuthenticationExecutions().get(3).getAuthenticator());
flowsPage.clickDelete();
modalDialog.confirmDeletion();
} }
@Test @Test
public void requirementTest() { public void requirementTest() {
//rest: add or copy flow to test navigation (browser), add reset, password //rest: add or copy flow to test navigation (browser), add reset, password
flowsPage.selectFlowOption(Flows.FlowOption.BROWSER);
flowsPage.table().changeRequirement("Cookie", FlowsTable.RequirementOption.DISABLED); flowsPage.table().changeRequirement("Cookie", FlowsTable.RequirementOption.DISABLED);
assertAlertSuccess();
flowsPage.table().changeRequirement("Kerberos", FlowsTable.RequirementOption.REQUIRED);
assertAlertSuccess();
flowsPage.table().changeRequirement("Kerberos", FlowsTable.RequirementOption.ALTERNATIVE); flowsPage.table().changeRequirement("Kerberos", FlowsTable.RequirementOption.ALTERNATIVE);
flowsPage.table().changeRequirement("Copy Of Browser Forms", FlowsTable.RequirementOption.REQUIRED); assertAlertSuccess();
flowsPage.table().changeRequirement("Reset Password", FlowsTable.RequirementOption.REQUIRED); flowsPage.table().changeRequirement("OTP Form", FlowsTable.RequirementOption.DISABLED);
assertAlertSuccess();
flowsPage.table().changeRequirement("OTP Form", FlowsTable.RequirementOption.OPTIONAL);
assertAlertSuccess();
//UI
List<String> expectedOrder = new ArrayList<>();
Collections.addAll(expectedOrder,"DISABLED", "ALTERNATIVE", "ALTERNATIVE",
"ALTERNATIVE", "REQUIRED", "OPTIONAL");
assertTrue(expectedOrder.containsAll(flowsPage.table().getFlowsAliasesWithRequirements().values()));
//rest:check //REST:
List<AuthenticationExecutionExportRepresentation> browserFlow = testRealmResource().flows()
.getFlows().get(0).getAuthenticationExecutions();
assertEquals("DISABLED", browserFlow.get(0).getRequirement());
assertEquals("ALTERNATIVE", browserFlow.get(1).getRequirement());
assertEquals("ALTERNATIVE", browserFlow.get(2).getRequirement());
} }
@Test @Test
public void actionsTest() { public void actionsTest() {
//rest: add or copy flow to test navigation (browser) //rest: add or copy flow to test navigation (browser)
flowsPage.selectFlowOption(Flows.FlowOption.BROWSER);
flowsPage.clickCopy();
modalDialog.ok();
flowsPage.table().performAction("Cookie", FlowsTable.Action.DELETE);
modalDialog.confirmDeletion();
assertAlertSuccess();
flowsPage.table().performAction("Kerberos", FlowsTable.Action.DELETE); flowsPage.table().performAction("Kerberos", FlowsTable.Action.DELETE);
modalDialog.confirmDeletion();
assertAlertSuccess();
flowsPage.table().performAction("Copy Of Browser Forms", FlowsTable.Action.ADD_FLOW); flowsPage.table().performAction("Copy Of Browser Forms", FlowsTable.Action.ADD_FLOW);
createFlowPage.form().setValues("nestedFlow", "testDesc", CreateFlowForm.FlowType.FORM);
createFlowPage.form().setValues("nestedFlow", "", CreateFlowForm.FlowType.CLIENT); assertAlertSuccess();
flowsPage.table().performAction("Copy Of Browser Forms",FlowsTable.Action.ADD_EXECUTION);
//todo: perform all remaining actions createExecutionPage.form().selectProviderOption(CreateExecutionForm.ProviderOption.RESET_PASSWORD);
createExecutionPage.form().save();
//rest: check assertAlertSuccess();
//UI
List<String> expectedOrder = new ArrayList<>();
Collections.addAll(expectedOrder, "Identity Provider Redirector", "Copy Of Browser Forms",
"Username Password Form", "OTP Form", "NestedFlow", "Reset Password");
assertEquals(6,flowsPage.table().getFlowsAliasesWithRequirements().size());
assertTrue(expectedOrder.containsAll(flowsPage.table().getFlowsAliasesWithRequirements().keySet()));
//REST
assertEquals("identity-provider-redirector", getLastFlowFromREST().getAuthenticationExecutions().get(0).getAuthenticator());
String tmpFlowAlias = getLastFlowFromREST().getAuthenticationExecutions().get(1).getFlowAlias();
assertEquals("Copy of browser forms", tmpFlowAlias);
assertEquals("Username Password Form", testRealmResource().flows().getExecutions(tmpFlowAlias).get(0).getDisplayName());
assertEquals("nestedFlow", testRealmResource().flows().getExecutions(tmpFlowAlias).get(2).getDisplayName());
}
private AuthenticationFlowRepresentation getLastFlowFromREST() {
List<AuthenticationFlowRepresentation> allFlows = testRealmResource().flows().getFlows();
return (AuthenticationFlowRepresentation) CollectionUtils.
get(allFlows, (allFlows.size() - 1));
} }
} }