Skip to content

Commit

Permalink
Merge pull request #213 from zebrunner/develop
Browse files Browse the repository at this point in the history
1.2.11
  • Loading branch information
vdelendik authored Apr 10, 2024
2 parents fb93ffc + e4191e2 commit efb7ad0
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 116 deletions.
15 changes: 15 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@
<hamcrest.version>1.3</hamcrest.version>
<org.json.version>20231013</org.json.version>
<joda-time.version>2.9.9</joda-time.version>
<apiguardian-api.version>1.1.2</apiguardian-api.version>
<mockito-core.version>3.2.4</mockito-core.version>
<slf4j-simple.version>2.0.12</slf4j-simple.version>
<testng.version>7.8.0</testng.version>
<guava.version>32.1.2-jre</guava.version>
<maven-source-plugin.version>3.0.1</maven-source-plugin.version>
Expand Down Expand Up @@ -302,13 +304,26 @@
<version>${imgscalr-lib.version}</version>
</dependency>

<dependency>
<groupId>org.apiguardian</groupId>
<artifactId>apiguardian-api</artifactId>
<version>${apiguardian-api.version}</version>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito-core.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j-simple.version}</version>
<scope>test</scope>
</dependency>

<!-- Test utilities -->
<dependency>
<groupId>org.testng</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,21 @@
import java.lang.invoke.MethodHandles;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.zebrunner.carina.webdriver.proxy.ZebrunnerProxyBuilder;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.openqa.selenium.InvalidArgumentException;
import org.openqa.selenium.MutableCapabilities;
Expand All @@ -45,6 +48,8 @@
import com.zebrunner.carina.utils.exception.InvalidConfigurationException;
import com.zebrunner.carina.webdriver.config.WebDriverConfiguration;

import javax.annotation.Nullable;

public abstract class AbstractCapabilities<T extends MutableCapabilities> {
// TODO: [VD] reorganize in the same way Firefox profiles args/options if any and review other browsers
// support customization for Chrome args and options
Expand Down Expand Up @@ -225,6 +230,7 @@ public static Map<String, Object> getGlobalCapabilities(Map<String, String> prop
return pair;
})
.map(p -> parseCapabilityType(p.getLeft(), p.getRight()))
.filter(Objects::nonNull) // null-safe
.collect(Collectors.toMap(MutablePair::getLeft, MutablePair::getRight));
}

Expand All @@ -248,6 +254,7 @@ public static Map<String, Object> getEnvCapabilities(Map<String, String> props)
return pair;
})
.map(p -> parseCapabilityType(p.getLeft(), p.getRight()))
.filter(Objects::nonNull) // null-safe
.collect(Collectors.toMap(MutablePair::getLeft, MutablePair::getRight));
}

