diff --git a/testsuite/integration-arquillian/HOW-TO-RUN.md b/testsuite/integration-arquillian/HOW-TO-RUN.md index 3098a358c1..6c1a07cf95 100644 --- a/testsuite/integration-arquillian/HOW-TO-RUN.md +++ b/testsuite/integration-arquillian/HOW-TO-RUN.md @@ -336,9 +336,15 @@ To run the tests run: #### Mozilla Firefox * **Supported version:** [latest ESR](https://www.mozilla.org/en-US/firefox/organizations/) (Extended Support Release) -* **Driver download required:** no +* **Driver download required:** no (using the old legacy Firefox driver) * **Run with:** `-Dbrowser=firefox`; optionally you can specify `-Dfirefox_binary=path/to/firefox/binary` +#### Mozilla Firefox with GeckoDriver +You can also use Firefox automation with modern Marionette protocol and GeckoDriver. However, this is **highly experimental** and the testsuite may not work as expected. +* **Supported version:** as latest as possible (Firefox has better support for Marionette with each version released) +* **Driver download required:** [GeckoDriver](https://github.com/mozilla/geckodriver/releases) +* **Run with:** `-Dbrowser=firefox -DfirefoxLegacyDriver=false -Dwebdriver.gecko.driver=path/to/geckodriver` + #### Google Chrome * **Supported version:** latest stable * **Driver download required:** [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/) which corresponds with your version of the browser @@ -346,9 +352,12 @@ To run the tests run: #### Internet Explorer * **Supported version:** 11 -* **Driver download required:** [Internet Explorer Driver Server](http://www.seleniumhq.org/download/); recommended version [2.53.1 32-bit](http://selenium-release.storage.googleapis.com/2.53/IEDriverServer_Win32_2.53.1.zip) +* **Driver download required:** [Internet Explorer Driver Server](http://www.seleniumhq.org/download/); recommended version [3.5.1 32-bit](http://selenium-release.storage.googleapis.com/3.5/IEDriverServer_Win32_3.5.1.zip) * **Run with:** `-Dbrowser=internetExplorer -Dwebdriver.ie.driver=path/to/IEDriverServer.exe` - + +#### Automatic driver downloads +You can rely on automatic driver downloads which is provided by [Arquillian Drone](http://arquillian.org/arquillian-extension-drone/#_automatic_download). To do so just omit the `-Dwebdriver.{browser}.driver` CLI argument when running the tests. + ## Run X.509 tests To run the X.509 client certificate authentication tests: diff --git a/testsuite/integration-arquillian/pom.xml b/testsuite/integration-arquillian/pom.xml index 78a76480b1..e2f300c40d 100644 --- a/testsuite/integration-arquillian/pom.xml +++ b/testsuite/integration-arquillian/pom.xml @@ -41,14 +41,14 @@ ${java.home} - 1.1.11.Final - 2.53.0 - 2.0.1.Final - 2.1.0.Alpha3 + 1.1.13.Final + 3.5.1 + 2.4.0 + 2.3.1 2.1.0.Beta1 1.0.1.Final - 1.2.0.Alpha2 - 2.2.2 + 1.2.0.Beta2 + 2.2.6 1.0.0.Alpha2 diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/PhotozClientAuthzTestApp.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/PhotozClientAuthzTestApp.java index 4d11f93747..32cc58f0d3 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/PhotozClientAuthzTestApp.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/PhotozClientAuthzTestApp.java @@ -93,9 +93,9 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { } public void navigateToAdminAlbum() { - URLUtils.navigateToUri(driver, toString() + "/#/admin/album", true); + URLUtils.navigateToUri(toString() + "/#/admin/album", true); driver.navigate().refresh(); // This is sometimes necessary for loading the new policy settings - waitForPageToLoad(driver); + waitForPageToLoad(); pause(WAIT_AFTER_OPERATION); } @@ -136,7 +136,7 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { scopesValue.append(scope); } - URLUtils.navigateToUri(driver, this.driver.getCurrentUrl() + " " + scopesValue, true); + URLUtils.navigateToUri(this.driver.getCurrentUrl() + " " + scopesValue, true); } this.loginPage.form().login(username, password); @@ -155,7 +155,7 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { public void viewAlbum(String name) throws InterruptedException { this.driver.findElement(By.xpath("//a[text() = '" + name + "']")).click(); - waitForPageToLoad(driver); + waitForPageToLoad(); driver.navigate().refresh(); // This is sometimes necessary for loading the new policy settings pause(WAIT_AFTER_OPERATION); } @@ -172,6 +172,6 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { @Override public boolean isCurrent() { - return URLUtils.currentUrlStartWith(driver, toString()); + return URLUtils.currentUrlStartWith(toString()); } } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java index 33dc8c2140..4671ccb257 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java @@ -17,18 +17,17 @@ package org.keycloak.testsuite.arquillian; -import org.jboss.arquillian.container.spi.client.container.DeployableContainer; import org.jboss.arquillian.container.osgi.OSGiApplicationArchiveProcessor; +import org.jboss.arquillian.container.spi.client.container.DeployableContainer; import org.jboss.arquillian.container.test.impl.enricher.resource.URLResourceProvider; import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor; import org.jboss.arquillian.container.test.spi.client.deployment.DeploymentScenarioGenerator; import org.jboss.arquillian.core.spi.LoadableExtension; import org.jboss.arquillian.drone.spi.Configurator; -import org.jboss.arquillian.drone.spi.Instantiator; -import org.jboss.arquillian.drone.webdriver.factory.HtmlUnitDriverFactory; import org.jboss.arquillian.drone.webdriver.factory.WebDriverFactory; import org.jboss.arquillian.graphene.location.ContainerCustomizableURLResourceProvider; import org.jboss.arquillian.graphene.location.CustomizableURLResourceProvider; +import org.jboss.arquillian.test.spi.TestEnricher; import org.jboss.arquillian.test.spi.enricher.resource.ResourceProvider; import org.jboss.arquillian.test.spi.execution.TestExecutionDecider; import org.keycloak.testsuite.arquillian.h2.H2TestEnricher; @@ -43,9 +42,7 @@ import org.keycloak.testsuite.arquillian.provider.TestContextProvider; import org.keycloak.testsuite.arquillian.provider.URLProvider; import org.keycloak.testsuite.drone.HtmlUnitScreenshots; import org.keycloak.testsuite.drone.KeycloakDronePostSetup; -import org.keycloak.testsuite.drone.KeycloakHtmlUnitInstantiator; import org.keycloak.testsuite.drone.KeycloakWebDriverConfigurator; -import org.jboss.arquillian.test.spi.TestEnricher; /** * @@ -83,7 +80,6 @@ public class KeycloakArquillianExtension implements LoadableExtension { builder .override(Configurator.class, WebDriverFactory.class, KeycloakWebDriverConfigurator.class) - .override(Instantiator.class, HtmlUnitDriverFactory.class, KeycloakHtmlUnitInstantiator.class) .observer(HtmlUnitScreenshots.class) .observer(KeycloakDronePostSetup.class); diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/account/AccountFields.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/account/AccountFields.java index 0e55060baf..bb1b330b20 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/account/AccountFields.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/account/AccountFields.java @@ -83,7 +83,7 @@ public class AccountFields extends Form { } public void waitForUsernameInputNotPresent() { - waitUntilElementIsNotPresent(driver, usernameInput); + waitUntilElementIsNotPresent(usernameInput); } } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/account/AccountManagement.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/account/AccountManagement.java index 59c5026e5b..5f5da8c328 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/account/AccountManagement.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/account/AccountManagement.java @@ -24,6 +24,7 @@ import org.openqa.selenium.support.FindBy; import javax.ws.rs.core.UriBuilder; +import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad; import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; /** @@ -77,6 +78,7 @@ public class AccountManagement extends AuthRealm implements PageWithLogOutAction public void signOut() { signOutLink.click(); + waitForPageToLoad(); } @Override @@ -86,34 +88,36 @@ public class AccountManagement extends AuthRealm implements PageWithLogOutAction public void account() { accountLink.click(); + waitForPageToLoad(); } public void password() { passwordLink.click(); + waitForPageToLoad(); } public void authenticator() { authenticatorLink.click(); + waitForPageToLoad(); } public void sessions() { sessionsLink.click(); + waitForPageToLoad(); } public void applications() { applicationsLink.click(); + waitForPageToLoad(); } public void save() { save.click(); + waitForPageToLoad(); } // public RealmResource realmResource() { // return keycloak().realm(getAuthRealm()); // } - public void waitForAccountLinkPresent() { - waitUntilElement(accountLink, "account link should be present").is().present(); - } - } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/LoginForm.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/LoginForm.java index 9a38cf6705..ff2a570058 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/LoginForm.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/LoginForm.java @@ -25,7 +25,7 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import static org.keycloak.testsuite.admin.Users.getPasswordOf; -import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad; +import static org.keycloak.testsuite.util.UIUtils.clickLink; import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; import static org.keycloak.testsuite.util.WaitUtils.waitUntilElementIsNotPresent; @@ -76,28 +76,24 @@ public class LoginForm extends Form { } public void register() { - registerLink.click(); - waitForPageToLoad(driver); + clickLink(registerLink); } public void login() { labelPassword.click(); // This is a nasty trick for IE; As IE was "moving the cursor" towards the login button // it opened the internationalization menu (when present) and then clicked // one of the languages instead of the Login button - loginButton.click(); - waitForPageToLoad(driver); + clickLink(loginButton); } public void forgotPassword() { - forgottenPassword.click(); - waitForPageToLoad(driver); + clickLink(forgottenPassword); } public void rememberMe(boolean value) { boolean selected = rememberMe.isSelected(); if ((value && !selected) || !value && selected) { rememberMe.click(); - waitForPageToLoad(driver); } } @@ -111,7 +107,7 @@ public class LoginForm extends Form { } public void waitForRegisterLinkNotPresent() { - waitUntilElementIsNotPresent(driver, registerLink); + waitUntilElementIsNotPresent(registerLink); } public void waitForResetPasswordLinkNotPresent() { @@ -123,7 +119,7 @@ public class LoginForm extends Form { } public void waitForRememberMeNotPresent() { - waitUntilElementIsNotPresent(driver, rememberMe); + waitUntilElementIsNotPresent(rememberMe); } public void waitForLoginButtonPresent() { @@ -157,8 +153,7 @@ public class LoginForm extends Form { } public void submit() { - submit.click(); - waitForPageToLoad(driver); + clickLink(submit); } } } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/TermsAndConditions.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/TermsAndConditions.java index a732c473f7..9adb530a47 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/TermsAndConditions.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/TermsAndConditions.java @@ -37,16 +37,16 @@ public class TermsAndConditions extends LoginActions { @Override public boolean isCurrent() { - return UIUtils.currentTitleEquals(driver, "Terms and Conditions"); + return UIUtils.currentTitleEquals("Terms and Conditions"); } public void acceptTerms() { acceptButton.click(); - WaitUtils.waitForPageToLoad(driver); + WaitUtils.waitForPageToLoad(); } public void declineTerms() { declineButton.click(); - WaitUtils.waitForPageToLoad(driver); + WaitUtils.waitForPageToLoad(); } public String getAcceptButtonText() { diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/AbstractMultipleSelect2.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/AbstractMultipleSelect2.java index 3c4dda8d19..c29b160362 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/AbstractMultipleSelect2.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/AbstractMultipleSelect2.java @@ -16,22 +16,23 @@ */ package org.keycloak.testsuite.console.page.fragment; +import org.jboss.arquillian.drone.api.annotation.Drone; +import org.jboss.arquillian.graphene.fragment.Root; +import org.openqa.selenium.By; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; + import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.BiFunction; import java.util.function.Function; -import org.jboss.arquillian.drone.api.annotation.Drone; -import org.jboss.arquillian.graphene.fragment.Root; -import org.keycloak.testsuite.util.WaitUtils; -import org.openqa.selenium.By; -import org.openqa.selenium.JavascriptExecutor; -import org.openqa.selenium.Keys; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.support.FindBy; +import static org.keycloak.testsuite.util.WaitUtils.pause; +import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad; /** * @author Pedro Igor @@ -44,7 +45,7 @@ public abstract class AbstractMultipleSelect2 { @Drone private WebDriver driver; - @FindBy(xpath = ".//input[contains(@class,'select2-input')]") + @FindBy(xpath = "//input[contains(@class,'select2-focused')]") private WebElement search; @FindBy(xpath = "//div[contains(@class,'select2-result-label')]") @@ -76,17 +77,17 @@ public abstract class AbstractMultipleSelect2 { } public void select(R value) { + pause(500); root.click(); - WaitUtils.pause(500); + pause(500); String id = identity().apply(value); - Actions actions = new Actions(driver); - actions.sendKeys(id).perform(); - WaitUtils.pause(500); + search.sendKeys(id); + waitForPageToLoad(); if (result.isEmpty()) { - actions.sendKeys(Keys.ESCAPE).perform(); + search.sendKeys(Keys.ESCAPE); return; } @@ -137,7 +138,7 @@ public abstract class AbstractMultipleSelect2 { WebElement element = selected.findElement(By.xpath(".//a[contains(@class,'select2-search-choice-close')]")); JavascriptExecutor executor = (JavascriptExecutor) driver; executor.executeScript("arguments[0].click();", element); - WaitUtils.pause(500); + pause(500); return true; } return false; diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/DataTable.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/DataTable.java index 4f128cd59c..9906b133a4 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/DataTable.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/DataTable.java @@ -25,6 +25,7 @@ import org.openqa.selenium.support.FindBy; import java.util.List; +import static org.keycloak.testsuite.util.WaitUtils.pause; import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad; import static org.openqa.selenium.By.xpath; @@ -59,12 +60,12 @@ public class DataTable { public void clickHeaderButton(String buttonText) { header.findElement(By.xpath(".//button[text()='" + buttonText + "']")).click(); - waitForPageToLoad(driver); + waitForPageToLoad(); } public void clickHeaderLink(String linkText) { header.findElement(By.linkText(linkText)).click(); - waitForPageToLoad(driver); + waitForPageToLoad(); } public WebElement body() { @@ -72,6 +73,7 @@ public class DataTable { } public List rows() { + pause(500); // wait a bit to ensure the table is no more changing return rows; } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/Dropdown.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/Dropdown.java index e5081e6e0e..6c5d4e1f30 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/Dropdown.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/Dropdown.java @@ -6,6 +6,7 @@ import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import static org.keycloak.testsuite.util.URLUtils.navigateToUri; import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; /** @@ -27,6 +28,6 @@ public class Dropdown { public void selectByText(String text) { waitUntilElement(dropDownRoot).is().present(); WebElement element = dropDownRoot.findElement(By.xpath("./ul/li/a[text()='" + text + "']")); - driver.navigate().to(element.getAttribute("href")); + navigateToUri(element.getAttribute("href"), true); // TODO: move cursor to show the menu and then click the menu item } } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/ModalDialog.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/ModalDialog.java index 9639749394..2d3b7f656b 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/ModalDialog.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/ModalDialog.java @@ -52,21 +52,21 @@ public class ModalDialog { private WebElement message; public void ok() { - waitForModalFadeIn(driver); + waitForModalFadeIn(); okButton.click(); - waitForModalFadeOut(driver); + waitForModalFadeOut(); } public void confirmDeletion() { - waitForModalFadeIn(driver); + waitForModalFadeIn(); deleteButton.click(); - waitForModalFadeOut(driver); + waitForModalFadeOut(); } public void cancel() { - waitForModalFadeIn(driver); + waitForModalFadeIn(); cancelButton.click(); - waitForModalFadeOut(driver); + waitForModalFadeOut(); } public void setName(String name) { 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 ccb6817add..5c57758c9f 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 @@ -17,12 +17,8 @@ package org.keycloak.testsuite.console.page.fragment; import org.jboss.arquillian.graphene.fragment.Root; -import org.jboss.arquillian.test.api.ArquillianResource; -import org.openqa.selenium.By; import org.openqa.selenium.WebElement; -import org.openqa.selenium.interactions.Actions; - -import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; +import org.openqa.selenium.support.FindBy; /** * @@ -33,26 +29,18 @@ public class OnOffSwitch { @Root private WebElement root; - @ArquillianResource - private Actions actions; + @FindBy(tagName = "input") + private WebElement inputTag; - public OnOffSwitch() { - } - - public OnOffSwitch(WebElement root, Actions actions) { - this.root = root; - this.actions = actions; - } + @FindBy(tagName = "label") + private WebElement labelTag; public boolean isOn() { - waitUntilElement(root).is().present(); - return root.findElement(By.tagName("input")).isSelected(); + return inputTag.isSelected(); } private void click() { - waitUntilElement(root).is().present(); - actions.moveToElement(root.findElement(By.tagName("label"))) - .click().build().perform(); + labelTag.click(); } public void toggle() { diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/drone/KeycloakHtmlUnitInstantiator.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/drone/KeycloakHtmlUnitInstantiator.java deleted file mode 100644 index d8a275cb83..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/drone/KeycloakHtmlUnitInstantiator.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.testsuite.drone; - -import java.lang.reflect.Method; - -import com.gargoylesoftware.htmlunit.WebClient; -import org.jboss.arquillian.drone.spi.Instantiator; -import org.jboss.arquillian.drone.webdriver.configuration.WebDriverConfiguration; -import org.jboss.arquillian.drone.webdriver.factory.HtmlUnitDriverFactory; -import org.jboss.logging.Logger; -import org.keycloak.common.util.reflections.Reflections; -import org.openqa.selenium.htmlunit.HtmlUnitDriver; - -/** - * @author Marek Posolda - */ -public class KeycloakHtmlUnitInstantiator extends HtmlUnitDriverFactory implements Instantiator { - - protected final Logger log = Logger.getLogger(KeycloakHtmlUnitInstantiator.class); - - @Override - public int getPrecedence() { - return 1; - } - - - @Override - public HtmlUnitDriver createInstance(WebDriverConfiguration configuration) { - HtmlUnitDriver htmlUnitDriver = super.createInstance(configuration); - - // Disable CSS - Method getWebClient = Reflections.findDeclaredMethod(HtmlUnitDriver.class, "getWebClient"); - WebClient webClient = (WebClient) Reflections.invokeMethod(true, getWebClient, htmlUnitDriver); - webClient.getOptions().setCssEnabled(false); - - return htmlUnitDriver; - } - -} diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/AbstractAlert.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/AbstractAlert.java index 59f1021d36..4778da62da 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/AbstractAlert.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/AbstractAlert.java @@ -51,7 +51,7 @@ public abstract class AbstractAlert { } protected boolean checkAlertType(String type) { - WaitUtils.waitForPageToLoad(driver); + WaitUtils.waitForPageToLoad(); try { (new WebDriverWait(driver, 1)).until(ExpectedConditions.attributeContains(root, "class", "alert-" + type)); } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/AbstractPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/AbstractPage.java index 4d002fc3f0..34daa16138 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/AbstractPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/AbstractPage.java @@ -95,11 +95,11 @@ public abstract class AbstractPage { } public void navigateTo(boolean waitForMatch) { - URLUtils.navigateToUri(driver, buildUri().toASCIIString(), waitForMatch); + URLUtils.navigateToUri(buildUri().toASCIIString(), waitForMatch); } public boolean isCurrent() { - return URLUtils.currentUrlEqual(driver, toString()); + return URLUtils.currentUrlEqual(toString()); } } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/Form.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/Form.java index 6af4998ce9..6eab0c7d19 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/Form.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/Form.java @@ -47,7 +47,7 @@ public class Form { public void save() { // guardAjax(save).click(); save.click(); - WaitUtils.waitForPageToLoad(driver); + WaitUtils.waitForPageToLoad(); } public void cancel() { diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AppServerWelcomePage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AppServerWelcomePage.java index d7056ee872..de8bc098a2 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AppServerWelcomePage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AppServerWelcomePage.java @@ -50,29 +50,29 @@ public class AppServerWelcomePage extends AppServerContextRoot { public void navigateToConsole() { WaitUtils.pause(2000); - URLUtils.navigateToUri(driver, getInjectedUrl().toString() + "/console", true); - waitForPageToLoad(driver); + URLUtils.navigateToUri(getInjectedUrl().toString() + "/console", true); + waitForPageToLoad(); } public void login(String username, String password) { loginPage.form().waitForLoginButtonPresent(); loginPage.form().login(username, password); - waitForPageToLoad(driver); + waitForPageToLoad(); } public void navigateToAccessControl() { accessControlLink.click(); - waitForPageToLoad(driver); + waitForPageToLoad(); } public void navigateManageProfile() { manageProfileLink.click(); - waitForPageToLoad(driver); + waitForPageToLoad(); } public void logout() { logoutLink.click(); - waitForPageToLoad(driver); + waitForPageToLoad(); } public boolean isLoginPage() { diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/DroneUtils.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/DroneUtils.java new file mode 100644 index 0000000000..8efb968fa6 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/DroneUtils.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.util; + +import org.jboss.arquillian.graphene.context.GrapheneContext; +import org.openqa.selenium.WebDriver; + +/** + * @author Vaclav Muzikar + */ +public final class DroneUtils { + public static WebDriver getCurrentDriver() { + return GrapheneContext.lastContext().getWebDriver(); + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java index e577758ced..f4c9819483 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java @@ -19,7 +19,6 @@ package org.keycloak.testsuite.util; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.ByteArrayOutputStream; -import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; @@ -50,7 +49,6 @@ import org.keycloak.representations.IDToken; import org.keycloak.representations.RefreshToken; import org.keycloak.representations.idm.KeysMetadataRepresentation; import org.keycloak.testsuite.arquillian.AuthServerTestEnricher; -import org.keycloak.testsuite.arquillian.SuiteContext; import org.keycloak.util.BasicAuthHelper; import org.keycloak.util.JsonSerialization; import org.keycloak.util.TokenUtil; @@ -60,7 +58,6 @@ import org.openqa.selenium.WebDriver; import javax.ws.rs.core.UriBuilder; -import java.io.Closeable; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; @@ -204,7 +201,7 @@ public class OAuthClient { } public void fillLoginForm(String username, String password) { - WaitUtils.waitForPageToLoad(driver); + WaitUtils.waitForPageToLoad(); String src = driver.getPageSource(); try { driver.findElement(By.id("username")).sendKeys(username); diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UIUtils.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UIUtils.java index ec54244a04..84cd7c8bfb 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UIUtils.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UIUtils.java @@ -1,12 +1,14 @@ package org.keycloak.testsuite.util; import org.openqa.selenium.TimeoutException; -import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.Select; import org.openqa.selenium.support.ui.WebDriverWait; +import static org.keycloak.testsuite.util.DroneUtils.getCurrentDriver; +import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad; + /** * @author Vaclav Muzikar */ @@ -21,13 +23,40 @@ public final class UIUtils { return false; } - public static boolean currentTitleEquals(WebDriver driver, String url) { + public static boolean currentTitleEquals(String url) { try { - (new WebDriverWait(driver, 5)).until(ExpectedConditions.titleIs(url)); + (new WebDriverWait(getCurrentDriver(), 5)).until(ExpectedConditions.titleIs(url)); } catch (TimeoutException e) { return false; } return true; } + + /** + * Safely performs an operation which is expected to cause a page reload, e.g. a link click. + * This ensures the page will be fully loaded after the operation. + * This is intended for use in UI tests only. + * + * @param operation + */ + public static void performOperationWithPageReload(Runnable operation) { + operation.run(); + waitForPageToLoad(); + } + + public static void clickLink(WebElement element) { + performOperationWithPageReload(element::click); + } + + /** + * Navigates to a link directly instead of clicking on it. + * Some browsers are sometimes having problems with clicking on links, so this should be used only in that cases, + * i.e. only when clicking directly doesn't work + * + * @param element + */ + public static void navigateToLink(WebElement element) { + URLUtils.navigateToUri(element.getAttribute("href"), true); + } } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/URLUtils.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/URLUtils.java index ea7d72c911..e3985c5a3c 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/URLUtils.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/URLUtils.java @@ -10,8 +10,9 @@ import org.openqa.selenium.support.ui.WebDriverWait; import java.util.regex.Pattern; +import static org.keycloak.testsuite.util.DroneUtils.getCurrentDriver; +import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad; import static org.openqa.selenium.support.ui.ExpectedConditions.not; -import static org.openqa.selenium.support.ui.ExpectedConditions.or; import static org.openqa.selenium.support.ui.ExpectedConditions.urlMatches; import static org.openqa.selenium.support.ui.ExpectedConditions.urlToBe; @@ -20,12 +21,15 @@ import static org.openqa.selenium.support.ui.ExpectedConditions.urlToBe; */ public final class URLUtils { - public static void navigateToUri(WebDriver driver, String uri, boolean waitForMatch) { - navigateToUri(driver, uri, waitForMatch, true); + private static Logger log = Logger.getLogger(URLUtils.class); + + public static void navigateToUri(String uri, boolean waitForMatch) { + navigateToUri(uri, waitForMatch, true); } - private static void navigateToUri(WebDriver driver, String uri, boolean waitForMatch, boolean enableIEWorkaround) { - Logger log = Logger.getLogger(URLUtils.class); + // TODO: remove waitForMatch + private static void navigateToUri(String uri, boolean waitForMatch, boolean enableIEWorkaround) { + WebDriver driver = getCurrentDriver(); log.info("starting navigation"); @@ -34,27 +38,20 @@ public final class URLUtils { if (driver instanceof InternetExplorerDriver && driver.getCurrentUrl().equals(uri)) { log.info("IE workaround: target URL equals current URL - refreshing the page"); driver.navigate().refresh(); + waitForPageToLoad(); } - WaitUtils.waitForPageToLoad(driver); - log.info("current URL: " + driver.getCurrentUrl()); log.info("navigating to " + uri); - driver.navigate().to(uri); - - if (waitForMatch) { - // Possible login URL; this is to eliminate unnecessary wait when navigating to a secured page and being - // redirected to the login page - String loginUrl = "^[^\\?]+/auth/realms/[^/]+/(protocol|login-actions).+$"; - - try { - (new WebDriverWait(driver, 3)).until(or(urlMatches("^" + Pattern.quote(uri) + ".*$"), urlMatches(loginUrl))); - } catch (TimeoutException e) { - log.info("new current URL doesn't start with desired URL"); - } + if (driver.getCurrentUrl().equals(uri)) { // Some browsers won't do anything if navigating to the same URL; this "fixes" it + log.info("target URL equals current URL - refreshing the page"); + driver.navigate().refresh(); + } + else { + driver.navigate().to(uri); } - WaitUtils.waitForPageToLoad(driver); + waitForPageToLoad(); log.info("new current URL: " + driver.getCurrentUrl()); @@ -65,45 +62,45 @@ public final class URLUtils { && (driver.getCurrentUrl().matches("^[^#]+/#state=[^#/&]+&code=[^#/&]+$") || driver.getCurrentUrl().matches("^.+/auth/admin/[^/]+/console/$"))) { log.info("IE workaround: reloading the page after deleting the cookies..."); - navigateToUri(driver, uri, waitForMatch, false); + navigateToUri(uri, waitForMatch, false); } else { log.info("navigation complete"); } } - public static boolean currentUrlEqual(WebDriver driver, String url) { - return urlCheck(driver, urlToBe(url)); + public static boolean currentUrlEqual(String url) { + return urlCheck(urlToBe(url)); } - public static boolean currentUrlDoesntEqual(WebDriver driver, String url) { - return urlCheck(driver, not(urlToBe(url))); + public static boolean currentUrlDoesntEqual(String url) { + return urlCheck(not(urlToBe(url))); } - public static boolean currentUrlStartWith(WebDriver driver, String url) { - return urlCheck(driver, urlMatches("^" + Pattern.quote(url) + ".*$")); + public static boolean currentUrlStartWith(String url) { + return urlCheck(urlMatches("^" + Pattern.quote(url) + ".*$")); } - public static boolean currentUrlDoesntStartWith(WebDriver driver, String url) { - return urlCheck(driver, urlMatches("^(?!" + Pattern.quote(url) + ").+$")); + public static boolean currentUrlDoesntStartWith(String url) { + return urlCheck(urlMatches("^(?!" + Pattern.quote(url) + ").+$")); } - private static boolean urlCheck(WebDriver driver, ExpectedCondition condition) { - return urlCheck(driver, condition, false); + private static boolean urlCheck(ExpectedCondition condition) { + return urlCheck(condition, false); } - private static boolean urlCheck(WebDriver driver, ExpectedCondition condition, boolean secondTry) { - Logger log = Logger.getLogger(URLUtils.class); + private static boolean urlCheck(ExpectedCondition condition, boolean secondTry) { + WebDriver driver = getCurrentDriver(); try { - (new WebDriverWait(driver, 1, 100)).until(condition); + (new WebDriverWait(driver, 5, 100)).until(condition); } catch (TimeoutException e) { if (driver instanceof InternetExplorerDriver && !secondTry) { // IE WebDriver has sometimes invalid current URL log.info("IE workaround: checking URL failed at first attempt - refreshing the page and trying one more time..."); driver.navigate().refresh(); - urlCheck(driver, condition, true); + urlCheck(condition, true); } else { return false; diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java index 216e2cae83..30ec1a8710 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java @@ -21,17 +21,18 @@ import org.openqa.selenium.By; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import org.openqa.selenium.htmlunit.HtmlUnitDriver; +import org.openqa.selenium.support.ui.FluentWait; import org.openqa.selenium.support.ui.WebDriverWait; import java.util.Collections; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import static org.jboss.arquillian.graphene.Graphene.waitGui; -import static org.openqa.selenium.support.ui.ExpectedConditions.invisibilityOfAllElements; -import static org.openqa.selenium.support.ui.ExpectedConditions.javaScriptThrowsNoExceptions; -import static org.openqa.selenium.support.ui.ExpectedConditions.not; -import static org.openqa.selenium.support.ui.ExpectedConditions.urlContains; +import static org.keycloak.testsuite.util.DroneUtils.getCurrentDriver; +import static org.openqa.selenium.support.ui.ExpectedConditions.*; /** * @@ -64,13 +65,14 @@ public final class WaitUtils { return waitGui().until(failMessage).element(element); } - public static void waitUntilElementIsNotPresent(WebDriver driver, By locator) { - waitUntilElementIsNotPresent(driver, driver.findElement(locator)); + public static void waitUntilElementIsNotPresent(By locator) { + waitUntilElement(locator).is().not().present(); } - public static void waitUntilElementIsNotPresent(WebDriver driver, WebElement element) { - (new WebDriverWait(driver, IMPLICIT_ELEMENT_WAIT_MILLIS)) - .until(invisibilityOfAllElements(Collections.singletonList(element))); + public static void waitUntilElementIsNotPresent(WebElement element) { + waitUntilElement(element).is().not().present(); +// (new WebDriverWait(driver, IMPLICIT_ELEMENT_WAIT_MILLIS)) +// .until(invisibilityOfAllElements(Collections.singletonList(element))); } public static void pause(long millis) { @@ -89,15 +91,32 @@ public final class WaitUtils { * Waits for page to finish any pending redirects, REST API requests etc. * Because Keycloak's Admin Console is a single-page application, we need to * take extra steps to ensure the page is fully loaded - * - * @param driver */ - public static void waitForPageToLoad(WebDriver driver) { - WebDriverWait wait = new WebDriverWait(driver, PAGELOAD_TIMEOUT_MILLIS / 1000); + public static void waitForPageToLoad() { + WebDriver driver = getCurrentDriver(); + + if (driver instanceof HtmlUnitDriver) { + return; // not needed + } + + // Ensure the URL is "stable", i.e. is not changing anymore; if it'd changing, some redirects are probably still in progress + for (int maxRedirects = 2; maxRedirects > 0; maxRedirects--) { + String currentUrl = driver.getCurrentUrl(); + FluentWait wait = new FluentWait<>(driver).withTimeout(250, TimeUnit.MILLISECONDS); + try { + wait.until(not(urlToBe(currentUrl))); + } + catch (TimeoutException e) { + break; // URL has not changed recently - ok, the URL is stable and page is current + } + if (maxRedirects == 1) { + log.warn("URL seems unstable! (Some redirect are probably still in progress)"); + } + } + + WebDriverWait wait = new WebDriverWait(getCurrentDriver(), PAGELOAD_TIMEOUT_MILLIS / 1000); try { - wait.until(not(urlContains("redirect_fragment"))); - // Checks if the document is ready and asks AngularJS, if present, whether there are any REST API requests // in progress wait.until(javaScriptThrowsNoExceptions( @@ -112,12 +131,12 @@ public final class WaitUtils { } } - public static void waitForModalFadeIn(WebDriver driver) { + public static void waitForModalFadeIn() { pause(500); // TODO: Find out how to do in more 'elegant' way, e.g. like in the waitForModalFadeOut } - public static void waitForModalFadeOut(WebDriver driver) { - waitUntilElementIsNotPresent(driver, By.className("modal-backdrop")); + public static void waitForModalFadeOut() { + waitUntilElementIsNotPresent(By.className("modal-backdrop")); } } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzFunctionalAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzFunctionalAdapterTest.java index 49158faacf..a46f8f142b 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzFunctionalAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletAuthzFunctionalAdapterTest.java @@ -207,7 +207,7 @@ public abstract class AbstractServletAuthzFunctionalAdapterTest extends Abstract public void testAccessPublicResource() throws Exception { performTests(() -> { driver.navigate().to(getResourceServerUrl() + "/public-html.html"); - WaitUtils.waitForPageToLoad(driver); + WaitUtils.waitForPageToLoad(); assertTrue(hasText("This is public resource that should be accessible without login.")); }); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractClientInitiatedAccountLinkTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractClientInitiatedAccountLinkTest.java index f95fe7f241..ace58078a8 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractClientInitiatedAccountLinkTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractClientInitiatedAccountLinkTest.java @@ -48,7 +48,6 @@ import org.keycloak.testsuite.pages.AccountUpdateProfilePage; import org.keycloak.testsuite.pages.ErrorPage; import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.LoginUpdateProfilePage; -import org.keycloak.testsuite.pages.UpdateAccountInformationPage; import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.WaitUtils; import org.keycloak.util.JsonSerialization; @@ -61,8 +60,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT; import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT_LINKS; @@ -545,7 +542,7 @@ public abstract class AbstractClientInitiatedAccountLinkTest extends AbstractSer // Login to account mgmt first profilePage.open(CHILD_IDP); - WaitUtils.waitForPageToLoad(driver); + WaitUtils.waitForPageToLoad(); Assert.assertTrue(loginPage.isCurrent(CHILD_IDP)); loginPage.login("child", "password"); @@ -590,7 +587,7 @@ public abstract class AbstractClientInitiatedAccountLinkTest extends AbstractSer // Login to account mgmt first profilePage.open(CHILD_IDP); - WaitUtils.waitForPageToLoad(driver); + WaitUtils.waitForPageToLoad(); Assert.assertTrue(loginPage.isCurrent(CHILD_IDP)); loginPage.login("child", "password"); @@ -624,7 +621,7 @@ public abstract class AbstractClientInitiatedAccountLinkTest extends AbstractSer private void navigateTo(String uri) { driver.navigate().to(uri); - WaitUtils.waitForPageToLoad(driver); + WaitUtils.waitForPageToLoad(); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java index f7a9335336..721c89ee8f 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java @@ -53,8 +53,6 @@ import org.keycloak.testsuite.util.*; import org.keycloak.testsuite.util.URLUtils; import org.keycloak.util.BasicAuthHelper; -import org.openqa.selenium.By; - import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; @@ -197,7 +195,7 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); testRealmLoginPage.form().login("bburke@redhat.com", "password"); assertCurrentUrlEquals(driver, inputPortal + "/secured/post"); - waitForPageToLoad(driver); + waitForPageToLoad(); String pageSource = driver.getPageSource(); assertThat(pageSource, containsString("parameter=hello")); @@ -564,7 +562,7 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd // Test I need to reauthenticate with prompt=login String appUri = tokenMinTTLPage.getUriBuilder().queryParam(OIDCLoginProtocol.PROMPT_PARAM, OIDCLoginProtocol.PROMPT_VALUE_LOGIN).build().toString(); - URLUtils.navigateToUri(driver, appUri, true); + URLUtils.navigateToUri(appUri, true); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); testRealmLoginPage.form().login("bburke@redhat.com", "password"); AccessToken token = tokenMinTTLPage.getAccessToken(); @@ -624,7 +622,7 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd oAuthGrantPage.accept(); String pageSource = driver.getPageSource(); - waitForPageToLoad(driver); + waitForPageToLoad(); assertThat(pageSource, containsString("Bill Burke")); assertThat(pageSource, containsString("Stian Thorgersen")); @@ -682,7 +680,7 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd testRealmLoginPage.form().login("bburke@redhat.com", "password"); - waitForPageToLoad(driver); + waitForPageToLoad(); String pageSource = driver.getPageSource(); assertThat(pageSource, containsString("Bill Burke")); assertThat(pageSource, containsString("Stian Thorgersen")); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java index b62ba31b8a..a2b263445c 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java @@ -397,7 +397,7 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd private void checkLoggedOut(AbstractPage page, Login loginPage) { page.navigateTo(); - waitForPageToLoad(driver); + waitForPageToLoad(); assertCurrentUrlStartsWith(loginPage); } @@ -950,7 +950,7 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd assertCurrentUrlStartsWith(testRealmSAMLPostLoginPage); testRealmSAMLPostLoginPage.form().login("bburke", "password"); assertCurrentUrlStartsWith(employeeServletPage); - waitForPageToLoad(driver); + waitForPageToLoad(); String pageSource = driver.getPageSource(); assertThat(pageSource, containsString("Relay state: " + SamlSPFacade.RELAY_STATE)); assertThat(pageSource, not(containsString("SAML response: null"))); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/cluster/AbstractSAMLAdapterClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/cluster/AbstractSAMLAdapterClusterTest.java index 3868fb5cee..3a87cdc694 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/cluster/AbstractSAMLAdapterClusterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/cluster/AbstractSAMLAdapterClusterTest.java @@ -17,7 +17,6 @@ package org.keycloak.testsuite.adapter.servlet.cluster; import org.keycloak.admin.client.resource.RealmResource; -import org.keycloak.admin.client.resource.UsersResource; import org.keycloak.representations.idm.*; import org.keycloak.testsuite.Retry; import org.keycloak.testsuite.adapter.page.EmployeeServletDistributable; @@ -57,7 +56,6 @@ import org.openqa.selenium.support.ui.WebDriverWait; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; -import static org.keycloak.testsuite.AbstractAuthTest.createUserRepresentation; import static org.keycloak.testsuite.admin.Users.setPasswordFor; import static org.keycloak.testsuite.arquillian.AppServerTestEnricher.getNearestSuperclassWithAnnotation; import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO; @@ -223,7 +221,7 @@ public abstract class AbstractSAMLAdapterClusterTest extends AbstractServletsAda protected void checkLoggedOut(AbstractPage page, AuthRealm loginPage) { page.navigateTo(); - WaitUtils.waitForPageToLoad(driver); + WaitUtils.waitForPageToLoad(); assertCurrentUrlStartsWith(loginPage); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java index 096fb7657b..547d039502 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java @@ -225,10 +225,10 @@ public class SocialLoginTest extends AbstractKeycloakTest { // Just to be sure there's no redirect in progress WaitUtils.pause(3000); - WaitUtils.waitForPageToLoad(driver); + WaitUtils.waitForPageToLoad(); // Only when there's not active session for the social provider, i.e. login is required - if (URLUtils.currentUrlDoesntStartWith(driver, getAuthServerRoot().toASCIIString())) { + if (URLUtils.currentUrlDoesntStartWith(getAuthServerRoot().toASCIIString())) { log.infof("current URL: %s", driver.getCurrentUrl()); log.infof("performing log in to '%s' ...", currentTestProvider.id()); AbstractSocialLoginPage loginPage = Graphene.createPageFragment(currentTestProvider.pageObjectClazz(), driver.findElement(By.tagName("html"))); @@ -240,7 +240,7 @@ public class SocialLoginTest extends AbstractKeycloakTest { } private void assertAccount() { - assertTrue(URLUtils.currentUrlStartWith(driver, accountPage.toString())); // Sometimes after login the URL ends with /# or similar + assertTrue(URLUtils.currentUrlStartWith(accountPage.toString())); // Sometimes after login the URL ends with /# or similar assertEquals(getConfig("profile.firstName"), accountPage.getFirstName()); assertEquals(getConfig("profile.lastName"), accountPage.getLastName()); @@ -248,7 +248,7 @@ public class SocialLoginTest extends AbstractKeycloakTest { } private void assertUpdateProfile(boolean firstName, boolean lastName, boolean email) { - assertTrue(URLUtils.currentUrlDoesntStartWith(driver, accountPage.toString())); + assertTrue(URLUtils.currentUrlDoesntStartWith(accountPage.toString())); if (firstName) { assertTrue(updateAccountPage.fields().getFirstName().isEmpty()); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/URLAssert.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/URLAssert.java index 90ee6cefa8..2fd0cb6d84 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/URLAssert.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/URLAssert.java @@ -53,12 +53,12 @@ public class URLAssert { public static void assertCurrentUrlEquals(WebDriver driver, final AbstractPage page) { String expected = page.toString(); assertTrue("Expected URL: " + expected + "; actual: " + driver.getCurrentUrl(), - currentUrlEqual(driver, page.toString())); + currentUrlEqual(page.toString())); } public static void assertCurrentUrlEquals(WebDriver driver, final String url) { assertTrue("Expected URL: " + url + "; actual: " + driver.getCurrentUrl(), - currentUrlEqual(driver, url)); + currentUrlEqual(url)); } public static void assertCurrentUrlStartsWith(AbstractPage page) { @@ -67,7 +67,7 @@ public class URLAssert { public static void assertCurrentUrlStartsWith(WebDriver driver, final String url) { assertTrue("URL expected to begin with:" + url + "; actual URL: " + driver.getCurrentUrl(), - currentUrlStartWith(driver, url)); + currentUrlStartWith(url)); } public static void assertCurrentUrlDoesntStartWith(AbstractPage page) { @@ -76,7 +76,7 @@ public class URLAssert { public static void assertCurrentUrlDoesntStartWith(WebDriver driver, final String url) { assertTrue("URL expected NOT to begin with:" + url + "; actual URL: " + driver.getCurrentUrl(), - currentUrlDoesntStartWith(driver, url)); + currentUrlDoesntStartWith(url)); } public static void assertCurrentUrlStartsWithLoginUrlOf(PageWithLoginUrl page) { diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml index acf153c810..f3b3a69384 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml @@ -24,10 +24,22 @@ ${browser} + ${webdriverDownloadBinaries} + + ${htmlUnitBrowserVersion} - ${firefox_binary} - ${chromeArguments} + cssEnabled=false;historyPageCacheLimit=1 + + ${phantomjs.cli.args} --ssl-certificates-path=${client.certificate.ca.path} --ssl-client-certificate-file=${client.certificate.file} --ssl-client-key-file=${client.key.file} --ssl-client-key-passphrase=${client.key.passphrase} + + + ${firefox_binary} + OFF + ${firefoxLegacyDriver} + + + ${chromeArguments} diff --git a/testsuite/integration-arquillian/tests/other/console/pom.xml b/testsuite/integration-arquillian/tests/other/console/pom.xml index 003e24c939..796e9396e6 100644 --- a/testsuite/integration-arquillian/tests/other/console/pom.xml +++ b/testsuite/integration-arquillian/tests/other/console/pom.xml @@ -33,6 +33,7 @@ ${auth.server.home}/themes + firefox|chrome|internetExplorer @@ -55,6 +56,27 @@ + + maven-enforcer-plugin + + + + enforce + + + + + browser + Browser property must be set! + ${supportedBrowsers} + Unsupported browser "${browser}"! Only the following are supported: ${supportedBrowsers} + + + true + + + + diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/authentication/PasswordPolicy.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/authentication/PasswordPolicy.java index 8f8073ca61..02ad49e0a7 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/authentication/PasswordPolicy.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/authentication/PasswordPolicy.java @@ -36,7 +36,7 @@ public class PasswordPolicy extends Authentication { addPolicySelect.selectByVisibleText(policy.getName()); if (value != null) {setPolicyValue(policy, value);} primaryButton.click(); - waitForPageToLoad(driver); + waitForPageToLoad(); } @@ -53,7 +53,7 @@ public class PasswordPolicy extends Authentication { if (primaryButton.isEnabled()) { primaryButton.click(); } - waitForPageToLoad(driver); + waitForPageToLoad(); } public void editPolicy(Type policy, int value) { @@ -65,7 +65,7 @@ public class PasswordPolicy extends Authentication { if (primaryButton.isEnabled()) { primaryButton.click(); } - waitForPageToLoad(driver); + waitForPageToLoad(); } private void setPolicyValue(Type policy, String value) { diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/authentication/RequiredActions.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/authentication/RequiredActions.java index 09f5f1cb48..f9c4edebd1 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/authentication/RequiredActions.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/authentication/RequiredActions.java @@ -33,7 +33,7 @@ public class RequiredActions extends Authentication { WebElement checkbox = requiredActionTable.findElement(By.id(id)); - if (checkbox.isSelected() != value) { + if (checkbox.isEnabled() && checkbox.isSelected() != value) { checkbox.click(); } } diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/authentication/flows/Flows.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/authentication/flows/Flows.java index 262a834ea2..6e410add0f 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/authentication/flows/Flows.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/authentication/flows/Flows.java @@ -8,6 +8,8 @@ import org.openqa.selenium.support.ui.Select; import java.util.List; import java.util.stream.Collectors; +import static org.keycloak.testsuite.util.UIUtils.performOperationWithPageReload; + /** * @author tkyjovsk * @author mhajas @@ -61,7 +63,7 @@ public class Flows extends Authentication { } public void selectFlowOption(FlowOption option) { - flowSelect.selectByVisibleText(option.getName()); + performOperationWithPageReload(() -> flowSelect.selectByVisibleText(option.getName())); } public String getFlowSelectValue() { diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/Client.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/Client.java index 39999ba104..619a06527b 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/Client.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/Client.java @@ -6,6 +6,8 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import static org.keycloak.testsuite.console.page.fragment.Breadcrumb.BREADCRUMB_XPATH; +import static org.keycloak.testsuite.util.UIUtils.clickLink; + import org.openqa.selenium.NoSuchElementException; /** @@ -44,7 +46,7 @@ public class Client extends Clients { private WebElement deleteIcon; public void delete() { - deleteIcon.click(); + clickLink(deleteIcon); modalDialog.confirmDeletion(); } @@ -80,35 +82,35 @@ public class Client extends Clients { private WebElement authorizationLink; public void settings() { - settingsLink.click(); + clickLink(settingsLink); } public void roles() { - rolesLink.click(); + clickLink(rolesLink); } public void mappers() { - mappersLink.click(); + clickLink(mappersLink); } public void scope() { - scopeLink.click(); + clickLink(scopeLink); } public void revocation() { - revocationLink.click(); + clickLink(revocationLink); } public void sessions() { - sessionsLink.click(); + clickLink(sessionsLink); } public void installation() { - installationLink.click(); + clickLink(installationLink); } public void authorization() { - authorizationLink.click(); + clickLink(authorizationLink); } public boolean isServiceAccountRolesDisplayed() { diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/Authorization.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/Authorization.java index 5510d7e631..391e1e6006 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/Authorization.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/Authorization.java @@ -16,6 +16,7 @@ */ package org.keycloak.testsuite.console.page.clients.authorization; +import org.jboss.arquillian.drone.api.annotation.Drone; import org.jboss.arquillian.graphene.fragment.Root; import org.jboss.arquillian.graphene.page.Page; import org.keycloak.testsuite.console.page.clients.Client; @@ -23,9 +24,12 @@ import org.keycloak.testsuite.console.page.clients.authorization.permission.Perm import org.keycloak.testsuite.console.page.clients.authorization.policy.Policies; import org.keycloak.testsuite.console.page.clients.authorization.resource.Resources; import org.keycloak.testsuite.console.page.clients.authorization.scope.Scopes; +import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; +import static org.keycloak.testsuite.util.UIUtils.navigateToLink; + /** * * @author Pedro Igor @@ -97,6 +101,9 @@ public class Authorization extends Client { @Root private WebElement root; + @Drone + private WebDriver driver; + @FindBy(linkText = "Settings") private WebElement settingsLink; @@ -113,23 +120,28 @@ public class Authorization extends Client { private WebElement policiesLink; public void settings() { - settingsLink.click(); + //clickLink(settingsLink); + navigateToLink(settingsLink); // for some reason, GeckoDriver is currently having problems clicking on those tabs } public void resources() { - resourcesLink.click(); + //clickLink(resourcesLink); + navigateToLink(resourcesLink); } private void scopes() { - scopesLink.click(); + //clickLink(scopesLink); + navigateToLink(scopesLink); } private void permissions() { - permissionsLink.click(); + //clickLink(permissionsLink); + navigateToLink(permissionsLink); } private void policies() { - policiesLink.click(); + //clickLink(policiesLink); + navigateToLink(policiesLink); } } } diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/Permissions.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/Permissions.java index de9c13c339..f861c85292 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/Permissions.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/permission/Permissions.java @@ -16,8 +16,6 @@ */ package org.keycloak.testsuite.console.page.clients.authorization.permission; -import static org.openqa.selenium.By.tagName; - import org.jboss.arquillian.graphene.page.Page; import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation; import org.keycloak.representations.idm.authorization.PolicyRepresentation; @@ -25,13 +23,15 @@ import org.keycloak.representations.idm.authorization.ResourcePermissionRepresen import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation; import org.keycloak.testsuite.console.page.clients.authorization.policy.PolicyTypeUI; import org.keycloak.testsuite.page.Form; -import org.keycloak.testsuite.util.URLUtils; import org.keycloak.testsuite.util.WaitUtils; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.ui.Select; +import static org.keycloak.testsuite.util.UIUtils.clickLink; +import static org.openqa.selenium.By.tagName; + /** * @author Pedro Igor */ @@ -73,8 +73,8 @@ public class Permissions extends Form { for (WebElement row : permissions().rows()) { PolicyRepresentation actual = permissions().toRepresentation(row); if (actual.getName().equalsIgnoreCase(name)) { - URLUtils.navigateToUri(driver, row.findElements(tagName("a")).get(0).getAttribute("href"), true); - WaitUtils.waitForPageToLoad(driver); + clickLink(row.findElements(tagName("a")).get(0)); + WaitUtils.waitForPageToLoad(); String type = representation.getType(); if ("resource".equals(type)) { @@ -92,8 +92,8 @@ public class Permissions extends Form { for (WebElement row : permissions().rows()) { PolicyRepresentation actual = permissions().toRepresentation(row); if (actual.getName().equalsIgnoreCase(name)) { - URLUtils.navigateToUri(driver, row.findElements(tagName("a")).get(0).getAttribute("href"), true); - WaitUtils.waitForPageToLoad(driver); + clickLink(row.findElements(tagName("a")).get(0)); + WaitUtils.waitForPageToLoad(); String type = actual.getType(); if ("resource".equals(type)) { return (P) resourcePermission; @@ -109,8 +109,8 @@ public class Permissions extends Form { for (WebElement row : permissions().rows()) { PolicyRepresentation actual = permissions().toRepresentation(row); if (actual.getName().equalsIgnoreCase(name)) { - URLUtils.navigateToUri(driver, row.findElements(tagName("a")).get(0).getAttribute("href"), true); - WaitUtils.waitForPageToLoad(driver); + clickLink(row.findElements(tagName("a")).get(0)); + WaitUtils.waitForPageToLoad(); String type = actual.getType(); diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicyForm.java index 389a214d57..d063f6cd8e 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicyForm.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/GroupPolicyForm.java @@ -16,6 +16,7 @@ */ package org.keycloak.testsuite.console.page.clients.authorization.policy; +import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; import static org.openqa.selenium.By.tagName; import java.util.ArrayList; @@ -93,6 +94,7 @@ public class GroupPolicyForm extends Form { String groupName = path.substring(path.lastIndexOf('/') + 1); WebElement element = driver.findElement(By.xpath("//span[text()='" + groupName + "']")); element.click(); + waitUntilElement(selectGroupButton).is().enabled(); selectGroupButton.click(); driver.findElements(By.xpath("(//table[@id='selected-groups'])/tbody/tr")).stream() .filter(webElement -> webElement.findElements(tagName("td")).size() > 1) diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java index a42e12e07e..79c69578fd 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/Policies.java @@ -16,8 +16,6 @@ */ package org.keycloak.testsuite.console.page.clients.authorization.policy; -import static org.openqa.selenium.By.tagName; - import org.jboss.arquillian.graphene.page.Page; import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentation; import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation; @@ -30,13 +28,15 @@ import org.keycloak.representations.idm.authorization.RulePolicyRepresentation; import org.keycloak.representations.idm.authorization.TimePolicyRepresentation; import org.keycloak.representations.idm.authorization.UserPolicyRepresentation; import org.keycloak.testsuite.page.Form; -import org.keycloak.testsuite.util.URLUtils; -import org.keycloak.testsuite.util.WaitUtils; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.ui.Select; +import static org.keycloak.testsuite.util.UIUtils.clickLink; +import static org.keycloak.testsuite.util.UIUtils.performOperationWithPageReload; +import static org.openqa.selenium.By.tagName; + /** * @author Pedro Igor */ @@ -79,7 +79,7 @@ public class Policies extends Form { public

