Skip to content

Commit e5fa9de

Browse files
chore: Add the rest of XCUITest driver options (#1561)
1 parent 98c8a3c commit e5fa9de

20 files changed

+538
-159
lines changed

src/main/java/io/appium/java_client/AppiumDriver.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,20 @@
1717
package io.appium.java_client;
1818

1919
import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_NAME;
20+
import static org.apache.commons.lang3.StringUtils.isBlank;
2021

2122
import io.appium.java_client.remote.AppiumCommandExecutor;
2223
import io.appium.java_client.remote.AppiumNewSessionCommandPayload;
2324
import io.appium.java_client.remote.MobileCapabilityType;
25+
import io.appium.java_client.remote.options.BaseOptions;
2426
import io.appium.java_client.service.local.AppiumDriverLocalService;
2527
import io.appium.java_client.service.local.AppiumServiceBuilder;
2628
import org.openqa.selenium.Capabilities;
2729
import org.openqa.selenium.ImmutableCapabilities;
2830
import org.openqa.selenium.MutableCapabilities;
2931
import org.openqa.selenium.SessionNotCreatedException;
3032
import org.openqa.selenium.WebDriverException;
33+
import org.openqa.selenium.remote.CapabilityType;
3134
import org.openqa.selenium.remote.DriverCommand;
3235
import org.openqa.selenium.remote.ErrorHandler;
3336
import org.openqa.selenium.remote.ExecuteMethod;
@@ -199,7 +202,13 @@ protected void startSession(Capabilities capabilities) {
199202
}
200203

201204
@SuppressWarnings("unchecked") Map<String, Object> rawCapabilities = (Map<String, Object>) responseValue;
202-
MutableCapabilities returnedCapabilities = new MutableCapabilities(rawCapabilities);
205+
// A workaround for Selenium API enforcing some legacy capability values
206+
rawCapabilities.remove(CapabilityType.PLATFORM);
207+
if (rawCapabilities.containsKey(CapabilityType.BROWSER_NAME)
208+
&& isBlank((String) rawCapabilities.get(CapabilityType.BROWSER_NAME))) {
209+
rawCapabilities.remove(CapabilityType.BROWSER_NAME);
210+
}
211+
MutableCapabilities returnedCapabilities = new BaseOptions<>(rawCapabilities);
203212
try {
204213
Field capsField = RemoteWebDriver.class.getDeclaredField("capabilities");
205214
capsField.setAccessible(true);

src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
import io.appium.java_client.android.options.mjpeg.SupportsMjpegScreenshotUrlOption;
7979
import io.appium.java_client.android.options.mjpeg.SupportsMjpegServerPortOption;
8080
import io.appium.java_client.android.options.other.SupportsDisableSuppressAccessibilityServiceOption;
81-
import io.appium.java_client.android.options.other.SupportsSkipLogCaptureOption;
81+
import io.appium.java_client.remote.options.SupportsSkipLogCaptureOption;
8282
import io.appium.java_client.android.options.other.SupportsUserProfileOption;
8383
import io.appium.java_client.android.options.server.SupportsDisableWindowAnimationOption;
8484
import io.appium.java_client.android.options.server.SupportsSkipDeviceInitializationOption;
@@ -104,6 +104,8 @@
104104
import io.appium.java_client.remote.options.SupportsUdidOption;
105105
import org.openqa.selenium.Capabilities;
106106

107+
import java.util.Map;
108+
107109
/**
108110
* https://github.com/appium/appium-uiautomator2-driver#capabilities
109111
*/
@@ -211,6 +213,11 @@ public UiAutomator2Options(Capabilities source) {
211213
setCommonOptions();
212214
}
213215

216+
public UiAutomator2Options(Map<String, ?> source) {
217+
super(source);
218+
setCommonOptions();
219+
}
220+
214221
private void setCommonOptions() {
215222
setPlatformName(MobilePlatform.ANDROID);
216223
setAutomationName(AutomationName.ANDROID_UIAUTOMATOR2);

src/main/java/io/appium/java_client/ios/options/XCUITestOptions.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
import io.appium.java_client.ios.options.app.SupportsLocalizableStringsDirOption;
2323
import io.appium.java_client.ios.options.general.SupportsIncludeDeviceCapsToSessionInfoOption;
2424
import io.appium.java_client.ios.options.general.SupportsResetLocationServiceOption;
25+
import io.appium.java_client.ios.options.other.SupportsCommandTimeoutsOption;
26+
import io.appium.java_client.ios.options.other.SupportsLaunchWithIdbOption;
27+
import io.appium.java_client.ios.options.other.SupportsResetOnSessionStartOnlyOption;
28+
import io.appium.java_client.ios.options.other.SupportsShowIosLogOption;
29+
import io.appium.java_client.ios.options.other.SupportsUseJsonSourceOption;
2530
import io.appium.java_client.ios.options.simulator.SupportsCalendarAccessAuthorizedOption;
2631
import io.appium.java_client.ios.options.simulator.SupportsCalendarFormatOption;
2732
import io.appium.java_client.ios.options.simulator.SupportsConnectHardwareKeyboardOption;
@@ -106,9 +111,12 @@
106111
import io.appium.java_client.remote.options.SupportsLocaleOption;
107112
import io.appium.java_client.remote.options.SupportsOrientationOption;
108113
import io.appium.java_client.remote.options.SupportsOtherAppsOption;
114+
import io.appium.java_client.remote.options.SupportsSkipLogCaptureOption;
109115
import io.appium.java_client.remote.options.SupportsUdidOption;
110116
import org.openqa.selenium.Capabilities;
111117

118+
import java.util.Map;
119+
112120
/**
113121
* https://github.com/appium/appium-xcuitest-driver#capabilities
114122
*/
@@ -205,9 +213,15 @@ public class XCUITestOptions extends BaseOptions<XCUITestOptions> implements
205213
SupportsWebkitResponseTimeoutOption<XCUITestOptions>,
206214
SupportsEnableAsyncExecuteFromHttpsOption<XCUITestOptions>,
207215
SupportsFullContextListOption<XCUITestOptions>,
208-
// TODO: Other options: https://github.com/appium/appium-xcuitest-driver#other
209-
SupportsClearSystemFilesOption<XCUITestOptions>,
210-
SupportsEnablePerformanceLoggingOption<XCUITestOptions> {
216+
SupportsEnablePerformanceLoggingOption<XCUITestOptions>,
217+
// Other options: https://github.com/appium/appium-xcuitest-driver#other
218+
SupportsResetOnSessionStartOnlyOption<XCUITestOptions>,
219+
SupportsCommandTimeoutsOption<XCUITestOptions>,
220+
SupportsUseJsonSourceOption<XCUITestOptions>,
221+
SupportsSkipLogCaptureOption<XCUITestOptions>,
222+
SupportsLaunchWithIdbOption<XCUITestOptions>,
223+
SupportsShowIosLogOption<XCUITestOptions>,
224+
SupportsClearSystemFilesOption<XCUITestOptions> {
211225

212226
public XCUITestOptions() {
213227
setCommonOptions();
@@ -218,6 +232,11 @@ public XCUITestOptions(Capabilities source) {
218232
setCommonOptions();
219233
}
220234

235+
public XCUITestOptions(Map<String, ?> source) {
236+
super(source);
237+
setCommonOptions();
238+
}
239+
221240
private void setCommonOptions() {
222241
setPlatformName(MobilePlatform.IOS);
223242
setAutomationName(AutomationName.IOS_XCUI_TEST);
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* See the NOTICE file distributed with this work for additional
5+
* information regarding copyright ownership.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.appium.java_client.ios.options.other;
18+
19+
import com.google.gson.JsonObject;
20+
import io.appium.java_client.remote.options.BaseOptions;
21+
import io.appium.java_client.remote.options.CanSetCapability;
22+
import org.openqa.selenium.Capabilities;
23+
24+
import java.time.Duration;
25+
import java.util.Optional;
26+
27+
public interface SupportsCommandTimeoutsOption<T extends BaseOptions<T>> extends
28+
Capabilities, CanSetCapability<T> {
29+
String COMMAND_TIMEOUTS_OPTION = "commandTimeouts";
30+
31+
/**
32+
* Custom timeout(s) in milliseconds for WDA backend commands execution.
33+
* This might be useful if WDA backend freezes unexpectedly or requires too
34+
* much time to fail and blocks automated test execution. The value is expected
35+
* to be of type string and can either contain max milliseconds to wait for
36+
* each WDA command to be executed before terminating the session forcefully
37+
* or a valid JSON string, where keys are internal Appium command names (you
38+
* can find these in logs, look for "Executing command 'command_name'" records)
39+
* and values are timeouts in milliseconds. You can also set the 'default' key
40+
* to assign the timeout for all other commands not explicitly enumerated as
41+
* JSON keys.
42+
*
43+
* @param timeouts E.g. '{"findElement": 40000, "findElements": 40000}'.
44+
* @return self instance for chaining.
45+
*/
46+
default T setCommandTimeouts(JsonObject timeouts) {
47+
return amend(COMMAND_TIMEOUTS_OPTION, timeouts.toString());
48+
}
49+
50+
/**
51+
* Custom timeout(s) in milliseconds for WDA backend commands execution.
52+
* This might be useful if WDA backend freezes unexpectedly or requires too
53+
* much time to fail and blocks automated test execution. The value is expected
54+
* to be of type string and can either contain max milliseconds to wait for
55+
* each WDA command to be executed before terminating the session forcefully
56+
* or a valid JSON string, where keys are internal Appium command names (you
57+
* can find these in logs, look for "Executing command 'command_name'" records)
58+
* and values are timeouts in milliseconds. You can also set the 'default' key
59+
* to assign the timeout for all other commands not explicitly enumerated as
60+
* JSON keys.
61+
*
62+
* @param timeout The timeout value for all commands.
63+
* @return self instance for chaining.
64+
*/
65+
default T setCommandTimeouts(Duration timeout) {
66+
return amend(COMMAND_TIMEOUTS_OPTION, String.valueOf(timeout.toMillis()));
67+
}
68+
69+
/**
70+
* Get custom timeout(s) in milliseconds for WDA backend commands execution.
71+
*
72+
* @return Command timeouts.
73+
*/
74+
default Optional<String> getCommandTimeouts() {
75+
return Optional.ofNullable(
76+
(String) getCapability(COMMAND_TIMEOUTS_OPTION)
77+
);
78+
}
79+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* See the NOTICE file distributed with this work for additional
5+
* information regarding copyright ownership.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.appium.java_client.ios.options.other;
18+
19+
import io.appium.java_client.remote.options.BaseOptions;
20+
import io.appium.java_client.remote.options.CanSetCapability;
21+
import org.openqa.selenium.Capabilities;
22+
23+
import java.util.Optional;
24+
25+
import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean;
26+
27+
public interface SupportsLaunchWithIdbOption<T extends BaseOptions<T>> extends
28+
Capabilities, CanSetCapability<T> {
29+
String LAUNCH_WITH_IDB_OPTION = "launchWithIDB";
30+
31+
/**
32+
* Enforces launching of WebDriverAgentRunner with idb instead of xcodebuild.
33+
*
34+
* @return self instance for chaining.
35+
*/
36+
default T launchWithIdb() {
37+
return amend(LAUNCH_WITH_IDB_OPTION, true);
38+
}
39+
40+
/**
41+
* Launch WebDriverAgentRunner with idb instead of xcodebuild. This could save
42+
* a significant amount of time by skipping the xcodebuild process, although the
43+
* idb might not be very reliable, especially with fresh Xcode SDKs. Check
44+
* the idb repository for more details on possible compatibility issues.
45+
* Defaults to false.
46+
*
47+
* @param value Whether to launch WebDriverAgentRunner with idb instead of xcodebuild.
48+
* @return self instance for chaining.
49+
*/
50+
default T setLaunchWithIdb(boolean value) {
51+
return amend(LAUNCH_WITH_IDB_OPTION, value);
52+
}
53+
54+
/**
55+
* Get whether to launch WebDriverAgentRunner with idb instead of xcodebuild.
56+
*
57+
* @return True or false.
58+
*/
59+
default Optional<Boolean> doesLaunchWithIdb() {
60+
return Optional.ofNullable(toSafeBoolean(getCapability(LAUNCH_WITH_IDB_OPTION)));
61+
}
62+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* See the NOTICE file distributed with this work for additional
5+
* information regarding copyright ownership.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.appium.java_client.ios.options.other;
18+
19+
import io.appium.java_client.remote.options.BaseOptions;
20+
import io.appium.java_client.remote.options.CanSetCapability;
21+
import org.openqa.selenium.Capabilities;
22+
23+
import java.util.Optional;
24+
25+
import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean;
26+
27+
public interface SupportsResetOnSessionStartOnlyOption<T extends BaseOptions<T>> extends
28+
Capabilities, CanSetCapability<T> {
29+
String RESET_ON_SESSION_START_ONLY_OPTION = "resetOnSessionStartOnly";
30+
31+
/**
32+
* Whether to perform reset on test session finish (false) or not (true).
33+
* Keeping this variable set to true and Simulator running (the default
34+
* behaviour since version 1.6.4) may significantly shorten the duration of
35+
* test session initialization.
36+
*
37+
* @param value Whether to perform reset on test session finish (false) or not (true)..
38+
* @return self instance for chaining.
39+
*/
40+
default T setResetOnSessionStartOnly(boolean value) {
41+
return amend(RESET_ON_SESSION_START_ONLY_OPTION, value);
42+
}
43+
44+
/**
45+
* Get whether to perform reset on test session finish (false) or not (true).
46+
*
47+
* @return True or false.
48+
*/
49+
default Optional<Boolean> doesResetOnSessionStartOnly() {
50+
return Optional.ofNullable(toSafeBoolean(getCapability(RESET_ON_SESSION_START_ONLY_OPTION)));
51+
}
52+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* See the NOTICE file distributed with this work for additional
5+
* information regarding copyright ownership.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.appium.java_client.ios.options.other;
18+
19+
import io.appium.java_client.remote.options.BaseOptions;
20+
import io.appium.java_client.remote.options.CanSetCapability;
21+
import org.openqa.selenium.Capabilities;
22+
23+
import java.util.Optional;
24+
25+
import static io.appium.java_client.internal.CapabilityHelpers.toSafeBoolean;
26+
27+
public interface SupportsShowIosLogOption<T extends BaseOptions<T>> extends
28+
Capabilities, CanSetCapability<T> {
29+
String SHOW_IOS_LOG_OPTION = "showIOSLog";
30+
31+
/**
32+
* Enforces showing any logs captured from a device in the appium logs.
33+
*
34+
* @return self instance for chaining.
35+
*/
36+
default T showIosLog() {
37+
return amend(SHOW_IOS_LOG_OPTION, true);
38+
}
39+
40+
/**
41+
* Whether to show any logs captured from a device in the appium logs.
42+
* Default false.
43+
*
44+
* @param value Whether to show any logs captured from a device in the appium logs.
45+
* @return self instance for chaining.
46+
*/
47+
default T setShowIosLog(boolean value) {
48+
return amend(SHOW_IOS_LOG_OPTION, value);
49+
}
50+
51+
/**
52+
* Get whether to show any logs captured from a device in the appium logs.
53+
*
54+
* @return True or false.
55+
*/
56+
default Optional<Boolean> doesShowIosLog() {
57+
return Optional.ofNullable(toSafeBoolean(getCapability(SHOW_IOS_LOG_OPTION)));
58+
}
59+
}

0 commit comments

Comments
 (0)