Expand Down Expand Up @@ -310,9 +317,13 @@ static <C extends MutableCapabilities> void addPropertiesCapabilities(C options,
*
* @param capabilityName name of the capability, for example {@code platformName} or {zebrunner:options.enableVideo[boolean]}
* @param capabilityValue capability value. Since we take it from the configuration file, it is immediately of type String
* @return {@link MutablePair}, where left is the capability name and right is the value
* @return {@link MutablePair}, where left is the capability name and right is the value, or null if capability is not w3c
*/
static MutablePair<String, Object> parseCapabilityType(String capabilityName, String capabilityValue) {
static @Nullable MutablePair<String, Object> parseCapabilityType(String capabilityName, String capabilityValue) {
if(StringUtils.containsAnyIgnoreCase(capabilityName, "enableLog", "enableVideo", "enableVNC", "provider", "memory", "cpu", "newSessionWaitTimeout") && !StringUtils.contains(capabilityName, ":")) {
LOGGER.warn("Capability '{}' will not be added to the session because it does not comply with the w3c style.", capabilityName);
return null;
}
MutablePair<String, Object> pair = new MutablePair<>();
Matcher matcher = CAPABILITY_WITH_TYPE_PATTERN.matcher(capabilityName);
if (matcher.find()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,6 @@ public ImmutablePair<WebDriver, Capabilities> create(String name, Capabilities c
LOGGER.debug("Appended udid to capabilities: {}", capabilities);
}

Object mobileAppCapability = CapabilityHelpers.getCapability(capabilities, MobileCapabilityType.APP, String.class);
if (mobileAppCapability != null) {
MutableCapabilities appCaps = new MutableCapabilities();
appCaps.setCapability(MobileCapabilityType.APP, getAppLink(String.valueOf(mobileAppCapability)));
capabilities = capabilities.merge(appCaps);
}

LOGGER.debug("capabilities: {}", capabilities);

try {
Expand All @@ -112,6 +105,7 @@ public ImmutablePair<WebDriver, Capabilities> create(String name, Capabilities c
clientConfig = clientConfig.readTimeout(Duration.ofSeconds(readTimeout.get()));
}
EventFiringAppiumCommandExecutor commandExecutor = new EventFiringAppiumCommandExecutor(MobileCommand.commandRepository, clientConfig);
commandExecutor.setCapabilities(capabilities);

if (MobilePlatform.ANDROID.equalsIgnoreCase(mobilePlatformName)) {
driver = new AndroidDriver(commandExecutor, capabilities);
Expand Down Expand Up @@ -257,5 +251,5 @@ private String getParamFromDebugInfo(String debugInfo, String paramName) {

return paramValue;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
import java.lang.reflect.Type;
import java.util.List;

import com.zebrunner.carina.webdriver.gui.AbstractPage;
import com.zebrunner.carina.webdriver.helper.IExtendedWebElementHelper;
import com.zebrunner.carina.webdriver.locator.converter.LocatorConverter;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang3.reflect.ConstructorUtils;
Expand All @@ -36,7 +33,10 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zebrunner.carina.webdriver.gui.AbstractPage;
import com.zebrunner.carina.webdriver.helper.IExtendedWebElementHelper;
import com.zebrunner.carina.webdriver.locator.ExtendedElementLocator;
import com.zebrunner.carina.webdriver.locator.converter.LocatorConverter;
import com.zebrunner.carina.webdriver.locator.internal.LocatingListHandler;

public class ExtendedFieldDecorator implements FieldDecorator, IExtendedWebElementHelper {
Expand Down Expand Up @@ -83,16 +83,16 @@ public Object decorate(ClassLoader loader, Field field) {
if (ClassUtils.isAssignable(fieldType, ExtendedWebElement.class)) {
try {
ExtendedWebElement element;
if (ConstructorUtils.getAccessibleConstructor(fieldType, WebDriver.class) != null) {
element = (ExtendedWebElement) ConstructorUtils.invokeConstructor(fieldType, new Object[] { locator.getDriver() },
new Class<?>[] { WebDriver.class });
} else if (ConstructorUtils.getAccessibleConstructor(fieldType, WebDriver.class, SearchContext.class) != null) {
if (ConstructorUtils.getAccessibleConstructor(fieldType, WebDriver.class, SearchContext.class) != null) {
element = (ExtendedWebElement) ConstructorUtils.invokeConstructor(fieldType,
new Object[] { locator.getDriver(), locator.getSearchContext() },
new Class<?>[] { WebDriver.class, SearchContext.class });
} else if (ConstructorUtils.getAccessibleConstructor(fieldType, WebDriver.class) != null) {
element = (ExtendedWebElement) ConstructorUtils.invokeConstructor(fieldType, new Object[] { locator.getDriver() },
new Class<?>[] { WebDriver.class });
} else {
throw new NoSuchMethodException(
String.format("Could not find suitable constructor (WebDriver) or (WebDriver, SearchContext) in '%s' class.", fieldType));
String.format("Could not find suitable constructor (WebDriver, SearchContext) or (WebDriver) in '%s' class.", fieldType));
}

element.setBy(buildConvertedBy(locator.getBy(), locator.getLocatorConverters()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public abstract class AbstractUIObject extends ExtendedWebElement {
@SuppressWarnings("squid:S5993")
public AbstractUIObject(WebDriver driver) {
this(driver, driver);
//hotfix for custom elements (without ExtendedFieldDecorator)
setBy(By.xpath("(/*)[1]"));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.apache.commons.lang3.reflect.ConstructorUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Action;
Expand Down Expand Up @@ -510,12 +511,23 @@ default <T extends ExtendedWebElement> T findExtendedWebElement(T extendedElemen
@SuppressWarnings("unchecked")
default <T extends ExtendedWebElement> T findExtendedWebElement(T extendedElement, final By by, String name, Duration timeout) {
DriverListener.setMessages(Messager.ELEMENT_FOUND.getMessage(name), Messager.ELEMENT_NOT_FOUND.getMessage(name));
if (!waitUntil(ExpectedConditions.presenceOfElementLocated(Objects.requireNonNull(by)), timeout)) {
if (!waitUntil(ExpectedConditions.presenceOfNestedElementLocatedBy(extendedElement.getElement(), Objects.requireNonNull(by)), timeout)) {
Messager.ELEMENT_NOT_FOUND.error(name);
return null;
}
try {
T foundElement = (T) ConstructorUtils.invokeConstructor(extendedElement.getClass(), extendedElement.getDriver(), extendedElement);
T foundElement;
if (ConstructorUtils.getAccessibleConstructor(extendedElement.getClass(), WebDriver.class, SearchContext.class) != null) {
foundElement = (T) ConstructorUtils.invokeConstructor(extendedElement.getClass(),
new Object[] { extendedElement.getDriver(), extendedElement },
new Class<?>[] { WebDriver.class, SearchContext.class });
} else if (ConstructorUtils.getAccessibleConstructor(extendedElement.getClass(), WebDriver.class) != null) {
foundElement = (T) ConstructorUtils.invokeConstructor(extendedElement.getClass(), new Object[] { extendedElement.getDriver() },
new Class<?>[] { WebDriver.class });
} else {
throw new NoSuchMethodException(
String.format("Could not find suitable constructor (WebDriver) or (WebDriver, SearchContext) in '%s' class.", extendedElement.getClass()));
}
foundElement.setBy(by);
foundElement.setName(name);
return foundElement;
Expand Down Expand Up @@ -548,14 +560,25 @@ default <T extends ExtendedWebElement> List<T> findExtendedWebElements(T extende
default <T extends ExtendedWebElement> List<T> findExtendedWebElements(T extendedElement, final By by, Duration timeout) {
try {
List<T> extendedWebElements = new ArrayList<>();
if (!waitUntil(ExpectedConditions.presenceOfElementLocated(by), timeout)) {
if (!waitUntil(ExpectedConditions.presenceOfNestedElementLocatedBy(extendedElement.getElement(), Objects.requireNonNull(by)), timeout)) {
Messager.ELEMENT_NOT_FOUND.info(by.toString());
return extendedWebElements;
}

int i = 0;
for (WebElement webElement : extendedElement.findElements(by)) {
T foundElement = (T) ConstructorUtils.invokeConstructor(extendedElement.getClass(), extendedElement.getDriver(), extendedElement);
T foundElement;
if (ConstructorUtils.getAccessibleConstructor(extendedElement.getClass(), WebDriver.class, SearchContext.class) != null) {
foundElement = (T) ConstructorUtils.invokeConstructor(extendedElement.getClass(),
new Object[] { extendedElement.getDriver(), extendedElement },
new Class<?>[] { WebDriver.class, SearchContext.class });
} else if (ConstructorUtils.getAccessibleConstructor(extendedElement.getClass(), WebDriver.class) != null) {
foundElement = (T) ConstructorUtils.invokeConstructor(extendedElement.getClass(), new Object[] { extendedElement.getDriver() },
new Class<?>[] { WebDriver.class });
} else {
throw new NoSuchMethodException(
String.format("Could not find suitable constructor (WebDriver) or (WebDriver, SearchContext) in '%s' class.", extendedElement.getClass()));
}
foundElement.setName(String.format("ExtendedWebElement - [%d]", i));
foundElement.setElement(webElement);
extendedWebElements.add(foundElement);
Expand Down Expand Up @@ -626,7 +649,9 @@ default <T extends ExtendedWebElement> T format(T extendedElement, Object... obj
}
FormatLocatorConverter converter = new FormatLocatorConverter(objects);
converters.addFirst(converter);
formatElement.setBy(buildConvertedBy(ORIGINAL_LOCATORS.get(extendedElement.getUuid()), converters));
By originalBy = ORIGINAL_LOCATORS.get(extendedElement.getUuid()) != null ?
ORIGINAL_LOCATORS.get(extendedElement.getUuid()) : extendedElement.getBy();
formatElement.setBy(buildConvertedBy(originalBy, converters));
return formatElement;
}

Expand Down Expand Up @@ -660,9 +685,10 @@ default <T extends ExtendedWebElement> List<T> formatToList(T extendedElement, O
List<T> extendedElements = new ArrayList<>();
T tempExtendedElement = format(extendedElement, objects);
int index = 0;
for (WebElement element : extendedElement.findElements(Objects.requireNonNull(tempExtendedElement.getBy()))) {
for (WebElement element : extendedElement.getSearchContext()
.findElements(Objects.requireNonNull(tempExtendedElement.getBy()))) {
T extendedElementOfList = (T) ConstructorUtils.invokeConstructor(extendedElement.getClass(), extendedElement.getDriver(),
extendedElement);
extendedElement.getSearchContext());
extendedElementOfList.setElement(element);
extendedElementOfList.setBy(null);
extendedElementOfList.setName(String.format("%s - [%s]", extendedElement.getName(), index++));
Expand Down
Loading

0 comments on commit efb7ad0

Please sign in to comment.