From 314d303a99bc7b44547de090fdcca08d22fa3b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Barto=C5=A1?= Date: Tue, 15 Feb 2022 08:54:37 +0100 Subject: [PATCH] Possibility to ignore tests for particular browsers Closes #10213 --- .../KeycloakArquillianExtension.java | 4 +- .../annotation/IgnoreBrowserDriver.java | 53 ++++++++++++ .../annotation/IgnoreBrowserDrivers.java | 43 ++++++++++ .../decider/BrowserDriverIgnoreDecider.java | 85 +++++++++++++++++++ .../drone/KeycloakDronePostSetup.java | 11 ++- .../testsuite/util/BrowserDriverUtil.java | 57 +++++++++++++ .../other/IgnoreBrowserDriverClassTest.java | 54 ++++++++++++ .../other/IgnoreBrowserDriverMethodTest.java | 79 +++++++++++++++++ .../utils/WebAuthnBrowserDriverUtil.java | 32 +++++++ 9 files changed, 415 insertions(+), 3 deletions(-) create mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/annotation/IgnoreBrowserDriver.java create mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/annotation/IgnoreBrowserDrivers.java create mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/decider/BrowserDriverIgnoreDecider.java create mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/BrowserDriverUtil.java create mode 100644 testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/other/IgnoreBrowserDriverClassTest.java create mode 100644 testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/other/IgnoreBrowserDriverMethodTest.java create mode 100644 testsuite/integration-arquillian/tests/other/webauthn/src/main/java/org/keycloak/testsuite/webauthn/utils/WebAuthnBrowserDriverUtil.java 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 afe2ac41a0..af01583a31 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 @@ -27,6 +27,7 @@ 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.decider.BrowserDriverIgnoreDecider; import org.keycloak.testsuite.arquillian.h2.H2TestEnricher; import org.keycloak.testsuite.arquillian.jmx.JmxConnectorRegistryCreator; import org.keycloak.testsuite.arquillian.decider.AdapterTestExecutionDecider; @@ -73,7 +74,8 @@ public class KeycloakArquillianExtension implements LoadableExtension { .service(TestExecutionDecider.class, MigrationTestExecutionDecider.class) .service(TestExecutionDecider.class, AdapterTestExecutionDecider.class) .service(TestExecutionDecider.class, VaultTestExecutionDecider.class) - .service(TestExecutionDecider.class, AuthServerExcludeExecutionDecider.class); + .service(TestExecutionDecider.class, AuthServerExcludeExecutionDecider.class) + .service(TestExecutionDecider.class, BrowserDriverIgnoreDecider.class); builder .override(ResourceProvider.class, URLResourceProvider.class, URLProvider.class) diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/annotation/IgnoreBrowserDriver.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/annotation/IgnoreBrowserDriver.java new file mode 100644 index 0000000000..897675c686 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/annotation/IgnoreBrowserDriver.java @@ -0,0 +1,53 @@ +/* + * Copyright 2022 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.arquillian.annotation; + +import org.openqa.selenium.WebDriver; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Annotation for marking test method/class which should be ignored + * + * @author Martin Bartos + */ +@Documented +@Retention(RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +@Repeatable(IgnoreBrowserDrivers.class) +public @interface IgnoreBrowserDriver { + + /** + * Define for which WebDriver the test method/class should be ignored + */ + Class value(); + + /** + * Define whether the value should be negated + * + * Usable in cases when we want to execute test method/class with all WebDrivers except the one specified in value() + */ + boolean negate() default false; + +} \ No newline at end of file diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/annotation/IgnoreBrowserDrivers.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/annotation/IgnoreBrowserDrivers.java new file mode 100644 index 0000000000..91d6e2f994 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/annotation/IgnoreBrowserDrivers.java @@ -0,0 +1,43 @@ +/* + * Copyright 2022 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.arquillian.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Define more WebDrivers that should be ignored for a particular test method/class + *

