Sometimes you want to create a single ruby script using exact versions of some gems, but you don’t want to have to create a directory just to have a Gemfile
and your script file in it, then have to do the bundle install
/bundle exec
dance to run it properly.
Enter bundler/inline
This require
will allow your script to install and use the exact gems you specify, right inside the file.
You can then run it using only ruby my_single_file.rb
.
Here’s an example which allows to test a complex interaction using a Chrome
browser (installed on demand) all in a single script.
It uses capybara
‘s puma
integration to start an HTTP server, then access it using the specified version of Chrome for Testing (installed automatically by selenium-webdriver
‘s Selenium Manager
) running in headless
mode.
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'puma'
gem 'capybara', '3.40.0'
gem 'selenium-webdriver', "~> 4.29.1"
end
require 'selenium-webdriver'
require 'capybara/dsl'
# Make sure selenium-webdriver will download the proper `Chrome for Testing` if
# not already in cache.
ENV["SE_FORCE_BROWSER_DOWNLOAD"] = "true"
Capybara.register_driver :chrome do |app|
Capybara::Selenium::Driver.new(
app,
browser: :chrome,
options: Selenium::WebDriver::Options.chrome.tap do |options|
options.add_option :browser_version, '126.0.6478.182'
options.add_argument 'headless'
end
)
end
html = <<~HTML
<!DOCTYPE html>
<html lang="en">
<head>
<title>Testing beforeunload in Chrome with Capybara</title>
<meta charset="utf-8">
<script type="text/javascript">
window.addEventListener('beforeunload', (event) => {
event.preventDefault();
return 'HERE';
});
</script>
</head>
<body>
<h1><a href="/demo">Load another page</a></h1>
</body>
</html>
HTML
app = proc { |env| [200, { "Content-Type" => "text/html" }, [html] ] }
session = Capybara::Session.new(:chrome, app)
session.visit "/"
session.accept_alert do
# interact with the page, to get Chrome to fire `beforeunload`
# It doesn't work anymore starting from Chrome >= 127 as it's disabled until
# a `user interaction` which never happens when driven by selenium.
session.click_on "Load another page"
end
# Ensure the alert/confirm is gone after the end of previous block
session.find_all("a")
session.reset!
puts "it worked!"