diff --git a/pom.xml b/pom.xml index 4265b2d..6dc75bf 100644 --- a/pom.xml +++ b/pom.xml @@ -82,7 +82,7 @@ com.github.aquality-automation aquality-selenium-core - 4.0.3 + 4.0.4 org.apache.commons diff --git a/src/main/java/aquality/selenium/browser/Browser.java b/src/main/java/aquality/selenium/browser/Browser.java index 4a70cd5..aadd148 100644 --- a/src/main/java/aquality/selenium/browser/Browser.java +++ b/src/main/java/aquality/selenium/browser/Browser.java @@ -12,6 +12,8 @@ import org.openqa.selenium.*; import org.openqa.selenium.WebDriver.Navigation; import org.openqa.selenium.devtools.HasDevTools; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.interactions.WheelInput.ScrollOrigin; import org.openqa.selenium.logging.LogEntries; import org.openqa.selenium.remote.Augmenter; import org.openqa.selenium.remote.RemoteWebDriver; @@ -352,9 +354,32 @@ public void handlePromptAlert(AlertActions alertAction, String text) { * @param y coordinate y */ public void scrollWindowBy(int x, int y) { + localizedLogger.info("loc.scrolling.by", x, y); + new Actions(getDriver()).scrollByAmount(x, y).perform(); + } + + /** + * Executes scrolling of the page to given coordinates x and y using JavaScript. + * + * @param x coordinate x + * @param y coordinate y + */ + public void scrollWindowByViaJs(int x, int y) { + localizedLogger.info("loc.scrolling.by.js", x, y); executeScript(JavaScript.SCROLL_WINDOW_BY.getScript(), x, y); } + /** + * Scrolls portion of screen from specified origin. + * + * @param scrollOrigin Origination point (either viewport or element, with possible offset) + * @param x coordinate x + * @param y coordinate y + */ + public void scrollFromOrigin(ScrollOrigin scrollOrigin, int x, int y) { + new Actions(getDriver()).scrollFromOrigin(scrollOrigin, x, y).perform(); + } + /** * Sets given window size * diff --git a/src/main/java/aquality/selenium/elements/actions/JsActions.java b/src/main/java/aquality/selenium/elements/actions/JsActions.java index 286a043..2a70dd6 100644 --- a/src/main/java/aquality/selenium/elements/actions/JsActions.java +++ b/src/main/java/aquality/selenium/elements/actions/JsActions.java @@ -92,7 +92,7 @@ public void scrollIntoView() { * @param y vertical coordinate */ public void scrollBy(int x, int y) { - logElementAction("loc.scrolling.js"); + logElementAction("loc.scrolling.by.js", x, y); executeScript(JavaScript.SCROLL_BY, x, y); } diff --git a/src/main/java/aquality/selenium/elements/actions/MouseActions.java b/src/main/java/aquality/selenium/elements/actions/MouseActions.java index 6cc33dc..13d5fac 100644 --- a/src/main/java/aquality/selenium/elements/actions/MouseActions.java +++ b/src/main/java/aquality/selenium/elements/actions/MouseActions.java @@ -1,11 +1,14 @@ package aquality.selenium.elements.actions; import aquality.selenium.browser.AqualityServices; +import aquality.selenium.core.localization.ILocalizedLogger; import aquality.selenium.core.utilities.IElementActionRetrier; import aquality.selenium.elements.interfaces.IElement; +import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.interactions.WheelInput.ScrollOrigin; -import java.util.function.UnaryOperator; +import java.util.function.BiFunction; import static aquality.selenium.browser.AqualityServices.getBrowser; @@ -13,69 +16,108 @@ public class MouseActions { private final IElement element; private final String type; private final String name; + private final ILocalizedLogger logger; + private final IElementActionRetrier elementActionRetrier; public MouseActions(IElement element, String type) { this.element = element; this.type = type; this.name = element.getName(); + this.logger = AqualityServices.getLocalizedLogger(); + this.elementActionRetrier = AqualityServices.get(IElementActionRetrier.class); } /** * Click via Action. */ public void click() { - infoLoc("loc.clicking"); + logElementAction("loc.clicking"); new JsActions(element, type).highlightElement(); - performAction(Actions::click); + performActionAfterMove((elem, actions) -> actions.click()); } /** * Click Right (calls context menu) on the element */ public void rightClick() { - infoLoc("loc.clicking.right"); - performAction(actions -> actions.contextClick(element.getElement())); + logElementAction("loc.clicking.right"); + performActionAfterMove((elem, actions) -> actions.contextClick(elem)); + } + + /** + * Scrolling to element + */ + public void scrollToElement() { + logElementAction("loc.scrolling"); + performAction((elem, actions) -> actions.scrollToElement(elem)); + } + + /** + * Scrolling by coordinates + * + * @param x horizontal coordinate + * @param y vertical coordinate + */ + public void scrollFromOrigin(int x, int y) { + scrollFromOrigin(x, y, 0, 0); + } + + /** + * Scrolling by coordinates + * + * @param x horizontal coordinate + * @param y vertical coordinate + * @param xOffset horizontal offset + * @param yOffset vertical offset + */ + public void scrollFromOrigin(int x, int y, int xOffset, int yOffset) + { + logElementAction("loc.scrolling.by", x, y); + elementActionRetrier.doWithRetry(() -> { + ScrollOrigin scrollOrigin = ScrollOrigin.fromElement(element.getElement(), xOffset, yOffset); + getBrowser().scrollFromOrigin(scrollOrigin, x, y); + }); } /** * Move mouse to this element. */ public void moveMouseToElement() { - infoLoc("loc.moving"); - performAction(actions -> actions); + logElementAction("loc.moving"); + performActionAfterMove((elem, actions) -> actions); } /** * Move mouse from this element. */ public void moveMouseFromElement() { - infoLoc("loc.movingFrom"); - AqualityServices.get(IElementActionRetrier.class).doWithRetry(() -> - new Actions(getBrowser().getDriver()) - .moveToElement(element.getElement(), -element.getElement().getSize().width, -element.getElement().getSize().height) - .build().perform()); + logElementAction("loc.movingFrom"); + performAction(((elem, actions) -> actions.moveToElement(elem, elem.getSize().width, elem.getSize().height))); } /** * Performs double-click on the element. */ public void doubleClick() { - infoLoc("loc.clicking.double"); - performAction(actions -> actions.doubleClick(element.getElement())); + logElementAction("loc.clicking.double"); + performActionAfterMove((elem, actions) -> actions.doubleClick(elem)); + } + + private void performActionAfterMove(BiFunction function) { + performAction((elem, actions) -> function.apply(elem, actions.moveToElement(elem))); } - private void performAction(UnaryOperator function) { - Actions actions = new Actions(getBrowser().getDriver()).moveToElement(element.getElement()); - AqualityServices.get(IElementActionRetrier.class).doWithRetry(() -> - function.apply(actions).build().perform()); + private void performAction(BiFunction action) { + elementActionRetrier.doWithRetry(() -> action.apply(element.getElement(), new Actions(getBrowser().getDriver())).perform()); } /** * The implementation of a method for logging of MouseActions * - * @param key key in localization resource of message to display in the log. + * @param key key in localization resource of message to display in the log. + * @param args Arguments, which will be provided to template of localized message. */ - private void infoLoc(String key) { - AqualityServices.getLocalizedLogger().infoElementAction(type, name, key); + private void logElementAction(String key, Object... args) { + logger.infoElementAction(type, name, key, args); } } diff --git a/src/main/java/aquality/selenium/forms/Form.java b/src/main/java/aquality/selenium/forms/Form.java index 68fd2ce..6de6886 100644 --- a/src/main/java/aquality/selenium/forms/Form.java +++ b/src/main/java/aquality/selenium/forms/Form.java @@ -71,6 +71,16 @@ public IElementStateProvider state() { * @param y vertical coordinate */ public void scrollBy(int x, int y) { + getFormLabel().getMouseActions().scrollFromOrigin(x, y); + } + + /** + * Scroll form via JavaScript without scrolling entire page + * + * @param x horizontal coordinate + * @param y vertical coordinate + */ + public void scrollByJs(int x, int y) { getFormLabel().getJsActions().scrollBy(x, y); } diff --git a/src/main/resources/localization/be.json b/src/main/resources/localization/be.json index 9d7a554..b52cfab 100644 --- a/src/main/resources/localization/be.json +++ b/src/main/resources/localization/be.json @@ -70,7 +70,10 @@ "loc.movingFrom": "Адводзім курсор мышы ад элемента", "loc.radio": "Радыёкнопка", "loc.scrolling.center.js": "Пракручваем старонку да цэнтра элемента праз JavaScript", - "loc.scrolling.js": "Пракручваем старонку праз JavaScript", + "loc.scrolling.js": "Пракручваем старонку да элемента праз JavaScript", + "loc.scrolling": "Пракручваем старонку да элемента", + "loc.scrolling.by": "Пракручваем на (%s,%s)", + "loc.scrolling.by.js": "Пракручваем на (%s,%s) праз JavaScript", "loc.selecting.value": "Выбіраем значэнне - '%s'", "loc.deselecting.value": "Адмяняем выбар значэння - '%s'", "loc.send.text": "Задаем тэкст - '%s'", diff --git a/src/main/resources/localization/en.json b/src/main/resources/localization/en.json index 1bb0bc4..53b7759 100644 --- a/src/main/resources/localization/en.json +++ b/src/main/resources/localization/en.json @@ -70,7 +70,10 @@ "loc.movingFrom": "Moving mouse from element", "loc.radio": "RadioButton", "loc.scrolling.center.js": "Scrolling to the center via JavaScript", - "loc.scrolling.js": "Scrolling via JavaScript", + "loc.scrolling.js": "Scrolling to element via JavaScript", + "loc.scrolling": "Scrolling to element", + "loc.scrolling.by": "Scrolling by (%s,%s)", + "loc.scrolling.by.js": "Scrolling by (%s,%s) via JavaScript", "loc.selecting.value": "Selecting value - '%s'", "loc.deselecting.value": "Deselecting value - '%s'", "loc.send.text": "Setting text - '%s'", diff --git a/src/main/resources/localization/pl.json b/src/main/resources/localization/pl.json index ab3ba14..f317ebc 100644 --- a/src/main/resources/localization/pl.json +++ b/src/main/resources/localization/pl.json @@ -70,7 +70,10 @@ "loc.movingFrom": "Przesuwanie myszy z elementu", "loc.radio": "RadioButton", "loc.scrolling.center.js": "Przewijanie do centrum przez JavaScript", - "loc.scrolling.js": "Przewijanie przez JavaScript", + "loc.scrolling.js": "Przewijanie do elementu przez JavaScript", + "loc.scrolling": "Przewijanie do elementu", + "loc.scrolling.by": "Przewijanie o (%s,%s)", + "loc.scrolling.by.js": "Przewijanie o (%s,%s) przez JavaScript", "loc.selecting.value": "Wybieranie wartości - '%s'", "loc.deselecting.value": "Anulowanie wybierania wartości - '%s'", "loc.send.text": "Ustawianie tekstu - '%s'", diff --git a/src/main/resources/localization/ru.json b/src/main/resources/localization/ru.json index a1f40d3..51f5822 100644 --- a/src/main/resources/localization/ru.json +++ b/src/main/resources/localization/ru.json @@ -70,7 +70,10 @@ "loc.movingFrom": "Сдвиг курсора с элемента", "loc.radio": "Радиокнопка", "loc.scrolling.center.js": "Скроллинг в центр (посредством JavaScript)", - "loc.scrolling.js": "Скроллинг посредством JavaScript", + "loc.scrolling.js": "Скроллинг к элементу (посредством JavaScript)", + "loc.scrolling": "Скроллинг к элементу", + "loc.scrolling.by": "Скроллинг на (%s,%s)", + "loc.scrolling.by.js": "Скроллинг на (%s,%s) посредством JavaScript", "loc.selecting.value": "Выбор значения - '%s'", "loc.deselecting.value": "Отмена выбора значения - '%s'", "loc.send.text": "Ввод текста - '%s'", diff --git a/src/main/resources/localization/uk.json b/src/main/resources/localization/uk.json index f4914ff..db4cb16 100644 --- a/src/main/resources/localization/uk.json +++ b/src/main/resources/localization/uk.json @@ -70,7 +70,10 @@ "loc.movingFrom": "Переміщення миші від елемента", "loc.radio": "Радіокнопка", "loc.scrolling.center.js": "Прокрутка до центру за допомогою JavaScript", - "loc.scrolling.js": "Прокрутка за допомогою JavaScript", + "loc.scrolling.js": "Прокрутка до елемента за допомогою JavaScript", + "loc.scrolling": "Прокрутка до елемента", + "loc.scrolling.by": "Прокрутка на (%s,%s)", + "loc.scrolling.by.js": "Прокрутка на (%s,%s) за допомогою JavaScript", "loc.selecting.value": "Вибір значення - '%s'", "loc.deselecting.value": "Скасування выбору значення - '%s'", "loc.send.text": "Встановлення тексту - '%s'", diff --git a/src/test/java/tests/integration/ActionTests.java b/src/test/java/tests/integration/ActionTests.java index 25c06c7..cfdfa69 100644 --- a/src/test/java/tests/integration/ActionTests.java +++ b/src/test/java/tests/integration/ActionTests.java @@ -14,6 +14,7 @@ import theinternet.forms.JQueryMenuForm; import theinternet.forms.WelcomeForm; +import java.awt.*; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; @@ -22,7 +23,7 @@ public class ActionTests extends BaseTest { @BeforeMethod @Override protected void beforeMethod() { - AqualityServices.getBrowser().getDriver().manage().window().maximize(); + getBrowser().maximize(); } @Test @@ -35,11 +36,42 @@ public void testScrollToTheCenter() { Long windowHeight = getScriptResultOrDefault("getWindowSize.js", 10L); double currentY = getScriptResultOrDefault("getElementYCoordinate.js", 0.0, link.getElement()); - double coordinateRelatingWindowCenter = windowHeight.doubleValue() / 2 - currentY; + double coordinateRelatingWindowCenter = windowHeight.doubleValue() / 2 - currentY; Assert.assertTrue(Math.abs(coordinateRelatingWindowCenter) <= accuracy, "Upper bound of element should be in the center of the page"); } + @Test + public void testScrollToElement() throws TimeoutException { + InfiniteScrollForm infiniteScrollForm = new InfiniteScrollForm(); + getBrowser().goTo(infiniteScrollForm.getUrl()); + infiniteScrollForm.waitForMoreExamples(); + Dimension size = infiniteScrollForm.getLastExampleLabel().visual().getSize(); + getBrowser().scrollWindowBy(size.width, size.height); + getBrowser().setWindowSize(size.width, size.height); + getBrowser().scrollWindowBy(0, 0); + int defaultCount = infiniteScrollForm.getExampleLabels().size(); + AtomicReference lastExampleLabel = new AtomicReference<>(infiniteScrollForm.getLastExampleLabel()); + AqualityServices.getConditionalWait().waitForTrue(() -> { + lastExampleLabel.set(infiniteScrollForm.getLastExampleLabel()); + lastExampleLabel.get().getMouseActions().scrollToElement(); + return infiniteScrollForm.getExampleLabels().size() > defaultCount; + }, "Some examples should be added after scroll"); + } + + @Test + public void testScrollFromOrigin() throws TimeoutException { + InfiniteScrollForm infiniteScrollForm = new InfiniteScrollForm(); + getBrowser().goTo(infiniteScrollForm.getUrl()); + int defaultCount = infiniteScrollForm.getExampleLabels().size(); + AtomicReference lastExampleLabel = new AtomicReference<>(infiniteScrollForm.getLastExampleLabel()); + AqualityServices.getConditionalWait().waitForTrue(() -> { + lastExampleLabel.set(infiniteScrollForm.getLastExampleLabel()); + lastExampleLabel.get().getMouseActions().scrollFromOrigin(0, lastExampleLabel.get().visual().getSize().height); + return infiniteScrollForm.getExampleLabels().size() > defaultCount; + }, "Some examples should be added after scroll"); + } + @Test public void testScrollIntoView() throws TimeoutException { InfiniteScrollForm infiniteScrollForm = new InfiniteScrollForm(); diff --git a/src/test/java/tests/integration/BrowserTests.java b/src/test/java/tests/integration/BrowserTests.java index 71f13a9..c439447 100644 --- a/src/test/java/tests/integration/BrowserTests.java +++ b/src/test/java/tests/integration/BrowserTests.java @@ -188,6 +188,15 @@ public void testShouldBePossibleToScrollWindowBy(){ getBrowser().scrollWindowBy(0, formHeight); Assert.assertEquals(initialY - scrollForm.getFormPointInViewPort().getY(), formHeight); } + @Test + public void testShouldBePossibleToScrollWindowByViaJavaScript(){ + WelcomeForm scrollForm = new WelcomeForm(); + getBrowser().goTo(scrollForm.getUrl()); + int initialY = scrollForm.getFormPointInViewPort().getY(); + int formHeight = (int) scrollForm.getSize().getHeight(); + getBrowser().scrollWindowByViaJs(0, formHeight); + Assert.assertEquals(initialY - scrollForm.getFormPointInViewPort().getY(), formHeight); + } @Test public void testShouldBePossibleToGetBrowserName() { diff --git a/src/test/java/tests/usecases/devtools/DeviceEmulationTest.java b/src/test/java/tests/usecases/devtools/DeviceEmulationTest.java index 7d5ab68..5b223fa 100644 --- a/src/test/java/tests/usecases/devtools/DeviceEmulationTest.java +++ b/src/test/java/tests/usecases/devtools/DeviceEmulationTest.java @@ -3,8 +3,8 @@ import aquality.selenium.browser.AqualityServices; import aquality.selenium.browser.devtools.EmulationHandling; import com.google.common.collect.ImmutableMap; -import org.openqa.selenium.devtools.v124.emulation.Emulation; -import org.openqa.selenium.devtools.v124.emulation.model.DisplayFeature; +import org.openqa.selenium.devtools.v127.emulation.Emulation; +import org.openqa.selenium.devtools.v127.emulation.model.DisplayFeature; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; diff --git a/src/test/java/tests/usecases/devtools/NetworkSpeedEmulationTest.java b/src/test/java/tests/usecases/devtools/NetworkSpeedEmulationTest.java index b8e30a5..44fb24d 100644 --- a/src/test/java/tests/usecases/devtools/NetworkSpeedEmulationTest.java +++ b/src/test/java/tests/usecases/devtools/NetworkSpeedEmulationTest.java @@ -2,7 +2,7 @@ import aquality.selenium.browser.AqualityServices; import org.openqa.selenium.TimeoutException; -import org.openqa.selenium.devtools.v124.network.model.ConnectionType; +import org.openqa.selenium.devtools.v127.network.model.ConnectionType; import org.testng.Assert; import org.testng.annotations.Test; import tests.BaseTest; diff --git a/src/test/java/tests/usecases/devtools/OverrideUserAgentTest.java b/src/test/java/tests/usecases/devtools/OverrideUserAgentTest.java index d5b966c..e8fbc09 100644 --- a/src/test/java/tests/usecases/devtools/OverrideUserAgentTest.java +++ b/src/test/java/tests/usecases/devtools/OverrideUserAgentTest.java @@ -8,7 +8,7 @@ import manytools.BrowserLanguageForm; import manytools.UserAgentForm; import org.openqa.selenium.devtools.idealized.Network; -import org.openqa.selenium.devtools.v124.emulation.Emulation; +import org.openqa.selenium.devtools.v127.emulation.Emulation; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test;