Skip to content

Commit

Permalink
Enhance and standardize capabilities between drivers
Browse files Browse the repository at this point in the history
- Enables the ability to set capabilities by passing them as an option
and using application configuration.

- Implements default capabilities for Selenium.

- Moves configuration options for using chrome headlessly, the chrome
  binary, and the chromedriver binary to the `:chromedriver` key in the
  `:wallaby` application config.

- Moves documentation for Chrome and Selenium from the README and into
  their respective moduledocs.
  • Loading branch information
mhanberg committed Sep 14, 2019
1 parent d8b801b commit 2ae3191
Show file tree
Hide file tree
Showing 9 changed files with 533 additions and 157 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## Master

### Improvements

- Enables the ability to set capabilities by passing them as an option and using application configuration.
- Implements default capabilities for Selenium.

#### Breaking

- Moves configuration options for using chrome headlessly, the chrome binary, and the chromedriver binary to the `:chromedriver` key in the `:wallaby` application config.

## 0.23.0 (2019-08-14)

### Improvements
Expand Down
62 changes: 10 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -553,64 +553,22 @@ See below for more information on the experimental drivers.
## Experimental Driver Support

Currently Wallaby provides experimental support for both headless chrome and selenium.
Both of these drivers are still "experimental" because they don't support the full
api yet and because the implementation is changing rapidly. But, if you would like
to use them in your project here's what you'll need to do.
Both of these drivers are still "experimental" because they don't support the full API yet and because the implementation is changing rapidly.
But, if you would like to use them in your project here's what you'll need to do.

### Headless Chrome

In order to run headless chrome you'll need to have chromedriver 2.30 and chrome 60.
Previous versions of both of these tools _may_ work, but several features will be
buggy. If you want to setup chrome in a CI environment then you'll still
need to install and run xvfb. This is due to a bug in chromedriver 2.30 that inhibits
chromedriver from handling input text correctly. The bug should be fixed in chromedriver 2.31.

If you would like to disable headless mode in chrome you can pass `headless: false` in your config like so:

```elixir
config :wallaby,
chrome: [
headless: false
]
```

### Custom Chromedriver binary

If `chromedriver` is on your `PATH`, then you can skip this step.
Otherwise (e.g., on NPM-installed `chromedriver` binaries), you can override the path like so:

