Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
51d7c1e
feat: support directConnect
KazuCocoa Aug 25, 2022
65e494f
add an argument for directConnect
KazuCocoa Aug 25, 2022
05d0976
add flag in android drivers
KazuCocoa Aug 25, 2022
5c3f950
add config
KazuCocoa Aug 25, 2022
a5c3baa
add for ios
KazuCocoa Aug 25, 2022
48b42e8
add config to other drivers
KazuCocoa Aug 25, 2022
55ad185
update imports, license
KazuCocoa Aug 25, 2022
d0ff28a
use a tag
KazuCocoa Aug 25, 2022
16dd824
fix lint
KazuCocoa Aug 25, 2022
0125a97
update part of
KazuCocoa Aug 25, 2022
138fbd4
fix lint
KazuCocoa Aug 25, 2022
03833d7
create a new client with given config and factory
KazuCocoa Aug 27, 2022
2a89299
add constructor
KazuCocoa Aug 27, 2022
97e8b62
refer to this
KazuCocoa Aug 27, 2022
821c89d
update ios
KazuCocoa Aug 27, 2022
08a4d01
upadte others as well
KazuCocoa Aug 27, 2022
0afaf50
refer to super
KazuCocoa Aug 27, 2022
e6ea969
raise an exception
KazuCocoa Aug 27, 2022
9ee52cb
keep clientconfig as part of appiumclientconfig
KazuCocoa Aug 28, 2022
11c54b5
tweak
KazuCocoa Aug 28, 2022
e7a751a
tweak
KazuCocoa Aug 28, 2022
790857d
modify address
KazuCocoa Aug 28, 2022
fc96519
fix typo
KazuCocoa Aug 28, 2022
1751304
tweak base url
KazuCocoa Aug 28, 2022
160cf8e
fix the default local service
KazuCocoa Aug 28, 2022
8862d75
do not use orElse
KazuCocoa Aug 28, 2022
d923503
fixlint
KazuCocoa Aug 28, 2022
139161b
update null case
KazuCocoa Aug 28, 2022
3b576aa
tweak a bit
KazuCocoa Aug 29, 2022
5358125
Merge branch 'master' into direct-connect
KazuCocoa Sep 29, 2022
ca93f6e
update to extend client config
KazuCocoa Sep 29, 2022
bd1f78c
follows client config
KazuCocoa Sep 30, 2022
bab6830
tweak docstring
KazuCocoa Sep 30, 2022
8d9b785
rever some unnecessary changes
KazuCocoa Sep 30, 2022
839df21
run tests in internal as unitTests, add user agent definition
KazuCocoa Sep 30, 2022
ec63fb1
add tests, tweak some lines
KazuCocoa Sep 30, 2022
0460169
add a key
KazuCocoa Sep 30, 2022
6db723c
add docstring
KazuCocoa Sep 30, 2022
c2676ee
remove unnecessary argument
KazuCocoa Sep 30, 2022
7326811
chore: add comments
KazuCocoa Sep 30, 2022
397f596
chore: tweak
KazuCocoa Sep 30, 2022
9cc5e4a
chore: add UA in a new session request
KazuCocoa Sep 30, 2022
f2dc84a
fix: lint
KazuCocoa Sep 30, 2022
c00697d
chore: remove done todo
KazuCocoa Sep 30, 2022
b1a9413
Merge branch 'master' into direct-connect
KazuCocoa Oct 7, 2022
9ab8547
remove user agent stuff
KazuCocoa Oct 20, 2022
e455f52
remove ua stuff more
KazuCocoa Oct 20, 2022
f6570d2
remove UA stuff
KazuCocoa Oct 20, 2022
69ff238
collect similar process into one method
KazuCocoa Oct 20, 2022
7b2ff2a
tweak
KazuCocoa Oct 20, 2022
bd0395b
add a class object
KazuCocoa Oct 20, 2022
0a11b8a
Merge branch 'direct-connect' of github.com:KazuCocoa/java-client int…
KazuCocoa Oct 20, 2022
bfdd997
tweak
KazuCocoa Oct 20, 2022
6d3d3ec
remove a few lines
KazuCocoa Oct 20, 2022
26ded53
extract direct connect and add tests
KazuCocoa Oct 21, 2022
1961a1d
fix lint
KazuCocoa Oct 21, 2022
35547b5
tweak docstring
KazuCocoa Oct 21, 2022
c31226e
fix review
KazuCocoa Oct 23, 2022
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
2 changes: 1 addition & 1 deletion .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ jobs:
java-version: ${{ matrix.java }}
cache: 'gradle'
- name: Build with Gradle
run: ./gradlew clean build -x test -x checkstyleTest
run: ./gradlew clean build -x unitTest -x checkstyleTest
9 changes: 9 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,15 @@ processResources {
]
}