+ * See {@link IgnoreBrowserDriver } + * + * @author Martin Bartos + */ +@Documented +@Retention(RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +public @interface IgnoreBrowserDrivers { + + /** + * Several WebDrivers for which the test method/class should be ignored + */ + IgnoreBrowserDriver[] value() default {}; +} diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/decider/BrowserDriverIgnoreDecider.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/decider/BrowserDriverIgnoreDecider.java new file mode 100644 index 0000000000..99b2953a4f --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/decider/BrowserDriverIgnoreDecider.java @@ -0,0 +1,85 @@ +/* + * Copyright 2022 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.arquillian.decider; + +import org.jboss.arquillian.core.api.Instance; +import org.jboss.arquillian.core.api.annotation.Inject; +import org.jboss.arquillian.test.spi.execution.ExecutionDecision; +import org.jboss.arquillian.test.spi.execution.TestExecutionDecider; +import org.keycloak.testsuite.arquillian.TestContext; +import org.keycloak.testsuite.arquillian.annotation.IgnoreBrowserDriver; +import org.keycloak.testsuite.arquillian.annotation.IgnoreBrowserDrivers; +import org.openqa.selenium.WebDriver; + +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.function.Predicate; + +import static org.keycloak.testsuite.util.BrowserDriverUtil.isDriverInstanceOf; + +/** + * Decider for ignoring tests for particular browsers (WebDrivers) + * + * @author Martin Bartos + */ +public class BrowserDriverIgnoreDecider implements TestExecutionDecider { + + @Inject + private Instance driver; + + @Inject + private Instance testContextInstance; + + @Override + public ExecutionDecision decide(Method method) { + if (isAnnotationPresent(method)) { + return decideIgnoring(method); + } else { //class + final TestContext testContext = testContextInstance.get(); + + if (isAnnotationPresent(testContext.getTestClass())) { + return decideIgnoring(testContext.getTestClass()); + } + } + return ExecutionDecision.execute(); + } + + private boolean isAnnotationPresent(AnnotatedElement element) { + return element.isAnnotationPresent(IgnoreBrowserDriver.class) || element.isAnnotationPresent(IgnoreBrowserDrivers.class); + } + + private ExecutionDecision decideIgnoring(AnnotatedElement element) { + final WebDriver webDriver = driver.get(); + + Predicate shouldBeIgnored = (item) -> { + return webDriver != null && (isDriverInstanceOf(webDriver, item.value()) ^ item.negate()); + }; + + return Arrays.stream(element.getAnnotationsByType(IgnoreBrowserDriver.class)) + .filter(shouldBeIgnored) + .findAny() + .map(f -> ExecutionDecision.dontExecute("This test should not be executed with this browser.")) + .orElse(ExecutionDecision.execute()); + } + + @Override + public int precedence() { + return Integer.MIN_VALUE; + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/drone/KeycloakDronePostSetup.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/drone/KeycloakDronePostSetup.java index 219ad15790..ef4c008818 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/drone/KeycloakDronePostSetup.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/drone/KeycloakDronePostSetup.java @@ -20,6 +20,8 @@ package org.keycloak.testsuite.drone; import java.util.concurrent.TimeUnit; import io.appium.java_client.AppiumDriver; +import org.jboss.arquillian.core.api.InstanceProducer; +import org.jboss.arquillian.core.api.annotation.Inject; import org.jboss.arquillian.core.api.annotation.Observes; import org.jboss.arquillian.drone.spi.DroneContext; import org.jboss.arquillian.drone.spi.DronePoint; @@ -27,6 +29,7 @@ import org.jboss.arquillian.drone.spi.event.AfterDroneEnhanced; import org.jboss.arquillian.graphene.proxy.GrapheneProxyInstance; import org.jboss.arquillian.graphene.proxy.Interceptor; import org.jboss.arquillian.graphene.proxy.InvocationContext; +import org.jboss.arquillian.test.spi.annotation.ClassScoped; import org.jboss.logging.Logger; import org.keycloak.testsuite.util.WaitUtils; import org.openqa.selenium.WebDriver; @@ -38,8 +41,11 @@ import org.openqa.selenium.remote.RemoteWebDriver; */ public class KeycloakDronePostSetup { - protected static final Logger log = org.jboss.logging.Logger.getLogger(KeycloakDronePostSetup.class); + @Inject + @ClassScoped // needed in BrowserDriverIgnoreDecider + private InstanceProducer webDriverProducer; + protected static final Logger log = org.jboss.logging.Logger.getLogger(KeycloakDronePostSetup.class); public void configureWebDriver(@Observes AfterDroneEnhanced event, DroneContext droneContext) { DronePoint dronePoint = event.getDronePoint(); @@ -48,12 +54,13 @@ public class KeycloakDronePostSetup { if (drone instanceof RemoteWebDriver) { RemoteWebDriver remoteWebDriver = (RemoteWebDriver) drone; log.infof("Detected browser: %s %s", remoteWebDriver.getCapabilities().getBrowserName(), remoteWebDriver.getCapabilities().getVersion()); + webDriverProducer.set(remoteWebDriver); } - if (drone instanceof WebDriver && !(drone instanceof AppiumDriver)) { WebDriver webDriver = (WebDriver) drone; configureDriverSettings(webDriver); + webDriverProducer.set(webDriver); } else { log.warn("Drone is not instanceof WebDriver for a desktop browser! Drone is " + drone); } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/BrowserDriverUtil.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/BrowserDriverUtil.java new file mode 100644 index 0000000000..09967a2e2b --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/BrowserDriverUtil.java @@ -0,0 +1,57 @@ +/* + * Copyright 2022 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.openqa.selenium.WebDriver; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.edge.EdgeDriver; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.opera.OperaDriver; +import org.openqa.selenium.safari.SafariDriver; + +/** + * Determine which WebDriver is used + * + * @author Martin Bartos + */ +public class BrowserDriverUtil { + + public static boolean isDriverInstanceOf(WebDriver driver, Class clazz) { + return clazz.isAssignableFrom(driver.getClass()); + } + + public static boolean isDriverChrome(WebDriver driver) { + return isDriverInstanceOf(driver, ChromeDriver.class); + } + + public static boolean isDriverFirefox(WebDriver driver) { + return isDriverInstanceOf(driver, FirefoxDriver.class); + } + + public static boolean isDriverOpera(WebDriver driver) { + return isDriverInstanceOf(driver, OperaDriver.class); + } + + public static boolean isDriverEdge(WebDriver driver) { + return isDriverInstanceOf(driver, EdgeDriver.class); + } + + public static boolean isDriverSafari(WebDriver driver) { + return isDriverInstanceOf(driver, SafariDriver.class); + } +} diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/other/IgnoreBrowserDriverClassTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/other/IgnoreBrowserDriverClassTest.java new file mode 100644 index 0000000000..19c6777fbe --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/other/IgnoreBrowserDriverClassTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2022 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.console.other; + +import org.junit.Test; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.testsuite.arquillian.annotation.IgnoreBrowserDriver; +import org.keycloak.testsuite.arquillian.annotation.IgnoreBrowserDrivers; +import org.keycloak.testsuite.console.AbstractConsoleTest; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.firefox.FirefoxDriver; + +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.keycloak.testsuite.util.BrowserDriverUtil.isDriverChrome; +import static org.keycloak.testsuite.util.BrowserDriverUtil.isDriverFirefox; + +/** + * @author Martin Bartos + */ +@IgnoreBrowserDrivers({ + @IgnoreBrowserDriver(FirefoxDriver.class), + @IgnoreBrowserDriver(value = ChromeDriver.class, negate = true)}) +public class IgnoreBrowserDriverClassTest extends AbstractConsoleTest { + + @Test + public void ignoreFirefoxAndNotChrome() { + assertThat(isDriverChrome(driver), is(true)); + assertThat(isDriverFirefox(driver), is(false)); + } + + @Test + @IgnoreBrowserDriver(ChromeDriver.class) + public void ignoreChrome() { + assertThat(isDriverChrome(driver), is(false)); + } +} diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/other/IgnoreBrowserDriverMethodTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/other/IgnoreBrowserDriverMethodTest.java new file mode 100644 index 0000000000..b36fb2f370 --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/other/IgnoreBrowserDriverMethodTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2022 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.console.other; + +import org.junit.Test; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.testsuite.arquillian.annotation.IgnoreBrowserDriver; +import org.keycloak.testsuite.arquillian.annotation.IgnoreBrowserDrivers; +import org.keycloak.testsuite.console.AbstractConsoleTest; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.firefox.FirefoxDriver; + +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.keycloak.testsuite.util.BrowserDriverUtil.isDriverChrome; +import static org.keycloak.testsuite.util.BrowserDriverUtil.isDriverFirefox; + +/** + * @author Martin Bartos + */ +public class IgnoreBrowserDriverMethodTest extends AbstractConsoleTest { + + @Test + @IgnoreBrowserDriver(FirefoxDriver.class) + public void allExceptFirefox() { + assertThat(isDriverFirefox(driver), is(false)); + } + + @Test + @IgnoreBrowserDriver(value = FirefoxDriver.class, negate = true) + public void onlyFirefox() { + assertThat(isDriverFirefox(driver), is(true)); + } + + @Test + @IgnoreBrowserDriver(ChromeDriver.class) + public void allExceptChrome() { + assertThat(isDriverChrome(driver), is(false)); + } + + @Test + @IgnoreBrowserDriver(value = ChromeDriver.class, negate = true) + public void onlyChrome() { + assertThat(isDriverChrome(driver), is(true)); + } + + @Test + @IgnoreBrowserDrivers({ + @IgnoreBrowserDriver(FirefoxDriver.class), + @IgnoreBrowserDriver(ChromeDriver.class) + }) + public void ignoreChromeAndFirefox() { + assertThat(isDriverChrome(driver), is(false)); + assertThat(isDriverFirefox(driver), is(false)); + } + + @Test + public void executeWithEachDriver() { + assertThat(driver, notNullValue()); + } +} diff --git a/testsuite/integration-arquillian/tests/other/webauthn/src/main/java/org/keycloak/testsuite/webauthn/utils/WebAuthnBrowserDriverUtil.java b/testsuite/integration-arquillian/tests/other/webauthn/src/main/java/org/keycloak/testsuite/webauthn/utils/WebAuthnBrowserDriverUtil.java new file mode 100644 index 0000000000..3db51a29e9 --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/webauthn/src/main/java/org/keycloak/testsuite/webauthn/utils/WebAuthnBrowserDriverUtil.java @@ -0,0 +1,32 @@ +/* + * Copyright 2022 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.webauthn.utils; + +import org.keycloak.testsuite.util.BrowserDriverUtil; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.chromium.ChromiumDriver; + +/** + * @author Martin Bartos + */ +public class WebAuthnBrowserDriverUtil extends BrowserDriverUtil { + + public static boolean isDriverChromiumBased(WebDriver driver) { + return BrowserDriverUtil.isDriverInstanceOf(driver, ChromiumDriver.class); + } +}