Skip to content

Commit b04a389

Browse files
committed
Do not persist a driver instance in the configuration object but in the browser
1 parent e1ff939 commit b04a389

File tree

7 files changed

+82
-50
lines changed

7 files changed

+82
-50
lines changed

doc/manual-snippets/src/test/groovy/configuration/DriverConfigSpec.groovy

+5-5
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class DriverConfigSpec extends Specification implements InlineConfigurationLoade
5454
"""
5555

5656
then:
57-
config.driver instanceof FirefoxDriver
57+
config.createDriver() instanceof FirefoxDriver
5858

5959
cleanup:
6060
CachingDriverFactory.clearCacheAndQuitDriver()
@@ -72,7 +72,7 @@ class DriverConfigSpec extends Specification implements InlineConfigurationLoade
7272
"""
7373

7474
then:
75-
config.driver instanceof FirefoxDriver
75+
config.createDriver() instanceof FirefoxDriver
7676

7777
cleanup:
7878
CachingDriverFactory.clearCacheAndQuitDriver()
@@ -90,7 +90,7 @@ class DriverConfigSpec extends Specification implements InlineConfigurationLoade
9090
"""
9191

9292
then:
93-
config.driver instanceof FirefoxDriver
93+
config.createDriver() instanceof FirefoxDriver
9494

9595
cleanup:
9696
CachingDriverFactory.clearCacheAndQuitDriver()
@@ -130,7 +130,7 @@ class DriverConfigSpec extends Specification implements InlineConfigurationLoade
130130
""")
131131

132132
then:
133-
config.driver in driverClass
133+
config.createDriver() in driverClass
134134

135135
cleanup:
136136
CachingDriverFactory.clearCacheAndQuitDriver()
@@ -140,4 +140,4 @@ class DriverConfigSpec extends Specification implements InlineConfigurationLoade
140140
null | HtmlUnitDriver
141141
"remote" | RemoteWebDriver
142142
}
143-
}
143+
}

module/geb-core/src/main/groovy/geb/Browser.groovy