task unitTest( type: Test ) {
useJUnitPlatform()
testLogging.showStandardStreams = true
testLogging.exceptionFormat = 'full'
filter {
includeTestsMatching 'io.appium.java_client.internal.*'
}
}

task xcuiTest( type: Test ) {
useJUnitPlatform()
testLogging.showStandardStreams = true
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ signing.secretKeyRingFile=PathToYourKeyRingFile
ossrhUsername=your-jira-id
ossrhPassword=your-jira-password

selenium.version=4.4.0
selenium.version=4.5.0
191 changes: 191 additions & 0 deletions src/main/java/io/appium/java_client/AppiumClientConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* 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 io.appium.java_client;

import org.openqa.selenium.Credentials;
import org.openqa.selenium.internal.Require;
import org.openqa.selenium.remote.http.AddSeleniumUserAgent;
import org.openqa.selenium.remote.http.ClientConfig;
import org.openqa.selenium.remote.http.Filter;

import java.net.Proxy;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.time.Duration;

/**
* A class to store the appium http client configuration.
*/
public class AppiumClientConfig extends ClientConfig {
private final boolean directConnect;

private static final Filter DEFAULT_FILTER = new AddSeleniumUserAgent();

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

private static final Duration DEFAULT_CONNECTION_TIMEOUT = Duration.ofSeconds(10);

/**
* Client side configuration.
*
* @param baseUri Base URL the client sends HTTP request to.
* @param connectionTimeout The client connection timeout.
* @param readTimeout The client read timeout.
* @param filters Filters to modify incoming {@link org.openqa.selenium.remote.http.HttpRequest} or outgoing
* {@link org.openqa.selenium.remote.http.HttpResponse}.
* @param proxy The client proxy preference.
* @param credentials Credentials used for authenticating http requests
* @param directConnect If directConnect is enabled.
*/
protected AppiumClientConfig(
URI baseUri,
Duration connectionTimeout,
Duration readTimeout,
Filter filters,
Proxy proxy,
Credentials credentials,
Boolean directConnect) {
super(baseUri, connectionTimeout, readTimeout, filters, proxy, credentials);

this.directConnect = Require.nonNull("Direct Connect", directConnect);
}

/**
* Return the instance of {@link AppiumClientConfig} with a default config.
* @return the instance of {@link AppiumClientConfig}.
*/
public static AppiumClientConfig defaultConfig() {
return new AppiumClientConfig(
null,
DEFAULT_CONNECTION_TIMEOUT,
DEFAULT_READ_TIMEOUT,
DEFAULT_FILTER,
null,
null,
false);
}

/**
* Return the instance of {@link AppiumClientConfig} from the given {@link ClientConfig} parameters.
* @param clientConfig take a look at {@link ClientConfig}
* @return the instance of {@link AppiumClientConfig}.
*/
public static AppiumClientConfig fromClientConfig(ClientConfig clientConfig) {
return new AppiumClientConfig(
clientConfig.baseUri(),
clientConfig.connectionTimeout(),
clientConfig.readTimeout(),
clientConfig.filter(),
clientConfig.proxy(),
clientConfig.credentials(),
false);
}

private AppiumClientConfig buildAppiumClientConfig(ClientConfig clientConfig, Boolean directConnect) {
return new AppiumClientConfig(
clientConfig.baseUri(),
clientConfig.connectionTimeout(),
clientConfig.readTimeout(),
clientConfig.filter(),
clientConfig.proxy(),
clientConfig.credentials(),
directConnect);
}

@Override
public AppiumClientConfig baseUri(URI baseUri) {
ClientConfig clientConfig = super.baseUri(baseUri);
return buildAppiumClientConfig(clientConfig, directConnect);
}

@Override
public AppiumClientConfig baseUrl(URL baseUrl) {
try {
return baseUri(Require.nonNull("Base URL", baseUrl).toURI());
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}

@Override
public AppiumClientConfig connectionTimeout(Duration timeout) {
ClientConfig clientConfig = super.connectionTimeout(timeout);
return buildAppiumClientConfig(clientConfig, directConnect);
}

@Override
public AppiumClientConfig readTimeout(Duration timeout) {
ClientConfig clientConfig = super.connectionTimeout(timeout);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should call super.readTimeout(timeout)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, fixed in #1959

return buildAppiumClientConfig(clientConfig, directConnect);
}

@Override
public AppiumClientConfig withFilter(Filter filter) {
ClientConfig clientConfig = super.withFilter(filter);
return buildAppiumClientConfig(clientConfig, directConnect);
}

@Override
public AppiumClientConfig withRetries() {
ClientConfig clientConfig = super.withRetries();
return buildAppiumClientConfig(clientConfig, directConnect);
}


@Override
public ClientConfig proxy(Proxy proxy) {
ClientConfig clientConfig = super.proxy(proxy);
return buildAppiumClientConfig(clientConfig, directConnect);
}

@Override
public AppiumClientConfig authenticateAs(Credentials credentials) {
ClientConfig clientConfig = super.authenticateAs(credentials);
return buildAppiumClientConfig(clientConfig, directConnect);
}

/**
* Whether enable directConnect feature described in
* <a href="https://appiumpro.com/editions/86-connecting-directly-to-appium-hosts-in-distributed-environments">
* Connecting Directly to Appium Hosts in Distributed Environments</a>.
*
* @param directConnect if enable the directConnect feature
* @return A new instance of AppiumClientConfig
*/
public AppiumClientConfig directConnect(boolean directConnect) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets use a common approach and have set prefix for all builder setter methods

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if here should follow ClientConfig, that had no set:

e.g.

  public ClientConfig baseUrl(URL baseUrl) {
    try {
      return baseUri(Require.nonNull("Base URL", baseUrl).toURI());
    } catch (URISyntaxException e) {
      throw new RuntimeException(e);
    }
  }

  public URI baseUri() {
    return baseUri;
  }

Still not decided yet to inherit, or just keep the clientconfig as a variable so that users can define their subclass of clientconfig as their clientconfig.

// follows ClientConfig's design
return new AppiumClientConfig(
this.baseUri(),
this.connectionTimeout(),
this.readTimeout(),
this.filter(),
this.proxy(),
this.credentials(),
directConnect
);
}

/**
* Whether enable directConnect feature is enabled.
*
* @return If the directConnect is enabled. Defaults false.
*/
public boolean isDirectConnectEnabled() {
return directConnect;
}
}
3 changes: 1 addition & 2 deletions src/main/java/io/appium/java_client/AppiumDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.Response;
import org.openqa.selenium.remote.html5.RemoteLocationContext;
import org.openqa.selenium.remote.http.ClientConfig;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpMethod;

Expand Down Expand Up @@ -84,7 +83,7 @@ public AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities) {
this.remoteAddress = executor.getAddressOfRemoteServer();
}

