ifndef::snippets-dir[]
:snippets-dir: ../../../../manual-snippets/src/test/groovy
:rb-snippets-dir: ../../../../manual-snippets/real-browser/src/test/groovy
endif::[]
[[driver]]
= The WebDriver implementation

A `{browser-api}` instance interacts with an actual browser via an instance of `{webdriver-api}`.
The browser's driver can always be retrieved via the `{browser-get-driver-api}` method.

[NOTE]
====
One of the key design principles that WebDriver embraces is that tests/scripts should be written to the `{webdriver-api}` API making them agnostic to the actual browser being driven,
and therefore portable.
Geb always supports this goal.
However, the reality is that there are still quirks and behavioural differences between driver implementations.
Each release of WebDriver has historically worked to minimise these issues so expect the situation to improve over time as WebDriver matures.
====

[[driver-management]]
== Explicit driver management

One option for specifying the driver implementation is to construct the driver instance and pass it to the `Browser` to be used <<browser,when it is constructed>>.

However, where possible prefer implicit driver management which is discussed later in this chapter.

[discrete]
[[explicit-driver-lifecycle]]
=== Explicit lifecycle

When the driver is constructed by the user, the user is responsible for quitting the driver at the appropriate time.
This can be done via the methods on the `WebDriver` instance (obtainable via `{browser-get-driver-api}`) or by calling the <<quitting-the-browser,delegating methods on the browser object>>.

== Implicit driver management

If a driver is not given when a `Browser` object is constructed, one will be created and managed implicitly by Geb by the <<driver-implementation-configuration,configuration mechanism>>.

[discrete]
[[implicit-driver-lifecycle]]
=== Implicit lifecycle

By default, Geb internally caches and reuses the first driver created, meaning that all subsequent browser instances created without an explicit driver will reuse the cached driver.
This avoids the overhead of creating a new driver each time, which can be significant when working with a real browser.

This means that you may need to call the `{browser-clear-cookies-api}` or `{browser-clear-cookies-urls-api}` as well as `{browser-clear-web-storage-api}` methods on the browser in order not to get strange results due to state carried on from previous executions.

[TIP]
====
Some of the integrations (e.g. Spock, JUnit) automatically clear the browser cookies and web storage for the current domain at appropriate times such as after each test.
Consult the sections on <<cookie-management-in-tests, cookie management>> and <<web-storage-management-in-tests,web storage management>> in tests for specifics.
====

The shared driver will be closed and quited when the JVM shuts down.

A new driver can be forced at anytime by calling either of `{clear-browser-cache-api}` or `{clear-browser-cache-and-quit-api}` both of which are `static`.
After calling any of these methods, the next request for a default driver will result in a new driver instance being created.

This caching behavior is <<driver-caching-configuration,configurable>>.

== Driver quirks

This section details various quirks or issues that have been encountered with different driver implementations.

[discrete]
=== `HTMLUnitDriver`

[discrete]
==== Dealing with pages that use HTML refreshes

The default behaviour of the HTMLUnit driver is to immediately refresh the page as soon as it encounters a `<meta http-equiv="refresh" content="5">` regardless of the specified time.
The solution is to use a refresh handler that handles the refresh asynchronously.

[source,groovy]
----
include::{snippets-dir}/driver/HtmlUnitRefreshHandlerSpec.groovy[tag=import,indent=0]

include::{snippets-dir}/driver/HtmlUnitRefreshHandlerSpec.groovy[tag=changing_handler,indent=0]
----
<1> From here on refresh meta tag value will be respected.

See link:https://web.archive.org/web/20120211213811/https://markmail.org/thread/bu3g56oxz2uqzq43[this mailing list thread] for details.

[discrete]
==== Configuring logging

HTMLUnit can be very noisy, and it's not clear how to make it not so noisy.

See link:https://github.com/geb/issues/issues/98[this issue] for some tips on how to tune its logging.
