Skip to content

Commit e30a7eb

Browse files
authored
[java] Ensure options presents in capabilities are merged as expected (#11396)
1 parent cd9c0fe commit e30a7eb

File tree

5 files changed

+267
-2
lines changed

5 files changed

+267
-2
lines changed

java/src/org/openqa/selenium/chromium/ChromiumOptions.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,43 @@ protected Object getExtraCapability(String capabilityName) {
280280
protected void mergeInPlace(Capabilities capabilities) {
281281
Require.nonNull("Capabilities to merge", capabilities);
282282

283-
capabilities.getCapabilityNames().forEach(name -> setCapability(name, capabilities.getCapability(name)));
283+
for (String name : capabilities.getCapabilityNames()) {
284+
if (!name.equals("binary") && !name.equals("extensions") && !name.equals("args")) {
285+
setCapability(name, capabilities.getCapability(name));
286+
}
287+
288+
if (name.equals("args") && capabilities.getCapability(name) != null) {
289+
List<String> arguments = (List<String>) (capabilities.getCapability(("args")));
290+
arguments.forEach(arg -> {
291+
if (!args.contains(arg)) {
292+
addArguments(arg);
293+
}
294+
});
295+
}
296+
297+
if (name.equals("extensions") && capabilities.getCapability(name) != null) {
298+
List<Object> extensionList = (List<Object>) (capabilities.getCapability(("extensions")));
299+
extensionList.forEach(extension -> {
300+
if (!extensions.contains(extension)) {
301+
if (extension instanceof File) {
302+
addExtensions((File) extension);
303+
} else if (extension instanceof String) {
304+
addEncodedExtensions((String) extension);
305+
}
306+
}
307+
});
308+
}
309+
310+
if (name.equals("binary") && capabilities.getCapability(name) != null) {
311+
Object binary = capabilities.getCapability("binary");
312+
if (binary instanceof String) {
313+
setBinary((String) binary);
314+
} else if (binary instanceof File) {
315+
setBinary((File) binary);
316+
}
317+
}
318+
}
319+
284320
if (capabilities instanceof ChromiumOptions) {
285321
ChromiumOptions<?> options = (ChromiumOptions<?>) capabilities;
286322
for (String arg : options.args) {

java/src/org/openqa/selenium/firefox/FirefoxOptions.java

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,65 @@ public FirefoxOptions merge(Capabilities capabilities) {
331331
Require.nonNull("Capabilities to merge", capabilities);
332332
FirefoxOptions newInstance = new FirefoxOptions();
333333
getCapabilityNames().forEach(name -> newInstance.setCapability(name, getCapability(name)));
334-
capabilities.getCapabilityNames().forEach(name -> newInstance.setCapability(name, capabilities.getCapability(name)));
335334
newInstance.mirror(this);
335+
336+
for (String name : capabilities.getCapabilityNames()) {
337+
338+
if (!name.equals(Keys.ARGS.key) &&
339+
!name.equals(Keys.PREFS.key) &&
340+
!name.equals(Keys.PROFILE.key) &&
341+
!name.equals(Keys.BINARY.key) &&
342+
!name.equals(Keys.LOG.key)) {
343+
newInstance.setCapability(name, capabilities.getCapability(name));
344+
}
345+
346+
if (name.equals(Keys.ARGS.key) && capabilities.getCapability(name) != null) {
347+
List<String> arguments = (List<String>) (capabilities.getCapability(("args")));
348+
arguments.forEach(arg -> {
349+
if (!((List<String>) newInstance.firefoxOptions.get(Keys.ARGS.key())).contains(arg)) {
350+
newInstance.addArguments(arg);
351+
}
352+
});
353+
}
354+
355+
if (name.equals(Keys.PREFS.key) && capabilities.getCapability(name) != null) {
356+
Map<String, Object> prefs =
357+
(Map<String, Object>) (capabilities.getCapability(("prefs")));
358+
prefs.forEach(newInstance::addPreference);
359+
}
360+
361+
if (name.equals(Keys.PROFILE.key) && capabilities.getCapability(name) != null) {
362+
String rawProfile =
363+
(String) capabilities.getCapability("profile");
364+
try {
365+
newInstance.setProfile(FirefoxProfile.fromJson(rawProfile));
366+
} catch (IOException e) {
367+
throw new WebDriverException(e);
368+
}
369+
}
370+
371+
if (name.equals(Keys.BINARY.key) && capabilities.getCapability(name) != null) {
372+
Object binary = capabilities.getCapability("binary");
373+
if (binary instanceof String) {
374+
newInstance.setBinary((String) binary);
375+
} else if (binary instanceof Path) {
376+
newInstance.setBinary((Path) binary);
377+
} else if (binary instanceof FirefoxBinary) {
378+
newInstance.setBinary((FirefoxBinary) binary);
379+
}
380+
}
381+
382+
if (name.equals(Keys.LOG.key) && capabilities.getCapability(name) != null) {
383+
Map<String, Object> logLevelMap =
384+
(Map<String, Object>) capabilities.getCapability("log");
385+
FirefoxDriverLogLevel logLevel =
386+
FirefoxDriverLogLevel.fromString((String) logLevelMap.get("level"));
387+
if (logLevel != null) {
388+
newInstance.setLogLevel(logLevel);
389+
}
390+
}
391+
}
392+
336393
if (capabilities instanceof FirefoxOptions) {
337394
newInstance.mirror((FirefoxOptions) capabilities);
338395
} else {

java/test/org/openqa/selenium/chrome/ChromeOptionsTest.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import java.io.File;
2929
import java.time.Duration;
30+
import java.util.Arrays;
3031
import java.util.Base64;
3132
import java.util.HashMap;
3233
import java.util.List;
@@ -264,6 +265,60 @@ void mergingOptionsWithMutableCapabilities() {
264265
.isEqualTo(binary.getPath());
265266
}
266267

268+
@Test
269+
void mergingOptionsWithOptionsAsMutableCapabilities() {
270+
File ext1 = TestUtilities.createTmpFile("ext1");
271+
String ext1Encoded = Base64.getEncoder().encodeToString("ext1".getBytes());
272+
String ext2 = Base64.getEncoder().encodeToString("ext2".getBytes());
273+
274+
MutableCapabilities browserCaps = new MutableCapabilities();
275+
276+
File binary = TestUtilities.createTmpFile("binary");
277+
278+
browserCaps.setCapability("binary", binary.getPath());
279+
browserCaps.setCapability("opt1", "val1");
280+
browserCaps.setCapability("opt2", "val4");
281+
browserCaps.setCapability("args", Arrays.asList("silent", "verbose"));
282+
browserCaps.setCapability("extensions", Arrays.asList(ext1, ext2));
283+
284+
MutableCapabilities one = new MutableCapabilities();
285+
one.setCapability(ChromeOptions.CAPABILITY, browserCaps);
286+
287+
ChromeOptions two = new ChromeOptions();
288+
two.addArguments("verbose");
289+
two.setExperimentalOption("opt2", "val2");
290+
two.setExperimentalOption("opt3", "val3");
291+
two = two.merge(one);
292+
293+
Map<String, Object> map = two.asMap();
294+
295+
assertThat(map).asInstanceOf(MAP)
296+
.extractingByKey(ChromeOptions.CAPABILITY).asInstanceOf(MAP)
297+
.extractingByKey("args").asInstanceOf(LIST)
298+
.containsExactly("verbose", "silent");
299+
300+
assertThat(map).asInstanceOf(MAP)
301+
.containsEntry("opt1", "val1");
302+
303+
assertThat(map).asInstanceOf(MAP)
304+
.containsEntry("opt2", "val4");
305+
306+
assertThat(map).asInstanceOf(MAP)
307+
.extractingByKey(ChromeOptions.CAPABILITY).asInstanceOf(MAP)
308+
.containsEntry("opt2", "val2")
309+
.containsEntry("opt3", "val3");
310+
311+
assertThat(map).asInstanceOf(MAP)
312+
.extractingByKey(ChromeOptions.CAPABILITY).asInstanceOf(MAP)
313+
.extractingByKey("extensions").asInstanceOf(LIST)
314+
.containsExactly(ext1Encoded, ext2);
315+
316+
assertThat(map).asInstanceOf(MAP)
317+
.extractingByKey(ChromeOptions.CAPABILITY).asInstanceOf(MAP)
318+
.extractingByKey("binary").asInstanceOf(STRING)
319+
.isEqualTo(binary.getPath());
320+
}
321+
267322
@Test
268323
void isW3CSafe() {
269324
Map<String, Object> converted = new ChromeOptions()

java/test/org/openqa/selenium/edge/EdgeOptionsTest.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,60 @@ void mergingOptionsWithMutableCapabilities() {
147147
.isEqualTo(binary.getPath());
148148
}
149149

150+
@Test
151+
void mergingOptionsWithOptionsAsMutableCapabilities() {
152+
File ext1 = TestUtilities.createTmpFile("ext1");
153+
String ext1Encoded = Base64.getEncoder().encodeToString("ext1".getBytes());
154+
String ext2 = Base64.getEncoder().encodeToString("ext2".getBytes());
155+
156+
MutableCapabilities browserCaps = new MutableCapabilities();
157+
158+
File binary = TestUtilities.createTmpFile("binary");
159+
160+
browserCaps.setCapability("binary", binary.getPath());
161+
browserCaps.setCapability("opt1", "val1");
162+
browserCaps.setCapability("opt2", "val4");
163+
browserCaps.setCapability("args", Arrays.asList("silent", "verbose"));
164+
browserCaps.setCapability("extensions", Arrays.asList(ext1, ext2));
165+
166+
MutableCapabilities one = new MutableCapabilities();
167+
one.setCapability(EdgeOptions.CAPABILITY, browserCaps);
168+
169+
EdgeOptions two = new EdgeOptions();
170+
two.addArguments("verbose");
171+
two.setExperimentalOption("opt2", "val2");
172+
two.setExperimentalOption("opt3", "val3");
173+
two = two.merge(one);
174+
175+
Map<String, Object> map = two.asMap();
176+
177+
assertThat(map).asInstanceOf(MAP)
178+
.extractingByKey(EdgeOptions.CAPABILITY).asInstanceOf(MAP)
179+
.extractingByKey("args").asInstanceOf(LIST)
180+
.containsExactly("verbose", "silent");
181+
182+
assertThat(map).asInstanceOf(MAP)
183+
.containsEntry("opt1", "val1");
184+
185+
assertThat(map).asInstanceOf(MAP)
186+
.containsEntry("opt2", "val4");
187+
188+
assertThat(map).asInstanceOf(MAP)
189+
.extractingByKey(EdgeOptions.CAPABILITY).asInstanceOf(MAP)
190+
.containsEntry("opt2", "val2")
191+
.containsEntry("opt3", "val3");
192+
193+
assertThat(map).asInstanceOf(MAP)
194+
.extractingByKey(EdgeOptions.CAPABILITY).asInstanceOf(MAP)
195+
.extractingByKey("extensions").asInstanceOf(LIST)
196+
.containsExactly(ext1Encoded, ext2);
197+
198+
assertThat(map).asInstanceOf(MAP)
199+
.extractingByKey(EdgeOptions.CAPABILITY).asInstanceOf(MAP)
200+
.extractingByKey("binary").asInstanceOf(STRING)
201+
.isEqualTo(binary.getPath());
202+
}
203+
150204
private void checkCommonStructure(EdgeOptions options) {
151205
assertThat(options.asMap())
152206
.containsEntry(CapabilityType.BROWSER_NAME, EDGE.browserName())

java/test/org/openqa/selenium/firefox/FirefoxOptionsTest.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import java.nio.file.Paths;
6060
import java.nio.file.attribute.PosixFilePermission;
6161
import java.util.Arrays;
62+
import java.util.HashMap;
6263
import java.util.List;
6364
import java.util.Map;
6465

@@ -439,6 +440,68 @@ void mergingOptionsWithMutableCapabilities() {
439440
assertThat(extractedProfile.getStringPreference(key, "-")).isEqualTo(value);
440441
}
441442

443+
@Test
444+
void mergingOptionsWithOptionsAsMutableCapabilities() throws IOException {
445+
Map<String, String> prefs = new HashMap<>();
446+
prefs.put("opt1", "val1");
447+
prefs.put("opt2", "val4");
448+
449+
String key = "browser.startup.homepage";
450+
String value = "about:robots";
451+
452+
FirefoxProfile profile = new FirefoxProfile();
453+
profile.setPreference(key, value);
454+
455+
File binary = TestUtilities.createTmpFile("binary");
456+
457+
MutableCapabilities browserCaps = new MutableCapabilities();
458+
459+
browserCaps.setCapability("args", Arrays.asList("verbose", "silent"));
460+
browserCaps.setCapability("prefs", prefs);
461+
browserCaps.setCapability("profile", profile.toJson());
462+
browserCaps.setCapability("binary", binary.getPath());
463+
browserCaps.setCapability("log", DEBUG.toJson());
464+
465+
MutableCapabilities one = new MutableCapabilities();
466+
one.setCapability(FIREFOX_OPTIONS, browserCaps);
467+
468+
FirefoxOptions two = new FirefoxOptions();
469+
two.addArguments("verbose");
470+
two.addPreference("opt2", "val2");
471+
two.addPreference("opt3", "val3");
472+
two = two.merge(one);
473+
474+
Map<String, Object> map = two.asMap();
475+
476+
assertThat(map).asInstanceOf(MAP)
477+
.extractingByKey(FIREFOX_OPTIONS).asInstanceOf(MAP)
478+
.extractingByKey("args").asInstanceOf(LIST)
479+
.containsExactly("verbose", "silent");
480+
481+
assertThat(map).asInstanceOf(MAP)
482+
.extractingByKey(FIREFOX_OPTIONS).asInstanceOf(MAP)
483+
.extractingByKey("prefs").asInstanceOf(MAP)
484+
.containsEntry("opt1", "val1")
485+
.containsEntry("opt2", "val4")
486+
.containsEntry("opt3", "val3");
487+
488+
assertThat(map).asInstanceOf(MAP)
489+
.extractingByKey(ACCEPT_INSECURE_CERTS).isExactlyInstanceOf(Boolean.class);
490+
491+
assertThat(map).asInstanceOf(MAP)
492+
.extractingByKey(FIREFOX_OPTIONS).asInstanceOf(MAP)
493+
.extractingByKey("binary").asInstanceOf(STRING)
494+
.isEqualTo(binary.getPath());
495+
496+
assertThat(map).asInstanceOf(MAP)
497+
.extractingByKey(FIREFOX_OPTIONS).asInstanceOf(MAP)
498+
.extractingByKey("log").asInstanceOf(MAP)
499+
.containsEntry("level", "debug");
500+
501+
FirefoxProfile extractedProfile = two.getProfile();
502+
assertThat(extractedProfile.getStringPreference(key, "-")).isEqualTo(value);
503+
}
504+
442505
@Test
443506
void firefoxOptionsShouldEqualEquivalentImmutableCapabilities() {
444507
FirefoxOptions

0 commit comments

Comments
 (0)