Skip to content

Commit 45a804e

Browse files
committed
feat(browserbuilder): Add firefoxBuilder: .headless() .withOptions() .withBinary()
closes #199
1 parent 450163a commit 45a804e

5 files changed

Lines changed: 177 additions & 28 deletions

File tree

src/main/java/io/github/seleniumquery/browser/driver/DriverBuilder.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ public abstract class DriverBuilder<T extends DriverBuilder<T>> {
4343

4444
private boolean autoQuitAskedFor = false;
4545

46+
/**
47+
* Configures the driver with the given capabilities.
48+
* @param desiredCapabilities The capabilities to be set.
49+
* @return A self reference for further configuration.
50+
* @since 0.9.0
51+
*/
4652
@SuppressWarnings("unchecked")
4753
public T withCapabilities(DesiredCapabilities desiredCapabilities) {
4854
markCapabilitiesWereSet();

src/main/java/io/github/seleniumquery/browser/driver/builders/FirefoxDriverBuilder.java

Lines changed: 81 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616

1717
package io.github.seleniumquery.browser.driver.builders;
1818

19+
import org.apache.commons.logging.Log;
20+
import org.apache.commons.logging.LogFactory;
1921
import org.openqa.selenium.WebDriver;
22+
import org.openqa.selenium.firefox.FirefoxBinary;
2023
import org.openqa.selenium.firefox.FirefoxDriver;
24+
import org.openqa.selenium.firefox.FirefoxOptions;
2125
import org.openqa.selenium.firefox.FirefoxProfile;
2226
import org.openqa.selenium.remote.DesiredCapabilities;
2327

@@ -32,30 +36,85 @@
3236
*/
3337
public class FirefoxDriverBuilder extends DriverBuilder<FirefoxDriverBuilder> {
3438

35-
private FirefoxProfile firefoxProfile;
39+
private static final Log LOGGER = LogFactory.getLog(FirefoxDriverBuilder.class);
40+
41+
private FirefoxOptions firefoxOptions;
42+
43+
private FirefoxOptions getInitializedFirefoxOptions() {
44+
if (this.firefoxOptions == null) {
45+
this.firefoxOptions = new FirefoxOptions();
46+
}
47+
return this.firefoxOptions;
48+
}
3649

3750
/**
38-
* @deprecated Firefox (geckodriver) no longer supports disabling JavaScript. Without it, geckodriver simply
39-
* can't communicate with Firefox.
40-
*
41-
* @return A self reference.
42-
* @since 0.9.0
51+
* Configures the driver with the given capabilities.
52+
* @param desiredCapabilities The capabilities to be set.
53+
* @return A self reference for further configuration.
54+
* @since 0.18.0
4355
*/
44-
public FirefoxDriverBuilder withoutJavaScript() {
45-
throw new SeleniumQueryException("Firefox no longer supports disabling JavaScript. Without it, " +
46-
"geckodriver simply can't communicate with Firefox.");
56+
@Override
57+
public FirefoxDriverBuilder withCapabilities(DesiredCapabilities desiredCapabilities) {
58+
getInitializedFirefoxOptions().merge(desiredCapabilities);
59+
return this;
4760
}
4861

4962
/**
5063
* Sets specific {@link FirefoxProfile} to be used in the {@link FirefoxDriver}.
5164
*
5265
* @param firefoxProfile Profile to be used.
5366
* @return A self reference, allowing further configuration.
54-
*
5567
* @since 0.9.0
5668
*/
5769
public FirefoxDriverBuilder withProfile(FirefoxProfile firefoxProfile) {
58-
this.firefoxProfile = firefoxProfile;
70+
getInitializedFirefoxOptions().setProfile(firefoxProfile);
71+
return this;
72+
}
73+
74+
/**
75+
* <p>Sets specific {@link FirefoxOptions} to be used in the {@link FirefoxDriver}.</p>
76+
* <br>
77+
* This overwrites most configuration done by other options of driverbuilder. If you want to use it, it
78+
* is best to have it as first configuration of the driver builder, e.g.:
79+
* <pre><code>
80+
* // instead of
81+
* $.driver().useFirefox().withBinary(...).withCapabilities(...)<b>.withOptions(yourCustomOptions)</b>;
82+
* // do
83+
* $.driver().useFirefox()<b>.withOptions(yourCustomOptions)</b>.withBinary(...).withCapabilities(...);
84+
* </code></pre>
85+
*
86+
* @param firefoxOptions Options to be used.
87+
* @return A self reference, allowing further configuration.
88+
* @since 0.18.0
89+
*/
90+
public FirefoxDriverBuilder withOptions(FirefoxOptions firefoxOptions) {
91+
if (this.firefoxOptions != null) {
92+
LOGGER.warn("FirefoxOptions has already been initialized. All previous configurations are being overwritten.");
93+
}
94+
this.firefoxOptions = firefoxOptions;
95+
return this;
96+
}
97+
98+
/**
99+
* Sets specific {@link FirefoxBinary} to be used in the {@link FirefoxDriver}.
100+
*
101+
* @param firefoxBinary Binary to be used.
102+
* @return A self reference, allowing further configuration.
103+
* @since 0.18.0
104+
*/
105+
public FirefoxDriverBuilder withBinary(FirefoxBinary firefoxBinary) {
106+
getInitializedFirefoxOptions().setBinary(firefoxBinary);
107+
return this;
108+
}
109+
110+
/**
111+
* Configures {@link FirefoxDriver} to run in headless mode.
112+
*
113+
* @return A self reference, allowing further configuration.
114+
* @since 0.18.0
115+
*/
116+
public FirefoxDriverBuilder headless() {
117+
getInitializedFirefoxOptions().setHeadless(true);
59118
return this;
60119
}
61120

@@ -68,19 +127,19 @@ protected WebDriver build() {
68127
}
69128

70129
private WebDriver buildFirefox() {
71-
DesiredCapabilities capabilities = createConfiguredCapabilities();
72-
return new FirefoxDriver(capabilities);
130+
return new FirefoxDriver(getInitializedFirefoxOptions());
73131
}
74132

75-
private DesiredCapabilities createConfiguredCapabilities() {
76-
DesiredCapabilities capabilities = capabilities(DesiredCapabilities.firefox());
77-
configureFirefoxProfile(capabilities);
78-
return capabilities;
79-
}
80-
81-
private void configureFirefoxProfile(DesiredCapabilities capabilities) {
82-
FirefoxProfile profile = this.firefoxProfile != null ? this.firefoxProfile : new FirefoxProfile();
83-
capabilities.setCapability(FirefoxDriver.PROFILE, profile);
133+
/**
134+
* @deprecated Firefox (geckodriver) no longer supports disabling JavaScript. Without it, geckodriver simply
135+
* can't communicate with Firefox.
136+
*
137+
* @return A self reference.
138+
* @since 0.9.0
139+
*/
140+
public FirefoxDriverBuilder withoutJavaScript() {
141+
throw new SeleniumQueryException("Firefox no longer supports disabling JavaScript. Without it, " +
142+
"geckodriver simply can't communicate with Firefox.");
84143
}
85144

86145
}

src/test/java/endtoend/browser/driver/builders/FirefoxDriverBuilderTest.java

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@
2020
import static org.junit.Assume.assumeTrue;
2121

2222
import org.junit.After;
23+
import org.junit.Assert;
2324
import org.junit.Before;
24-
import org.junit.Ignore;
2525
import org.junit.Test;
26+
import org.openqa.selenium.firefox.FirefoxBinary;
27+
import org.openqa.selenium.firefox.FirefoxOptions;
2628
import org.openqa.selenium.firefox.FirefoxProfile;
2729

2830
import endtoend.browser.util.DriverBuilderTestUtil;
31+
import endtoend.browser.util.HeadlessTestUtils;
2932
import endtoend.browser.util.JsOnOffTestUtils;
3033
import io.github.seleniumquery.SeleniumQueryException;
3134
import testinfrastructure.junitrule.SetUpAndTearDownDriver;
@@ -59,16 +62,15 @@ public void withoutJavaScript__should_throw_exception() {
5962
}
6063

6164
@Test
62-
@Ignore("It works, but we gotta find a way to TEST if the changed preference was really set")
6365
public void withProfile__should_set_the_given_profile() {
6466
// given
6567
FirefoxProfile profile = new FirefoxProfile();
66-
profile.setPreference("browser.startup.homepage", "about:blank?stuff");
68+
profile.setPreference("browser.startup.homepage", "about:blank?setViaProfile");
6769
// when
68-
$.driver().useFirefox().withProfile(profile);
70+
$.driver().useFirefox().autoDriverDownload().withProfile(profile).autoQuitDriver();
6971
// then
70-
// assert that preference was set
71-
// the code works, but I can't find a way to verify it yet
72+
$.driver().get();
73+
Assert.assertEquals("about:blank?setViaProfile", $.url());
7274
}
7375

7476
@Test
@@ -80,4 +82,31 @@ public void autoDriverDownload() {
8082
DriverBuilderTestUtil.openAnyUrl();
8183
}
8284

85+
@Test
86+
public void headless__yes() {
87+
// when
88+
$.driver().useFirefox().headless().autoDriverDownload();
89+
// then
90+
HeadlessTestUtils.assertHeadlessYes($.driver().get());
91+
}
92+
93+
@Test
94+
public void headless__not() {
95+
// when
96+
$.driver().useFirefox().autoDriverDownload();
97+
// then
98+
HeadlessTestUtils.assertHeadlessNot($.driver().get());
99+
}
100+
101+
@Test
102+
public void withOptions() {
103+
// when
104+
FirefoxOptions firefoxOptions = new FirefoxOptions();
105+
firefoxOptions.setHeadless(true);
106+
FirefoxBinary firefoxBinary = new FirefoxBinary();
107+
$.driver().useFirefox().withOptions(firefoxOptions).withBinary(firefoxBinary).autoDriverDownload();
108+
// then
109+
HeadlessTestUtils.assertHeadlessYes($.driver().get());
110+
}
111+
83112
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!DOCTYPE html>
2+
<!--
3+
~ Copyright (c) 2017 seleniumQuery authors
4+
~
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~
9+
~ http://www.apache.org/licenses/LICENSE-2.0
10+
~
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
-->
17+
18+
<html>
19+
<head>
20+
<meta charset="utf-8">
21+
<title>headless detection page</title>
22+
</head>
23+
<body>
24+
<script>
25+
// document.title = "Hah: " + [innerWidth, innerHeight, outerWidth, outerHeight].join(" | ");
26+
// this worked for firefox on my machine, don't know how reliable it is...
27+
document.title = "headless:" +(innerWidth === outerWidth);
28+
</script>
29+
</body>
30+
</html>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package endtoend.browser.util;
2+
3+
import static io.github.seleniumquery.SeleniumQuery.$;
4+
import static org.junit.Assert.assertEquals;
5+
import static testinfrastructure.EndToEndTestUtils.classNameToTestFileUrl;
6+
7+
import org.openqa.selenium.WebDriver;
8+
9+
public class HeadlessTestUtils {
10+
11+
public static void assertHeadlessYes(WebDriver driver) {
12+
assertTitle(driver, "headless:true");
13+
}
14+
15+
public static void assertHeadlessNot(WebDriver driver) {
16+
assertTitle(driver, "headless:false");
17+
}
18+
19+
private static void assertTitle(WebDriver driver, String expected) {
20+
driver.get(classNameToTestFileUrl(HeadlessTestUtils.class));
21+
$.pause(100);
22+
assertEquals(expected, $.title());
23+
}
24+
25+
}

0 commit comments

Comments
 (0)