From 70c5cdf7addd2cfad60643db4a64c2861d475a19 Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Mon, 27 Jan 2020 19:23:49 +0300 Subject: [PATCH 01/28] extracted ISettingsFile and added tests --- pom.xml | 5 +++++ src/test/resources/settings.json | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/test/resources/settings.json diff --git a/pom.xml b/pom.xml index 52f72bb..416699a 100644 --- a/pom.xml +++ b/pom.xml @@ -95,6 +95,11 @@ jackson-databind 2.10.2 + + com.fasterxml.jackson.core + jackson-databind + 2.10.1 + org.seleniumhq.selenium selenium-java diff --git a/src/test/resources/settings.json b/src/test/resources/settings.json new file mode 100644 index 0000000..e2b7382 --- /dev/null +++ b/src/test/resources/settings.json @@ -0,0 +1,15 @@ +{ + "timeouts": { + "timeoutImplicit": 0, + "timeoutCondition": 30, + "timeoutPollingInterval": 300, + "timeoutCommand": 60 + }, + "retry": { + "number": 2, + "pollingInterval": 300 + }, + "logger": { + "language": "en" + } +} \ No newline at end of file From a3d6cb10bf0997ca035f4a3c45803c08858b58a4 Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Tue, 28 Jan 2020 12:15:54 +0300 Subject: [PATCH 02/28] extracted ILoggerConfiguration --- .../core/localization/SupportedLanguage.java | 5 +++++ .../configurations/LoggerConfigurationTests.java | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/main/java/aquality/selenium/core/localization/SupportedLanguage.java create mode 100644 src/test/java/tests/configurations/LoggerConfigurationTests.java diff --git a/src/main/java/aquality/selenium/core/localization/SupportedLanguage.java b/src/main/java/aquality/selenium/core/localization/SupportedLanguage.java new file mode 100644 index 0000000..1ff75cc --- /dev/null +++ b/src/main/java/aquality/selenium/core/localization/SupportedLanguage.java @@ -0,0 +1,5 @@ +package aquality.selenium.core.localization; + +public enum SupportedLanguage { + EN,RU +} diff --git a/src/test/java/tests/configurations/LoggerConfigurationTests.java b/src/test/java/tests/configurations/LoggerConfigurationTests.java new file mode 100644 index 0000000..1263d91 --- /dev/null +++ b/src/test/java/tests/configurations/LoggerConfigurationTests.java @@ -0,0 +1,16 @@ +package tests.configurations; + +import aquality.selenium.core.configurations.ILoggerConfiguration; +import aquality.selenium.core.localization.SupportedLanguage; +import org.testng.annotations.Test; +import tests.application.CustomAqualityServices; +import static org.testng.Assert.assertEquals; + +public class LoggerConfigurationTests { + + @Test + public void testShouldBePossibleToGetLanguage() { + SupportedLanguage language = CustomAqualityServices.getInjector().getInstance(ILoggerConfiguration.class).getLanguage(); + assertEquals(language, SupportedLanguage.EN, "Current language should be got from logger configuration"); + } +} \ No newline at end of file From d47c94a5e57bec6f644515a4f428dd40476cafb7 Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Tue, 28 Jan 2020 15:23:28 +0300 Subject: [PATCH 03/28] extracted ITimeoutConfiguration --- .../TimeoutConfigurationTests.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/java/tests/configurations/TimeoutConfigurationTests.java diff --git a/src/test/java/tests/configurations/TimeoutConfigurationTests.java b/src/test/java/tests/configurations/TimeoutConfigurationTests.java new file mode 100644 index 0000000..77e2807 --- /dev/null +++ b/src/test/java/tests/configurations/TimeoutConfigurationTests.java @@ -0,0 +1,19 @@ +package tests.configurations; + +import aquality.selenium.core.configurations.ITimeoutConfiguration; +import org.testng.annotations.Test; +import tests.application.CustomAqualityServices; + +import static org.testng.Assert.assertEquals; + +public class TimeoutConfigurationTests { + + @Test + public void testShouldBePossibleToGetLanguage() { + ITimeoutConfiguration timeoutConfiguration = CustomAqualityServices.getInjector().getInstance(ITimeoutConfiguration.class); + assertEquals(timeoutConfiguration.getCommand(), 60, "Command timeout should be got"); + assertEquals(timeoutConfiguration.getCondition(), 30, "Condition timeout should be got"); + assertEquals(timeoutConfiguration.getImplicit(), 0, "Implicit timeout should be got"); + assertEquals(timeoutConfiguration.getPollingInterval(), 300, "Polling interval should be got"); + } +} \ No newline at end of file From b95e87e1053ba0708cb414f7087eff1d91f948be Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Tue, 28 Jan 2020 15:34:40 +0300 Subject: [PATCH 04/28] extracted IRetryConfiguration --- .../RetryConfigurationTests.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/test/java/tests/configurations/RetryConfigurationTests.java diff --git a/src/test/java/tests/configurations/RetryConfigurationTests.java b/src/test/java/tests/configurations/RetryConfigurationTests.java new file mode 100644 index 0000000..1104e8a --- /dev/null +++ b/src/test/java/tests/configurations/RetryConfigurationTests.java @@ -0,0 +1,18 @@ +package tests.configurations; + +import aquality.selenium.core.configurations.IRetryConfiguration; +import aquality.selenium.core.configurations.ITimeoutConfiguration; +import org.testng.annotations.Test; +import tests.application.CustomAqualityServices; + +import static org.testng.Assert.assertEquals; + +public class RetryConfigurationTests { + + @Test + public void testShouldBePossibleToGetRetryConfiguration() { + IRetryConfiguration retryConfiguration = CustomAqualityServices.getInjector().getInstance(IRetryConfiguration.class); + assertEquals(retryConfiguration.getNumber(), 2, "Number of retry attempts timeout should be got"); + assertEquals(retryConfiguration.getPollingInterval(), 300, "Polling interval of retrier should be got"); + } +} \ No newline at end of file From 3ca9faf012d0fd3a7ebcbbde6e47f8e2ad7a97c8 Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Tue, 28 Jan 2020 15:35:32 +0300 Subject: [PATCH 05/28] renamed one test --- .../java/tests/configurations/TimeoutConfigurationTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/tests/configurations/TimeoutConfigurationTests.java b/src/test/java/tests/configurations/TimeoutConfigurationTests.java index 77e2807..e49966f 100644 --- a/src/test/java/tests/configurations/TimeoutConfigurationTests.java +++ b/src/test/java/tests/configurations/TimeoutConfigurationTests.java @@ -9,7 +9,7 @@ public class TimeoutConfigurationTests { @Test - public void testShouldBePossibleToGetLanguage() { + public void testShouldBePossibleToGetTimeoutConfiguration() { ITimeoutConfiguration timeoutConfiguration = CustomAqualityServices.getInjector().getInstance(ITimeoutConfiguration.class); assertEquals(timeoutConfiguration.getCommand(), 60, "Command timeout should be got"); assertEquals(timeoutConfiguration.getCondition(), 30, "Condition timeout should be got"); From 6221008a1ea4fbead65c726ba1b66e1b2b98be13 Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Tue, 28 Jan 2020 15:44:34 +0300 Subject: [PATCH 06/28] added empty end line and updated com.fasterxml.jackson.core to 2.10.2 --- pom.xml | 2 +- src/test/resources/settings.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 416699a..43f2b97 100644 --- a/pom.xml +++ b/pom.xml @@ -98,7 +98,7 @@ com.fasterxml.jackson.core jackson-databind - 2.10.1 + 2.10.2 org.seleniumhq.selenium diff --git a/src/test/resources/settings.json b/src/test/resources/settings.json index e2b7382..4271f20 100644 --- a/src/test/resources/settings.json +++ b/src/test/resources/settings.json @@ -12,4 +12,4 @@ "logger": { "language": "en" } -} \ No newline at end of file +} From ecb9c0a13eff9dbf655ef40226fef580b7a5c387 Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Tue, 28 Jan 2020 18:41:34 +0300 Subject: [PATCH 07/28] fixed naming and added empty line at the end of files --- .../java/tests/configurations/LoggerConfigurationTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/tests/configurations/LoggerConfigurationTests.java b/src/test/java/tests/configurations/LoggerConfigurationTests.java index 1263d91..19c7985 100644 --- a/src/test/java/tests/configurations/LoggerConfigurationTests.java +++ b/src/test/java/tests/configurations/LoggerConfigurationTests.java @@ -13,4 +13,4 @@ public void testShouldBePossibleToGetLanguage() { SupportedLanguage language = CustomAqualityServices.getInjector().getInstance(ILoggerConfiguration.class).getLanguage(); assertEquals(language, SupportedLanguage.EN, "Current language should be got from logger configuration"); } -} \ No newline at end of file +} From 22f0ff47803a54eba8063077d0694f92183251bb Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Tue, 28 Jan 2020 18:44:58 +0300 Subject: [PATCH 08/28] fixed naming and added empty line at the end of files --- .../java/tests/configurations/TimeoutConfigurationTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/tests/configurations/TimeoutConfigurationTests.java b/src/test/java/tests/configurations/TimeoutConfigurationTests.java index e49966f..456f932 100644 --- a/src/test/java/tests/configurations/TimeoutConfigurationTests.java +++ b/src/test/java/tests/configurations/TimeoutConfigurationTests.java @@ -16,4 +16,4 @@ public void testShouldBePossibleToGetTimeoutConfiguration() { assertEquals(timeoutConfiguration.getImplicit(), 0, "Implicit timeout should be got"); assertEquals(timeoutConfiguration.getPollingInterval(), 300, "Polling interval should be got"); } -} \ No newline at end of file +} From 2e0080a0ad1cce439c6b7f4112cce78e11364f73 Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Tue, 28 Jan 2020 18:56:17 +0300 Subject: [PATCH 09/28] fixed naming and added empty line at the end of files --- src/test/java/tests/configurations/RetryConfigurationTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/tests/configurations/RetryConfigurationTests.java b/src/test/java/tests/configurations/RetryConfigurationTests.java index 1104e8a..42cbffc 100644 --- a/src/test/java/tests/configurations/RetryConfigurationTests.java +++ b/src/test/java/tests/configurations/RetryConfigurationTests.java @@ -15,4 +15,4 @@ public void testShouldBePossibleToGetRetryConfiguration() { assertEquals(retryConfiguration.getNumber(), 2, "Number of retry attempts timeout should be got"); assertEquals(retryConfiguration.getPollingInterval(), 300, "Polling interval of retrier should be got"); } -} \ No newline at end of file +} From b503d61bf6b065e2f6bb3888980b3a5c680d44a2 Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Wed, 29 Jan 2020 17:31:00 +0300 Subject: [PATCH 10/28] merged with master and added test for CustomSettingsFile --- src/test/java/tests/utilities/SettingsFileTests.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/java/tests/utilities/SettingsFileTests.java b/src/test/java/tests/utilities/SettingsFileTests.java index 15397b6..21e0caa 100644 --- a/src/test/java/tests/utilities/SettingsFileTests.java +++ b/src/test/java/tests/utilities/SettingsFileTests.java @@ -114,4 +114,8 @@ public void after() { private TestModule getTestModule() { return new TestModule(CustomAqualityServices::getApplication); } + + private TestModule getTestModule(){ + return new TestModule(CustomAqualityServices::getApplication); + } } From 7c4c470c19d08cd2d132cdc7c5a3213f635432aa Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Wed, 29 Jan 2020 18:17:07 +0300 Subject: [PATCH 11/28] merge and small refactoring of tests --- .../java/tests/configurations/LoggerConfigurationTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/tests/configurations/LoggerConfigurationTests.java b/src/test/java/tests/configurations/LoggerConfigurationTests.java index 19c7985..f6caa67 100644 --- a/src/test/java/tests/configurations/LoggerConfigurationTests.java +++ b/src/test/java/tests/configurations/LoggerConfigurationTests.java @@ -10,7 +10,7 @@ public class LoggerConfigurationTests { @Test public void testShouldBePossibleToGetLanguage() { - SupportedLanguage language = CustomAqualityServices.getInjector().getInstance(ILoggerConfiguration.class).getLanguage(); + SupportedLanguage language = CustomAqualityServices.getServiceProvider().getInstance(ILoggerConfiguration.class).getLanguage(); assertEquals(language, SupportedLanguage.EN, "Current language should be got from logger configuration"); } } From cba8d49db3944b4f93334344b4a37bf4ad3bd02e Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Wed, 29 Jan 2020 18:23:04 +0300 Subject: [PATCH 12/28] merge from master --- .../java/tests/configurations/TimeoutConfigurationTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/tests/configurations/TimeoutConfigurationTests.java b/src/test/java/tests/configurations/TimeoutConfigurationTests.java index 456f932..9b2f84a 100644 --- a/src/test/java/tests/configurations/TimeoutConfigurationTests.java +++ b/src/test/java/tests/configurations/TimeoutConfigurationTests.java @@ -10,7 +10,7 @@ public class TimeoutConfigurationTests { @Test public void testShouldBePossibleToGetTimeoutConfiguration() { - ITimeoutConfiguration timeoutConfiguration = CustomAqualityServices.getInjector().getInstance(ITimeoutConfiguration.class); + ITimeoutConfiguration timeoutConfiguration = CustomAqualityServices.getServiceProvider().getInstance(ITimeoutConfiguration.class); assertEquals(timeoutConfiguration.getCommand(), 60, "Command timeout should be got"); assertEquals(timeoutConfiguration.getCondition(), 30, "Condition timeout should be got"); assertEquals(timeoutConfiguration.getImplicit(), 0, "Implicit timeout should be got"); From 9350294f8fb1ff39b10dbe417312e9cc022c87e8 Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Wed, 29 Jan 2020 18:43:14 +0300 Subject: [PATCH 13/28] merge from master --- src/test/java/tests/configurations/RetryConfigurationTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/tests/configurations/RetryConfigurationTests.java b/src/test/java/tests/configurations/RetryConfigurationTests.java index 42cbffc..4e05212 100644 --- a/src/test/java/tests/configurations/RetryConfigurationTests.java +++ b/src/test/java/tests/configurations/RetryConfigurationTests.java @@ -11,7 +11,7 @@ public class RetryConfigurationTests { @Test public void testShouldBePossibleToGetRetryConfiguration() { - IRetryConfiguration retryConfiguration = CustomAqualityServices.getInjector().getInstance(IRetryConfiguration.class); + IRetryConfiguration retryConfiguration = CustomAqualityServices.getServiceProvider().getInstance(IRetryConfiguration.class); assertEquals(retryConfiguration.getNumber(), 2, "Number of retry attempts timeout should be got"); assertEquals(retryConfiguration.getPollingInterval(), 300, "Polling interval of retrier should be got"); } From 7c948cf1d68f44216d8578364f5d6e9c33dd499a Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Thu, 30 Jan 2020 10:20:54 +0300 Subject: [PATCH 14/28] extracted IElementCacheConfiguration --- .../ElementCacheConfigurationTests.java | 16 ++++++++++++++++ src/test/resources/settings.json | 3 +++ 2 files changed, 19 insertions(+) create mode 100644 src/test/java/tests/configurations/ElementCacheConfigurationTests.java diff --git a/src/test/java/tests/configurations/ElementCacheConfigurationTests.java b/src/test/java/tests/configurations/ElementCacheConfigurationTests.java new file mode 100644 index 0000000..f5735bd --- /dev/null +++ b/src/test/java/tests/configurations/ElementCacheConfigurationTests.java @@ -0,0 +1,16 @@ +package tests.configurations; + +import aquality.selenium.core.configurations.IElementCacheConfiguration; +import org.testng.annotations.Test; +import tests.application.CustomAqualityServices; + +import static org.testng.Assert.assertFalse; + +public class ElementCacheConfigurationTests { + + @Test + public void testShouldBePossibleCheckIsEnableElementCache() { + boolean isEnable = CustomAqualityServices.getServiceProvider().getInstance(IElementCacheConfiguration.class).isEnabled(); + assertFalse(isEnable, "Element cache is disabled by default"); + } +} diff --git a/src/test/resources/settings.json b/src/test/resources/settings.json index 4271f20..cc2e51d 100644 --- a/src/test/resources/settings.json +++ b/src/test/resources/settings.json @@ -11,5 +11,8 @@ }, "logger": { "language": "en" + }, + "elementCache": { + "isEnabled": false } } From 81383dd43cfe0457109e2ffacb5d03437d688b5c Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Thu, 30 Jan 2020 13:14:11 +0300 Subject: [PATCH 15/28] application to applications added tests for conditionalWait --- .../core/applications/AqualityServices.java | 10 +- .../core/applications/IApplication.java | 4 +- .../tests/application/IApplicationTests.java | 12 +- .../tests/waitings/ConditionalWaitTests.java | 175 ++++++++++++++++++ src/test/java/utils/TimeUtil.java | 8 + 5 files changed, 196 insertions(+), 13 deletions(-) create mode 100644 src/test/java/tests/waitings/ConditionalWaitTests.java create mode 100644 src/test/java/utils/TimeUtil.java diff --git a/src/main/java/aquality/selenium/core/applications/AqualityServices.java b/src/main/java/aquality/selenium/core/applications/AqualityServices.java index 03572d2..3cc435b 100644 --- a/src/main/java/aquality/selenium/core/applications/AqualityServices.java +++ b/src/main/java/aquality/selenium/core/applications/AqualityServices.java @@ -24,14 +24,14 @@ protected > AqualityServices(Provider application } /** - * @return true if the application is already started, false otherwise. + * @return true if the applications is already started, false otherwise. */ protected boolean isAppStarted() { return app != null && app.isStarted(); } /** - * Sets the application instance, saving it to DI container. + * Sets the applications instance, saving it to DI container. * @param application instance to set into container. */ protected void setApp(T application) { @@ -39,9 +39,9 @@ protected void setApp(T application) { } /** - * Returns an existing application or initializes a new one based on passed parameter. - * @param startApplicationFunction function to start the application, where the injector could be used. - * @return started application. + * Returns an existing applications or initializes a new one based on passed parameter. + * @param startApplicationFunction function to start the applications, where the injector could be used. + * @return started applications. */ protected T getApp(Function startApplicationFunction) { if (!isAppStarted()) { diff --git a/src/main/java/aquality/selenium/core/applications/IApplication.java b/src/main/java/aquality/selenium/core/applications/IApplication.java index 6b61943..c171c65 100644 --- a/src/main/java/aquality/selenium/core/applications/IApplication.java +++ b/src/main/java/aquality/selenium/core/applications/IApplication.java @@ -5,7 +5,7 @@ import java.util.concurrent.TimeUnit; /** - * Interface of any application controlled by Selenium WebDriver API + * Interface of any applications controlled by Selenium WebDriver API */ public interface IApplication { @@ -15,7 +15,7 @@ public interface IApplication { RemoteWebDriver getDriver(); /** - * @return Is the application already running or not. + * @return Is the applications already running or not. */ boolean isStarted(); diff --git a/src/test/java/tests/application/IApplicationTests.java b/src/test/java/tests/application/IApplicationTests.java index 9eef6e8..c3ded8d 100644 --- a/src/test/java/tests/application/IApplicationTests.java +++ b/src/test/java/tests/application/IApplicationTests.java @@ -22,7 +22,7 @@ default void testShouldBePossibleToGetApplication() { @Test default void testShouldBePossibleToGetDriver() { - Assert.assertNotNull(getApplication().getDriver(), "should be possible get driver from the application"); + Assert.assertNotNull(getApplication().getDriver(), "should be possible get driver from the applications"); } @Test @@ -42,17 +42,17 @@ default void checkImplicitWaitSetting(int valueInSeconds) { @Test default void testShouldBePossibleToDefineIsStarted() { Assert.assertFalse(isApplicationStarted(), - "application should not be started before getting"); + "applications should not be started before getting"); IApplication application = getApplication(); Assert.assertTrue(application.isStarted(), - "application should be started when got it from the aquality services"); + "applications should be started when got it from the aquality services"); Assert.assertTrue(isApplicationStarted(), - "application should be started when check it's state from the aquality services"); + "applications should be started when check it's state from the aquality services"); application.getDriver().quit(); Assert.assertFalse(application.isStarted(), - "application should not be started after quit"); + "applications should not be started after quit"); Assert.assertFalse(isApplicationStarted(), - "application should not be started when check it's state from the aquality services after quit"); + "applications should not be started when check it's state from the aquality services after quit"); } @AfterMethod diff --git a/src/test/java/tests/waitings/ConditionalWaitTests.java b/src/test/java/tests/waitings/ConditionalWaitTests.java new file mode 100644 index 0000000..174805d --- /dev/null +++ b/src/test/java/tests/waitings/ConditionalWaitTests.java @@ -0,0 +1,175 @@ +package tests.waitings; + +import aquality.selenium.core.configurations.ITimeoutConfiguration; +import aquality.selenium.core.waitings.IConditionalWait; +import org.openqa.selenium.StaleElementReferenceException; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import tests.application.CustomAqualityServices; +import utils.Timer; + +import java.util.Collections; +import java.util.concurrent.TimeoutException; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +public class ConditionalWaitTests { + + private static final long waitForTimeoutCondition = 10; + private static final long waitForTimeoutPolling = 150; + private Timer timer; + private ITimeoutConfiguration timeoutConfiguration; + private IConditionalWait conditionalWait; + + @BeforeMethod + public void init() { + timeoutConfiguration = CustomAqualityServices.getServiceProvider().getInstance(ITimeoutConfiguration.class); + conditionalWait = CustomAqualityServices.getServiceProvider().getInstance(IConditionalWait.class); + timer = new Timer(); + } + + @AfterMethod + public void quitApplication() { + CustomAqualityServices.getApplication().getDriver().quit(); + } + + @Test + public void testFalseShouldBeReturnedIfConditionIsNotMetAndDefaultTimeoutIsOver() { + long timeoutCondition = timeoutConfiguration.getCondition(); + boolean result = conditionalWait.waitForTrue(() -> + { + timer.start(); + return false; + }, "Condition should be true"); + double duration = timer.stop(); + + assertFalse(result); + assertTrue(duration > timeoutCondition && duration < 2 * timeoutCondition); + } + + @Test + public void testTimeoutExceptionShouldBeThrownIfConditionIsMetAndTimeoutIsOver() { + try { + conditionalWait.waitForTrue(() -> + { + timer.start(); + return false; + }, waitForTimeoutCondition, waitForTimeoutPolling, "Condition should be true"); + } catch (TimeoutException e) { + double duration = timer.stop(); + assertTrue(duration > waitForTimeoutCondition && duration < 2 * waitForTimeoutCondition); + } + } + + @Test + public void testTimeoutExceptionShouldNotBeThrownIfConditionIsMetAndDefaultTimeoutIsNotOver() { + long timeoutCondition = timeoutConfiguration.getCondition(); + + boolean result = conditionalWait.waitForTrue(() -> + { + timer.start(); + return true; + }, "Timeout exception should not be thrown"); + double duration = timer.stop(); + + assertTrue(result); + assertTrue(duration < timeoutCondition); + } + + @Test + public void testTimeoutExceptionShouldNotBeThrownIfConditionMetAndTimeoutIsNotOver() throws TimeoutException { + conditionalWait.waitForTrue(() -> + { + timer.start(); + return true; + }, waitForTimeoutCondition, waitForTimeoutPolling, "Timeout exception should not be thrown"); + double duration = timer.stop(); + + assertTrue(duration < waitForTimeoutCondition); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testNullCannotBePassedAsCondition() { + conditionalWait.waitForTrue(null, "Condition should not be null"); + } + + @Test + public void testTimeoutExceptionShouldBeThrownIfDriverConditionIsNotMetAndDefaultTimeoutIsOver() { + long timeoutCondition = timeoutConfiguration.getCondition(); + try { + conditionalWait.waitFor((driver) -> + { + timer.start(); + return false; + }, + "Condition should be true"); + + } catch (org.openqa.selenium.TimeoutException e) { + double duration = timer.stop(); + + assertTrue(duration > timeoutCondition && duration < 2 * timeoutCondition); + } + } + + @Test + public void testTimeoutExceptionShouldBeThrownIfDriverConditionIsNotMetAndTimeoutIsOver() { + try { + conditionalWait.waitFor((driver) -> + { + timer.start(); + return false; + }, waitForTimeoutCondition, waitForTimeoutPolling, + "Conditional should be true", Collections.singleton(StaleElementReferenceException.class)); + + } catch (org.openqa.selenium.TimeoutException e) { + double duration = timer.stop(); + + assertTrue(duration > waitForTimeoutCondition && duration < 2 * waitForTimeoutCondition); + + } + } + + @Test + public void testTimeoutExceptionShouldNotBeThrownIfDriverConditionIsMetAndDefaultTimeoutIsNotOver() { + conditionalWait.waitFor((driver) -> + { + timer.start(); + return true; + }, + "Conditional should be true"); + double duration = timer.stop(); + + assertTrue(duration < timeoutConfiguration.getCondition()); + } + + @Test + public void testExceptionShouldBeCaughtConditionIsMetAndDefaultTimeoutIsNotOver() { + try { + conditionalWait.waitFor((driver) -> + { + timer.start(); + throw new IllegalArgumentException("I am exception"); + }, waitForTimeoutCondition, waitForTimeoutPolling, + "Conditional should be true", Collections.singleton(IllegalArgumentException.class)); + } catch (org.openqa.selenium.TimeoutException e) { + double duration = timer.stop(); + + assertTrue(duration > waitForTimeoutCondition && duration < 2 * waitForTimeoutCondition); + } + } + + @Test + public void testTimeoutExceptionShouldNotBeThrownIfDriverConditionIsMetAndTimeoutIsNotOver() { + conditionalWait.waitFor((driver) -> + { + timer.start(); + return true; + }, waitForTimeoutCondition, waitForTimeoutPolling, + "Conditional should be true", Collections.singleton(IllegalArgumentException.class)); + double duration = timer.stop(); + + assertTrue(duration < waitForTimeoutCondition); + } +} diff --git a/src/test/java/utils/TimeUtil.java b/src/test/java/utils/TimeUtil.java new file mode 100644 index 0000000..76fc87a --- /dev/null +++ b/src/test/java/utils/TimeUtil.java @@ -0,0 +1,8 @@ +package utils; + +public class TimeUtil { + + public static double getCurrentTimeInSeconds() { + return System.nanoTime() / Math.pow(10, 9); + } +} From 2cde734047235f7433d86bb6b4d5a726a2b0b212 Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Thu, 30 Jan 2020 15:29:41 +0300 Subject: [PATCH 16/28] support multiple threads in ConditionalWaitTests added friendly messages to the tests --- .../tests/waitings/ConditionalWaitTests.java | 89 ++++++++++--------- 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/src/test/java/tests/waitings/ConditionalWaitTests.java b/src/test/java/tests/waitings/ConditionalWaitTests.java index 174805d..ffae995 100644 --- a/src/test/java/tests/waitings/ConditionalWaitTests.java +++ b/src/test/java/tests/waitings/ConditionalWaitTests.java @@ -19,7 +19,7 @@ public class ConditionalWaitTests { private static final long waitForTimeoutCondition = 10; private static final long waitForTimeoutPolling = 150; - private Timer timer; + private ThreadLocal timer = ThreadLocal.withInitial(Timer::new); private ITimeoutConfiguration timeoutConfiguration; private IConditionalWait conditionalWait; @@ -27,7 +27,6 @@ public class ConditionalWaitTests { public void init() { timeoutConfiguration = CustomAqualityServices.getServiceProvider().getInstance(ITimeoutConfiguration.class); conditionalWait = CustomAqualityServices.getServiceProvider().getInstance(IConditionalWait.class); - timer = new Timer(); } @AfterMethod @@ -40,13 +39,14 @@ public void testFalseShouldBeReturnedIfConditionIsNotMetAndDefaultTimeoutIsOver( long timeoutCondition = timeoutConfiguration.getCondition(); boolean result = conditionalWait.waitForTrue(() -> { - timer.start(); + timer.get().start(); return false; }, "Condition should be true"); - double duration = timer.stop(); - - assertFalse(result); - assertTrue(duration > timeoutCondition && duration < 2 * timeoutCondition); + double duration = timer.get().stop(); + assertFalse(result, "waitForTrue should return false when condition is not satisfied."); + assertTrue(duration > timeoutCondition && duration < 2 * timeoutCondition, + String.format("Duration '%s' should be between timeoutCondition '%s' and 2*timeoutCondition when condition is not satisfied.", + duration, timeoutCondition)); } @Test @@ -54,12 +54,14 @@ public void testTimeoutExceptionShouldBeThrownIfConditionIsMetAndTimeoutIsOver() try { conditionalWait.waitForTrue(() -> { - timer.start(); + timer.get().start(); return false; }, waitForTimeoutCondition, waitForTimeoutPolling, "Condition should be true"); } catch (TimeoutException e) { - double duration = timer.stop(); - assertTrue(duration > waitForTimeoutCondition && duration < 2 * waitForTimeoutCondition); + double duration = timer.get().stop(); + assertTrue(duration > waitForTimeoutCondition && duration < 2 * waitForTimeoutCondition, + String.format("Duration '%s' should be between waitForTimeoutCondition '%s' and 2*waitForTimeoutCondition when condition is not satisfied.", + duration, waitForTimeoutCondition)); } } @@ -69,25 +71,27 @@ public void testTimeoutExceptionShouldNotBeThrownIfConditionIsMetAndDefaultTimeo boolean result = conditionalWait.waitForTrue(() -> { - timer.start(); + timer.get().start(); return true; }, "Timeout exception should not be thrown"); - double duration = timer.stop(); - - assertTrue(result); - assertTrue(duration < timeoutCondition); + double duration = timer.get().stop(); + assertTrue(result, "waitForTrue should return true when condition is satisfied."); + assertTrue(duration < timeoutCondition, + String.format("Duration '%s' should be less than timeoutCondition '%s' when condition is satisfied.", + duration, timeoutCondition)); } @Test public void testTimeoutExceptionShouldNotBeThrownIfConditionMetAndTimeoutIsNotOver() throws TimeoutException { conditionalWait.waitForTrue(() -> { - timer.start(); + timer.get().start(); return true; }, waitForTimeoutCondition, waitForTimeoutPolling, "Timeout exception should not be thrown"); - double duration = timer.stop(); - - assertTrue(duration < waitForTimeoutCondition); + double duration = timer.get().stop(); + assertTrue(duration < waitForTimeoutCondition, + String.format("Duration '%s' should be less than waitForTimeoutCondition '%s' when condition is satisfied.", + duration, waitForTimeoutCondition)); } @Test(expectedExceptions = IllegalArgumentException.class) @@ -101,15 +105,15 @@ public void testTimeoutExceptionShouldBeThrownIfDriverConditionIsNotMetAndDefaul try { conditionalWait.waitFor((driver) -> { - timer.start(); + timer.get().start(); return false; }, "Condition should be true"); - } catch (org.openqa.selenium.TimeoutException e) { - double duration = timer.stop(); - - assertTrue(duration > timeoutCondition && duration < 2 * timeoutCondition); + double duration = timer.get().stop(); + assertTrue(duration > timeoutCondition && duration < 2 * timeoutCondition, + String.format("Duration '%s' before throwing should be between timeoutCondition '%s' and 2*timeoutCondition ", + duration, timeoutCondition)); } } @@ -118,16 +122,16 @@ public void testTimeoutExceptionShouldBeThrownIfDriverConditionIsNotMetAndTimeou try { conditionalWait.waitFor((driver) -> { - timer.start(); + timer.get().start(); return false; }, waitForTimeoutCondition, waitForTimeoutPolling, "Conditional should be true", Collections.singleton(StaleElementReferenceException.class)); } catch (org.openqa.selenium.TimeoutException e) { - double duration = timer.stop(); - - assertTrue(duration > waitForTimeoutCondition && duration < 2 * waitForTimeoutCondition); - + double duration = timer.get().stop(); + assertTrue(duration > waitForTimeoutCondition && duration < 2 * waitForTimeoutCondition, + String.format("Duration '%s' before throwing should be between waitForTimeoutCondition '%s' and 2*waitForTimeoutCondition", + duration, waitForTimeoutCondition)); } } @@ -135,13 +139,14 @@ public void testTimeoutExceptionShouldBeThrownIfDriverConditionIsNotMetAndTimeou public void testTimeoutExceptionShouldNotBeThrownIfDriverConditionIsMetAndDefaultTimeoutIsNotOver() { conditionalWait.waitFor((driver) -> { - timer.start(); + timer.get().start(); return true; }, "Conditional should be true"); - double duration = timer.stop(); - - assertTrue(duration < timeoutConfiguration.getCondition()); + double duration = timer.get().stop(); + assertTrue(duration < timeoutConfiguration.getCondition(), + String.format("Duration '%s' should be less than condition timeout '%s' when condition is satisfied.", + duration, timeoutConfiguration.getCondition())); } @Test @@ -149,14 +154,15 @@ public void testExceptionShouldBeCaughtConditionIsMetAndDefaultTimeoutIsNotOver( try { conditionalWait.waitFor((driver) -> { - timer.start(); + timer.get().start(); throw new IllegalArgumentException("I am exception"); }, waitForTimeoutCondition, waitForTimeoutPolling, "Conditional should be true", Collections.singleton(IllegalArgumentException.class)); } catch (org.openqa.selenium.TimeoutException e) { - double duration = timer.stop(); - - assertTrue(duration > waitForTimeoutCondition && duration < 2 * waitForTimeoutCondition); + double duration = timer.get().stop(); + assertTrue(duration > waitForTimeoutCondition && duration < 2 * waitForTimeoutCondition, + String.format("Duration '%s' before throwing should be between waitForTimeoutCondition '%s' and 2*waitForTimeoutCondition", + duration, waitForTimeoutCondition)); } } @@ -164,12 +170,13 @@ public void testExceptionShouldBeCaughtConditionIsMetAndDefaultTimeoutIsNotOver( public void testTimeoutExceptionShouldNotBeThrownIfDriverConditionIsMetAndTimeoutIsNotOver() { conditionalWait.waitFor((driver) -> { - timer.start(); + timer.get().start(); return true; }, waitForTimeoutCondition, waitForTimeoutPolling, "Conditional should be true", Collections.singleton(IllegalArgumentException.class)); - double duration = timer.stop(); - - assertTrue(duration < waitForTimeoutCondition); + double duration = timer.get().stop(); + assertTrue(duration < waitForTimeoutCondition, + String.format("Duration '%s' should be less than waitForTimeoutCondition '%s' when condition is satisfied.", + duration, waitForTimeoutCondition)); } } From d8d96cd96bab34a210147db442d7516796aa4db5 Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Thu, 30 Jan 2020 14:06:33 +0300 Subject: [PATCH 17/28] removed SupportedLanguaged and added default language if configuration is absent --- .../core/localization/SupportedLanguage.java | 5 ----- .../core/utilities/SettingsFileUtil.java | 11 +++++++++++ .../LoggerConfigurationTests.java | 6 +++--- src/test/resources/settings.json | 18 ------------------ 4 files changed, 14 insertions(+), 26 deletions(-) delete mode 100644 src/main/java/aquality/selenium/core/localization/SupportedLanguage.java create mode 100644 src/main/java/aquality/selenium/core/utilities/SettingsFileUtil.java delete mode 100644 src/test/resources/settings.json diff --git a/src/main/java/aquality/selenium/core/localization/SupportedLanguage.java b/src/main/java/aquality/selenium/core/localization/SupportedLanguage.java deleted file mode 100644 index 1ff75cc..0000000 --- a/src/main/java/aquality/selenium/core/localization/SupportedLanguage.java +++ /dev/null @@ -1,5 +0,0 @@ -package aquality.selenium.core.localization; - -public enum SupportedLanguage { - EN,RU -} diff --git a/src/main/java/aquality/selenium/core/utilities/SettingsFileUtil.java b/src/main/java/aquality/selenium/core/utilities/SettingsFileUtil.java new file mode 100644 index 0000000..eb9f67e --- /dev/null +++ b/src/main/java/aquality/selenium/core/utilities/SettingsFileUtil.java @@ -0,0 +1,11 @@ +package aquality.selenium.core.utilities; + +public class SettingsFileUtil { + + private SettingsFileUtil() { + } + + public static Object getValueOrDefault(ISettingsFile settingsFile, String path, Object defaultValue) { + return settingsFile.isValuePresent(path) ? settingsFile.getValue(path) : defaultValue; + } +} diff --git a/src/test/java/tests/configurations/LoggerConfigurationTests.java b/src/test/java/tests/configurations/LoggerConfigurationTests.java index f6caa67..de673d2 100644 --- a/src/test/java/tests/configurations/LoggerConfigurationTests.java +++ b/src/test/java/tests/configurations/LoggerConfigurationTests.java @@ -1,16 +1,16 @@ package tests.configurations; import aquality.selenium.core.configurations.ILoggerConfiguration; -import aquality.selenium.core.localization.SupportedLanguage; import org.testng.annotations.Test; import tests.application.CustomAqualityServices; + import static org.testng.Assert.assertEquals; public class LoggerConfigurationTests { @Test public void testShouldBePossibleToGetLanguage() { - SupportedLanguage language = CustomAqualityServices.getServiceProvider().getInstance(ILoggerConfiguration.class).getLanguage(); - assertEquals(language, SupportedLanguage.EN, "Current language should be got from logger configuration"); + String language = CustomAqualityServices.getServiceProvider().getInstance(ILoggerConfiguration.class).getLanguage(); + assertEquals(language, "en", "Current language should be got from logger configuration"); } } diff --git a/src/test/resources/settings.json b/src/test/resources/settings.json deleted file mode 100644 index cc2e51d..0000000 --- a/src/test/resources/settings.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "timeouts": { - "timeoutImplicit": 0, - "timeoutCondition": 30, - "timeoutPollingInterval": 300, - "timeoutCommand": 60 - }, - "retry": { - "number": 2, - "pollingInterval": 300 - }, - "logger": { - "language": "en" - }, - "elementCache": { - "isEnabled": false - } -} From b1ef703df43d98e1ad3568bf175b1ec734c20103 Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Thu, 30 Jan 2020 17:24:10 +0300 Subject: [PATCH 18/28] moved SettingsFileUtil to ISettingsFile --- .../selenium/core/utilities/SettingsFileUtil.java | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 src/main/java/aquality/selenium/core/utilities/SettingsFileUtil.java diff --git a/src/main/java/aquality/selenium/core/utilities/SettingsFileUtil.java b/src/main/java/aquality/selenium/core/utilities/SettingsFileUtil.java deleted file mode 100644 index eb9f67e..0000000 --- a/src/main/java/aquality/selenium/core/utilities/SettingsFileUtil.java +++ /dev/null @@ -1,11 +0,0 @@ -package aquality.selenium.core.utilities; - -public class SettingsFileUtil { - - private SettingsFileUtil() { - } - - public static Object getValueOrDefault(ISettingsFile settingsFile, String path, Object defaultValue) { - return settingsFile.isValuePresent(path) ? settingsFile.getValue(path) : defaultValue; - } -} From 4d9b80e430292e7e4483c8df93776b069716657c Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Thu, 30 Jan 2020 18:34:10 +0300 Subject: [PATCH 19/28] rename applications to application in docs --- .../selenium/core/applications/AqualityServices.java | 10 +++++----- .../selenium/core/applications/IApplication.java | 4 ++-- .../java/tests/application/IApplicationTests.java | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/aquality/selenium/core/applications/AqualityServices.java b/src/main/java/aquality/selenium/core/applications/AqualityServices.java index 3cc435b..03572d2 100644 --- a/src/main/java/aquality/selenium/core/applications/AqualityServices.java +++ b/src/main/java/aquality/selenium/core/applications/AqualityServices.java @@ -24,14 +24,14 @@ protected > AqualityServices(Provider application } /** - * @return true if the applications is already started, false otherwise. + * @return true if the application is already started, false otherwise. */ protected boolean isAppStarted() { return app != null && app.isStarted(); } /** - * Sets the applications instance, saving it to DI container. + * Sets the application instance, saving it to DI container. * @param application instance to set into container. */ protected void setApp(T application) { @@ -39,9 +39,9 @@ protected void setApp(T application) { } /** - * Returns an existing applications or initializes a new one based on passed parameter. - * @param startApplicationFunction function to start the applications, where the injector could be used. - * @return started applications. + * Returns an existing application or initializes a new one based on passed parameter. + * @param startApplicationFunction function to start the application, where the injector could be used. + * @return started application. */ protected T getApp(Function startApplicationFunction) { if (!isAppStarted()) { diff --git a/src/main/java/aquality/selenium/core/applications/IApplication.java b/src/main/java/aquality/selenium/core/applications/IApplication.java index c171c65..6b61943 100644 --- a/src/main/java/aquality/selenium/core/applications/IApplication.java +++ b/src/main/java/aquality/selenium/core/applications/IApplication.java @@ -5,7 +5,7 @@ import java.util.concurrent.TimeUnit; /** - * Interface of any applications controlled by Selenium WebDriver API + * Interface of any application controlled by Selenium WebDriver API */ public interface IApplication { @@ -15,7 +15,7 @@ public interface IApplication { RemoteWebDriver getDriver(); /** - * @return Is the applications already running or not. + * @return Is the application already running or not. */ boolean isStarted(); diff --git a/src/test/java/tests/application/IApplicationTests.java b/src/test/java/tests/application/IApplicationTests.java index c3ded8d..9eef6e8 100644 --- a/src/test/java/tests/application/IApplicationTests.java +++ b/src/test/java/tests/application/IApplicationTests.java @@ -22,7 +22,7 @@ default void testShouldBePossibleToGetApplication() { @Test default void testShouldBePossibleToGetDriver() { - Assert.assertNotNull(getApplication().getDriver(), "should be possible get driver from the applications"); + Assert.assertNotNull(getApplication().getDriver(), "should be possible get driver from the application"); } @Test @@ -42,17 +42,17 @@ default void checkImplicitWaitSetting(int valueInSeconds) { @Test default void testShouldBePossibleToDefineIsStarted() { Assert.assertFalse(isApplicationStarted(), - "applications should not be started before getting"); + "application should not be started before getting"); IApplication application = getApplication(); Assert.assertTrue(application.isStarted(), - "applications should be started when got it from the aquality services"); + "application should be started when got it from the aquality services"); Assert.assertTrue(isApplicationStarted(), - "applications should be started when check it's state from the aquality services"); + "application should be started when check it's state from the aquality services"); application.getDriver().quit(); Assert.assertFalse(application.isStarted(), - "applications should not be started after quit"); + "application should not be started after quit"); Assert.assertFalse(isApplicationStarted(), - "applications should not be started when check it's state from the aquality services after quit"); + "application should not be started when check it's state from the aquality services after quit"); } @AfterMethod From 033abb784fa6ee927052e87423f175c50650a10f Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Fri, 31 Jan 2020 13:21:41 +0300 Subject: [PATCH 20/28] #6 removed using of DI in tests --- .../tests/waitings/ConditionalWaitTests.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/test/java/tests/waitings/ConditionalWaitTests.java b/src/test/java/tests/waitings/ConditionalWaitTests.java index ffae995..6b358d2 100644 --- a/src/test/java/tests/waitings/ConditionalWaitTests.java +++ b/src/test/java/tests/waitings/ConditionalWaitTests.java @@ -1,7 +1,11 @@ package tests.waitings; +import aquality.selenium.core.applications.IApplication; import aquality.selenium.core.configurations.ITimeoutConfiguration; -import aquality.selenium.core.waitings.IConditionalWait; +import aquality.selenium.core.localization.ILocalizationManager; +import aquality.selenium.core.waitings.ConditionalWait; +import com.google.inject.Injector; +import com.google.inject.Provider; import org.openqa.selenium.StaleElementReferenceException; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; @@ -21,17 +25,21 @@ public class ConditionalWaitTests { private static final long waitForTimeoutPolling = 150; private ThreadLocal timer = ThreadLocal.withInitial(Timer::new); private ITimeoutConfiguration timeoutConfiguration; - private IConditionalWait conditionalWait; + private Provider application; + private ConditionalWait conditionalWait; @BeforeMethod public void init() { - timeoutConfiguration = CustomAqualityServices.getServiceProvider().getInstance(ITimeoutConfiguration.class); - conditionalWait = CustomAqualityServices.getServiceProvider().getInstance(IConditionalWait.class); + Injector serviceProvider = CustomAqualityServices.getServiceProvider(); + ILocalizationManager localizationManager = serviceProvider.getInstance(ILocalizationManager.class); + application = serviceProvider.getProvider(IApplication.class); + timeoutConfiguration = serviceProvider.getInstance(ITimeoutConfiguration.class); + conditionalWait = new ConditionalWait(application, timeoutConfiguration, localizationManager); } @AfterMethod public void quitApplication() { - CustomAqualityServices.getApplication().getDriver().quit(); + application.get().getDriver().quit(); } @Test @@ -78,7 +86,7 @@ public void testTimeoutExceptionShouldNotBeThrownIfConditionIsMetAndDefaultTimeo assertTrue(result, "waitForTrue should return true when condition is satisfied."); assertTrue(duration < timeoutCondition, String.format("Duration '%s' should be less than timeoutCondition '%s' when condition is satisfied.", - duration, timeoutCondition)); + duration, timeoutCondition)); } @Test From ffa1c1b1b0e4ed959e655481f359f310a6cccfb0 Mon Sep 17 00:00:00 2001 From: "Meleshko, Aleksey2" Date: Mon, 3 Feb 2020 18:33:38 +0300 Subject: [PATCH 21/28] Implement IElementFinder, add DesiredState and ElementState helpful classes --- .../selenium/core/elements/DesiredState.java | 47 +++++ .../selenium/core/elements/ElementFinder.java | 70 +++++++ .../selenium/core/elements/ElementState.java | 17 ++ .../elements/interfaces/IElementFinder.java | 183 ++++++++++++++++++ 4 files changed, 317 insertions(+) create mode 100644 src/main/java/aquality/selenium/core/elements/DesiredState.java create mode 100644 src/main/java/aquality/selenium/core/elements/ElementFinder.java create mode 100644 src/main/java/aquality/selenium/core/elements/ElementState.java create mode 100644 src/main/java/aquality/selenium/core/elements/interfaces/IElementFinder.java diff --git a/src/main/java/aquality/selenium/core/elements/DesiredState.java b/src/main/java/aquality/selenium/core/elements/DesiredState.java new file mode 100644 index 0000000..31c8c7b --- /dev/null +++ b/src/main/java/aquality/selenium/core/elements/DesiredState.java @@ -0,0 +1,47 @@ +package aquality.selenium.core.elements; + +import org.openqa.selenium.WebElement; + +import java.util.function.Predicate; + +/** + * Defines desired state for element with ability to handle exceptions. + */ +public class DesiredState { + + private final Predicate desiredStatePredicate; + private final String stateName; + private boolean isCatchingTimeoutException; + private boolean isThrowingNoSuchElementException; + + public DesiredState(Predicate desiredStatePredicate, String stateName){ + this.desiredStatePredicate = desiredStatePredicate; + this.stateName = stateName; + } + + public Predicate getElementStateCondition() { + return desiredStatePredicate; + } + + public String getStateName() { + return stateName; + } + + public DesiredState withCatchingTimeoutException(){ + this.isCatchingTimeoutException = true; + return this; + } + + public DesiredState withThrowingNoSuchElementException(){ + this.isThrowingNoSuchElementException = true; + return this; + } + + public boolean isCatchingInTimeoutException() { + return isCatchingTimeoutException; + } + + public boolean isThrowingNoSuchElementException() { + return isThrowingNoSuchElementException; + } +} diff --git a/src/main/java/aquality/selenium/core/elements/ElementFinder.java b/src/main/java/aquality/selenium/core/elements/ElementFinder.java new file mode 100644 index 0000000..da910db --- /dev/null +++ b/src/main/java/aquality/selenium/core/elements/ElementFinder.java @@ -0,0 +1,70 @@ +package aquality.selenium.core.elements; + +import aquality.selenium.core.elements.interfaces.IElementFinder; +import aquality.selenium.core.localization.ILocalizedLogger; +import aquality.selenium.core.waitings.IConditionalWait; +import com.google.inject.Inject; +import org.openqa.selenium.By; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.TimeoutException; +import org.openqa.selenium.WebElement; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class ElementFinder implements IElementFinder { + private final ILocalizedLogger localizedLogger; + private final IConditionalWait conditionalWait; + + @Inject + public ElementFinder(ILocalizedLogger localizedLogger, IConditionalWait conditionalWait) { + this.localizedLogger = localizedLogger; + this.conditionalWait = conditionalWait; + } + + @Override + public List findElements(By locator, DesiredState desiredState, Long timeoutInSeconds) { + List foundElements = new ArrayList<>(); + List resultElements = new ArrayList<>(); + try { + conditionalWait.waitFor(driver -> { + List currentFoundElements = driver == null ? new ArrayList<>() : driver.findElements(locator); + foundElements.addAll(currentFoundElements); + List filteredElements = currentFoundElements + .stream() + .filter(desiredState.getElementStateCondition()) + .collect(Collectors.toList()); + resultElements.addAll(filteredElements); + return !filteredElements.isEmpty(); + }, timeoutInSeconds, 100, null, null); //todo: rebase and use proper method + } + catch (TimeoutException e) { + applyResult(locator, desiredState, foundElements); + } + + return resultElements; + } + + /** + * depends on configuration of DesiredState object it can be required to throw or not NoSuchElementException + * @param locator locator that is using to find elements + * @param desiredState DesiredState object + * @param foundElements list of all found elements by locator. + */ + private void applyResult(By locator, DesiredState desiredState, List foundElements){ + String message = String.format("No elements with locator '%1$s' were found in %2$s state", locator, desiredState.getStateName()); + if (desiredState.isCatchingInTimeoutException()){ + if(foundElements.isEmpty()){ + if(desiredState.isThrowingNoSuchElementException()){ + throw new NoSuchElementException(message); + } + localizedLogger.debug("loc.no.elements.found.in.state", locator, desiredState.getStateName()); + }else { + localizedLogger.debug("loc.elements.were.found.but.not.in.state", locator, desiredState.getStateName()); + } + }else { + throw new TimeoutException(desiredState.getStateName()); + } + } +} diff --git a/src/main/java/aquality/selenium/core/elements/ElementState.java b/src/main/java/aquality/selenium/core/elements/ElementState.java new file mode 100644 index 0000000..707cd7e --- /dev/null +++ b/src/main/java/aquality/selenium/core/elements/ElementState.java @@ -0,0 +1,17 @@ +package aquality.selenium.core.elements; + +public enum ElementState { + DISPLAYED("displayed"), + EXISTS_IN_ANY_STATE("exists"); + + private final String state; + + ElementState(String state) { + this.state = state; + } + + @Override + public String toString() { + return state; + } +} diff --git a/src/main/java/aquality/selenium/core/elements/interfaces/IElementFinder.java b/src/main/java/aquality/selenium/core/elements/interfaces/IElementFinder.java new file mode 100644 index 0000000..2d18748 --- /dev/null +++ b/src/main/java/aquality/selenium/core/elements/interfaces/IElementFinder.java @@ -0,0 +1,183 @@ +package aquality.selenium.core.elements.interfaces; + +import aquality.selenium.core.elements.DesiredState; +import aquality.selenium.core.elements.ElementState; +import org.openqa.selenium.By; +import org.openqa.selenium.SearchContext; +import org.openqa.selenium.WebElement; + +import java.util.List; +import java.util.function.Predicate; + +/** + * Provides ability to find elements in desired ElementState. + */ +public interface IElementFinder extends SearchContext { + + /** + * Provides DesiredState with predicate for desired ElementState. + * @param state desired ElementState + * @return DesiredState with predicate. + */ + default DesiredState resolveState(ElementState state) { + Predicate elementStateCondition; + if (state == ElementState.DISPLAYED) { + elementStateCondition = WebElement::isDisplayed; + } else if (state == ElementState.EXISTS_IN_ANY_STATE) { + elementStateCondition = webElement -> true; + } else { + throw new UnsupportedOperationException(state.toString().concat(" state is not recognized")); + } + return new DesiredState(elementStateCondition, state.name()); + } + + /** + * Finds element in desired ElementState + * @param locator elements locator + * @param state desired ElementState + * @param timeoutInSeconds timeout for search + * @throws org.openqa.selenium.NoSuchElementException if element was not found in time in desired state + * @return found element + */ + default WebElement findElement(By locator, ElementState state, Long timeoutInSeconds) { + return findElements(locator, resolveState(state).withThrowingNoSuchElementException(), timeoutInSeconds).get(0); + } + + /** + * Finds element in desired ElementState with default timeout. + * @param locator elements locator + * @param state desired ElementState + * @throws org.openqa.selenium.NoSuchElementException if element was not found in time in desired state + * @return found element + */ + default WebElement findElement(By locator, ElementState state) { + return findElement(locator, state, null); + } + + /** + * Finds element in any state. + * @param locator elements locator + * @param timeoutInSeconds timeout for search + * @throws org.openqa.selenium.NoSuchElementException if element was not found in time + * @return found element + */ + default WebElement findElement(By locator, Long timeoutInSeconds) { + return findElement(locator, ElementState.EXISTS_IN_ANY_STATE, timeoutInSeconds); + } + + /** + * Finds element in any state with default timeout. + * @param locator elements locator + * @throws org.openqa.selenium.NoSuchElementException if element was not found in time + * @return found element + */ + default WebElement findElement(By locator) { + return findElement(locator, ElementState.EXISTS_IN_ANY_STATE, null); + } + + /** + * Finds element in desired ElementState defined by predicate. + * @param locator elements locator + * @param elementStateCondition predicate to define element state + * @param timeoutInSeconds timeout for search + * @throws org.openqa.selenium.NoSuchElementException if element was not found in time in desired state + * @return found element + */ + default WebElement findElement(By locator, Predicate elementStateCondition, Long timeoutInSeconds) { + DesiredState state = new DesiredState(elementStateCondition, "desired") + .withThrowingNoSuchElementException(); + return findElements(locator, state, timeoutInSeconds).get(0); + } + + /** + * Finds element in desired ElementState defined by predicate with default timeout. + * @param locator elements locator + * @param elementStateCondition predicate to define element state + * @throws org.openqa.selenium.NoSuchElementException if element was not found in time in desired state + * @return found element + */ + default WebElement findElement(By locator, Predicate elementStateCondition) { + return findElement(locator, elementStateCondition, null); + } + + /** + * Finds elements in desired ElementState. + * @param locator elements locator + * @param state desired ElementState + * @param timeoutInSeconds timeout for search + * @return list of found elements + */ + default List findElements(By locator, ElementState state, Long timeoutInSeconds) { + return findElements(locator, resolveState(state).withCatchingTimeoutException(), timeoutInSeconds); + } + + /** + * Finds elements in any state. + * @param locator elements locator + * @param timeoutInSeconds timeout for search + * @return list of found elements + */ + default List findElements(By locator, Long timeoutInSeconds) { + return findElements(locator, ElementState.EXISTS_IN_ANY_STATE, timeoutInSeconds); + } + + /** + * Finds elements in desired ElementState with default timeout. + * @param locator elements locator + * @param state desired ElementState + * @return list of found elements + */ + default List findElements(By locator, ElementState state) { + return findElements(locator, state, null); + } + + /** + * Finds elements in any state with default timeout. + * @param locator elements locator + * @return list of found elements + */ + default List findElements(By locator) { + return findElements(locator, ElementState.EXISTS_IN_ANY_STATE, null); + } + + /** + * Finds elements in state defined by predicate. + * @param locator elements locator + * @param timeoutInSeconds timeout for search + * @param elementStateCondition predicate to define element state + * @return list of found elements + */ + default List findElements(By locator, Predicate elementStateCondition, Long timeoutInSeconds) { + DesiredState state = new DesiredState(elementStateCondition, "desired").withCatchingTimeoutException(); + return findElements(locator, state, timeoutInSeconds); + } + + /** + * Finds elements in state defined by predicate with default timeout. + * @param locator elements locator + * @param elementStateCondition predicate to define element state + * @return list of found elements + */ + default List findElements(By locator, Predicate elementStateCondition) { + return findElements(locator, elementStateCondition, null); + } + + /** + * Finds elements in state defined by DesiredState. + * @param locator elements locator + * @param timeoutInSeconds timeout for search + * @param desiredState predicate to define element state + * @return list of found elements + */ + List findElements(By locator, DesiredState desiredState, Long timeoutInSeconds); + + /** + * Finds elements in state defined by DesiredState with default timeout. + * @param locator elements locator + * @param desiredState predicate to define element state + * @return list of found elements + */ + default List findElements(By locator, DesiredState desiredState) { + return findElements(locator, desiredState, null); + } +} From 0078bf7c2764be97149aaabef897293428e3a365 Mon Sep 17 00:00:00 2001 From: "Meleshko, Aleksey2" Date: Tue, 4 Feb 2020 16:37:38 +0300 Subject: [PATCH 22/28] Completed ElementFinder, add RelativeElementFinder, add tests --- .../core/applications/AqualityModule.java | 5 +- .../selenium/core/elements/ElementFinder.java | 34 ++-- .../core/elements/IElementsModule.java | 15 ++ .../core/elements/RelativeElementFinder.java | 51 +++++ src/test/java/tests/ITestWithApplication.java | 16 ++ .../tests/application/IApplicationTests.java | 14 +- .../windowsApp/CalculatorWindow.java | 33 +++ .../tests/elements/ElementFinderTests.java | 33 +++ .../tests/elements/IElementFinderTests.java | 109 ++++++++++ .../elements/RelativeElementFinderTests.java | 26 +++ .../tests/utilities/SettingsFileTests.java | 4 - .../tests/waitings/ConditionalWaitTests.java | 190 ------------------ src/test/resources/TestSuite.xml | 2 + 13 files changed, 313 insertions(+), 219 deletions(-) create mode 100644 src/main/java/aquality/selenium/core/elements/IElementsModule.java create mode 100644 src/main/java/aquality/selenium/core/elements/RelativeElementFinder.java create mode 100644 src/test/java/tests/ITestWithApplication.java create mode 100644 src/test/java/tests/application/windowsApp/CalculatorWindow.java create mode 100644 src/test/java/tests/elements/ElementFinderTests.java create mode 100644 src/test/java/tests/elements/IElementFinderTests.java create mode 100644 src/test/java/tests/elements/RelativeElementFinderTests.java delete mode 100644 src/test/java/tests/waitings/ConditionalWaitTests.java diff --git a/src/main/java/aquality/selenium/core/applications/AqualityModule.java b/src/main/java/aquality/selenium/core/applications/AqualityModule.java index 7bb3f17..94de27d 100644 --- a/src/main/java/aquality/selenium/core/applications/AqualityModule.java +++ b/src/main/java/aquality/selenium/core/applications/AqualityModule.java @@ -1,6 +1,8 @@ package aquality.selenium.core.applications; import aquality.selenium.core.configurations.*; +import aquality.selenium.core.elements.IElementsModule; +import aquality.selenium.core.elements.interfaces.IElementFinder; import aquality.selenium.core.localization.ILocalizationManager; import aquality.selenium.core.localization.ILocalizationModule; import aquality.selenium.core.localization.ILocalizedLogger; @@ -18,7 +20,7 @@ * Describes all dependencies which is registered for the project. */ public class AqualityModule extends AbstractModule - implements ILocalizationModule, IUtilitiesModule, IWaitingsModule { + implements ILocalizationModule, IUtilitiesModule, IWaitingsModule, IElementsModule { private final Provider applicationProvider; @@ -42,5 +44,6 @@ protected void configure() { bind(ILocalizationManager.class).to(getLocalizationManagerImplementation()).in(Singleton.class); bind(ILocalizedLogger.class).to(getLocalizedLoggerImplementation()).in(Singleton.class); bind(IConditionalWait.class).to(getConditionalWaitImplementation()); + bind(IElementFinder.class).to(getElementFinderImplementation()); } } diff --git a/src/main/java/aquality/selenium/core/elements/ElementFinder.java b/src/main/java/aquality/selenium/core/elements/ElementFinder.java index da910db..08453fa 100644 --- a/src/main/java/aquality/selenium/core/elements/ElementFinder.java +++ b/src/main/java/aquality/selenium/core/elements/ElementFinder.java @@ -13,6 +13,9 @@ import java.util.List; import java.util.stream.Collectors; +/** + * Implementation of IElementFinder. + */ public class ElementFinder implements IElementFinder { private final ILocalizedLogger localizedLogger; private final IConditionalWait conditionalWait; @@ -37,10 +40,9 @@ public List findElements(By locator, DesiredState desiredState, Long .collect(Collectors.toList()); resultElements.addAll(filteredElements); return !filteredElements.isEmpty(); - }, timeoutInSeconds, 100, null, null); //todo: rebase and use proper method - } - catch (TimeoutException e) { - applyResult(locator, desiredState, foundElements); + }, timeoutInSeconds, null); + } catch (TimeoutException e) { + handleTimeoutException(e, locator, desiredState, foundElements); } return resultElements; @@ -48,23 +50,29 @@ public List findElements(By locator, DesiredState desiredState, Long /** * depends on configuration of DesiredState object it can be required to throw or not NoSuchElementException - * @param locator locator that is using to find elements - * @param desiredState DesiredState object + * + * @param exception TimeoutException to handle + * @param locator locator that is using to find elements + * @param desiredState DesiredState object * @param foundElements list of all found elements by locator. */ - private void applyResult(By locator, DesiredState desiredState, List foundElements){ + protected void handleTimeoutException(TimeoutException exception, By locator, DesiredState desiredState, List foundElements) { String message = String.format("No elements with locator '%1$s' were found in %2$s state", locator, desiredState.getStateName()); - if (desiredState.isCatchingInTimeoutException()){ - if(foundElements.isEmpty()){ - if(desiredState.isThrowingNoSuchElementException()){ + if (desiredState.isCatchingInTimeoutException()) { + if (foundElements.isEmpty()) { + if (desiredState.isThrowingNoSuchElementException()) { throw new NoSuchElementException(message); } localizedLogger.debug("loc.no.elements.found.in.state", locator, desiredState.getStateName()); - }else { + } else { localizedLogger.debug("loc.elements.were.found.but.not.in.state", locator, desiredState.getStateName()); } - }else { - throw new TimeoutException(desiredState.getStateName()); + } else { + String combinedMessage = String.format("%1$s: %2$s", exception.getMessage(), message); + if (desiredState.isThrowingNoSuchElementException() && foundElements.isEmpty()) { + throw new NoSuchElementException(combinedMessage); + } + throw new TimeoutException(combinedMessage); } } } diff --git a/src/main/java/aquality/selenium/core/elements/IElementsModule.java b/src/main/java/aquality/selenium/core/elements/IElementsModule.java new file mode 100644 index 0000000..1b3f982 --- /dev/null +++ b/src/main/java/aquality/selenium/core/elements/IElementsModule.java @@ -0,0 +1,15 @@ +package aquality.selenium.core.elements; + +import aquality.selenium.core.elements.interfaces.IElementFinder; + +/** + * Describes implementations of elements services to be registered in DI container. + */ +public interface IElementsModule { + /** + * @return class which implements IElementFinder + */ + default Class getElementFinderImplementation() { + return ElementFinder.class; + } +} diff --git a/src/main/java/aquality/selenium/core/elements/RelativeElementFinder.java b/src/main/java/aquality/selenium/core/elements/RelativeElementFinder.java new file mode 100644 index 0000000..b520b52 --- /dev/null +++ b/src/main/java/aquality/selenium/core/elements/RelativeElementFinder.java @@ -0,0 +1,51 @@ +package aquality.selenium.core.elements; + +import aquality.selenium.core.localization.ILocalizedLogger; +import aquality.selenium.core.waitings.IConditionalWait; +import org.openqa.selenium.By; +import org.openqa.selenium.SearchContext; +import org.openqa.selenium.WebElement; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeoutException; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +/** + * Implementation of IElementFinder for a relative SearchContext. + */ +public class RelativeElementFinder extends ElementFinder { + private final IConditionalWait conditionalWait; + private final Supplier searchContextSupplier; + + public RelativeElementFinder(ILocalizedLogger localizedLogger, IConditionalWait conditionalWait, + Supplier searchContextSupplier) { + super(localizedLogger, conditionalWait); + this.conditionalWait = conditionalWait; + this.searchContextSupplier = searchContextSupplier; + } + + @Override + public List findElements(By locator, DesiredState desiredState, Long timeoutInSeconds) { + List foundElements = new ArrayList<>(); + List resultElements = new ArrayList<>(); + try { + conditionalWait.waitForTrue(() -> { + List currentFoundElements = searchContextSupplier.get().findElements(locator); + foundElements.addAll(currentFoundElements); + List filteredElements = currentFoundElements + .stream() + .filter(desiredState.getElementStateCondition()) + .collect(Collectors.toList()); + resultElements.addAll(filteredElements); + return !filteredElements.isEmpty(); + }, timeoutInSeconds, null); + } catch (TimeoutException e) { + handleTimeoutException(new org.openqa.selenium.TimeoutException(e.getMessage(), e), locator, desiredState, + foundElements); + } + + return resultElements; + } +} diff --git a/src/test/java/tests/ITestWithApplication.java b/src/test/java/tests/ITestWithApplication.java new file mode 100644 index 0000000..a4ec609 --- /dev/null +++ b/src/test/java/tests/ITestWithApplication.java @@ -0,0 +1,16 @@ +package tests; + +import aquality.selenium.core.applications.IApplication; +import org.testng.annotations.AfterMethod; + +public interface ITestWithApplication { + IApplication getApplication(); + boolean isApplicationStarted(); + + @AfterMethod + default void cleanUp () { + if (isApplicationStarted()) { + getApplication().getDriver().quit(); + } + } +} diff --git a/src/test/java/tests/application/IApplicationTests.java b/src/test/java/tests/application/IApplicationTests.java index 9eef6e8..f204de3 100644 --- a/src/test/java/tests/application/IApplicationTests.java +++ b/src/test/java/tests/application/IApplicationTests.java @@ -3,14 +3,13 @@ import aquality.selenium.core.applications.IApplication; import com.google.inject.Injector; import org.testng.Assert; -import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; +import tests.ITestWithApplication; + import java.util.concurrent.TimeUnit; -public interface IApplicationTests { - IApplication getApplication(); +public interface IApplicationTests extends ITestWithApplication { Injector getServiceProvider(); - boolean isApplicationStarted(); @Test default void testShouldBePossibleToGetApplication() { @@ -54,11 +53,4 @@ default void testShouldBePossibleToDefineIsStarted() { Assert.assertFalse(isApplicationStarted(), "application should not be started when check it's state from the aquality services after quit"); } - - @AfterMethod - default void cleanUp () { - if (isApplicationStarted()) { - getApplication().getDriver().quit(); - } - } } diff --git a/src/test/java/tests/application/windowsApp/CalculatorWindow.java b/src/test/java/tests/application/windowsApp/CalculatorWindow.java new file mode 100644 index 0000000..27868d9 --- /dev/null +++ b/src/test/java/tests/application/windowsApp/CalculatorWindow.java @@ -0,0 +1,33 @@ +package tests.application.windowsApp; + +import io.appium.java_client.MobileBy; +import org.openqa.selenium.By; + +public class CalculatorWindow { + private CalculatorWindow(){ + } + + public static By getWindowLocator() { + return By.tagName("Window"); + } + + public static By getOneButton() { + return By.name("1"); + } + + public static By getTwoButton() { + return By.name("2"); + } + + public static By getPlusButton() { + return By.name("+"); + } + + public static By getEqualsButton() { + return By.name("="); + } + + public static By getResultsLabel() { + return MobileBy.AccessibilityId("48"); + } +} diff --git a/src/test/java/tests/elements/ElementFinderTests.java b/src/test/java/tests/elements/ElementFinderTests.java new file mode 100644 index 0000000..8afa9fc --- /dev/null +++ b/src/test/java/tests/elements/ElementFinderTests.java @@ -0,0 +1,33 @@ +package tests.elements; + +import aquality.selenium.core.elements.interfaces.IElementFinder; +import aquality.selenium.core.waitings.IConditionalWait; +import org.testng.Assert; +import org.testng.annotations.Test; +import tests.application.windowsApp.AqualityServices; +import tests.application.windowsApp.CalculatorWindow; + +import java.util.function.BooleanSupplier; + +public class ElementFinderTests implements IElementFinderTests { + + @Override + public IElementFinder getElementFinder() { + return AqualityServices.get(IElementFinder.class); + } + + @Test + public void shouldBePossibleToUseConditionalWaitWithElementFinder() { + BooleanSupplier elementFinderCondition = () -> + getElementFinder().findElement(CalculatorWindow.getResultsLabel()).getText().contains("3"); + Assert.assertFalse(elementFinderCondition.getAsBoolean(), "condition should not match before actions"); + Assert.assertTrue(AqualityServices.get(IConditionalWait.class) + .waitFor(driver -> { + driver.findElement(CalculatorWindow.getTwoButton()).click(); + driver.findElement(CalculatorWindow.getPlusButton()).click(); + driver.findElement(CalculatorWindow.getOneButton()).click(); + driver.findElement(CalculatorWindow.getEqualsButton()).click(); + return elementFinderCondition.getAsBoolean(); + })); + } +} diff --git a/src/test/java/tests/elements/IElementFinderTests.java b/src/test/java/tests/elements/IElementFinderTests.java new file mode 100644 index 0000000..c7f8979 --- /dev/null +++ b/src/test/java/tests/elements/IElementFinderTests.java @@ -0,0 +1,109 @@ +package tests.elements; + +import aquality.selenium.core.applications.IApplication; +import aquality.selenium.core.elements.ElementState; +import aquality.selenium.core.elements.interfaces.IElementFinder; +import org.openqa.selenium.By; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebElement; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import tests.ITestWithApplication; +import tests.application.windowsApp.AqualityServices; +import tests.application.windowsApp.CalculatorWindow; + +public interface IElementFinderTests extends ITestWithApplication { + IElementFinder getElementFinder(); + + default IApplication getApplication() { + return AqualityServices.getApplication(); + } + + default boolean isApplicationStarted() { + return AqualityServices.isApplicationStarted(); + } + + @DataProvider + default Object[] elementStates() { + return ElementState.values(); + } + + default Long getCustomTimeout() { + return 10L; + } + + default Long getSmallTimeout() { + return 1L; + } + + default By getAbsentLocator() { + return By.name("absent"); + } + + @Test() + default void shouldFindMultipleElementsInDefaultStateWithCustomTimeout() { + Assert.assertTrue(getElementFinder() + .findElements(CalculatorWindow.getEqualsButton(), getCustomTimeout()) + .size() > 1); + } + + @Test(dataProvider = "elementStates") + default void shouldFindMultipleElements(ElementState state) { + Assert.assertTrue(getElementFinder() + .findElements(CalculatorWindow.getEqualsButton(), state) + .size() > 1); + } + + @Test(dataProvider = "elementStates") + default void shouldFindSingleElementViaFindElements(ElementState state) { + Assert.assertEquals(getElementFinder() + .findElements(CalculatorWindow.getOneButton(), state, getCustomTimeout()) + .size(), 1); + } + + @Test(dataProvider = "elementStates") + default void shouldFindSingleElement(ElementState state) { + Assert.assertNotNull(getElementFinder() + .findElement(CalculatorWindow.getOneButton(), state)); + } + + @Test(dataProvider = "elementStates") + default void shouldFindSingleElementWithCustomTimeout(ElementState state) { + Assert.assertNotNull(getElementFinder() + .findElement(CalculatorWindow.getOneButton(), state, getCustomTimeout())); + } + + @Test + default void shouldFindSingleElementByPredicate() { + Assert.assertNotNull(getElementFinder() + .findElement(CalculatorWindow.getOneButton(), WebElement::isEnabled)); + } + + @Test + default void shouldFindMultipleElementsByPredicate() { + Assert.assertTrue(getElementFinder() + .findElements(CalculatorWindow.getEqualsButton(), WebElement::isEnabled).size() > 1); + } + + @Test + default void shouldFindSingleElementByPredicateWithCustomTimeout() { + Assert.assertNotNull(getElementFinder() + .findElement(CalculatorWindow.getOneButton(), WebElement::isEnabled, getCustomTimeout())); + } + + @Test(dataProvider = "elementStates") + default void shouldResolveState(ElementState state) { + Assert.assertNotNull(getElementFinder().resolveState(state)); + } + + @Test + default void shouldThrowWhenElementAbsent() { + Assert.assertThrows(NoSuchElementException.class, () -> getElementFinder().findElement(getAbsentLocator(), getSmallTimeout())); + } + + @Test + default void shouldReturnEmptyListWhenElementsAreAbsent() { + Assert.assertTrue(getElementFinder().findElements(getAbsentLocator(), getSmallTimeout()).isEmpty()); + } +} diff --git a/src/test/java/tests/elements/RelativeElementFinderTests.java b/src/test/java/tests/elements/RelativeElementFinderTests.java new file mode 100644 index 0000000..db0dec2 --- /dev/null +++ b/src/test/java/tests/elements/RelativeElementFinderTests.java @@ -0,0 +1,26 @@ +package tests.elements; + +import aquality.selenium.core.elements.RelativeElementFinder; +import aquality.selenium.core.elements.interfaces.IElementFinder; +import aquality.selenium.core.localization.ILocalizedLogger; +import aquality.selenium.core.waitings.IConditionalWait; +import org.testng.Assert; +import org.testng.annotations.Test; +import tests.application.windowsApp.AqualityServices; +import tests.application.windowsApp.CalculatorWindow; + +public class RelativeElementFinderTests implements IElementFinderTests { + + @Override + public IElementFinder getElementFinder() { + return new RelativeElementFinder( + AqualityServices.get(ILocalizedLogger.class), + AqualityServices.get(IConditionalWait.class), + () -> getApplication().getDriver().findElement(CalculatorWindow.getWindowLocator())); + } + + @Test + public void shouldFindChildElements() { + Assert.assertNotNull(getElementFinder().findElement(CalculatorWindow.getOneButton())); + } +} diff --git a/src/test/java/tests/utilities/SettingsFileTests.java b/src/test/java/tests/utilities/SettingsFileTests.java index 21e0caa..15397b6 100644 --- a/src/test/java/tests/utilities/SettingsFileTests.java +++ b/src/test/java/tests/utilities/SettingsFileTests.java @@ -114,8 +114,4 @@ public void after() { private TestModule getTestModule() { return new TestModule(CustomAqualityServices::getApplication); } - - private TestModule getTestModule(){ - return new TestModule(CustomAqualityServices::getApplication); - } } diff --git a/src/test/java/tests/waitings/ConditionalWaitTests.java b/src/test/java/tests/waitings/ConditionalWaitTests.java deleted file mode 100644 index 6b358d2..0000000 --- a/src/test/java/tests/waitings/ConditionalWaitTests.java +++ /dev/null @@ -1,190 +0,0 @@ -package tests.waitings; - -import aquality.selenium.core.applications.IApplication; -import aquality.selenium.core.configurations.ITimeoutConfiguration; -import aquality.selenium.core.localization.ILocalizationManager; -import aquality.selenium.core.waitings.ConditionalWait; -import com.google.inject.Injector; -import com.google.inject.Provider; -import org.openqa.selenium.StaleElementReferenceException; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; -import tests.application.CustomAqualityServices; -import utils.Timer; - -import java.util.Collections; -import java.util.concurrent.TimeoutException; - -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; - -public class ConditionalWaitTests { - - private static final long waitForTimeoutCondition = 10; - private static final long waitForTimeoutPolling = 150; - private ThreadLocal timer = ThreadLocal.withInitial(Timer::new); - private ITimeoutConfiguration timeoutConfiguration; - private Provider application; - private ConditionalWait conditionalWait; - - @BeforeMethod - public void init() { - Injector serviceProvider = CustomAqualityServices.getServiceProvider(); - ILocalizationManager localizationManager = serviceProvider.getInstance(ILocalizationManager.class); - application = serviceProvider.getProvider(IApplication.class); - timeoutConfiguration = serviceProvider.getInstance(ITimeoutConfiguration.class); - conditionalWait = new ConditionalWait(application, timeoutConfiguration, localizationManager); - } - - @AfterMethod - public void quitApplication() { - application.get().getDriver().quit(); - } - - @Test - public void testFalseShouldBeReturnedIfConditionIsNotMetAndDefaultTimeoutIsOver() { - long timeoutCondition = timeoutConfiguration.getCondition(); - boolean result = conditionalWait.waitForTrue(() -> - { - timer.get().start(); - return false; - }, "Condition should be true"); - double duration = timer.get().stop(); - assertFalse(result, "waitForTrue should return false when condition is not satisfied."); - assertTrue(duration > timeoutCondition && duration < 2 * timeoutCondition, - String.format("Duration '%s' should be between timeoutCondition '%s' and 2*timeoutCondition when condition is not satisfied.", - duration, timeoutCondition)); - } - - @Test - public void testTimeoutExceptionShouldBeThrownIfConditionIsMetAndTimeoutIsOver() { - try { - conditionalWait.waitForTrue(() -> - { - timer.get().start(); - return false; - }, waitForTimeoutCondition, waitForTimeoutPolling, "Condition should be true"); - } catch (TimeoutException e) { - double duration = timer.get().stop(); - assertTrue(duration > waitForTimeoutCondition && duration < 2 * waitForTimeoutCondition, - String.format("Duration '%s' should be between waitForTimeoutCondition '%s' and 2*waitForTimeoutCondition when condition is not satisfied.", - duration, waitForTimeoutCondition)); - } - } - - @Test - public void testTimeoutExceptionShouldNotBeThrownIfConditionIsMetAndDefaultTimeoutIsNotOver() { - long timeoutCondition = timeoutConfiguration.getCondition(); - - boolean result = conditionalWait.waitForTrue(() -> - { - timer.get().start(); - return true; - }, "Timeout exception should not be thrown"); - double duration = timer.get().stop(); - assertTrue(result, "waitForTrue should return true when condition is satisfied."); - assertTrue(duration < timeoutCondition, - String.format("Duration '%s' should be less than timeoutCondition '%s' when condition is satisfied.", - duration, timeoutCondition)); - } - - @Test - public void testTimeoutExceptionShouldNotBeThrownIfConditionMetAndTimeoutIsNotOver() throws TimeoutException { - conditionalWait.waitForTrue(() -> - { - timer.get().start(); - return true; - }, waitForTimeoutCondition, waitForTimeoutPolling, "Timeout exception should not be thrown"); - double duration = timer.get().stop(); - assertTrue(duration < waitForTimeoutCondition, - String.format("Duration '%s' should be less than waitForTimeoutCondition '%s' when condition is satisfied.", - duration, waitForTimeoutCondition)); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testNullCannotBePassedAsCondition() { - conditionalWait.waitForTrue(null, "Condition should not be null"); - } - - @Test - public void testTimeoutExceptionShouldBeThrownIfDriverConditionIsNotMetAndDefaultTimeoutIsOver() { - long timeoutCondition = timeoutConfiguration.getCondition(); - try { - conditionalWait.waitFor((driver) -> - { - timer.get().start(); - return false; - }, - "Condition should be true"); - } catch (org.openqa.selenium.TimeoutException e) { - double duration = timer.get().stop(); - assertTrue(duration > timeoutCondition && duration < 2 * timeoutCondition, - String.format("Duration '%s' before throwing should be between timeoutCondition '%s' and 2*timeoutCondition ", - duration, timeoutCondition)); - } - } - - @Test - public void testTimeoutExceptionShouldBeThrownIfDriverConditionIsNotMetAndTimeoutIsOver() { - try { - conditionalWait.waitFor((driver) -> - { - timer.get().start(); - return false; - }, waitForTimeoutCondition, waitForTimeoutPolling, - "Conditional should be true", Collections.singleton(StaleElementReferenceException.class)); - - } catch (org.openqa.selenium.TimeoutException e) { - double duration = timer.get().stop(); - assertTrue(duration > waitForTimeoutCondition && duration < 2 * waitForTimeoutCondition, - String.format("Duration '%s' before throwing should be between waitForTimeoutCondition '%s' and 2*waitForTimeoutCondition", - duration, waitForTimeoutCondition)); - } - } - - @Test - public void testTimeoutExceptionShouldNotBeThrownIfDriverConditionIsMetAndDefaultTimeoutIsNotOver() { - conditionalWait.waitFor((driver) -> - { - timer.get().start(); - return true; - }, - "Conditional should be true"); - double duration = timer.get().stop(); - assertTrue(duration < timeoutConfiguration.getCondition(), - String.format("Duration '%s' should be less than condition timeout '%s' when condition is satisfied.", - duration, timeoutConfiguration.getCondition())); - } - - @Test - public void testExceptionShouldBeCaughtConditionIsMetAndDefaultTimeoutIsNotOver() { - try { - conditionalWait.waitFor((driver) -> - { - timer.get().start(); - throw new IllegalArgumentException("I am exception"); - }, waitForTimeoutCondition, waitForTimeoutPolling, - "Conditional should be true", Collections.singleton(IllegalArgumentException.class)); - } catch (org.openqa.selenium.TimeoutException e) { - double duration = timer.get().stop(); - assertTrue(duration > waitForTimeoutCondition && duration < 2 * waitForTimeoutCondition, - String.format("Duration '%s' before throwing should be between waitForTimeoutCondition '%s' and 2*waitForTimeoutCondition", - duration, waitForTimeoutCondition)); - } - } - - @Test - public void testTimeoutExceptionShouldNotBeThrownIfDriverConditionIsMetAndTimeoutIsNotOver() { - conditionalWait.waitFor((driver) -> - { - timer.get().start(); - return true; - }, waitForTimeoutCondition, waitForTimeoutPolling, - "Conditional should be true", Collections.singleton(IllegalArgumentException.class)); - double duration = timer.get().stop(); - assertTrue(duration < waitForTimeoutCondition, - String.format("Duration '%s' should be less than waitForTimeoutCondition '%s' when condition is satisfied.", - duration, waitForTimeoutCondition)); - } -} diff --git a/src/test/resources/TestSuite.xml b/src/test/resources/TestSuite.xml index c686b8d..cacebc9 100644 --- a/src/test/resources/TestSuite.xml +++ b/src/test/resources/TestSuite.xml @@ -22,6 +22,8 @@ + + From 913cc7ac969c7e815473450aec671e0067e0d424 Mon Sep 17 00:00:00 2001 From: "Meleshko, Aleksey2" Date: Tue, 4 Feb 2020 16:44:42 +0300 Subject: [PATCH 23/28] Resolve conflicts with the master --- pom.xml | 5 ----- .../ElementCacheConfigurationTests.java | 16 ---------------- .../LoggerConfigurationTests.java | 16 ---------------- .../RetryConfigurationTests.java | 18 ------------------ .../TimeoutConfigurationTests.java | 19 ------------------- src/test/java/utils/TimeUtil.java | 8 -------- 6 files changed, 82 deletions(-) delete mode 100644 src/test/java/tests/configurations/ElementCacheConfigurationTests.java delete mode 100644 src/test/java/tests/configurations/LoggerConfigurationTests.java delete mode 100644 src/test/java/tests/configurations/RetryConfigurationTests.java delete mode 100644 src/test/java/tests/configurations/TimeoutConfigurationTests.java delete mode 100644 src/test/java/utils/TimeUtil.java diff --git a/pom.xml b/pom.xml index 43f2b97..52f72bb 100644 --- a/pom.xml +++ b/pom.xml @@ -95,11 +95,6 @@ jackson-databind 2.10.2 - - com.fasterxml.jackson.core - jackson-databind - 2.10.2 - org.seleniumhq.selenium selenium-java diff --git a/src/test/java/tests/configurations/ElementCacheConfigurationTests.java b/src/test/java/tests/configurations/ElementCacheConfigurationTests.java deleted file mode 100644 index f5735bd..0000000 --- a/src/test/java/tests/configurations/ElementCacheConfigurationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package tests.configurations; - -import aquality.selenium.core.configurations.IElementCacheConfiguration; -import org.testng.annotations.Test; -import tests.application.CustomAqualityServices; - -import static org.testng.Assert.assertFalse; - -public class ElementCacheConfigurationTests { - - @Test - public void testShouldBePossibleCheckIsEnableElementCache() { - boolean isEnable = CustomAqualityServices.getServiceProvider().getInstance(IElementCacheConfiguration.class).isEnabled(); - assertFalse(isEnable, "Element cache is disabled by default"); - } -} diff --git a/src/test/java/tests/configurations/LoggerConfigurationTests.java b/src/test/java/tests/configurations/LoggerConfigurationTests.java deleted file mode 100644 index de673d2..0000000 --- a/src/test/java/tests/configurations/LoggerConfigurationTests.java +++ /dev/null @@ -1,16 +0,0 @@ -package tests.configurations; - -import aquality.selenium.core.configurations.ILoggerConfiguration; -import org.testng.annotations.Test; -import tests.application.CustomAqualityServices; - -import static org.testng.Assert.assertEquals; - -public class LoggerConfigurationTests { - - @Test - public void testShouldBePossibleToGetLanguage() { - String language = CustomAqualityServices.getServiceProvider().getInstance(ILoggerConfiguration.class).getLanguage(); - assertEquals(language, "en", "Current language should be got from logger configuration"); - } -} diff --git a/src/test/java/tests/configurations/RetryConfigurationTests.java b/src/test/java/tests/configurations/RetryConfigurationTests.java deleted file mode 100644 index 4e05212..0000000 --- a/src/test/java/tests/configurations/RetryConfigurationTests.java +++ /dev/null @@ -1,18 +0,0 @@ -package tests.configurations; - -import aquality.selenium.core.configurations.IRetryConfiguration; -import aquality.selenium.core.configurations.ITimeoutConfiguration; -import org.testng.annotations.Test; -import tests.application.CustomAqualityServices; - -import static org.testng.Assert.assertEquals; - -public class RetryConfigurationTests { - - @Test - public void testShouldBePossibleToGetRetryConfiguration() { - IRetryConfiguration retryConfiguration = CustomAqualityServices.getServiceProvider().getInstance(IRetryConfiguration.class); - assertEquals(retryConfiguration.getNumber(), 2, "Number of retry attempts timeout should be got"); - assertEquals(retryConfiguration.getPollingInterval(), 300, "Polling interval of retrier should be got"); - } -} diff --git a/src/test/java/tests/configurations/TimeoutConfigurationTests.java b/src/test/java/tests/configurations/TimeoutConfigurationTests.java deleted file mode 100644 index 9b2f84a..0000000 --- a/src/test/java/tests/configurations/TimeoutConfigurationTests.java +++ /dev/null @@ -1,19 +0,0 @@ -package tests.configurations; - -import aquality.selenium.core.configurations.ITimeoutConfiguration; -import org.testng.annotations.Test; -import tests.application.CustomAqualityServices; - -import static org.testng.Assert.assertEquals; - -public class TimeoutConfigurationTests { - - @Test - public void testShouldBePossibleToGetTimeoutConfiguration() { - ITimeoutConfiguration timeoutConfiguration = CustomAqualityServices.getServiceProvider().getInstance(ITimeoutConfiguration.class); - assertEquals(timeoutConfiguration.getCommand(), 60, "Command timeout should be got"); - assertEquals(timeoutConfiguration.getCondition(), 30, "Condition timeout should be got"); - assertEquals(timeoutConfiguration.getImplicit(), 0, "Implicit timeout should be got"); - assertEquals(timeoutConfiguration.getPollingInterval(), 300, "Polling interval should be got"); - } -} diff --git a/src/test/java/utils/TimeUtil.java b/src/test/java/utils/TimeUtil.java deleted file mode 100644 index 76fc87a..0000000 --- a/src/test/java/utils/TimeUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package utils; - -public class TimeUtil { - - public static double getCurrentTimeInSeconds() { - return System.nanoTime() / Math.pow(10, 9); - } -} From 4aaeb264962b6cadeb92bcf63319f637501e14ae Mon Sep 17 00:00:00 2001 From: "Meleshko, Aleksey2" Date: Wed, 5 Feb 2020 10:22:41 +0300 Subject: [PATCH 24/28] add links to IElementFinder documentation --- .../elements/interfaces/IElementFinder.java | 90 +++++++++++-------- 1 file changed, 55 insertions(+), 35 deletions(-) diff --git a/src/main/java/aquality/selenium/core/elements/interfaces/IElementFinder.java b/src/main/java/aquality/selenium/core/elements/interfaces/IElementFinder.java index 2d18748..400432e 100644 --- a/src/main/java/aquality/selenium/core/elements/interfaces/IElementFinder.java +++ b/src/main/java/aquality/selenium/core/elements/interfaces/IElementFinder.java @@ -10,14 +10,20 @@ import java.util.function.Predicate; /** - * Provides ability to find elements in desired ElementState. + * Provides ability to find elements by locator and search criteria. + * The criteria for search could be: + * - empty - to get all elements; + * - desired {@link ElementState}; + * - with {@link DesiredState}; + * - with {@link Predicate}. */ public interface IElementFinder extends SearchContext { /** - * Provides DesiredState with predicate for desired ElementState. - * @param state desired ElementState - * @return DesiredState with predicate. + * Provides {@link DesiredState} with predicate for desired {@link ElementState}. + * + * @param state desired {@link ElementState} + * @return {@link DesiredState} with predicate. */ default DesiredState resolveState(ElementState state) { Predicate elementStateCondition; @@ -32,23 +38,25 @@ default DesiredState resolveState(ElementState state) { } /** - * Finds element in desired ElementState - * @param locator elements locator - * @param state desired ElementState + * Finds element in desired {@link ElementState} + * + * @param locator elements locator + * @param state desired {@link ElementState} * @param timeoutInSeconds timeout for search - * @throws org.openqa.selenium.NoSuchElementException if element was not found in time in desired state * @return found element + * @throws org.openqa.selenium.NoSuchElementException if element was not found in time in desired state */ default WebElement findElement(By locator, ElementState state, Long timeoutInSeconds) { return findElements(locator, resolveState(state).withThrowingNoSuchElementException(), timeoutInSeconds).get(0); } /** - * Finds element in desired ElementState with default timeout. + * Finds element in desired {@link ElementState} with default timeout. + * * @param locator elements locator - * @param state desired ElementState - * @throws org.openqa.selenium.NoSuchElementException if element was not found in time in desired state + * @param state desired {@link ElementState} * @return found element + * @throws org.openqa.selenium.NoSuchElementException if element was not found in time in desired state */ default WebElement findElement(By locator, ElementState state) { return findElement(locator, state, null); @@ -56,10 +64,11 @@ default WebElement findElement(By locator, ElementState state) { /** * Finds element in any state. - * @param locator elements locator + * + * @param locator elements locator * @param timeoutInSeconds timeout for search - * @throws org.openqa.selenium.NoSuchElementException if element was not found in time * @return found element + * @throws org.openqa.selenium.NoSuchElementException if element was not found in time */ default WebElement findElement(By locator, Long timeoutInSeconds) { return findElement(locator, ElementState.EXISTS_IN_ANY_STATE, timeoutInSeconds); @@ -67,21 +76,23 @@ default WebElement findElement(By locator, Long timeoutInSeconds) { /** * Finds element in any state with default timeout. + * * @param locator elements locator - * @throws org.openqa.selenium.NoSuchElementException if element was not found in time * @return found element + * @throws org.openqa.selenium.NoSuchElementException if element was not found in time */ default WebElement findElement(By locator) { return findElement(locator, ElementState.EXISTS_IN_ANY_STATE, null); } /** - * Finds element in desired ElementState defined by predicate. - * @param locator elements locator + * Finds element in desired element's state defined by predicate. + * + * @param locator elements locator * @param elementStateCondition predicate to define element state - * @param timeoutInSeconds timeout for search - * @throws org.openqa.selenium.NoSuchElementException if element was not found in time in desired state + * @param timeoutInSeconds timeout for search * @return found element + * @throws org.openqa.selenium.NoSuchElementException if element was not found in time in desired state */ default WebElement findElement(By locator, Predicate elementStateCondition, Long timeoutInSeconds) { DesiredState state = new DesiredState(elementStateCondition, "desired") @@ -91,19 +102,21 @@ default WebElement findElement(By locator, Predicate elementStateCon /** * Finds element in desired ElementState defined by predicate with default timeout. - * @param locator elements locator + * + * @param locator elements locator * @param elementStateCondition predicate to define element state - * @throws org.openqa.selenium.NoSuchElementException if element was not found in time in desired state * @return found element + * @throws org.openqa.selenium.NoSuchElementException if element was not found in time in desired state */ default WebElement findElement(By locator, Predicate elementStateCondition) { return findElement(locator, elementStateCondition, null); } /** - * Finds elements in desired ElementState. - * @param locator elements locator - * @param state desired ElementState + * Finds elements in desired {@link ElementState}. + * + * @param locator elements locator + * @param state desired {@link ElementState} * @param timeoutInSeconds timeout for search * @return list of found elements */ @@ -113,7 +126,8 @@ default List findElements(By locator, ElementState state, Long timeo /** * Finds elements in any state. - * @param locator elements locator + * + * @param locator elements locator * @param timeoutInSeconds timeout for search * @return list of found elements */ @@ -122,9 +136,10 @@ default List findElements(By locator, Long timeoutInSeconds) { } /** - * Finds elements in desired ElementState with default timeout. + * Finds elements in desired {@link ElementState} with default timeout. + * * @param locator elements locator - * @param state desired ElementState + * @param state desired {@link ElementState} * @return list of found elements */ default List findElements(By locator, ElementState state) { @@ -133,6 +148,7 @@ default List findElements(By locator, ElementState state) { /** * Finds elements in any state with default timeout. + * * @param locator elements locator * @return list of found elements */ @@ -142,8 +158,9 @@ default List findElements(By locator) { /** * Finds elements in state defined by predicate. - * @param locator elements locator - * @param timeoutInSeconds timeout for search + * + * @param locator elements locator + * @param timeoutInSeconds timeout for search * @param elementStateCondition predicate to define element state * @return list of found elements */ @@ -154,7 +171,8 @@ default List findElements(By locator, Predicate elementS /** * Finds elements in state defined by predicate with default timeout. - * @param locator elements locator + * + * @param locator elements locator * @param elementStateCondition predicate to define element state * @return list of found elements */ @@ -163,18 +181,20 @@ default List findElements(By locator, Predicate elementS } /** - * Finds elements in state defined by DesiredState. - * @param locator elements locator + * Finds elements in state defined by {@link DesiredState}. + * + * @param locator elements locator * @param timeoutInSeconds timeout for search - * @param desiredState predicate to define element state + * @param desiredState object with predicate to define element state * @return list of found elements */ List findElements(By locator, DesiredState desiredState, Long timeoutInSeconds); /** - * Finds elements in state defined by DesiredState with default timeout. - * @param locator elements locator - * @param desiredState predicate to define element state + * Finds elements in state defined by {@link DesiredState} with default timeout. + * + * @param locator elements locator + * @param desiredState object with predicate to define element state * @return list of found elements */ default List findElements(By locator, DesiredState desiredState) { From e667c18cb2d0ac0dd272afb13798fc0f8c75e983 Mon Sep 17 00:00:00 2001 From: "Meleshko, Aleksey2" Date: Wed, 5 Feb 2020 10:49:38 +0300 Subject: [PATCH 25/28] fix the sonar code smells --- .../selenium/core/elements/ElementFinder.java | 23 +++++++++---------- .../core/elements/RelativeElementFinder.java | 17 +++++++------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/main/java/aquality/selenium/core/elements/ElementFinder.java b/src/main/java/aquality/selenium/core/elements/ElementFinder.java index 08453fa..75fb399 100644 --- a/src/main/java/aquality/selenium/core/elements/ElementFinder.java +++ b/src/main/java/aquality/selenium/core/elements/ElementFinder.java @@ -11,7 +11,7 @@ import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; +import java.util.concurrent.atomic.AtomicBoolean; /** * Implementation of IElementFinder. @@ -28,21 +28,20 @@ public ElementFinder(ILocalizedLogger localizedLogger, IConditionalWait conditio @Override public List findElements(By locator, DesiredState desiredState, Long timeoutInSeconds) { - List foundElements = new ArrayList<>(); + AtomicBoolean wasAnyElementFound = new AtomicBoolean(false); List resultElements = new ArrayList<>(); try { conditionalWait.waitFor(driver -> { List currentFoundElements = driver == null ? new ArrayList<>() : driver.findElements(locator); - foundElements.addAll(currentFoundElements); - List filteredElements = currentFoundElements + wasAnyElementFound.set(!currentFoundElements.isEmpty()); + currentFoundElements .stream() .filter(desiredState.getElementStateCondition()) - .collect(Collectors.toList()); - resultElements.addAll(filteredElements); - return !filteredElements.isEmpty(); + .forEachOrdered(resultElements::add); + return !resultElements.isEmpty(); }, timeoutInSeconds, null); } catch (TimeoutException e) { - handleTimeoutException(e, locator, desiredState, foundElements); + handleTimeoutException(e, locator, desiredState, wasAnyElementFound.get()); } return resultElements; @@ -54,12 +53,12 @@ public List findElements(By locator, DesiredState desiredState, Long * @param exception TimeoutException to handle * @param locator locator that is using to find elements * @param desiredState DesiredState object - * @param foundElements list of all found elements by locator. + * @param wasAnyElementFound was any element found by locator or not. */ - protected void handleTimeoutException(TimeoutException exception, By locator, DesiredState desiredState, List foundElements) { + protected void handleTimeoutException(TimeoutException exception, By locator, DesiredState desiredState, boolean wasAnyElementFound) { String message = String.format("No elements with locator '%1$s' were found in %2$s state", locator, desiredState.getStateName()); if (desiredState.isCatchingInTimeoutException()) { - if (foundElements.isEmpty()) { + if (!wasAnyElementFound) { if (desiredState.isThrowingNoSuchElementException()) { throw new NoSuchElementException(message); } @@ -69,7 +68,7 @@ protected void handleTimeoutException(TimeoutException exception, By locator, De } } else { String combinedMessage = String.format("%1$s: %2$s", exception.getMessage(), message); - if (desiredState.isThrowingNoSuchElementException() && foundElements.isEmpty()) { + if (desiredState.isThrowingNoSuchElementException() && !wasAnyElementFound) { throw new NoSuchElementException(combinedMessage); } throw new TimeoutException(combinedMessage); diff --git a/src/main/java/aquality/selenium/core/elements/RelativeElementFinder.java b/src/main/java/aquality/selenium/core/elements/RelativeElementFinder.java index b520b52..f5fe530 100644 --- a/src/main/java/aquality/selenium/core/elements/RelativeElementFinder.java +++ b/src/main/java/aquality/selenium/core/elements/RelativeElementFinder.java @@ -9,8 +9,8 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; -import java.util.stream.Collectors; /** * Implementation of IElementFinder for a relative SearchContext. @@ -28,22 +28,23 @@ public RelativeElementFinder(ILocalizedLogger localizedLogger, IConditionalWait @Override public List findElements(By locator, DesiredState desiredState, Long timeoutInSeconds) { - List foundElements = new ArrayList<>(); + AtomicBoolean wasAnyElementFound = new AtomicBoolean(false); List resultElements = new ArrayList<>(); try { conditionalWait.waitForTrue(() -> { List currentFoundElements = searchContextSupplier.get().findElements(locator); - foundElements.addAll(currentFoundElements); - List filteredElements = currentFoundElements + wasAnyElementFound.set(!currentFoundElements.isEmpty()); + currentFoundElements .stream() .filter(desiredState.getElementStateCondition()) - .collect(Collectors.toList()); - resultElements.addAll(filteredElements); - return !filteredElements.isEmpty(); + .forEachOrdered(resultElements::add); + return !resultElements.isEmpty(); }, timeoutInSeconds, null); } catch (TimeoutException e) { handleTimeoutException(new org.openqa.selenium.TimeoutException(e.getMessage(), e), locator, desiredState, - foundElements); + wasAnyElementFound.get()); + } catch (org.openqa.selenium.TimeoutException e) { + handleTimeoutException(e, locator, desiredState, wasAnyElementFound.get()); } return resultElements; From 64b9ae4144e3648f3eb0cf306b99f27247c377e7 Mon Sep 17 00:00:00 2001 From: "Meleshko, Aleksey2" Date: Wed, 5 Feb 2020 11:33:49 +0300 Subject: [PATCH 26/28] making chrome headless in tests --- src/test/java/tests/application/browser/ChromeApplication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/tests/application/browser/ChromeApplication.java b/src/test/java/tests/application/browser/ChromeApplication.java index 17d71c0..ec787df 100644 --- a/src/test/java/tests/application/browser/ChromeApplication.java +++ b/src/test/java/tests/application/browser/ChromeApplication.java @@ -12,7 +12,7 @@ public class ChromeApplication implements IApplication { private final RemoteWebDriver driver; public ChromeApplication(long implicitWaitSeconds) { - driver = new ChromeDriver(new ChromeOptions()); + driver = new ChromeDriver(new ChromeOptions().setHeadless(true)); setImplicitWaitTimeout(implicitWaitSeconds, TimeUnit.SECONDS); } From b360791ef4989a163295eb3e377b9a0458a518d7 Mon Sep 17 00:00:00 2001 From: Sergey Knysh Date: Wed, 5 Feb 2020 11:51:30 +0300 Subject: [PATCH 27/28] hot fix for conditional wait tests --- src/test/java/tests/waitings/BaseConditionalWaitTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/java/tests/waitings/BaseConditionalWaitTest.java b/src/test/java/tests/waitings/BaseConditionalWaitTest.java index 9076700..247d592 100644 --- a/src/test/java/tests/waitings/BaseConditionalWaitTest.java +++ b/src/test/java/tests/waitings/BaseConditionalWaitTest.java @@ -20,9 +20,8 @@ class BaseConditionalWaitTest { static final long accuracy = 3; static final Collection> ignoredExceptions = Collections.singleton(IllegalStateException.class); ThreadLocal timer = ThreadLocal.withInitial(Timer::new); - private Injector serviceProvider = AqualityServices.getServiceProvider(); - protected Provider application = serviceProvider.getProvider(IApplication.class); - ITimeoutConfiguration timeoutConfiguration = serviceProvider.getInstance(ITimeoutConfiguration.class); + protected Provider application = AqualityServices.getServiceProvider().getProvider(IApplication.class); + ITimeoutConfiguration timeoutConfiguration = AqualityServices.getServiceProvider().getInstance(ITimeoutConfiguration.class); ConditionalWait conditionalWait = new ConditionalWait(application, timeoutConfiguration); @AfterMethod From 29e444a7a6f4cf932973c1cb4e49436a81d470a5 Mon Sep 17 00:00:00 2001 From: "Meleshko, Aleksey2" Date: Wed, 5 Feb 2020 15:12:13 +0300 Subject: [PATCH 28/28] refactor ElementFinder, moved common part to base class --- .../selenium/core/elements/ElementFinder.java | 35 ++++++++++--------- .../core/elements/RelativeElementFinder.java | 14 +++----- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/main/java/aquality/selenium/core/elements/ElementFinder.java b/src/main/java/aquality/selenium/core/elements/ElementFinder.java index 75fb399..73f7455 100644 --- a/src/main/java/aquality/selenium/core/elements/ElementFinder.java +++ b/src/main/java/aquality/selenium/core/elements/ElementFinder.java @@ -4,10 +4,7 @@ import aquality.selenium.core.localization.ILocalizedLogger; import aquality.selenium.core.waitings.IConditionalWait; import com.google.inject.Inject; -import org.openqa.selenium.By; -import org.openqa.selenium.NoSuchElementException; -import org.openqa.selenium.TimeoutException; -import org.openqa.selenium.WebElement; +import org.openqa.selenium.*; import java.util.ArrayList; import java.util.List; @@ -31,15 +28,10 @@ public List findElements(By locator, DesiredState desiredState, Long AtomicBoolean wasAnyElementFound = new AtomicBoolean(false); List resultElements = new ArrayList<>(); try { - conditionalWait.waitFor(driver -> { - List currentFoundElements = driver == null ? new ArrayList<>() : driver.findElements(locator); - wasAnyElementFound.set(!currentFoundElements.isEmpty()); - currentFoundElements - .stream() - .filter(desiredState.getElementStateCondition()) - .forEachOrdered(resultElements::add); - return !resultElements.isEmpty(); - }, timeoutInSeconds, null); + conditionalWait.waitFor(driver -> + tryToFindElements(locator, desiredState, wasAnyElementFound, resultElements, driver), + timeoutInSeconds, + null); } catch (TimeoutException e) { handleTimeoutException(e, locator, desiredState, wasAnyElementFound.get()); } @@ -47,12 +39,23 @@ public List findElements(By locator, DesiredState desiredState, Long return resultElements; } + protected boolean tryToFindElements(By locator, DesiredState desiredState, AtomicBoolean wasAnyElementFound, + List resultElements, SearchContext context) { + List currentFoundElements = context.findElements(locator); + wasAnyElementFound.set(!currentFoundElements.isEmpty()); + currentFoundElements + .stream() + .filter(desiredState.getElementStateCondition()) + .forEachOrdered(resultElements::add); + return !resultElements.isEmpty(); + } + /** * depends on configuration of DesiredState object it can be required to throw or not NoSuchElementException * - * @param exception TimeoutException to handle - * @param locator locator that is using to find elements - * @param desiredState DesiredState object + * @param exception TimeoutException to handle + * @param locator locator that is using to find elements + * @param desiredState DesiredState object * @param wasAnyElementFound was any element found by locator or not. */ protected void handleTimeoutException(TimeoutException exception, By locator, DesiredState desiredState, boolean wasAnyElementFound) { diff --git a/src/main/java/aquality/selenium/core/elements/RelativeElementFinder.java b/src/main/java/aquality/selenium/core/elements/RelativeElementFinder.java index f5fe530..847114a 100644 --- a/src/main/java/aquality/selenium/core/elements/RelativeElementFinder.java +++ b/src/main/java/aquality/selenium/core/elements/RelativeElementFinder.java @@ -31,15 +31,11 @@ public List findElements(By locator, DesiredState desiredState, Long AtomicBoolean wasAnyElementFound = new AtomicBoolean(false); List resultElements = new ArrayList<>(); try { - conditionalWait.waitForTrue(() -> { - List currentFoundElements = searchContextSupplier.get().findElements(locator); - wasAnyElementFound.set(!currentFoundElements.isEmpty()); - currentFoundElements - .stream() - .filter(desiredState.getElementStateCondition()) - .forEachOrdered(resultElements::add); - return !resultElements.isEmpty(); - }, timeoutInSeconds, null); + conditionalWait.waitForTrue(() -> + tryToFindElements(locator, desiredState, wasAnyElementFound, resultElements, + searchContextSupplier.get()), + timeoutInSeconds, + null); } catch (TimeoutException e) { handleTimeoutException(new org.openqa.selenium.TimeoutException(e.getMessage(), e), locator, desiredState, wasAnyElementFound.get());