com.seleniumtests.uipage.htmlelements.PictureElement Maven / Gradle / Ivy
/**
* Orignal work: Copyright 2015 www.seleniumtests.com
* Modified work: Copyright 2016 www.infotel.com
* Copyright 2017-2019 B.Hecquet
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.seleniumtests.uipage.htmlelements;
import java.io.File;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import com.seleniumtests.core.SeleniumTestsContextManager;
import com.seleniumtests.driver.BrowserType;
import com.seleniumtests.driver.CustomEventFiringWebDriver;
import com.seleniumtests.driver.WebUIDriver;
import com.seleniumtests.driver.screenshots.ScreenshotUtil;
import com.seleniumtests.uipage.ReplayOnError;
import io.appium.java_client.touch.TapOptions;
import io.appium.java_client.touch.WaitOptions;
import io.appium.java_client.touch.offset.PointOption;
/**
* Element which is found inside driver snapshot
* @author behe
*
*/
public class PictureElement extends GenericPictureElement {
private HtmlElement intoElement;
public PictureElement() {
// for mocks
}
public PictureElement(String label, String resourcePath, HtmlElement intoElement) {
this(label, resourcePath, intoElement, 0.1);
}
public PictureElement(String label, String resourcePath, HtmlElement intoElement, double detectionThreshold) {
this(label, createFileFromResource(resourcePath), intoElement, detectionThreshold);
this.resourcePath = resourcePath;
}
public PictureElement(String label, File pictureFile, HtmlElement intoElement) {
this(label, pictureFile, intoElement, 0.1);
}
/**
*
* @param label
* @param pictureFile picture to search for in snapshot or on desktop
* @param intoElement HtmlElement inside of which our picture is. It allows scrolling to the zone where
* picture is searched before doing capture
* @param detectionThreshold sensitivity of search between 0 and 1. Be default, 0.1. More sensitivity means search can be less accurate, detect unwanted zones
*/
public PictureElement(String label, File pictureFile, HtmlElement intoElement, double detectionThreshold) {
super(label, pictureFile, detectionThreshold, false, new ScreenshotUtil());
if (intoElement == null) {
if (SeleniumTestsContextManager.isWebTest()) {
this.intoElement = new HtmlElement("", By.tagName("body"));
} else {
this.intoElement = new HtmlElement("", By.xpath("/*"));
}
} else {
this.intoElement = intoElement;
}
}
public ScreenshotUtil getScreenshotUtil() {
return new ScreenshotUtil();
}
/**
* Search the picture in the screenshot taken by Robot or WebDriver
* Robot is used in Desktop mode
* WebDriver is used in mobile, because Robot is not available for mobile platforms
*
* @param searchOnly
*
* @deprecated use findElement instead
*/
@Deprecated
public void findElement(boolean searchOnly) {
findElement();
}
public File getScreenshotFile() {
screenshotUtil = getScreenshotUtil(); // update driver
File screenshotFile = screenshotUtil.captureWebPageToFile();
return screenshotFile;
}
protected void doAfterPictureSearch() {
// scroll to element where our picture is so that we will be able to act on it
// scrolling will display, on top of window, the top of the element
intoElement.scrollToElement(0);
}
/**
* Click at the coordinates xOffset, yOffset of the center of the found picture. Use negative offset to click on the left or
* top of the picture center
* In case the size ratio between searched picture and found picture is not 1, then, offset is
* the source offset so that it's compatible with any screen size and resolution
*/
@ReplayOnError(replayDelayMs=1000)
public void clickAt(int xOffset, int yOffset) {
findElement();
Point intoElementPos = intoElement.getCoordinates().onPage();
int relativeX = detectedObjectRectangle.x + detectedObjectRectangle.width / 2 - intoElementPos.x;
int relativeY = detectedObjectRectangle.y + detectedObjectRectangle.height / 2 - intoElementPos.y;
moveAndClick(intoElement, relativeX + (int)(xOffset * pictureSizeRatio), relativeY + (int)(yOffset * pictureSizeRatio));
}
@ReplayOnError(replayDelayMs=1000)
public void swipe(int xMove, int yMove) {
findElement();
int xInit = detectedObjectRectangle.x + detectedObjectRectangle.width / 2;
int yInit = detectedObjectRectangle.y + detectedObjectRectangle.height / 2;
createTouchAction().press(PointOption.point(xInit, yInit))
.waitAction(WaitOptions.waitOptions(Duration.ofMillis(500)))
.moveTo(PointOption.point(xInit + xMove, yInit + yMove))
.release()
.perform();
}
@ReplayOnError(replayDelayMs=1000)
public void tap() {
findElement();
createTouchAction()
.moveTo(PointOption.point(detectedObjectRectangle.x + detectedObjectRectangle.width / 2, detectedObjectRectangle.y + detectedObjectRectangle.height / 2))
.tap(TapOptions.tapOptions().withTapsCount(1)).perform();
}
public void moveAndClick(WebElement element, int coordX, int coordY) {
if (SeleniumTestsContextManager.isWebTest()) {
// issue #133: handle new actions specific case
// more browsers will be added to this conditions once they are migrated to new composite actions
if (SeleniumTestsContextManager.getThreadContext().getBrowser() == BrowserType.FIREFOX) {
// issue #133: firefox moves to center of element in page
coordX -= element.getSize().width / 2;
coordY -= element.getSize().height / 2;
} else if (SeleniumTestsContextManager.getThreadContext().getBrowser() == BrowserType.INTERNET_EXPLORER) {
// issue #180: internet explorer moves to center of element in viewport
Dimension viewportDim = ((CustomEventFiringWebDriver)(WebUIDriver.getWebDriver())).getViewPortDimensionWithoutScrollbar();
coordX -= Math.min(element.getSize().width, viewportDim.width) / 2;
coordY -= Math.min(element.getSize().height, viewportDim.height) / 2;
}
}
new Actions(WebUIDriver.getWebDriver()).moveToElement(element, coordX, coordY).click().build().perform();
}
public void sendKeys(final CharSequence text, int xOffset, int yOffset) {
clickAt(xOffset, yOffset);
new Actions(WebUIDriver.getWebDriver()).sendKeys(text).build().perform();
}
/**
* Check if picture is visible on desktop. This is only available for desktop tests
* @param waitMs
* @return
*
* @deprecated use isElementPresent instead
*/
@Deprecated
public boolean isElementPresentOnDesktop(int waitMs) {
return isElementPresent(waitMs);
}
/**
* @deprecated use isElementPresent instead
*/
@Deprecated
public boolean isElementPresentOnDesktop() {
return isElementPresent(0);
}
// TODO: actions for mobile
// https://discuss.appium.io/t/tapping-on-the-screen-by-using-coordinates/5529/7
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy