Skip to content
This repository was archived by the owner on Mar 25, 2025. It is now read-only.

Commit f360348

Browse files
slu-itAxel Schüssler
authored andcommitted
New GridFactory for creating Selenium Grid Browsers
With this factory a RemoteDriver based Browser can be created. It will take the default configuration from the configuration, but also allow for overriding the Selenium Grid specific properties via System Properties. Since this is core functionallity, there are some new "named" properties for this factory.
1 parent 497666f commit f360348

File tree

11 files changed

+618
-14
lines changed

11 files changed

+618
-14
lines changed

documentation/chapters/configuration.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ The following shows all default properties loaded by the `DefaultFileConfigurati
7575
The values are the same as the fallback values of the `BaseConfiguration` implementation.
7676

7777
```properties
78-
# Weather or not the events should be fired.
78+
# Whether or not the events should be fired.
7979
# TYPE: boolean [true, false]
8080
events.enabled = true
8181

@@ -85,7 +85,7 @@ actions.deceleration = 0
8585

8686
# URL of the default entry point for the application under test.
8787
# TYPE: String [Resource URL]
88-
# defaults.entry-point =
88+
# defaults.entry-point =
8989

9090
# Folder in which to save screenshots if not otherwise specified.
9191
# TYPE: String [absolute or relative path to be initialized as a java.io.File instance]
@@ -126,6 +126,26 @@ wait.timeout = 2
126126
# Default interval in which to check a condition for wait operations.
127127
# TYPE: int [milliseconds]
128128
wait.interval = 100
129+
130+
# Name of the browser to use in Selenium Grid
131+
# TYPE: String [firefox, chrome, safari, ...]
132+
remote.browser.name = firefox
133+
134+
# Version of the browser to use in Selenium Grid. If not specified, any version will be used!
135+
# TYPE: String [eg. 46.0.1]
136+
# remote.browser.version =
137+
138+
# Whether the Marionette driver (Firefox 47++) should be used.
139+
# TYPE: boolean [true, false]
140+
remote.firefox.marionette = true
141+
142+
# Host or IO address where Selenium Grid is running
143+
# TYPE: String [localhost, 192.168.0.1, ...]
144+
remote.host = localhost
145+
146+
# Host or IO address where Selenium Grid is running
147+
# TYPE: Integer
148+
remote.port = 4444
129149
```
130150

131151
# Linked Documentation

webtester-core/src/main/java/info/novatec/testit/webtester/browser/BrowserFactory.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,6 @@ public interface BrowserFactory {
6464
*/
6565
Browser createBrowser();
6666

67-
/**
68-
* Creates a {@link Browser browser} using the given pre-initialized
69-
* {@link WebDriver web driver} and the {@link BrowserFactory factory's}
70-
* defaults.
71-
*
72-
* @param webDriver the web driver to use
73-
* @return the created browser
74-
* @since 2.0
75-
*/
76-
Browser createBrowser(WebDriver webDriver);
77-
7867
/**
7968
* Creates a {@link Browser browser} with the given
8069
* {@link DesiredCapabilities desired capabilities} and the
@@ -88,6 +77,17 @@ public interface BrowserFactory {
8877
*/
8978
Browser createBrowser(DesiredCapabilities capabilities);
9079

80+
/**
81+
* Creates a {@link Browser browser} using the given pre-initialized
82+
* {@link WebDriver web driver} and the {@link BrowserFactory factory's}
83+
* defaults.
84+
*
85+
* @param webDriver the web driver to use
86+
* @return the created browser
87+
* @since 2.0
88+
*/
89+
Browser createBrowser(WebDriver webDriver);
90+
9191
/**
9292
* Defines a {@link ProxyConfiguration proxy configuration} to use when
9393
* creating a {@link Browser browser} with this {@link BrowserFactory
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package info.novatec.testit.webtester.browser.factories;
2+
3+
import java.net.MalformedURLException;
4+
import java.net.URL;
5+
import java.util.function.BiFunction;
6+
7+
import org.openqa.selenium.Platform;
8+
import org.openqa.selenium.Proxy;
9+
import org.openqa.selenium.WebDriver;
10+
import org.openqa.selenium.remote.CapabilityType;
11+
import org.openqa.selenium.remote.DesiredCapabilities;
12+
import org.openqa.selenium.remote.RemoteWebDriver;
13+
14+
import lombok.extern.slf4j.Slf4j;
15+
16+
import info.novatec.testit.webtester.browser.Browser;
17+
import info.novatec.testit.webtester.browser.BrowserFactory;
18+
import info.novatec.testit.webtester.browser.WebDriverBrowser;
19+
import info.novatec.testit.webtester.browser.proxy.ProxyConfiguration;
20+
import info.novatec.testit.webtester.config.Configuration;
21+
import info.novatec.testit.webtester.config.ConfigurationAdapter;
22+
import info.novatec.testit.webtester.config.ConfigurationException;
23+
import info.novatec.testit.webtester.config.builders.DefaultConfigurationBuilder;
24+
import info.novatec.testit.webtester.internal.configuration.NamedProperties;
25+
26+
27+
/**
28+
* Factory class for creating Selenium Grid remote {@link Browser} instances.
29+
* <p>
30+
* The remote driver can be configured by setting the following properties in your {@link Configuration} file(s):
31+
* <ul>
32+
* <li>{@link NamedProperties#REMOTE_BROWSER_NAME}</li>
33+
* <li>{@link NamedProperties#REMOTE_BROWSER_VERSION}</li>
34+
* <li>{@link NamedProperties#REMOTE_FIREFOX_MARIONETTE}</li>
35+
* <li>{@link NamedProperties#REMOTE_HOST}</li>
36+
* <li>{@link NamedProperties#REMOTE_PORT}</li>
37+
* </ul>
38+
* You can also override these properties by specifying new values as System Properties.
39+
* <p>
40+
* <b>The following capabilities are set by default:</b>
41+
* <ul>
42+
* <li>Native Events are disabled</li>
43+
* <li>Unsigned certificates are accepted</li>
44+
* </ul>
45+
*
46+
* @see Browser
47+
* @see RemoteWebDriver
48+
* @see Configuration
49+
* @see Configuration#getRemoteBrowserName()
50+
* @see Configuration#getRemoteBrowserVersion()
51+
* @see Configuration#getRemoteFirefoxMarionette()
52+
* @see Configuration#getRemoteHost()
53+
* @see Configuration#getRemotePort()
54+
* @since 2.1
55+
*/
56+
@Slf4j
57+
public class RemoteFactory implements BrowserFactory {
58+
59+
private final Configuration configuration;
60+
private final BiFunction<URL, DesiredCapabilities, WebDriver> webDriverProducer;
61+
private ProxyConfiguration proxyConfiguration;
62+
63+
public RemoteFactory() {
64+
this(new RemoteConfigurationBuilder().build(), RemoteWebDriver::new);
65+
}
66+
67+
RemoteFactory(Configuration configuration, BiFunction<URL, DesiredCapabilities, WebDriver> webDriverProducer) {
68+
this.configuration = configuration;
69+
this.webDriverProducer = webDriverProducer;
70+
}
71+
72+
@Override
73+
public Browser createBrowser() {
74+
String browserName = configuration.getRemoteBrowserName();
75+
String browserVersion = configuration.getRemoteBrowserVersion();
76+
DesiredCapabilities capabilities = new DesiredCapabilities(browserName, browserVersion, Platform.ANY);
77+
capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
78+
capabilities.setCapability(CapabilityType.HAS_NATIVE_EVENTS, false);
79+
capabilities.setCapability("marionette", configuration.getRemoteFirefoxMarionette());
80+
setOptionalProxyConfiguration(capabilities);
81+
return createBrowser(capabilities);
82+
}
83+
84+
@Override
85+
public Browser createBrowser(DesiredCapabilities capabilities) {
86+
String host = configuration.getRemoteHost();
87+
Integer port = configuration.getRemotePort();
88+
String url = "http://" + host + ":" + port + "/wd/hub";
89+
try {
90+
log.debug("creating remote driver instance for {} with capabilities: {}", url, capabilities);
91+
return createBrowser(webDriverProducer.apply(new URL(url), capabilities));
92+
} catch (MalformedURLException e) {
93+
throw new MalformedRemoteFactoryUrlException(url, e);
94+
}
95+
}
96+
97+
private void setOptionalProxyConfiguration(DesiredCapabilities capabilities) {
98+
if (proxyConfiguration != null) {
99+
Proxy proxy = new Proxy();
100+
proxyConfiguration.configureProxy(proxy);
101+
capabilities.setCapability(CapabilityType.PROXY, proxy);
102+
}
103+
}
104+
105+
@Override
106+
public Browser createBrowser(WebDriver webDriver) {
107+
return WebDriverBrowser.forWebDriver(webDriver).withConfiguration(configuration).build();
108+
}
109+
110+
@Override
111+
public RemoteFactory withProxyConfiguration(ProxyConfiguration configuration) {
112+
proxyConfiguration = configuration;
113+
return this;
114+
}
115+
116+
static class RemoteConfigurationBuilder extends DefaultConfigurationBuilder {
117+
RemoteConfigurationBuilder() {
118+
withAdapter(new SystemPropertyOverrideAdapter());
119+
}
120+
}
121+
122+
private static class SystemPropertyOverrideAdapter implements ConfigurationAdapter {
123+
124+
@Override
125+
public boolean adapt(Configuration configuration) {
126+
adaptIfNotNull(configuration, NamedProperties.REMOTE_BROWSER_NAME);
127+
adaptIfNotNull(configuration, NamedProperties.REMOTE_BROWSER_VERSION);
128+
adaptIfNotNull(configuration, NamedProperties.REMOTE_HOST);
129+
adaptIfNotNull(configuration, NamedProperties.REMOTE_PORT);
130+
adaptIfNotNull(configuration, NamedProperties.REMOTE_FIREFOX_MARIONETTE);
131+
return true;
132+
}
133+
134+
private void adaptIfNotNull(Configuration configuration, NamedProperties property) {
135+
String key = property.getKey();
136+
String value = System.getProperty(key);
137+
if (value != null) {
138+
configuration.setProperty(key, value);
139+
}
140+
}
141+
142+
}
143+
144+
public static class MalformedRemoteFactoryUrlException extends ConfigurationException {
145+
public MalformedRemoteFactoryUrlException(String url, Throwable cause) {
146+
super("The Selenium Grid Hub URL was malformed: " + url, cause);
147+
}
148+
}
149+
150+
}

webtester-core/src/main/java/info/novatec/testit/webtester/config/BaseConfiguration.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.Set;
1313
import java.util.stream.Collectors;
1414

15+
import org.openqa.selenium.remote.BrowserType;
1516
import org.openqa.selenium.support.Color;
1617

1718
import lombok.extern.slf4j.Slf4j;
@@ -179,6 +180,56 @@ public BaseConfiguration setWaitInterval(long waitInterval) {
179180
return setProperty(key(NamedProperties.WAIT_INTERVAL), waitInterval);
180181
}
181182

183+
@Override
184+
public String getRemoteBrowserName() {
185+
return getStringProperty(key(NamedProperties.REMOTE_BROWSER_NAME), BrowserType.FIREFOX);
186+
}
187+
188+
@Override
189+
public Configuration setRemoteBrowserName(String name) {
190+
return setProperty(key(NamedProperties.REMOTE_BROWSER_NAME), name);
191+
}
192+
193+
@Override
194+
public String getRemoteBrowserVersion() {
195+
return getStringProperty(key(NamedProperties.REMOTE_BROWSER_VERSION), "");
196+
}
197+
198+
@Override
199+
public Configuration setRemoteBrowserVersion(String version) {
200+
return setProperty(key(NamedProperties.REMOTE_BROWSER_VERSION), version);
201+
}
202+
203+
@Override
204+
public boolean getRemoteFirefoxMarionette() {
205+
return getBooleanProperty(key(NamedProperties.REMOTE_FIREFOX_MARIONETTE), true);
206+
}
207+
208+
@Override
209+
public Configuration setRemoteFirefoxMarionette(boolean marionette) {
210+
return setProperty(key(NamedProperties.REMOTE_FIREFOX_MARIONETTE), marionette);
211+
}
212+
213+
@Override
214+
public String getRemoteHost() {
215+
return getStringProperty(key(NamedProperties.REMOTE_HOST), "localhost");
216+
}
217+
218+
@Override
219+
public Configuration setRemoteHost(String host) {
220+
return setProperty(key(NamedProperties.REMOTE_HOST), host);
221+
}
222+
223+
@Override
224+
public int getRemotePort() {
225+
return getIntegerProperty(key(NamedProperties.REMOTE_PORT), 4444);
226+
}
227+
228+
@Override
229+
public Configuration setRemotePort(int port) {
230+
return setProperty(key(NamedProperties.REMOTE_PORT), port);
231+
}
232+
182233
private String key(NamedProperties property) {
183234
return property.getKey();
184235
}

0 commit comments

Comments
 (0)