public AppiumDriver(ClientConfig clientConfig, Capabilities capabilities) {
public AppiumDriver(AppiumClientConfig clientConfig, Capabilities capabilities) {
this(new AppiumCommandExecutor(MobileCommand.commandRepository, clientConfig), capabilities);
}

Expand Down
28 changes: 27 additions & 1 deletion src/main/java/io/appium/java_client/android/AndroidDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import com.google.common.collect.ImmutableMap;

import io.appium.java_client.AppiumClientConfig;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.CommandExecutionHelper;
import io.appium.java_client.ExecuteCDPCommand;
Expand Down Expand Up @@ -203,7 +204,32 @@ public AndroidDriver(HttpClient.Factory httpClientFactory, Capabilities capabili
*
*/
public AndroidDriver(ClientConfig clientConfig, Capabilities capabilities) {
super(clientConfig, ensurePlatformName(capabilities, ANDROID_PLATFORM));
super(AppiumClientConfig.fromClientConfig(clientConfig), ensurePlatformName(capabilities,
ANDROID_PLATFORM));
}

/**
* Creates a new instance based on the given ClientConfig and {@code capabilities}.
* The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}.
* For example:
*
* <pre>
*
* AppiumClientConfig appiumClientConfig = AppiumClientConfig.defaultConfig()
* .directConnect(true)
* .baseUri(URI.create("WebDriver URL"))
* .readTimeout(Duration.ofMinutes(5));
* UiAutomator2Options options = new UiAutomator2Options();
* AndroidDriver driver = new AndroidDriver(appiumClientConfig, options);
*
* </pre>
*
* @param appiumClientConfig take a look at {@link AppiumClientConfig}
* @param capabilities take a look at {@link Capabilities}
*
*/
public AndroidDriver(AppiumClientConfig appiumClientConfig, Capabilities capabilities) {
super(appiumClientConfig, ensurePlatformName(capabilities, ANDROID_PLATFORM));
}

/**
Expand Down
27 changes: 26 additions & 1 deletion src/main/java/io/appium/java_client/gecko/GeckoDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.appium.java_client.gecko;

import io.appium.java_client.AppiumClientConfig;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.remote.AutomationName;
import io.appium.java_client.service.local.AppiumDriverLocalService;
Expand Down Expand Up @@ -94,7 +95,31 @@ public GeckoDriver(HttpClient.Factory httpClientFactory, Capabilities capabiliti
*
*/
public GeckoDriver(ClientConfig clientConfig, Capabilities capabilities) {
super(clientConfig, ensureAutomationName(capabilities, AUTOMATION_NAME));
super(AppiumClientConfig.fromClientConfig(clientConfig), ensureAutomationName(capabilities, AUTOMATION_NAME));
}

/**
* Creates a new instance based on the given ClientConfig and {@code capabilities}.
* The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}.
* For example:
*
* <pre>
*
* AppiumClientConfig appiumClientConfig = AppiumClientConfig.defaultConfig()
* .directConnect(true)
* .baseUri(URI.create("WebDriver URL"))
* .readTimeout(Duration.ofMinutes(5));
* GeckoOptions options = new GeckoOptions();
* GeckoDriver driver = new GeckoDriver(options, appiumClientConfig);
*
* </pre>
*
* @param appiumClientConfig take a look at {@link AppiumClientConfig}
* @param capabilities take a look at {@link Capabilities}
*
*/
public GeckoDriver(AppiumClientConfig appiumClientConfig, Capabilities capabilities) {
super(appiumClientConfig, ensureAutomationName(capabilities, AUTOMATION_NAME));
}

public GeckoDriver(Capabilities capabilities) {
Expand Down
29 changes: 28 additions & 1 deletion src/main/java/io/appium/java_client/ios/IOSDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import com.google.common.collect.ImmutableMap;

import io.appium.java_client.AppiumClientConfig;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.HasAppStrings;
import io.appium.java_client.HasDeviceTime;
Expand Down Expand Up @@ -192,9 +193,35 @@ public IOSDriver(HttpClient.Factory httpClientFactory, Capabilities capabilities
*
*/
public IOSDriver(ClientConfig clientConfig, Capabilities capabilities) {
super(clientConfig, ensurePlatformName(capabilities, PLATFORM_NAME));
super(AppiumClientConfig.fromClientConfig(clientConfig),
ensurePlatformName(capabilities, PLATFORM_NAME));
}

/**
* Creates a new instance based on the given ClientConfig and {@code capabilities}.
* The HTTP client is default client generated by {@link HttpCommandExecutor#getDefaultClientFactory}.
* For example:
*
* <pre>
*
* AppiumClientConfig appiumClientConfig = AppiumClientConfig.defaultConfig()
* .directConnect(true)
* .baseUri(URI.create("WebDriver URL"))
* .readTimeout(Duration.ofMinutes(5));
* XCUITestOptions options = new XCUITestOptions();
* IOSDriver driver = new IOSDriver(options, appiumClientConfig);
*
* </pre>
*
* @param appiumClientConfig take a look at {@link AppiumClientConfig}
* @param capabilities take a look at {@link Capabilities}
*
*/
public IOSDriver(AppiumClientConfig appiumClientConfig, Capabilities capabilities) {
super(appiumClientConfig, ensurePlatformName(capabilities, PLATFORM_NAME));
}


/**
* Creates a new instance based on {@code capabilities}.
*
Expand Down
Loading