com.smartbear.visualtest.util.Utils Maven / Gradle / Ivy
The newest version!
package com.smartbear.visualtest.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.io.CharSource;
import com.google.common.io.Files;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import com.smartbear.visualtest.api.ApiBuilder;
import com.smartbear.visualtest.models.*;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.ios.IOSDriver;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.openqa.selenium.*;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.remote.RemoteWebDriver;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* The Utils class contains various utility functions for tasks such as creating temporary directories,
* getting page dimensions, and converting JSON to Java objects.
*/
public class Utils {
// A function to create a temporary directory.
public static final Gson gson = new Gson();
public static final ObjectMapper mapper = new ObjectMapper();
public static final Logger logger = Logger.getLogger(Utils.class.getName()).getParent();
public static final Level FINE = Level.FINE;
public static final Level ERROR = Level.SEVERE;
public static final Properties applicationMessages = new Properties();
/**
* This function calculates the number of times a webpage needs to be scrolled to view the entire
* page based on the dimensions of the viewport and the full page.
*
* @param pageDimensions It is an object that contains information about the dimensions of the
* webpage. It has two properties:
* @return The method is returning an integer value which represents the number of times the page
* needs to be scrolled to view the entire page based on the given page dimensions.
*/
public static Integer getNumberOfPagesToScroll(PageDimensions pageDimensions) {
double viewportHeight = pageDimensions.getWindowInner().getHeight();
double fullPageHeight = pageDimensions.getFullpage().getHeight();
return (Integer) (int) Math.ceil(fullPageHeight / viewportHeight);
}
/**
* This Java function returns the dimensions (width and height) of an image file.
* dimensions.
* @return The method is returning a Dimension object that contains the width and height of the
* image file passed as a parameter. If there is an exception, the method returns null.
*/
public static Dimension getImageDimension(BufferedImage image) {
try {
int h = image.getHeight();
int w = image.getWidth();
return new Dimension(w, h);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* This Java function retrieves the initial state of a web page using a JavascriptExecutor.
*
* @param driver The "driver" parameter is an object that represents the web browser being used for
* automated testing. It is typically an instance of a WebDriver implementation, such as
* ChromeDriver or FirefoxDriver. The driver allows the automation script to interact with the web
* page, perform actions, and retrieve information.
* @return The method is returning an object of type `InitialPageState`.
*/
public static InitialPageState getInitialPageState(Object driver) throws IOException {
JavascriptExecutor js = (JavascriptExecutor) driver;
String script = loadJavascriptFileAsString(Scripts.INITIAL_STATE);
return getInitialPageStateFromJSON((String) (js.executeScript("return " + script)));
}
/**
* This Java function uses a appium driver method to return app dimensions as
* a JSON object.
*
* @param driver The "driver" parameter is an object that represents the web browser or mobile
* device being used for automated testing. It is typically created by Appium
* @return The method is returning an object of type `PageDimensions`.
*/
public static PageDimensions getAppDimensions(Object driver, double devicePixelRatio) throws IOException {
Dimension dim;
Capabilities caps = ((RemoteWebDriver)driver).getCapabilities();
if(Integer.parseInt(caps.getCapability("platformVersion").toString().split("\\.")[0]) < 11 && caps.getCapability("platformName").equals(Platform.ANDROID)){
dim = new Dimension(Math.toIntExact((Long) ((Map) caps.getCapability("appium:viewportRect")).get("height")), Math.toIntExact((Long) ((Map) caps.getCapability("appium:viewportRect")).get("width")));
}else{
if (caps.getCapability("platformName").equals(Platform.ANDROID)){
dim = ((AndroidDriver) driver).manage().window().getSize();
}else{
dim = ((IOSDriver) driver).manage().window().getSize();
}
}
PageDimensions dimensions = new PageDimensions(new Document(dim.getHeight(), dim.getWidth()), new Body(dim.getHeight(), dim.getWidth()), new WindowInner(dim.getHeight(),dim.getWidth()), new Fullpage(dim.getHeight(), dim.getWidth()), devicePixelRatio, new InitialScroll(0.0,0.0));
return dimensions;
}
/**
* This Java function uses a JavascriptExecutor to execute a script that returns page dimensions as
* a JSON object.
*
* @param driver The "driver" parameter is an object that represents the web browser or mobile
* device being used for automated testing. It is typically created using a WebDriver
* implementation such as Selenium.
* @return The method is returning an object of type `PageDimensions`.
*/
public static PageDimensions getPageDimensions(Object driver) throws IOException {
JavascriptExecutor js = (JavascriptExecutor) driver;
String script = loadJavascriptFileAsString(Scripts.PAGE_DIMENSIONS);
return getPageDimensionsFromJSON((String) (js.executeScript("return " + script)));
}
/**
* This Java function retrieves the user agent data of a web browser using a JavascriptExecutor
* object.
*
* @param driver The "driver" parameter is an object that represents the web browser driver being
* used in the code. It is used to execute JavaScript code in the context of the web page being
* accessed.
* @return The method is returning an object of type UserAgentInfo.
*/
@SuppressWarnings("unchecked")
public static UserAgentInfo getNavigatorUserAgentData(Object driver) throws IOException {
JavascriptExecutor js = (JavascriptExecutor) driver;
String script = loadJavascriptFileAsString(Scripts.USER_AGENT);
return getUserAgentFromMap((Map) js.executeScript("return " + script));
}
/**
* This Java function retrieves the user agent data of an appium driver capabilities.
*
* @param driver The "driver" parameter is an object that represents the web browser driver being
* used in the code. It is used to execute JavaScript code in the context of the web page being
* accessed.
* @return The method is returning an object of type UserAgentInfo.
*/
public static UserAgentInfo getAppiumNavigatorUserAgentData(Object driver, double devicepixelratio){
UserAgentInfo agent =new UserAgentInfo();
Capabilities capabilities = ((RemoteWebDriver) driver).getCapabilities();
agent.setAppPackage(capabilities.getCapability("appium:appActivity") != null ?
capabilities.getCapability("appium:appPackage").toString():
(capabilities.getCapability("appium:bundleId") != null ?
capabilities.getCapability("appium:app") != null ?
capabilities.getCapability("appium:app").toString():
capabilities.getCapability("appium:bundleId").toString():
null));
agent.setAppActivity(capabilities.getCapability("appium:appActivity") != null ?
capabilities.getCapability("appium:appActivity").toString():
capabilities.getCapability("appium:app") != null ?
capabilities.getCapability("appium:app").toString():
capabilities.getCapability("appium:bundleId").toString());
agent.setAppiumDriverType(capabilities.getCapability("appium:automationName").toString().toLowerCase());
agent.setDriverType("Appium");
agent.setDeviceName(capabilities.getCapability("appium:deviceModel") != null ?
capabilities.getCapability("appium:deviceModel").toString():
capabilities.getCapability("appium:deviceName") != null?
capabilities.getCapability("appium:deviceName").toString():
null);
agent.setDevicePixelRatio(devicepixelratio);
agent.setDeviceType("mobile");
agent.setOrientation("portrait");
agent.setOsName(capabilities.getCapability("platformName").toString().toLowerCase());
agent.setOsVersion(capabilities.getCapability("appium:platformVersion").toString());
agent.setScreenHeight((int) (((RemoteWebDriver)driver).manage().window().getSize().getHeight()* devicepixelratio));
agent.setScreenWidth((int) (((RemoteWebDriver)driver).manage().window().getSize().getWidth()* devicepixelratio));
if(capabilities.getCapabilityNames().contains("appium:deviceManufacturer")){
agent.setDeviceName(capabilities.getCapability("appium:deviceManufacturer").toString() + " " + agent.getDeviceName());
}
return agent;
}
/**
* The function returns a version of Chrome OS using a JavascriptExecutor object.
*
* @param driver The "driver" parameter is an object that represents the web browser driver being
* used to automate browser actions. It could be an instance of a class such as ChromeDriver.
* @return The method is returning a String that represents version of chrome.
*/
public static String getChromeOsVersion(Object driver) throws IOException {
JavascriptExecutor js = (JavascriptExecutor) driver;
String script = loadJavascriptFileAsString(Scripts.CHROME_OS_VERSION);
return (String) js.executeAsyncScript(script);
}
/**
* The function returns a string representation of the captured DOM data using a JavascriptExecutor
* object.
*
* @param driver The "driver" parameter is an object that represents the web browser driver being
* used to automate browser actions. It could be an instance of a class such as ChromeDriver,
* FirefoxDriver, or SafariDriver, depending on the specific browser being used.
* @return The method is returning a String that represents the captured DOM data as a JSON object.
*/
public static String getDomCaptureDataAsString(Object driver, String type) throws IOException {
JavascriptExecutor js = (JavascriptExecutor) driver;
String script = loadJavascriptFileAsString(Scripts.DOM_CAPTURE);
String dom = (String) js.executeScript("return " + script);
JsonElement domElement = JsonParser.parseString(dom);
JsonObject domObject = domElement.getAsJsonObject();
domObject.add("screenshotType", JsonParser.parseString(type));
return domObject.toString();
}
/**
* This Java function parses a JSON string and returns a specific element as a string.
*
* @param domCaptureInfo The parameter "domCaptureInfo" is a string that contains information about
* the captured DOM (Document Object Model) of a web page. It is expected to be in JSON format and
* should include a field called "ignoredElementsData" which contains information about any
* elements that were ignored during the capture process.
* @return The method returns a String representation of the "ignoredElementsData" element from the
* input JSON string "domCaptureInfo". If there is an error while parsing the JSON, the method
* returns null.
*/
public static String getIgnoredElementsDataAsString(String domCaptureInfo) {
try {
JsonElement ignoredElement = JsonParser.parseString(domCaptureInfo);
JsonObject ignoredElementObject = ignoredElement.getAsJsonObject();
JsonElement ignoredElements = ignoredElementObject.get("ignoredElementsData");
return ignoredElements.toString();
} catch (Exception e) {
Utils.logger.log(Level.SEVERE, "Error while parsing ignoredElements from DOM");
}
return null;
}
/**
* This function loads a JavaScript file as a string given its name.
*
* @param name The name of the JavaScript file that needs to be loaded as a string.
* @return The method is returning a String representation of the contents of a JavaScript file.
*/
public static String loadJavascriptFileAsString(String name) throws IOException {
// File sourceFile = new File("src/main/resources/scripts/" + name);
File sourceFile = File.createTempFile("temp", ".js");
FileWriter writer = new FileWriter(sourceFile);
writer.write(name);
writer.close();
CharSource externalJS = Files.asCharSource(sourceFile, StandardCharsets.UTF_8);
return externalJS.read();
}
/**
* The function parses a JSON string into a PageDimensions object using the Gson library in Java.
*
* @param json A string containing JSON data that represents a PageDimensions object.
* @return A `PageDimensions` object is being returned. The method uses the Gson library to parse a
* JSON string and convert it into a `PageDimensions` object.
*/
private static PageDimensions getPageDimensionsFromJSON(String json) {
Utils.logger.info("Webpage Dimensions: " + json);
return new Gson().fromJson(
json, new TypeToken() {}.getType()
);
}
/**
* The function parses a JSON string into an object of type InitialPageState using the Gson
* library.
*
* @param json The parameter "json" is a string that contains JSON data. This JSON data represents
* the initial state of a web page. The method "getInitialPageStateFromJSON" uses the Gson library
* to parse this JSON data and convert it into an object of type "InitialPageState".
* @return The method is returning an object of type `InitialPageState` which is obtained by
* deserializing the JSON string passed as a parameter using the Gson library.
*/
private static InitialPageState getInitialPageStateFromJSON(String json) {
return new Gson().fromJson(
json, new TypeToken() {}.getType()
);
}
/**
* The function converts a map to a UserAgentInfo object using a mapper.
*
* @param map A Map object that contains key-value pairs representing the properties of a user
* agent. The keys are strings that represent the names of the properties, and the values are
* objects that represent the values of the properties. The method converts this map into a
* UserAgentInfo object using the Jackson ObjectMapper.
* @return The method is returning an object of type `UserAgentInfo`. It is using the
* `convertValue` method from the `mapper` object of the `Utils` class to convert the `map`
* parameter to an instance of `UserAgentInfo` class.
*/
private static UserAgentInfo getUserAgentFromMap(Map map) {
return Utils.mapper.convertValue(map, UserAgentInfo.class);
}
/**
* The function converts a JSON string to a Java object using the Gson library.
*
* @param json a String representing a JSON object
* @param clazz The "clazz" parameter is a Class object that represents the type of the Java object
* that the JSON string should be converted to. It is used by the Gson library to deserialize the
* JSON string into a Java object of the specified type.
* @return The method returns an Object, which is either the converted Java object from the
* provided JSON string or null if there was an error during the conversion process.
*/
public static Object gsonToJavaObject(String json, Class> clazz) {
try {
JsonObject jsonObject = new Gson().fromJson(json, JsonObject.class);
return gson.fromJson(jsonObject, clazz);
} catch (Exception e) {
System.out.println("Error while converting json to java object");
}
return null;
}
/**
* The function capitalizes the first letter of a given string.
*
* @param str The input string that needs to be capitalized.
* @return The method `capitalize` returns a capitalized version of the input string `str`. If the
* input string is null or empty, the method returns the same string. Otherwise, the method returns
* the first character of the string in uppercase, followed by the rest of the string.
*/
public static String capitalize(String str) {
if (str == null || str.isEmpty()) {
return str;
}
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
/**
* The function returns the webpage to its initial state by resetting the body's transform, scroll
* position, and overflow properties using JavaScript.
*
* @param js The "js" parameter is an instance of the JavascriptExecutor interface, which allows
* the execution of JavaScript code from within Java code.
* @param initialPageState The initialPageState parameter is an object that contains the initial
* state of the webpage. It includes the transform, scrollX, scrollY, and overflow properties.
* These properties are used to reset the webpage to its initial state.
*/
public static void returnToInitialState(JavascriptExecutor js, InitialPageState initialPageState) {
js.executeScript("document.body.style.transform = '"+ initialPageState.getTransform() + "';");
js.executeScript("window.scrollTo(" + initialPageState.getScrollX() + "," + initialPageState.getScrollY() + ")");
js.executeScript("document.body.style.overflow = '" + initialPageState.getOverflowBody() + "';");
js.executeScript("document.documentElement.style.overflow = '" + initialPageState.getOverflowDocument() + "';");
}
/**
* This function loads a message from a properties file and interpolates any provided values into
* the message.
*
* @param key The key is a string that represents the message to be retrieved from the properties
* file. It is used to identify the specific message that needs to be loaded.
* @return The method is returning a String value which is the message corresponding to the given
* key in the "ApplicationMessages.properties" file. If there are any placeholders in the message,
* they will be replaced with the values provided in the "interpolate" parameter using the
* String.format() method.
*/
public static String loadResourceAsString(String key, String... interpolate) throws IOException, NullPointerException {
Utils.applicationMessages.load(Utils.class.getClassLoader().getResourceAsStream("ApplicationMessages.properties"));
String message = Utils.applicationMessages.getProperty(key);
for(String one:interpolate) {
message = String.format(message, one);
}
return message;
}
/**
* The function freezes the current page using a JavascriptExecutor object.
*
* @param js The "js" parameter is an instance of the JavascriptExecutor interface, which allows
* for the execution of JavaScript code from within Java code. In this particular method, it is
* used to execute a JavaScript script that freezes the current page.
*/
@SuppressWarnings("unchecked")
public static Map freezePage(JavascriptExecutor js) {
return (Map) js.executeScript("return " + Scripts.FREEZE_PAGE);
}
public static int getFullPageHeight(JavascriptExecutor js) {
String script = "return Math.max(window.document.body.offsetHeight,window.document.body.scrollHeight, window.document.documentElement.offsetHeight, window.document.documentElement.scrollHeight);";
Object result = js.executeScript(script);
return ((Number) result).intValue();
}
public static Double getScrollOffset(JavascriptExecutor js) {
String script = "return window.scrollY";
return (Long) js.executeScript(script) * 1.0;
}
public static String getParamsString(Map params)
throws UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
for (Map.Entry entry : params.entrySet()) {
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
result.append("&");
}
String resultString = result.toString();
return resultString.length() > 0
? resultString.substring(0, resultString.length() - 1)
: resultString;
}
public static byte[] toByteArray(BufferedImage bi)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bi, "png", baos);
return baos.toByteArray();
}
public static String getTypeOfImage(Map options) throws Exception {
if (options.containsKey("viewport")) {
if (options.get("viewport") instanceof Boolean) {
if ((Boolean) options.get("viewport")) {
return "viewport";
} else {
throw new Exception("\"viewport\" should be set to \"true\" in oder to take a viewport screenshot");
}
} else {
throw new Exception("Type of \"viewport\" option should be Boolean.");
}
} else if (options.containsKey("element")) {
if (options.get("element") instanceof WebElement) {
return "element";
} else {
throw new Exception("Type of \"element\" option should be WebElement.");
}
} else {
return "fullpage";
}
}
public static boolean pixelsAreCloseMatch(int p1, int p2){
//see if p1 and p2 pixels are within a tolerance of 50
//based on the euclidean distance formula
Color c1 = new Color(p1);
Color c2 = new Color(p2);
double d = euclideanDiff(c1,c2);
//seeing first shaded red in android chrome pretest at diff of 72
return d <= 100;
}
private static double euclideanDiff(Color c1, Color c2){
return Math.sqrt( Math.pow(c2.getRed() - c1.getRed(), 2) + Math.pow(c2.getGreen() - c1.getGreen(),2) + Math.pow(c2.getBlue() - c1.getBlue(),2) );
}
public static void hideScrollBar(Object driver){
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("return document.body.style.overflow='hidden';");
js.executeScript("return document.documentElement.style.overflow='hidden';");
}
public static void checkSdkVersion(String latest) throws Exception {
Properties properties = new Properties();
properties.load(ApiBuilder.class.getClassLoader().getResourceAsStream("config.properties"));
String version = properties.getProperty("VERSION");
if (new DefaultArtifactVersion(version).compareTo(new DefaultArtifactVersion(latest)) < 0){
ReportPrinter.print(new String[]{"WARNING: A newer version of visualtest-java SDK is available. Your version ", version, ". Latest version ", latest, ". See https://central.sonatype.com/artifact/com.smartbear/visualtest for more information.", }, "", ReportPrinter.ANSI_YELLOW);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy