Capybara driver for Ruby on Rails application
playwright-ruby-client
is a client library just for browser automation, while Rails uses Capybara for system testing.
capybara-playwright-driver
provides a Capybara driver based on playwright-ruby-client and makes it easy to integrate into Ruby on Rails applications.
Installation
Add the line below into Gemfile:
gem 'capybara-playwright-driver'
and then bundle install
.
Note that capybara-playwright-driver does not depend on Selenium. But selenium-webdriver
is also required on Rails 5.x, 6.0
Register and configure Capybara driver
Capybara.register_driver(:playwright) do |app|
Capybara::Playwright::Driver.new(app,
browser_type: :chromium, # :chromium (default) or :firefox, :webkit
headless: false, # true for headless mode (default), false for headful mode.
)
end
Update timeout
Capybara sets the default value of timeout to 2 seconds. Generally it is too short to wait for HTTP responses.
It is recommended to set the timeout to 15-30 seconds for Playwright driver.
Capybara.default_max_wait_time = 15
(Optional) Update default driver
By default, Capybara driver is set to :rack_test
, which works only with non-JS contents. If your Rails application has many JavaScript contents, it is recommended to change the default driver to :playwright
.
Capybara.default_driver = :playwright
Capybara.javascript_driver = :playwright
It is not mandatry. Without changing the default driver, you can still use Playwright driver by specifying Capybara.current_driver = :playwright
(or driven_by :playwright
in system spec) explicitly.
(reference) Available driver options
These parameters can be passed into Capybara::Playwright::Driver.new
playwright_cli_executable_path
- Refer this article to understand what to specify.
browser_type
:chromium
(default),:firefox
, or:webkit
- Parameters for Playwright::BrowserType#launch
- args
- channel
chrome
,msedge
,chrome-beta
,chrome-dev
,chrome-canary
,msedge-beta
,msedge-dev
Browser distribution channel. Read more about using Google Chrome & Microsoft Edge
- devtools
- downloadsPath
- env
- executablePath
- firefoxUserPrefs
- headless
- ignoreDefaultArgs
- proxy
- slowMo
- timeout
- Parameters for Playwright::Browser#new_context
- bypassCSP
- colorScheme
- deviceScaleFactor
- extraHTTPHeaders
- geolocation
- hasTouch
- httpCredentials
- ignoreHTTPSErrors
- isMobile
- javaScriptEnabled
- locale
- noViewport
- offline
- permissions
- proxy
- record_har_omit_content
- record_har_path
- record_video_dir
- record_video_size
- screen
- serviceWorkers
- storageState
- timezoneId
- userAgent
- viewport
driver_opts = {
# `playwright` command path.
playwright_cli_executable_path: './node_modules/.bin/playwright',
# Use firefox for testing.
browser_type: :firefox,
# Headful mode.
headless: false,
# Slower operation
slowMo: 50, # integer. (50-100 would be good for most cases)
}
Capybara::Playwright::Driver.new(app, driver_opts)
Available functions and Limitations
Capybara DSL
Most of the methods of Capybara::Session
and Capybara::Node::Element
are available. However the following method is not yet implemented.
Capybara::Node::Element#drop
Playwright-native scripting
We can also describe Playwright-native automation script using with_playwright_page
and with_playwright_element_handle
.
# With Capybara DSL
find('a[data-item-type="global_search"]').click
# With Playwright-native Page
Capybara.current_session.driver.with_playwright_page do |page|
# `page` is an instance of Playwright::Page.
page.click('a[data-item-type="global_search"]')
end
all('.list-item').each do |li|
# With Capybara::Node::Element method
puts li.all('a').first.text
# With Playwright-native ElementHandle
puts li.with_playwright_element_handle do |handle|
# `handle` is an instance of Playwright::ElementHandle
handle.query_selector('a').text_content
end
end
Generally, Capybara DSL seems simple, but Playwright-native scripting are more precise and efficient. Also waitForNavigation
, waitForSelector
, and many other Playwright functions are available with Playwright-native scripting.
Screen recording
NO NEED to keep sitting in front of screen during test. Just record what happened with video.
For example, we can store the video for Allure report as below:
before do |example|
Capybara.current_session.driver.on_save_screenrecord do |video_path|
Allure.add_attachment(
name: "screenrecord - #{example.description}",
source: File.read(video_path),
type: Allure::ContentType::WEBM,
test_case: true,
)
end
end
For more details, refer Recording video
Screenshot just before teardown
In addition to Capybara::Session#save_screenshot
, capybara-playwright-driver have another method for storing last screen state just before teardown.
For example, we can attach the screenshot for Allure report as below:
before do |example|
Capybara.current_session.driver.on_save_raw_screenshot_before_reset do |raw_screenshot|
Allure.add_attachment(
name: "screenshot - #{example.description}",
source: raw_screenshot,
type: Allure::ContentType::PNG,
test_case: true,
)
end
end
Tracing for postmortem
Playwright users often expect to see what happened in the browser when the test failed. capybara-playwright-driver
provides a feature to store the trace easily.
before do |example|
Capybara.current_session.driver.on_save_trace do |trace_zip_path|
Allure.add_attachment(
name: "trace - #{example.description}",
source: File.read(trace_zip_path),
type: 'application/zip',
test_case: true,
)
end
end
This example code would attach the trace zip file to Allure report for each test case.
We can download and show the trace with playwright show-trace
command.
npx playwright show-trace ababcdcdefef.zip
Instead of the easy configuration using on_save_trace
, we can also use page.driver.start_tracing
/ page.driver.stop_tracing
or page.driver.with_trace do { ... }
for storing the trace with detailed options. See the PR for more details including example codes for RSpec.
Limitations
- Playwright doesn't allow clicking invisible DOM elements or moving elements.
click
sometimes doesn't work as Selenium does. See the detail in https://playwright.dev/docs/actionability/ current_window.maximize
andcurrent_window.fullscreen
work only on headful (non-headless) mode, as selenium driver does.Capybara::Node::Element#drag_to
does not accepthtml5
parameter. HTML5 drag and drop is not fully supported in Playwright.