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/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..73f7455 --- /dev/null +++ b/src/main/java/aquality/selenium/core/elements/ElementFinder.java @@ -0,0 +1,80 @@ +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.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Implementation of IElementFinder. + */ +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) { + AtomicBoolean wasAnyElementFound = new AtomicBoolean(false); + List resultElements = new ArrayList<>(); + try { + conditionalWait.waitFor(driver -> + tryToFindElements(locator, desiredState, wasAnyElementFound, resultElements, driver), + timeoutInSeconds, + null); + } catch (TimeoutException e) { + handleTimeoutException(e, locator, desiredState, wasAnyElementFound.get()); + } + + 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 wasAnyElementFound was any element found by locator or not. + */ + 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 (!wasAnyElementFound) { + 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 { + String combinedMessage = String.format("%1$s: %2$s", exception.getMessage(), message); + if (desiredState.isThrowingNoSuchElementException() && !wasAnyElementFound) { + throw new NoSuchElementException(combinedMessage); + } + throw new TimeoutException(combinedMessage); + } + } +} 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/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..847114a --- /dev/null +++ b/src/main/java/aquality/selenium/core/elements/RelativeElementFinder.java @@ -0,0 +1,48 @@ +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.concurrent.atomic.AtomicBoolean; +import java.util.function.Supplier; + +/** + * 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) { + AtomicBoolean wasAnyElementFound = new AtomicBoolean(false); + List resultElements = new ArrayList<>(); + try { + 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()); + } catch (org.openqa.selenium.TimeoutException e) { + handleTimeoutException(e, locator, desiredState, wasAnyElementFound.get()); + } + + return resultElements; + } +} 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..400432e --- /dev/null +++ b/src/main/java/aquality/selenium/core/elements/interfaces/IElementFinder.java @@ -0,0 +1,203 @@ +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 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 {@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; + 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 {@link ElementState} + * + * @param locator elements locator + * @param state desired {@link ElementState} + * @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, ElementState state, Long timeoutInSeconds) { + return findElements(locator, resolveState(state).withThrowingNoSuchElementException(), timeoutInSeconds).get(0); + } + + /** + * Finds element in desired {@link ElementState} with default timeout. + * + * @param locator elements locator + * @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); + } + + /** + * Finds element in any state. + * + * @param locator elements locator + * @param timeoutInSeconds timeout for search + * @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); + } + + /** + * Finds element in any state with default timeout. + * + * @param locator elements locator + * @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 element's state defined by predicate. + * + * @param locator elements locator + * @param elementStateCondition predicate to define element 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") + .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 + * @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 {@link ElementState}. + * + * @param locator elements locator + * @param state desired {@link 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 {@link ElementState} with default timeout. + * + * @param locator elements locator + * @param state desired {@link 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 {@link DesiredState}. + * + * @param locator elements locator + * @param timeoutInSeconds timeout for search + * @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 {@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) { + return findElements(locator, desiredState, null); + } +} 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/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); } 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/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 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 @@ + +