```elixir
config :wallaby, chromedriver: "<path/to/chromedriver>"
```
Please refer to the [documentation](https://hexdocs.pm/wallaby/Wallaby.Experimental.Chrome.html#content) for further information about using the Chrome driver.

### Headless Chrome

### Custom Chrome binary

By default chromedriver will find chrome for you but if you want to test against a different version you may use this option to point to the other chrome binary.

```elixir
config :wallaby,
chrome: [
binary: "path/to/google/chrome"
]
```
In order to run headless chrome you'll need to have ChromeDriver >= 2.30 and chrome >= 60.
Previous versions of both of these tools _may_ work, but several features will be buggy.
If you want to setup chrome in a CI environment then you'll still need to install and run xvfb.
This is due to a bug in ChromeDriver 2.30 that inhibits ChromeDriver from handling input text correctly.
The bug should be fixed in ChromeDriver 2.31.

### Selenium

To run selenium you'll need to install selenium-server-standalone and geckodriver.
Once you have these tools installed you'll need to manually start selenium-server separately
from your test run.

#### Custom Selenium URL

To configure the `remote_url` that Wallaby will use to connect to the Selenium server, pass it as an option to `Wallaby.start_session`.

```elixir
Wallaby.start_session(
remote_url: "http://selenium:4444/wd/hub/",
capabilities: %{browserName: "firefox"}
)
```
Please refer to the [documentation](https://hexdocs.pm/wallaby/Wallaby.Experimental.Selenium.html#content) for further information about using the Selenium driver.

## Contributing

Expand Down
1 change: 1 addition & 0 deletions integration_test/chrome/all_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ Code.require_file "../cases/browser/move_mouse_by_test.exs", __DIR__
Code.require_file "../cases/browser/send_keys_to_active_element_test.exs", __DIR__
Code.require_file "../cases/browser/window_handles_test.exs", __DIR__
Code.require_file "../cases/browser/window_position_test.exs", __DIR__
Code.require_file "../chrome/capabilities_test.exs", __DIR__
97 changes: 97 additions & 0 deletions integration_test/chrome/capabilities_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
defmodule Wallaby.Integration.CapabilitiesTest do
use ExUnit.Case, async: true
use Wallaby.DSL
alias Wallaby.Integration.SessionCase
alias Wallaby.Experimental.Selenium.WebdriverClient

setup do
on_exit fn ->
Application.delete_env(:wallaby, :chromedriver)
end
end

describe "capabilities" do
test "reads default capabilities" do
expected_capabilities = %{
javascriptEnabled: false,
loadImages: false,
version: "",
rotatable: false,
takesScreenshot: true,
cssSelectorsEnabled: true,
nativeEvents: false,
platform: "ANY",
unhandledPromptBehavior: "accept",
loggingPrefs: %{
browser: "DEBUG"
},
chromeOptions: %{
args: [
"--no-sandbox",
"window-size=1280,800",
"--disable-gpu",
"--headless",
"--fullscreen",
"--user-agent=Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"
]
}
}

create_session_fn = fn url, capabilities ->
assert capabilities == expected_capabilities

WebdriverClient.create_session(url, capabilities)
end

{:ok, session} = SessionCase.start_test_session(create_session_fn: create_session_fn)

session
|> visit("page_1.html")
|> assert_has(Query.text("Page 1"))

assert :ok = Wallaby.end_session(session)
end

test "reads capabilities from application config" do
expected_capabilities = %{chromeOptions: %{args: ["--headless"]}}
Application.put_env(:wallaby, :chromedriver, capabilities: expected_capabilities)

create_session_fn = fn url, capabilities ->
assert capabilities == expected_capabilities

WebdriverClient.create_session(url, capabilities)
end

{:ok, session} = SessionCase.start_test_session(create_session_fn: create_session_fn)

session
|> visit("page_1.html")
|> assert_has(Query.text("Page 1"))

assert :ok = Wallaby.end_session(session)
end

test "reads capabilities from opts when also using application config" do
Application.put_env(:wallaby, :chromedriver, capabilities: %{})
expected_capabilities = %{chromeOptions: %{args: ["--headless"]}}

create_session_fn = fn url, capabilities ->
assert capabilities == expected_capabilities

WebdriverClient.create_session(url, capabilities)
end

{:ok, session} =
SessionCase.start_test_session(
capabilities: expected_capabilities,
create_session_fn: create_session_fn
)

session
|> visit("page_1.html")
|> assert_has(Query.text("Page 1"))

assert :ok = Wallaby.end_session(session)
end
end
end
1 change: 1 addition & 0 deletions integration_test/selenium/all_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ Code.require_file "../cases/element/hover_test.exs", __DIR__
Code.require_file "../cases/browser/move_mouse_by_test.exs", __DIR__
Code.require_file "../cases/browser/window_handles_test.exs", __DIR__
Code.require_file "../cases/browser/window_position_test.exs", __DIR__
Code.require_file "../selenium/capabilities_test.exs", __DIR__
92 changes: 92 additions & 0 deletions integration_test/selenium/capabilities_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
defmodule Wallaby.Integration.CapabilitiesTest do
use ExUnit.Case, async: true
use Wallaby.DSL
alias Wallaby.Integration.SessionCase
alias Wallaby.Experimental.Selenium.WebdriverClient

setup do
on_exit(fn ->
Application.delete_env(:wallaby, :selenium)
end)
end

describe "capabilities" do
test "reads default capabilities" do
expected_capabilities = %{
javascriptEnabled: true,
browserName: "firefox",
"moz:firefoxOptions": %{
args: ["-headless"]
}
}

create_session_fn = fn url, capabilities ->
assert capabilities == expected_capabilities

WebdriverClient.create_session(url, capabilities)
end

{:ok, session} = SessionCase.start_test_session(create_session_fn: create_session_fn)

session
|> visit("page_1.html")
|> assert_has(Query.text("Page 1"))

assert :ok = Wallaby.end_session(session)
end

test "reads capabilities from application config" do
expected_capabilities = %{
browserName: "firefox",
"moz:firefoxOptions": %{
args: ["-headless"]
}
}

Application.put_env(:wallaby, :selenium, capabilities: expected_capabilities)

create_session_fn = fn url, capabilities ->
assert capabilities == expected_capabilities

WebdriverClient.create_session(url, capabilities)
end

{:ok, session} = SessionCase.start_test_session(create_session_fn: create_session_fn)

session
|> visit("page_1.html")
|> assert_has(Query.text("Page 1"))

assert :ok = Wallaby.end_session(session)
end

test "reads capabilities from opts when also using application config" do
Application.put_env(:wallaby, :selenium, capabilities: %{})

expected_capabilities = %{
browserName: "firefox",
"moz:firefoxOptions": %{
args: ["-headless"]
}
}

create_session_fn = fn url, capabilities ->
assert capabilities == expected_capabilities

WebdriverClient.create_session(url, capabilities)
end

{:ok, session} =
SessionCase.start_test_session(
capabilities: expected_capabilities,
create_session_fn: create_session_fn
)

session
|> visit("page_1.html")
|> assert_has(Query.text("Page 1"))

assert :ok = Wallaby.end_session(session)
end
end
end
24 changes: 1 addition & 23 deletions integration_test/support/session_case.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,7 @@ defmodule Wallaby.Integration.SessionCase do
Starts a test session with the default opts for the given driver
"""
def start_test_session(opts \\ []) do
session_opts =
"WALLABY_DRIVER"
|> System.get_env()
|> default_opts_for_driver
|> Keyword.merge(opts)

with {:ok, session} <- retry(2, fn -> Wallaby.start_session(session_opts) end),
with {:ok, session} <- retry(2, fn -> Wallaby.start_session(opts) end),
do: {:ok, session}
end

Expand All @@ -42,20 +36,4 @@ defmodule Wallaby.Integration.SessionCase do
_ -> retry(times - 1, f)
end
end

defp default_opts_for_driver("phantom"), do: []
defp default_opts_for_driver("selenium") do
[
capabilities: %{
browserName: "firefox",
"moz:firefoxOptions": %{
args: ["-headless"]
}
}
]
end
defp default_opts_for_driver("chrome"), do: []
defp default_opts_for_driver(other) do
raise "Unknown value for WALLABY_DRIVER environment variable: #{other}"
end
end
Loading

0 comments on commit 2ae3191

Please sign in to comment.