Skip to content

Commit 54d55b9

Browse files
authored
Merge pull request #17 from seleniumhq-community/pr/prefix-browserVersion-cap
Normalize [browserVersion] for grid compatibility
2 parents b0d3653 + 27d6e34 commit 54d55b9

File tree

4 files changed

+105
-4
lines changed

4 files changed

+105
-4
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,14 @@ java -jar selenium-server-<version>.jar --ext htmlunit-remote-<version>-grid-ext
4444
```
4545
The `grid-extension` artifact provides all of the specifications and service providers required to enable **Selenium 4 Grid** to supply remote sessions of **HtmlUnitDriver**. This artifact combines `htmlunit-remote` with `htmlunit3-driver`, `htmlunit`, and all of their unique dependencies.
4646

47+
### Specification of [browserVersion]
48+
49+
In **HtmlUnit Driver**, you can use the standard `browserVersion` capability to select a specific browser emulation profile. This works as expected in local operation but will cause driver acquisition to fail in remote configurations. The reason for this is that `browserVersion` is an _identity_ value that the Selenium Grid distributor expects to match against the stereotype of a compatible node. In **HtmlUnit Driver**, `browserVersion` is a _configuration_ value, so this capability should not be considered for slot matching.
50+
51+
**HtmlUnit Remote** adds a vendor-specific capability for selecting a specific browser emulation profile: `garg:browserVersion`. If you use the standard **HtmlUnitDriverOptions** class to build your driver specification, this issue is handled for you automatically. If you specify driver capabilities directly, be sure to use this new vendor-specific capability name.
52+
53+
```
54+
{"browserName": "htmlunit", "garg:browserVersion": "firefox-115"}
55+
```
56+
4757
> Written with [StackEdit](https://stackedit.io/).

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<groupId>com.nordstrom.ui-tools</groupId>
77
<artifactId>htmlunit-remote</artifactId>
8-
<version>4.38.1-SNAPSHOT</version>
8+
<version>4.39.0-SNAPSHOT</version>
99

1010
<name>htmlunit-remote</name>
1111
<description>This is the remote wrapper for HtmlUnitDriver</description>
@@ -32,8 +32,8 @@
3232
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
3333
<maven.compiler.source>11</maven.compiler.source>
3434
<maven.compiler.target>11</maven.compiler.target>
35-
<selenium.version>4.38.0</selenium.version>
36-
<htmlunit.version>4.38.0</htmlunit.version>
35+
<selenium.version>4.39.0</selenium.version>
36+
<htmlunit.version>4.39.0</htmlunit.version>
3737
<junit.version>4.13.2</junit.version>
3838
<checkstyle.version>10.15.0</checkstyle.version>
3939
<spotbugs.version>4.8.4</spotbugs.version>

src/main/java/org/openqa/selenium/htmlunit/remote/HtmlUnitDriverInfo.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@
2424

2525
import org.openqa.selenium.Capabilities;
2626
import org.openqa.selenium.ImmutableCapabilities;
27+
import org.openqa.selenium.MutableCapabilities;
2728
import org.openqa.selenium.SessionNotCreatedException;
2829
import org.openqa.selenium.WebDriver;
2930
import org.openqa.selenium.WebDriverInfo;
3031
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
3132
import org.openqa.selenium.htmlunit.options.HtmlUnitDriverOptions;
33+
import org.openqa.selenium.remote.CapabilityType;
3234

3335
import com.google.auto.service.AutoService;
36+
import com.google.common.annotations.VisibleForTesting;
3437

3538
/**
3639
* Describes an {@link HtmlUnitDriver} instance. This allows services to query the system at
@@ -117,6 +120,38 @@ public Optional<WebDriver> createDriver(final Capabilities capabilities) throws
117120
return Optional.empty();
118121
}
119122

120-
return Optional.of(new HtmlUnitDriver(new HtmlUnitDriverOptions().merge(capabilities)));
123+
Capabilities normalized = normalizeBrowserVersion(capabilities);
124+
return Optional.of(new HtmlUnitDriver(new HtmlUnitDriverOptions().merge(normalized)));
125+
}
126+
127+
/**
128+
* The following implementation ensures grid-compatible handling of
129+
* the [browserVersion] capability. If the standard [browserVersion]
130+
* capability is defined, it's removed. If the [garg:browserVersion]
131+
* is undefined, the original value of [browserVersion] is adopted.
132+
*
133+
* @param capabilities {@link Capabilities} object to normalize
134+
* @return grid-compatible capabilities with normalized [browserVersion]
135+
*/
136+
@VisibleForTesting
137+
static MutableCapabilities normalizeBrowserVersion(final Capabilities capabilities) {
138+
// create mutable Capabilities object
139+
MutableCapabilities mutable = new MutableCapabilities(capabilities);
140+
// get standard [browserVersion] if non-null
141+
Optional.ofNullable(mutable.getBrowserVersion())
142+
// filter out if value is empty
143+
.filter(versionVal -> !versionVal.isEmpty())
144+
// if value exists
145+
.ifPresent(versionVal -> {
146+
// if vendor-specific browser version is undefined
147+
if (mutable.getCapability(HtmlUnitDriverOptions.BROWSER_VERSION) == null) {
148+
// set value of vendor-specific browser version
149+
mutable.setCapability(HtmlUnitDriverOptions.BROWSER_VERSION, versionVal);
150+
}
151+
// remove standard [browserVersion] capability
152+
mutable.setCapability(CapabilityType.BROWSER_VERSION, (String) null);
153+
}
154+
);
155+
return mutable;
121156
}
122157
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package org.openqa.selenium.htmlunit.remote;
2+
3+
import static org.junit.Assert.assertEquals;
4+
5+
import org.junit.Test;
6+
import org.openqa.selenium.Capabilities;
7+
import org.openqa.selenium.htmlunit.options.HtmlUnitDriverOptions;
8+
import org.openqa.selenium.remote.Browser;
9+
import org.openqa.selenium.remote.CapabilityType;
10+
import org.openqa.selenium.remote.DesiredCapabilities;
11+
12+
public class HtmlUnitDriverInfoTest {
13+
14+
@Test
15+
public void testNormalizationOfStandardCapabilities() {
16+
DesiredCapabilities desired =
17+
// set [browserName] and [browserVersion]
18+
new DesiredCapabilities(Browser.HTMLUNIT.browserName(), Browser.EDGE.browserName(), null);
19+
20+
Capabilities capabilities = HtmlUnitDriverInfo.normalizeBrowserVersion(desired);
21+
assertEquals(Browser.HTMLUNIT.browserName(), capabilities.getBrowserName());
22+
assertEquals(null, capabilities.getCapability(CapabilityType.BROWSER_VERSION));
23+
assertEquals(Browser.EDGE.browserName(), capabilities.getCapability(HtmlUnitDriverOptions.BROWSER_VERSION));
24+
}
25+
26+
@Test
27+
public void testNormalizationOfVendorSpecificCapabilities() {
28+
DesiredCapabilities desired =
29+
// set [browserName]
30+
new DesiredCapabilities(Browser.HTMLUNIT.browserName(), null, null);
31+
32+
// set [garg:browserVersion]
33+
desired.setCapability(HtmlUnitDriverOptions.BROWSER_VERSION, Browser.FIREFOX.browserName());
34+
35+
Capabilities capabilities = HtmlUnitDriverInfo.normalizeBrowserVersion(desired);
36+
assertEquals(Browser.HTMLUNIT.browserName(), capabilities.getBrowserName());
37+
assertEquals(null, capabilities.getCapability(CapabilityType.BROWSER_VERSION));
38+
assertEquals(Browser.FIREFOX.browserName(), capabilities.getCapability(HtmlUnitDriverOptions.BROWSER_VERSION));
39+
}
40+
41+
@Test
42+
public void testVendorSpecificBrowserVersionOverride() {
43+
DesiredCapabilities desired =
44+
// set [browserName] and [browserVersion]
45+
new DesiredCapabilities(Browser.HTMLUNIT.browserName(), Browser.IE.browserName(), null);
46+
47+
// set [garg:browserVersion]
48+
desired.setCapability(HtmlUnitDriverOptions.BROWSER_VERSION, Browser.CHROME.browserName());
49+
50+
Capabilities capabilities = HtmlUnitDriverInfo.normalizeBrowserVersion(desired);
51+
assertEquals(Browser.HTMLUNIT.browserName(), capabilities.getBrowserName());
52+
assertEquals(null, capabilities.getCapability(CapabilityType.BROWSER_VERSION));
53+
assertEquals(Browser.CHROME.browserName(), capabilities.getCapability(HtmlUnitDriverOptions.BROWSER_VERSION));
54+
}
55+
56+
}

0 commit comments

Comments
 (0)