25
25
26
26
import com .google .gson .Gson ;
27
27
import com .google .gson .GsonBuilder ;
28
+ import io .appium .java_client .remote .AndroidMobileCapabilityType ;
29
+ import io .appium .java_client .remote .MobileCapabilityType ;
28
30
import io .appium .java_client .service .local .flags .ServerArgument ;
29
31
30
32
import org .apache .commons .io .IOUtils ;
31
33
import org .apache .commons .lang3 .StringUtils ;
32
34
import org .apache .commons .lang3 .SystemUtils ;
33
35
import org .apache .commons .validator .routines .InetAddressValidator ;
34
36
import org .openqa .selenium .Capabilities ;
37
+ import org .openqa .selenium .Platform ;
35
38
import org .openqa .selenium .os .ExecutableFinder ;
36
39
import org .openqa .selenium .remote .BrowserType ;
37
40
import org .openqa .selenium .remote .DesiredCapabilities ;
@@ -78,6 +81,7 @@ public final class AppiumServiceBuilder
78
81
private File node ;
79
82
private String ipAddress = BROADCAST_IP_ADDRESS ;
80
83
private DesiredCapabilities capabilities ;
84
+ private boolean autoQuoteCapabilitiesOnWindows = false ;
81
85
private static final Function <File , String > APPIUM_JS_NOT_EXIST_ERROR = (fullPath ) -> String .format (
82
86
"The main Appium script does not exist at '%s'" , fullPath .getAbsolutePath ());
83
87
private static final Function <File , String > NODE_JS_NOT_EXIST_ERROR = (fullPath ) ->
@@ -86,6 +90,8 @@ public final class AppiumServiceBuilder
86
90
// The first starting is slow sometimes on some environment
87
91
private long startupTimeout = 120 ;
88
92
private TimeUnit timeUnit = TimeUnit .SECONDS ;
93
+ private static final List <String > PATH_CAPABILITIES = ImmutableList .of (AndroidMobileCapabilityType .KEYSTORE_PATH ,
94
+ AndroidMobileCapabilityType .CHROMEDRIVER_EXECUTABLE , MobileCapabilityType .APP );
89
95
90
96
public AppiumServiceBuilder () {
91
97
usingPort (DEFAULT_APPIUM_PORT );
@@ -239,6 +245,21 @@ public AppiumServiceBuilder withCapabilities(DesiredCapabilities capabilities) {
239
245
return this ;
240
246
}
241
247
248
+ /**
249
+ * Adds a desired capabilities.
250
+ *
251
+ * @param capabilities is an instance of {@link DesiredCapabilities}.
252
+ * @param autoQuoteCapabilitiesOnWindows automatically escape quote all
253
+ * capabilities when calling appium.
254
+ * This is required on windows systems only.
255
+ * @return the self-reference.
256
+ */
257
+ public AppiumServiceBuilder withCapabilities (DesiredCapabilities capabilities ,
258
+ boolean autoQuoteCapabilitiesOnWindows ) {
259
+ this .autoQuoteCapabilitiesOnWindows = autoQuoteCapabilitiesOnWindows ;
260
+ return withCapabilities (capabilities );
261
+ }
262
+
242
263
/**
243
264
* Sets an executable appium.js.
244
265
*
@@ -296,7 +317,46 @@ private void loadPathToMainScript() {
296
317
this .appiumJS = findMainScript ();
297
318
}
298
319
320
+ private String parseCapabilitiesIfWindows () {
321
+ if (capabilities == null ) {
322
+ return "{}" ;
323
+ }
324
+ StringBuilder result = new StringBuilder ();
325
+ Map <String , ?> capabilitiesMap = capabilities .asMap ();
326
+ Set <? extends Map .Entry <String , ?>> entries = capabilitiesMap .entrySet ();
327
+
328
+ for (Map .Entry <String , ?> entry : entries ) {
329
+ Object value = entry .getValue ();
330
+
331
+ if (value == null ) {
332
+ continue ;
333
+ }
334
+
335
+ if (value instanceof String ) {
336
+ String valueString = (String ) value ;
337
+ if (PATH_CAPABILITIES .contains (entry .getKey ())) {
338
+ value = "\\ \" " + valueString .replace ("\\ " , "/" ) + "\\ \" " ;
339
+ } else {
340
+ value = "\\ \" " + valueString + "\\ \" " ;
341
+ }
342
+ } else {
343
+ value = String .valueOf (value );
344
+ }
345
+
346
+ String key = "\\ \" " + entry .getKey () + "\\ \" " ;
347
+ if (result .length () > 0 ) {
348
+ result .append (", " );
349
+ }
350
+ result .append (key ).append (": " ).append (value );
351
+ }
352
+
353
+ return "{" + result .toString () + "}" ;
354
+ }
355
+
299
356
private String capabilitiesToCmdlineArg () {
357
+ if (autoQuoteCapabilitiesOnWindows && Platform .getCurrent ().is (Platform .WINDOWS )) {
358
+ return parseCapabilitiesIfWindows ();
359
+ }
300
360
Gson gson = new GsonBuilder ()
301
361
.disableHtmlEscaping ()
302
362
.serializeNulls ()
0 commit comments