Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
}
}
Loading