Skip to content

Commit

Permalink
refactor!: Update selenium dependencies to v4.14 (#2036)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The library is now only compatible to Java11 and above
BREAKING CHANGE: The previously deprecated MobileBy class has been removed. Use AppiumBy instead
BREAKING CHANGE: The previously deprecated launchApp, resetApp and closeApp methods have been removed. Use extension methods instead
BREAKING CHANGE: The previously deprecated WindowsBy class and related location strategies have been removed
BREAKING CHANGE: The previously deprecated ByAll class has been removed in favour of the Selenium one
BREAKING CHANGE: The previously deprecated AndroidMobileCapabilityType interface has been removed. Use driver options instead
BREAKING CHANGE: The previously deprecated IOSMobileCapabilityType interface has been removed. Use driver options instead
BREAKING CHANGE: The previously deprecated MobileCapabilityType interface has been removed. Use driver options instead
BREAKING CHANGE: The previously deprecated MobileOptions class has been removed. Use driver options instead
BREAKING CHANGE: The previously deprecated YouiEngineCapabilityType interface has been removed. Use driver options instead
BREAKING CHANGE: Removed several misspelled methods. Use properly spelled alternatives instead
BREAKING CHANGE: Removed startActivity method from AndroidDriver. Use 'mobile: startActivity' extension method instead
BREAKING CHANGE: Removed the previously deprecated APPIUM constant from the AutomationName interface
BREAKING CHANGE: Removed the previously deprecated PRE_LAUNCH value from the GeneralServerFlag enum
BREAKING CHANGE: Moved AppiumUserAgentFilter class to io.appium.java_client.internal.filters package

Removed dependencies to Apache Commons libraries
  • Loading branch information
mykola-mokhnach committed Oct 12, 2023
1 parent c6f2154 commit 39c2526
Show file tree
Hide file tree
Showing 58 changed files with 239 additions and 2,906 deletions.
11 changes: 7 additions & 4 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ on:
- 'docs/**'
- '*.md'

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

env:
ANDROID_SDK_VERSION: 28
ANDROID_EMU_NAME: test
Expand All @@ -27,14 +31,13 @@ jobs:
strategy:
matrix:
include:
# TODO: add new LTS Java ( 21 ) once it's released
- java: 8
platform: macos-latest
e2e-tests: android
- java: 11
# Need to use specific (not `-latest`) version of macOS to be sure the required version of Xcode/simulator is available
platform: macos-12
e2e-tests: ios
- java: 15
platform: macos-latest
e2e-tests: android
- java: 17
platform: ubuntu-latest
fail-fast: false
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
- name: Set up Java
uses: actions/setup-java@v3
with:
java-version: '8'
java-version: '11'
distribution: 'zulu'
cache: 'gradle'
- name: Publish package
Expand Down
27 changes: 11 additions & 16 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ repositories {
}

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
withJavadocJar()
withSourcesJar()
}
Expand All @@ -34,25 +34,23 @@ dependencies {

api ('org.seleniumhq.selenium:selenium-api') {
version {
strictly "[${seleniumVersion}, 4.14)"
strictly "[${seleniumVersion}, 5.0)"
prefer "${seleniumVersion}"
}
}
api ('org.seleniumhq.selenium:selenium-remote-driver') {
version {
strictly "[${seleniumVersion}, 4.14)"
strictly "[${seleniumVersion}, 5.0)"
prefer "${seleniumVersion}"
}
}
api ('org.seleniumhq.selenium:selenium-support') {
version {
strictly "[${seleniumVersion}, 4.14)"
strictly "[${seleniumVersion}, 5.0)"
prefer "${seleniumVersion}"
}
}
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'org.apache.commons:commons-lang3:3.13.0'
implementation 'commons-io:commons-io:2.14.0'
implementation "org.slf4j:slf4j-api:${slf4jVersion}"

testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
Expand Down Expand Up @@ -93,16 +91,13 @@ tasks.withType(JacocoReport) {
}
jacocoTestReport.dependsOn test

// Checkstyle requires Java 11 starting from 10.0
if (JavaVersion.current().isJava11Compatible()) {
apply plugin: 'checkstyle'
apply plugin: 'checkstyle'

checkstyle {
toolVersion = '10.12.1'
configFile = configDirectory.file('appium-style.xml').get().getAsFile()
showViolations = true
ignoreFailures = false
}
checkstyle {
toolVersion = '10.12.1'
configFile = configDirectory.file('appium-style.xml').get().getAsFile()
showViolations = true
ignoreFailures = false
}

javadoc {
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
org.gradle.daemon=true

selenium.version=4.9.1
selenium.version=4.14.1
# Please increment the value in a release
appiumClient.version=8.6.0
6 changes: 4 additions & 2 deletions src/main/java/io/appium/java_client/AppiumBy.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

package io.appium.java_client;

import com.google.common.base.Preconditions;
import lombok.Getter;
import org.apache.commons.lang3.Validate;
import org.openqa.selenium.By;
import org.openqa.selenium.By.Remotable;
import org.openqa.selenium.SearchContext;
Expand All @@ -27,13 +27,15 @@
import java.util.List;
import java.util.Objects;

import static com.google.common.base.Strings.isNullOrEmpty;

public abstract class AppiumBy extends By implements Remotable {

@Getter private final Parameters remoteParameters;
private final String locatorName;

protected AppiumBy(String selector, String locatorString, String locatorName) {
Validate.notBlank(locatorString, "Must supply a not empty locator value.");
Preconditions.checkArgument(!isNullOrEmpty(locatorString), "Must supply a not empty locator value.");
this.remoteParameters = new Parameters(selector, locatorString);
this.locatorName = locatorName;
}
Expand Down
28 changes: 23 additions & 5 deletions src/main/java/io/appium/java_client/AppiumClientConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@

package io.appium.java_client;

import io.appium.java_client.internal.filters.AppiumIdempotencyFilter;
import io.appium.java_client.internal.filters.AppiumUserAgentFilter;
import org.openqa.selenium.Credentials;
import org.openqa.selenium.internal.Require;
import org.openqa.selenium.remote.http.ClientConfig;
import org.openqa.selenium.remote.http.Filter;

import javax.annotation.Nullable;
import javax.net.ssl.SSLContext;
import java.net.Proxy;
import java.net.URI;
import java.net.URISyntaxException;
Expand All @@ -33,7 +37,10 @@
public class AppiumClientConfig extends ClientConfig {
private final boolean directConnect;

private static final Filter DEFAULT_FILTER = new AppiumUserAgentFilter();
private static final Filter DEFAULT_FILTERS = new AppiumUserAgentFilter()
.andThen(new AppiumIdempotencyFilter());

private static final String DEFAULT_HTTP_VERSION = "HTTP_1_1";

private static final Duration DEFAULT_READ_TIMEOUT = Duration.ofMinutes(10);

Expand All @@ -49,17 +56,20 @@ public class AppiumClientConfig extends ClientConfig {
* {@link org.openqa.selenium.remote.http.HttpResponse}.
* @param proxy The client proxy preference.
* @param credentials Credentials used for authenticating http requests
* @param sslContext SSL context (if present)
* @param directConnect If directConnect is enabled.
*/
protected AppiumClientConfig(
URI baseUri,
Duration connectionTimeout,
Duration readTimeout,
Filter filters,
Proxy proxy,
Credentials credentials,
@Nullable Proxy proxy,
@Nullable Credentials credentials,
@Nullable SSLContext sslContext,
@Nullable String version,
Boolean directConnect) {
super(baseUri, connectionTimeout, readTimeout, filters, proxy, credentials);
super(baseUri, connectionTimeout, readTimeout, filters, proxy, credentials, sslContext, version);

this.directConnect = Require.nonNull("Direct Connect", directConnect);
}
Expand All @@ -73,9 +83,11 @@ public static AppiumClientConfig defaultConfig() {
null,
DEFAULT_CONNECTION_TIMEOUT,
DEFAULT_READ_TIMEOUT,
DEFAULT_FILTER,
DEFAULT_FILTERS,
null,
null,
null,
DEFAULT_HTTP_VERSION,
false);
}

Expand All @@ -92,6 +104,8 @@ public static AppiumClientConfig fromClientConfig(ClientConfig clientConfig) {
clientConfig.filter(),
clientConfig.proxy(),
clientConfig.credentials(),
clientConfig.sslContext(),
clientConfig.version(),
false);
}

Expand All @@ -103,6 +117,8 @@ private AppiumClientConfig buildAppiumClientConfig(ClientConfig clientConfig, Bo
clientConfig.filter(),
clientConfig.proxy(),
clientConfig.credentials(),
clientConfig.sslContext(),
clientConfig.version(),
directConnect);
}

Expand Down Expand Up @@ -175,6 +191,8 @@ public AppiumClientConfig directConnect(boolean directConnect) {
this.filter(),
this.proxy(),
this.credentials(),
this.sslContext(),
this.version(),
directConnect
);
}
Expand Down
38 changes: 19 additions & 19 deletions src/main/java/io/appium/java_client/AppiumDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
import io.appium.java_client.remote.AppiumCommandExecutor;
import io.appium.java_client.remote.AppiumNewSessionCommandPayload;
import io.appium.java_client.remote.AppiumW3CHttpCommandCodec;
import io.appium.java_client.remote.MobileCapabilityType;
import io.appium.java_client.remote.options.BaseOptions;
import io.appium.java_client.service.local.AppiumDriverLocalService;
import io.appium.java_client.service.local.AppiumServiceBuilder;
import lombok.Getter;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.ImmutableCapabilities;
import org.openqa.selenium.MutableCapabilities;
Expand All @@ -53,10 +53,10 @@
import java.util.Map;
import java.util.Set;

import static com.google.common.base.Strings.isNullOrEmpty;
import static io.appium.java_client.internal.CapabilityHelpers.APPIUM_PREFIX;
import static io.appium.java_client.remote.MobileCapabilityType.AUTOMATION_NAME;
import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_NAME;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static io.appium.java_client.remote.options.SupportsAutomationNameOption.AUTOMATION_NAME_OPTION;
import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME;

/**
* Default Appium driver implementation.
Expand All @@ -72,6 +72,7 @@ public class AppiumDriver extends RemoteWebDriver implements

private static final ErrorHandler ERROR_HANDLER = new ErrorHandler(new ErrorCodesMobile(), true);
// frequently used command parameters
@Getter
private final URL remoteAddress;
protected final RemoteLocationContext locationContext;
private final ExecuteMethod executeMethod;
Expand Down Expand Up @@ -154,7 +155,7 @@ public AppiumDriver(URL remoteSessionAddress, String platformName, String automa
RemoteWebDriver.class, this, "capabilities", new ImmutableCapabilities(
ImmutableMap.of(
PLATFORM_NAME, platformName,
APPIUM_PREFIX + AUTOMATION_NAME, automationName
APPIUM_PREFIX + AUTOMATION_NAME_OPTION, automationName
)
)
);
Expand All @@ -177,8 +178,7 @@ public AppiumDriver(URL remoteSessionAddress, String platformName, String automa
* Changes platform name if it is not set and returns merged capabilities.
*
* @param originalCapabilities the given {@link Capabilities}.
* @param defaultName a {@link MobileCapabilityType#PLATFORM_NAME} value which has
* to be set up
* @param defaultName a platformName value which has to be set up
* @return {@link Capabilities} with changed platform name value or the original capabilities
*/
protected static Capabilities ensurePlatformName(
Expand All @@ -192,17 +192,16 @@ protected static Capabilities ensurePlatformName(
* Changes automation name if it is not set and returns merged capabilities.
*
* @param originalCapabilities the given {@link Capabilities}.
* @param defaultName a {@link MobileCapabilityType#AUTOMATION_NAME} value which has
* to be set up
* @param defaultName a platformName value which has to be set up
* @return {@link Capabilities} with changed mobile automation name value or the original capabilities
*/
protected static Capabilities ensureAutomationName(
Capabilities originalCapabilities, String defaultName) {
String currentAutomationName = CapabilityHelpers.getCapability(
originalCapabilities, AUTOMATION_NAME, String.class);
if (isBlank(currentAutomationName)) {
originalCapabilities, AUTOMATION_NAME_OPTION, String.class);
if (isNullOrEmpty(currentAutomationName)) {
String capabilityName = originalCapabilities.getCapabilityNames()
.contains(AUTOMATION_NAME) ? AUTOMATION_NAME : APPIUM_PREFIX + AUTOMATION_NAME;
.contains(AUTOMATION_NAME_OPTION) ? AUTOMATION_NAME_OPTION : APPIUM_PREFIX + AUTOMATION_NAME_OPTION;
return originalCapabilities.merge(new ImmutableCapabilities(capabilityName, defaultName));
}
return originalCapabilities;
Expand All @@ -213,8 +212,7 @@ protected static Capabilities ensureAutomationName(
* and returns merged capabilities.
*
* @param originalCapabilities the given {@link Capabilities}.
* @param defaultPlatformName a {@link MobileCapabilityType#PLATFORM_NAME} value which has
* to be set up
* @param defaultPlatformName a platformName value which has to be set up
* @param defaultAutomationName The default automation name to set up for this class
* @return {@link Capabilities} with changed platform/automation name value or the original capabilities
*/
Expand Down Expand Up @@ -265,10 +263,6 @@ public void addCommand(HttpMethod httpMethod, String url, String methodName) {
((AppiumCommandExecutor) getCommandExecutor()).refreshAdditionalCommands();
}

public URL getRemoteAddress() {
return remoteAddress;
}

@Override
protected void startSession(Capabilities capabilities) {
Response response = execute(new AppiumNewSessionCommandPayload(capabilities));
Expand All @@ -293,7 +287,7 @@ protected void startSession(Capabilities capabilities) {
// TODO: remove this workaround for Selenium API enforcing some legacy capability values in major version
rawCapabilities.remove("platform");
if (rawCapabilities.containsKey(CapabilityType.BROWSER_NAME)
&& isBlank((String) rawCapabilities.get(CapabilityType.BROWSER_NAME))) {
&& isNullOrEmpty((String) rawCapabilities.get(CapabilityType.BROWSER_NAME))) {
rawCapabilities.remove(CapabilityType.BROWSER_NAME);
}
MutableCapabilities returnedCapabilities = new BaseOptions<>(rawCapabilities);
Expand Down Expand Up @@ -346,4 +340,10 @@ public AppiumDriver markExtensionAbsence(String extName) {
absentExtensionNames.add(extName);
return this;
}

protected HttpClient getHttpClient() {
return ReflectionHelpers.getPrivateFieldValue(
HttpCommandExecutor.class, getCommandExecutor(), "client", HttpClient.class
);
}
}
16 changes: 8 additions & 8 deletions src/main/java/io/appium/java_client/ComparesImages.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
import io.appium.java_client.imagecomparison.OccurrenceMatchingResult;
import io.appium.java_client.imagecomparison.SimilarityMatchingOptions;
import io.appium.java_client.imagecomparison.SimilarityMatchingResult;
import org.apache.commons.io.FileUtils;

import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Base64;
import java.util.Map;

Expand Down Expand Up @@ -93,8 +93,8 @@ default FeaturesMatchingResult matchImagesFeatures(File image1, File image2) thr
*/
default FeaturesMatchingResult matchImagesFeatures(File image1, File image2,
@Nullable FeaturesMatchingOptions options) throws IOException {
return matchImagesFeatures(Base64.getEncoder().encode(FileUtils.readFileToByteArray(image1)),
Base64.getEncoder().encode(FileUtils.readFileToByteArray(image2)), options);
return matchImagesFeatures(Base64.getEncoder().encode(Files.readAllBytes(image1.toPath())),
Base64.getEncoder().encode(Files.readAllBytes(image2.toPath())), options);
}

/**
Expand Down Expand Up @@ -160,8 +160,8 @@ default OccurrenceMatchingResult findImageOccurrence(File fullImage, File partia
default OccurrenceMatchingResult findImageOccurrence(File fullImage, File partialImage,
@Nullable OccurrenceMatchingOptions options)
throws IOException {
return findImageOccurrence(Base64.getEncoder().encode(FileUtils.readFileToByteArray(fullImage)),
Base64.getEncoder().encode(FileUtils.readFileToByteArray(partialImage)), options);
return findImageOccurrence(Base64.getEncoder().encode(Files.readAllBytes(fullImage.toPath())),
Base64.getEncoder().encode(Files.readAllBytes(partialImage.toPath())), options);
}

/**
Expand Down Expand Up @@ -227,7 +227,7 @@ default SimilarityMatchingResult getImagesSimilarity(File image1, File image2) t
default SimilarityMatchingResult getImagesSimilarity(File image1, File image2,
@Nullable SimilarityMatchingOptions options)
throws IOException {
return getImagesSimilarity(Base64.getEncoder().encode(FileUtils.readFileToByteArray(image1)),
Base64.getEncoder().encode(FileUtils.readFileToByteArray(image2)), options);
return getImagesSimilarity(Base64.getEncoder().encode(Files.readAllBytes(image1.toPath())),
Base64.getEncoder().encode(Files.readAllBytes(image2.toPath())), options);
}
}
}

0 comments on commit 39c2526

Please sign in to comment.