P create(AbstractPolicyRepresentation expected) { String type = expected.getType(); - createSelect.selectByValue(type); + performOperationWithPageReload(() -> createSelect.selectByValue(type)); if ("role".equals(type)) { rolePolicy.form().populate((RolePolicyRepresentation) expected); @@ -104,7 +104,6 @@ public class Policies extends Form { return (P) clientPolicy; } else if ("group".equals(type)) { groupPolicy.form().populate((GroupPolicyRepresentation) expected); - groupPolicy.form().save(); return (P) groupPolicy; } @@ -115,8 +114,7 @@ public class Policies extends Form { for (WebElement row : policies().rows()) { PolicyRepresentation actual = policies().toRepresentation(row); if (actual.getName().equalsIgnoreCase(name)) { - URLUtils.navigateToUri(driver, row.findElements(tagName("a")).get(0).getAttribute("href"), true); - WaitUtils.waitForPageToLoad(driver); + clickLink(row.findElements(tagName("a")).get(0)); String type = representation.getType(); if ("role".equals(type)) { @@ -146,7 +144,7 @@ public class Policies extends Form { for (WebElement row : policies().rows()) { PolicyRepresentation actual = policies().toRepresentation(row); if (actual.getName().equalsIgnoreCase(name)) { - URLUtils.navigateToUri(driver, row.findElements(tagName("a")).get(0).getAttribute("href"), true); + clickLink(row.findElements(tagName("a")).get(0)); String type = actual.getType(); if ("role".equals(type)) { return (P) rolePolicy; @@ -174,7 +172,7 @@ public class Policies extends Form { for (WebElement row : policies().rows()) { PolicyRepresentation actual = policies().toRepresentation(row); if (actual.getName().equalsIgnoreCase(name)) { - URLUtils.navigateToUri(driver, row.findElements(tagName("a")).get(0).getAttribute("href"), true); + clickLink(row.findElements(tagName("a")).get(0)); String type = actual.getType(); diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RulePolicyForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RulePolicyForm.java index 0ba43f14d6..3b02288a43 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RulePolicyForm.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/policy/RulePolicyForm.java @@ -77,7 +77,7 @@ public class RulePolicyForm extends Form { setInputValue(artifactVersion, expected.getArtifactVersion()); resolveModuleButton.click(); - WaitUtils.waitForPageToLoad(driver); + WaitUtils.waitForPageToLoad(); moduleName.selectByVisibleText(expected.getModuleName()); WaitUtils.pause(1000); diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/resource/Resources.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/resource/Resources.java index 199be95091..d079ce69d8 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/resource/Resources.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/resource/Resources.java @@ -16,17 +16,17 @@ */ package org.keycloak.testsuite.console.page.clients.authorization.resource; -import static org.openqa.selenium.By.tagName; - import org.jboss.arquillian.graphene.page.Page; import org.keycloak.representations.idm.authorization.ResourceRepresentation; import org.keycloak.testsuite.page.Form; -import org.keycloak.testsuite.util.URLUtils; import org.keycloak.testsuite.util.WaitUtils; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; +import static org.keycloak.testsuite.util.UIUtils.clickLink; +import static org.openqa.selenium.By.tagName; + /** * @author Pedro Igor */ @@ -54,8 +54,8 @@ public class Resources extends Form { for (WebElement row : resources().rows()) { ResourceRepresentation actual = resources().toRepresentation(row); if (actual.getName().equalsIgnoreCase(name)) { - URLUtils.navigateToUri(driver, row.findElements(tagName("a")).get(0).getAttribute("href"), true); - WaitUtils.waitForPageToLoad(driver); + clickLink(row.findElements(tagName("a")).get(0)); + WaitUtils.waitForPageToLoad(); resource.form().populate(representation); return; } @@ -66,8 +66,8 @@ public class Resources extends Form { for (WebElement row : resources().rows()) { ResourceRepresentation actual = resources().toRepresentation(row); if (actual.getName().equalsIgnoreCase(name)) { - URLUtils.navigateToUri(driver, row.findElements(tagName("a")).get(0).getAttribute("href"), true); - WaitUtils.waitForPageToLoad(driver); + clickLink(row.findElements(tagName("a")).get(0)); + WaitUtils.waitForPageToLoad(); resource.form().delete(); return; } @@ -89,8 +89,8 @@ public class Resources extends Form { for (WebElement row : resources().rows()) { ResourceRepresentation actual = resources().toRepresentation(row); if (actual.getName().equalsIgnoreCase(name)) { - URLUtils.navigateToUri(driver, row.findElements(tagName("a")).get(0).getAttribute("href"), true); - WaitUtils.waitForPageToLoad(driver); + clickLink(row.findElements(tagName("a")).get(0)); + WaitUtils.waitForPageToLoad(); return resource; } } diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/scope/Scopes.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/scope/Scopes.java index 3974e35fae..7324996aa6 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/scope/Scopes.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/authorization/scope/Scopes.java @@ -16,16 +16,16 @@ */ package org.keycloak.testsuite.console.page.clients.authorization.scope; -import static org.openqa.selenium.By.tagName; - import org.jboss.arquillian.graphene.page.Page; import org.keycloak.representations.idm.authorization.ScopeRepresentation; import org.keycloak.testsuite.page.Form; -import org.keycloak.testsuite.util.URLUtils; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; +import static org.keycloak.testsuite.util.UIUtils.clickLink; +import static org.openqa.selenium.By.tagName; + /** * @author Pedro Igor */ @@ -53,7 +53,7 @@ public class Scopes extends Form { for (WebElement row : scopes().rows()) { ScopeRepresentation actual = scopes().toRepresentation(row); if (actual.getName().equalsIgnoreCase(name)) { - URLUtils.navigateToUri(driver, row.findElements(tagName("a")).get(0).getAttribute("href"), true); + clickLink(row.findElements(tagName("a")).get(0)); scope.form().populate(representation); } } @@ -63,7 +63,7 @@ public class Scopes extends Form { for (WebElement row : scopes().rows()) { ScopeRepresentation actual = scopes().toRepresentation(row); if (actual.getName().equalsIgnoreCase(name)) { - URLUtils.navigateToUri(driver, row.findElements(tagName("a")).get(0).getAttribute("href"), true); + clickLink(row.findElements(tagName("a")).get(0)); scope.form().delete(); } } diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/credentials/ClientCredentialsForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/credentials/ClientCredentialsForm.java index 3ec2773e74..b29de62c0e 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/credentials/ClientCredentialsForm.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/credentials/ClientCredentialsForm.java @@ -57,18 +57,18 @@ public class ClientCredentialsForm extends Form { public void regenerateSecret() { waitUntilElement(regenerateSecretButton).is().visible(); regenerateSecretButton.click(); - waitForPageToLoad(driver); + waitForPageToLoad(); } public void regenerateRegistrationAccessToken() { waitUntilElement(regenerateRegistrationAccessTokenButton).is().visible(); regenerateRegistrationAccessTokenButton.click(); - waitForPageToLoad(driver); + waitForPageToLoad(); } public void generateNewKeysAndCert() { waitUntilElement(generateNewKeysAndCert).is().visible(); generateNewKeysAndCert.click(); - waitForPageToLoad(driver); + waitForPageToLoad(); } } diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/installation/ClientInstallationForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/installation/ClientInstallationForm.java index fbd415ab69..2458931d06 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/installation/ClientInstallationForm.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/installation/ClientInstallationForm.java @@ -41,7 +41,7 @@ public class ClientInstallationForm extends Form { public void setConfigFormat(String value) { configFormatsSelect.selectByVisibleText(value); - WaitUtils.waitForPageToLoad(driver); + WaitUtils.waitForPageToLoad(); } public String getTextareaContent() { diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/mappers/CreateClientMappersForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/mappers/CreateClientMappersForm.java index a4b3107919..c43dfe0f52 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/mappers/CreateClientMappersForm.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/clients/mappers/CreateClientMappersForm.java @@ -116,7 +116,7 @@ public class CreateClientMappersForm extends Form { } WaitUtils.pause(1000); selectRealmRoleButton.click(); - WaitUtils.waitForModalFadeOut(driver); + WaitUtils.waitForModalFadeOut(); } public void selectClientRole(String clientName, String roleName) { @@ -126,7 +126,7 @@ public class CreateClientMappersForm extends Form { } WaitUtils.pause(1000); selectClientRoleButton.click(); - WaitUtils.waitForModalFadeOut(driver); + WaitUtils.waitForModalFadeOut(); } } diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/users/Users.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/users/Users.java index 4232289415..ca1fa9eb18 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/users/Users.java +++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/users/Users.java @@ -79,18 +79,18 @@ public class Users extends AdminConsoleRealm { } public void clickUser(String username) { - URLUtils.navigateToUri(driver, getRowByUsername(username).findElement(By.xpath("./td[position()=1]/a")).getAttribute("href"), true); - waitForPageToLoad(driver); + URLUtils.navigateToUri(getRowByUsername(username).findElement(By.xpath("./td[position()=1]/a")).getAttribute("href"), true); + waitForPageToLoad(); } public void editUser(String username) { clickRowActionButton(getRowByUsername(username), EDIT); - waitForPageToLoad(driver); + waitForPageToLoad(); } public void impersonateUser(String username) { clickRowActionButton(getRowByUsername(username), IMPERSONATE); - waitForPageToLoad(driver); + waitForPageToLoad(); } public void deleteUser(String username) { diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authentication/RequiredActionsTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authentication/RequiredActionsTest.java index b879e18322..d0c9068a5a 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authentication/RequiredActionsTest.java +++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authentication/RequiredActionsTest.java @@ -22,10 +22,8 @@ import org.junit.Before; import org.junit.Test; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.testsuite.Assert; -import org.keycloak.testsuite.auth.page.AuthRealm; import org.keycloak.testsuite.auth.page.login.Registration; import org.keycloak.testsuite.console.AbstractConsoleTest; -import org.keycloak.testsuite.console.page.AdminConsoleRealm; import org.keycloak.testsuite.console.page.authentication.RequiredActions; import org.keycloak.testsuite.console.page.realm.LoginSettings; import org.openqa.selenium.By; diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/events/LoginEventsTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/events/LoginEventsTest.java index 7a12f61a67..24b7a083a5 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/events/LoginEventsTest.java +++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/events/LoginEventsTest.java @@ -62,7 +62,7 @@ public class LoginEventsTest extends AbstractConsoleTest { resultList.get(0).findElement(By.xpath("//td[text()='LOGIN']")); resultList.get(0).findElement(By.xpath("//td[text()='User']/../td[text()='" + testUser.getId() + "']")); resultList.get(0).findElement(By.xpath("//td[text()='Client']/../td[text()='security-admin-console']")); - resultList.get(0).findElement(By.xpath("//td[text()='IP Address']/../td[text()='127.0.0.1']")); + resultList.get(0).findElement(By.xpath("//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']")); loginEventsPage.table().reset(); loginEventsPage.table().filterForm().addEventType("LOGOUT"); @@ -73,7 +73,7 @@ public class LoginEventsTest extends AbstractConsoleTest { assertEquals(1, resultList.size()); resultList.get(0).findElement(By.xpath("//td[text()='LOGOUT']")); resultList.get(0).findElement(By.xpath("//td[text()='User']/../td[text()='" + testUser.getId() + "']")); - resultList.get(0).findElement(By.xpath("//td[text()='IP Address']/../td[text()='127.0.0.1']")); + resultList.get(0).findElement(By.xpath("//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']")); loginEventsPage.table().reset(); loginEventsPage.table().filterForm().addEventType("LOGIN_ERROR"); @@ -86,7 +86,7 @@ public class LoginEventsTest extends AbstractConsoleTest { resultList.get(0).findElement(By.xpath("//td[text()='User']/../td[text()='" + testUser.getId() + "']")); resultList.get(0).findElement(By.xpath("//td[text()='Client']/../td[text()='security-admin-console']")); resultList.get(0).findElement(By.xpath("//td[text()='Error']/../td[text()='invalid_user_credentials']")); - resultList.get(0).findElement(By.xpath("//td[text()='IP Address']/../td[text()='127.0.0.1']")); + resultList.get(0).findElement(By.xpath("//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']")); } diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/realm/LoginSettingsTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/realm/LoginSettingsTest.java index 9495cdefea..d92b493884 100644 --- a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/realm/LoginSettingsTest.java +++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/realm/LoginSettingsTest.java @@ -42,6 +42,7 @@ import static org.keycloak.testsuite.admin.ApiUtil.createUserAndResetPasswordWit import static org.keycloak.testsuite.admin.Users.setPasswordFor; import static org.keycloak.testsuite.auth.page.AuthRealm.TEST; import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith; +import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf; /** * @@ -136,15 +137,16 @@ public class LoginSettingsTest extends AbstractRealmTest { log.info("edit username"); testAccountPage.navigateTo(); testRealmLoginPage.form().login(testUser); - testAccountPage.waitForAccountLinkPresent(); + assertCurrentUrlStartsWith(testAccountPage); testAccountPage.setUsername(NEW_USERNAME); testAccountPage.save(); testAccountPage.signOut(); log.debug("edited"); log.info("log in with edited username"); + assertCurrentUrlStartsWithLoginUrlOf(testAccountPage); testRealmLoginPage.form().login(NEW_USERNAME, PASSWORD); - testAccountPage.waitForAccountLinkPresent(); + assertCurrentUrlStartsWith(testAccountPage); log.debug("user is logged in with edited username"); log.info("disabling edit username"); @@ -202,6 +204,7 @@ public class LoginSettingsTest extends AbstractRealmTest { testAccountPage.navigateTo(); testRealmLoginPage.form().rememberMe(true); testRealmLoginPage.form().login(testUser); + assertCurrentUrlStartsWith(testAccountPage); assertTrue("Cookie KEYCLOAK_REMEMBER_ME should be present.", getCookieNames().contains("KEYCLOAK_REMEMBER_ME")); @@ -265,7 +268,7 @@ public class LoginSettingsTest extends AbstractRealmTest { log.info("log in as new user"); testAccountPage.navigateTo(); testRealmLoginPage.form().login(newUser); - testAccountPage.waitForAccountLinkPresent(); + assertCurrentUrlStartsWith(testAccountPage); log.info("verified verify email is disabled"); diff --git a/testsuite/integration-arquillian/tests/other/nodejs_adapter/src/main/java/org/keycloak/testsuite/adapter/nodejs/page/NodejsExamplePage.java b/testsuite/integration-arquillian/tests/other/nodejs_adapter/src/main/java/org/keycloak/testsuite/adapter/nodejs/page/NodejsExamplePage.java index 0c223f429d..0feb8ecc16 100644 --- a/testsuite/integration-arquillian/tests/other/nodejs_adapter/src/main/java/org/keycloak/testsuite/adapter/nodejs/page/NodejsExamplePage.java +++ b/testsuite/integration-arquillian/tests/other/nodejs_adapter/src/main/java/org/keycloak/testsuite/adapter/nodejs/page/NodejsExamplePage.java @@ -50,11 +50,11 @@ public class NodejsExamplePage extends AbstractNodejsExamplePage { public boolean isOnLoginSecuredPage() { UriBuilder uriBuilder = createUriBuilder().path("login"); - return URLUtils.currentUrlEqual(driver, uriBuilder.build().toASCIIString()); + return URLUtils.currentUrlEqual(uriBuilder.build().toASCIIString()); } @Override public boolean isCurrent() { - return URLUtils.currentUrlStartWith(driver, toString()); + return URLUtils.currentUrlStartWith(toString()); } } diff --git a/testsuite/integration-arquillian/tests/pom.xml b/testsuite/integration-arquillian/tests/pom.xml index 324f7265e8..4a8fb3e425 100755 --- a/testsuite/integration-arquillian/tests/pom.xml +++ b/testsuite/integration-arquillian/tests/pom.xml @@ -93,9 +93,12 @@ ${project.build.directory}/examples htmlUnit + true chrome - /usr/bin/firefox --ignore-ssl-errors=true --web-security=false + /usr/bin/firefox + true + true true @@ -252,8 +255,13 @@ ${browser} ${htmlUnitBrowserVersion} + ${webdriverDownloadBinaries} + ${firefox_binary} ${phantomjs.cli.args} + ${chromeArguments} + + ${firefoxLegacyDriver} ${project.version} ${migration.project.version} @@ -313,6 +321,12 @@ org.jboss.arquillian.container arquillian-container-osgi 2.1.0.CR18 + + + com.google.guava + guava + + org.osgi @@ -986,9 +1000,18 @@ org.apache.commons commons-io + + com.google.guava + guava + + + org.apache.httpcomponents + httpclient + 4.5.3 + jfree jfreechart @@ -1067,6 +1090,12 @@ org.keycloak keycloak-dependencies-server-all pom + + + com.google.guava + guava + + @@ -1184,6 +1213,18 @@ + + + + + + org.seleniumhq.selenium + htmlunit-driver + 2.27 + + + +