+32-20
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class Browser {
6060

6161
private Page page
6262
private final Configuration config
63+
private WebDriver driver
6364
private final RemoteDriverOperations remoteDriverOperations = new RemoteDriverOperations(this.class.classLoader)
6465
private String reportGroup = null
6566
private NavigatorFactory navigatorFactory = null
@@ -68,7 +69,7 @@ class Browser {
6869
* If the driver is remote, this object allows access to its capabilities (users of Geb should not access this object, it is used internally).
6970
*/
7071
@Lazy
71-
WebDriver augmentedDriver = remoteDriverOperations.getAugmentedDriver(driver)
72+
WebDriver augmentedDriver = remoteDriverOperations.getAugmentedDriver(getDriver())
7273

7374
/**
7475
* Create a new browser with a default configuration loader, loading the default configuration file.
@@ -164,10 +165,14 @@ class Browser {
164165
* <p>
165166
* The driver implementation to use is determined by the configuration.
166167
*
167-
* @see geb.Configuration#getDriver()
168+
* @see geb.Configuration#createDriver()
168169
*/
169170
WebDriver getDriver() {
170-
config.driver
171+
if (driver == null) {
172+
driver = createDriver()
173+
}
174+
175+
driver
171176
}
172177

173178
/**
@@ -189,11 +194,9 @@ class Browser {
189194
* This should only be called before making any requests as a means to override the driver instance
190195
* that would be created from the configuration. Where possible, prefer using the configuration mechanism
191196
* to specify the driver implementation to use.
192-
* <p>
193-
* This method delegates to {@link geb.Configuration#setDriver(org.openqa.selenium.WebDriver)}.
194197
*/
195198
void setDriver(WebDriver driver) {
196-
config.driver = driver
199+
this.driver = driver
197200
}
198201

199202
/**
@@ -223,7 +226,7 @@ class Browser {
223226
* @see org.openqa.selenium.WebDriver#getCurrentUrl()
224227
*/
225228
String getCurrentUrl() {
226-
driver.currentUrl
229+
getDriver().currentUrl
227230
}
228231

229232
/**
@@ -509,9 +512,9 @@ class Browser {
509512
void go(Map params = [:], String url = null, UrlFragment fragment = null) {
510513
def newUri = calculateUri(url, params, fragment)
511514
def currentUri = retrieveCurrentUri()
512-
driver.get(newUri.toString())
515+
getDriver().get(newUri.toString())
513516
if (sameUrlWithDifferentFragment(currentUri, newUri)) {
514-
driver.navigate().refresh()
517+
getDriver().navigate().refresh()
515518
}
516519
if (!page) {
517520
page(Page)
@@ -630,7 +633,7 @@ class Browser {
630633
* @see org.openqa.selenium.WebDriver.Options#deleteAllCookies()
631634
*/
632635
void clearCookies() {
633-
driver?.manage()?.deleteAllCookies()
636+
getDriver()?.manage()?.deleteAllCookies()
634637
}
635638

636639
/**
@@ -669,7 +672,7 @@ class Browser {
669672
* @see org.openqa.selenium.WebDriver#quit()
670673
*/
671674
void quit() {
672-
driver.quit()
675+
getDriver().quit()
673676
}
674677

675678
/**
@@ -678,7 +681,7 @@ class Browser {
678681
* @see org.openqa.selenium.WebDriver#close()
679682
*/
680683
void close() {
681-
driver.close()
684+
getDriver().close()
682685
}
683686

684687
/**
@@ -687,7 +690,7 @@ class Browser {
687690
* @see org.openqa.selenium.WebDriver#getWindowHandle()
688691
*/
689692
String getCurrentWindow() {
690-
driver.windowHandle
693+
getDriver().windowHandle
691694
}
692695

693696
/**
@@ -696,7 +699,7 @@ class Browser {
696699
* @see org.openqa.selenium.WebDriver#getWindowHandles()
697700
*/
698701
Set<String> getAvailableWindows() {
699-
driver.windowHandles
702+
getDriver().windowHandles
700703
}
701704

702705
/**
@@ -812,7 +815,7 @@ class Browser {
812815
cloned.call()
813816
} finally {
814817
if ((!options.containsKey(CLOSE_OPTION) && config.withNewWindowConfig.close.orElse(true)) || options.close) {
815-
driver.close()
818+
getDriver().close()
816819
}
817820
switchToWindow(originalWindow)
818821
page originalPage
@@ -996,8 +999,8 @@ class Browser {
996999
}
9971000

9981001
public <T> Optional<T> driverAs(Class<T> castType) {
999-
if (castType.isInstance(driver)) {
1000-
Optional.of(driver as T)
1002+
if (castType.isInstance(getDriver())) {
1003+
Optional.of(getDriver() as T)
10011004
} else if (castType.isInstance(augmentedDriver)) {
10021005
Optional.of(augmentedDriver as T)
10031006
} else {
@@ -1006,7 +1009,7 @@ class Browser {
10061009
}
10071010

10081011
protected switchToWindow(String window) {
1009-
driver.switchTo().window(window)
1012+
getDriver().switchTo().window(window)
10101013
}
10111014

10121015
protected <T> T doWithWindow(Map options, Closure<T> block) {
@@ -1021,7 +1024,7 @@ class Browser {
10211024
cloned.call()
10221025
} finally {
10231026
if (options.close || (!options.containsKey(CLOSE_OPTION) && config.withWindowConfig.close)) {
1024-
driver.close()
1027+
getDriver().close()
10251028
}
10261029
}
10271030
}
@@ -1035,6 +1038,15 @@ class Browser {
10351038
config.createNavigatorFactory(this)
10361039
}
10371040

1041+
/**
1042+
* Called to create the driver, the first time it is requested.
1043+
*
1044+
* @return The driver
1045+
*/
1046+
protected WebDriver createDriver() {
1047+
config.createDriver()
1048+
}
1049+
10381050
private WebDriver getDriverWithNetworkConditions() {
10391051
optionalHasNetworkConditionsClass.map { hasNetworkConditionsClass ->
10401052
driverAs(hasNetworkConditionsClass).orElse(null)
@@ -1230,7 +1242,7 @@ class Browser {
12301242
private URI retrieveCurrentUri() {
12311243
def currentUri = null
12321244
try {
1233-
def currentUrl = driver.currentUrl
1245+
def currentUrl = getDriver().currentUrl
12341246
currentUri = currentUrl ? new URI(currentUrl) : null
12351247
} catch (NullPointerException npe) {
12361248
} catch (URISyntaxException use) {

module/geb-core/src/main/groovy/geb/Configuration.groovy

+15-9
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ class Configuration {
256256
* This may be the class name of a driver implementation, a driver short name or a closure
257257
* that when invoked with no arguments returns a driver implementation.
258258
*
259-
* @see #getDriver()
259+
* @see #createDriver()
260260
*/
261261
void setDriverConf(value) {
262262
rawConfig.driver = value
@@ -268,7 +268,7 @@ class Configuration {
268268
* This may be the class name of a driver implementation, a short name, or a closure
269269
* that when invoked returns an actual driver.
270270
*
271-
* @see #getDriver()
271+
* @see #createDriver()
272272
*/
273273
def getDriverConf() {
274274
def value = properties.getProperty("geb.driver") ?: readValue("driver", null)
@@ -376,16 +376,22 @@ class Configuration {
376376
rawConfig.pageEventListener = pageEventListener
377377
}
378378

379+
/**
380+
* @deprecated As of 8.0, replaced by {@link #createDriver()}, the configuration does
381+
* no longer carry a driver instance.
382+
*/
383+
@Deprecated
379384
WebDriver getDriver() {
380-
if (driver == null) {
381-
driver = createDriver()
382-
}
383-
384-
driver
385+
createDriver()
385386
}
386387

388+
/**
389+
* @deprecated As of 8.0, the configuration does no longer carry a driver
390+
* instance, but only create new driver instances, the driver
391+
* instance used is stored in the browser instance.
392+
*/
393+
@Deprecated
387394
void setDriver(WebDriver driver) {
388-
this.driver = driver
389395
}
390396

391397
/**
@@ -700,7 +706,7 @@ class Configuration {
700706
throw new InvalidGebConfiguration("Configuration for bounds and 'required' template options is conflicting")
701707
}
702708

703-
protected WebDriver createDriver() {
709+
WebDriver createDriver() {
704710
wrapDriverFactoryInCachingIfNeeded(getDriverFactory(getDriverConf())).driver
705711
}
706712

module/geb-core/src/test/groovy/geb/PauseSpec.groovy

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class PauseSpec extends GebSpecWithCallbackServer {
5656
@InheritConstructors
5757
private static class ThreadSafeScriptExecutionDriverConfiguration extends Configuration {
5858
@Override
59-
protected WebDriver createDriver() {
59+
WebDriver createDriver() {
6060
def driver = super.createDriver()
6161
driver.javascriptEnabled = true
6262
ThreadSafeScriptExecutionDriver.of(driver)

module/geb-core/src/test/groovy/geb/conf/ConfigurationDriverCreationSpec.groovy

+2-2
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ class ConfigurationDriverCreationSpec extends Specification {
168168
def config = new ConfigObject()
169169
config.cacheDriver = false
170170
config.driver = { new HtmlUnitDriver() }
171-
d = new Configuration(config, p()).driver
171+
d = new Configuration(config, p()).createDriver()
172172

173173
then:
174174
d instanceof HtmlUnitDriver
@@ -182,7 +182,7 @@ class ConfigurationDriverCreationSpec extends Specification {
182182
config.driver = { 'not a driver' }
183183

184184
when:
185-
new Configuration(config).driver
185+
new Configuration(config).createDriver()
186186

187187
then:
188188
thrown(DriverCreationException)

module/geb-core/src/test/groovy/geb/conf/DriverCachingSpec.groovy

+26-12
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,11 @@ class DriverCachingSpec extends Specification {
3535
File getReportsDir() { null }
3636
}
3737

38-
def conf(cacheDriverPerThread = false) {
38+
def conf(cacheDriverPerThread = false, cacheDriver = true) {
3939
def conf = new Configuration(new ConfigObject(), new Properties(), new NullBuildAdapter())
40+
conf.cacheDriver = cacheDriver
4041
conf.cacheDriverPerThread = cacheDriverPerThread
4142
conf.driverConf = { new HtmlUnitDriver() }
42-
43-
assert conf.cacheDriver
44-
4543
conf
4644
}
4745

@@ -58,23 +56,23 @@ class DriverCachingSpec extends Specification {
5856
def holder = new BlockingVariable()
5957

6058
when:
61-
Thread.start { holder.set(conf2.driver) }
59+
Thread.start { holder.set(conf2.createDriver()) }
6260

6361
and:
64-
def driver1 = conf1.driver
62+
def driver1 = conf1.createDriver()
6563
def driver2 = holder.get()
6664

6765
then:
6866
!driver1.is(driver2)
6967

7068
and:
71-
driver1.is conf(true).driver
69+
driver1.is conf(true).createDriver()
7270

7371
when:
7472
CachingDriverFactory.clearCacheAndQuitDriver()
7573

7674
then:
77-
!driver1.is(conf(true).driver)
75+
!driver1.is(conf(true).createDriver())
7876

7977
cleanup:
8078
driver1.quit()
@@ -90,23 +88,39 @@ class DriverCachingSpec extends Specification {
9088
def holder = new BlockingVariable()
9189

9290
when:
93-
Thread.start { holder.set(conf2.driver) }
91+
Thread.start { holder.set(conf2.createDriver()) }
9492

9593
and:
96-
def driver1 = conf1.driver
94+
def driver1 = conf1.createDriver()
9795
def driver2 = holder.get()
9896

9997
then:
10098
driver1.is(driver2)
10199

102100
and:
103-
driver1.is conf().driver
101+
driver1.is conf().createDriver()
104102

105103
when:
106104
CachingDriverFactory.clearCacheAndQuitDriver()
107105

108106
then:
109-
!driver1.is(conf(true).driver)
107+
!driver1.is(conf(true).createDriver())
108+
109+
cleanup:
110+
driver1.quit()
111+
driver2.quit()
112+
}
113+
114+
def "disabled caching yields different drivers on each call"() {
115+
given:
116+
def conf = conf(false, false)
117+
118+
when:
119+
def driver1 = conf.createDriver()
120+
def driver2 = conf.createDriver()
121+
122+
then:
123+
!driver1.is(driver2)
110124

111125
cleanup:
112126
driver1.quit()

module/geb-core/src/test/groovy/geb/test/GebTestManagerBrowserResetSpec.groovy

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class GebTestManagerBrowserResetSpec extends Specification {
4848
driver = new RemoteWebDriverWithExpectations(
4949
webDriverServer.url, DEFAULT_IGNORED_COMMANDS - 'quit'
5050
)
51-
configuration.driver = driver
51+
configuration.driverConf = { driver }
5252
gebTestManager = new GebTestManagerBuilder()
5353
.withBrowserCreator {
5454
new Browser(configuration)

0 commit comments

Comments
 (0)