1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
|
# frozen_string_literal: true
require 'spec_helper'
require 'selenium-webdriver'
require 'shared_selenium_session'
require 'shared_selenium_node'
require 'rspec/shared_spec_matchers'
browser_options = ::Selenium::WebDriver::Firefox::Options.new
browser_options.headless! if ENV['HEADLESS']
# browser_options.add_option("log", {"level": "trace"})
browser_options.profile = Selenium::WebDriver::Firefox::Profile.new.tap do |profile|
profile['browser.download.dir'] = Capybara.save_path
profile['browser.download.folderList'] = 2
profile['browser.helperApps.neverAsk.saveToDisk'] = 'text/csv'
profile['browser.startup.homepage'] = 'about:blank' # workaround bug in Selenium 4 alpha4-7
profile['accessibility.tabfocus'] = 7 # make tab move over links too
end
Capybara.register_driver :selenium_firefox do |app|
# ::Selenium::WebDriver.logger.level = "debug"
version = Capybara::Selenium::Driver.load_selenium
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
driver_options = { browser: :firefox, timeout: 31 }.tap do |opts|
opts[options_key] = browser_options
# Get a trace level log from geckodriver
# :driver_opts => { args: ['-vv'] }
end
Capybara::Selenium::Driver.new(app, **driver_options)
end
Capybara.register_driver :selenium_firefox_not_clear_storage do |app|
version = Capybara::Selenium::Driver.load_selenium
options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
driver_options = { browser: :firefox, clear_local_storage: false, clear_session_storage: false }.tap do |opts|
opts[options_key] = browser_options
end
Capybara::Selenium::Driver.new(app, **driver_options)
end
module TestSessions
SeleniumFirefox = Capybara::Session.new(:selenium_firefox, TestApp)
end
skipped_tests = %i[response_headers status_code trigger]
Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Firefox) if ENV['CI']
Capybara::SpecHelper.run_specs TestSessions::SeleniumFirefox, 'selenium', capybara_skip: skipped_tests do |example|
case example.metadata[:full_description]
when 'Capybara::Session selenium node #click should allow multiple modifiers'
pending "Firefox on OSX doesn't generate an event for shift+control+click" if firefox_gte?(62, @session) && Selenium::WebDriver::Platform.mac?
when /^Capybara::Session selenium node #double_click/
pending "selenium-webdriver/geckodriver doesn't generate double click event" if firefox_lt?(59, @session)
when 'Capybara::Session selenium #accept_prompt should accept the prompt with a blank response when there is a default'
pending "Geckodriver doesn't set a blank response in FF < 63 - https://bugzilla.mozilla.org/show_bug.cgi?id=1486485" if firefox_lt?(63, @session)
when 'Capybara::Session selenium #attach_file with multipart form should fire change once when uploading multiple files from empty'
pending "FF < 62 doesn't support setting all files at once" if firefox_lt?(62, @session)
when 'Capybara::Session selenium #accept_confirm should work with nested modals'
skip 'Broken in 63 <= FF < 69 - https://bugzilla.mozilla.org/show_bug.cgi?id=1487358' if firefox_gte?(63, @session) && firefox_lt?(69, @session)
skip 'Hangs in 69 <= FF < 71 - Dont know what issue for this - previous issue was closed as fixed but it is not' if firefox_gte?(69, @session) && firefox_lt?(71, @session)
skip 'Broken again intermittently in FF 71 - jus skip it'
when 'Capybara::Session selenium #click_link can download a file'
skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?
when 'Capybara::Session selenium #reset_session! removes ALL cookies'
pending "Geckodriver doesn't provide a way to remove cookies outside the current domain"
when /drag_to.*HTML5/
pending "Firefox < 62 doesn't support a DataTransfer constuctor" if firefox_lt?(62.0, @session)
when 'Capybara::Session selenium #accept_alert should handle the alert if the page changes',
'Capybara::Session selenium #accept_alert with an asynchronous alert should accept the alert'
skip 'No clue what Firefox is doing here - works fine on MacOS locally'
end
end
RSpec.describe 'Capybara::Session with firefox' do # rubocop:disable RSpec/MultipleDescribes
include Capybara::SpecHelper
['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
include_examples examples, TestSessions::SeleniumFirefox, :selenium_firefox
end
describe 'filling in Firefox-specific date and time fields with keystrokes' do
let(:datetime) { Time.new(1983, 6, 19, 6, 30) }
let(:session) { TestSessions::SeleniumFirefox }
before do
session.visit('/form')
end
it 'should fill in a date input with a String' do
session.fill_in('form_date', with: datetime.to_date.iso8601)
session.click_button('awesome')
expect(Date.parse(extract_results(session)['date'])).to eq datetime.to_date
end
it 'should fill in a time input with a String' do
session.fill_in('form_time', with: datetime.to_time.strftime('%T'))
session.click_button('awesome')
results = extract_results(session)['time']
expect(Time.parse(results).strftime('%r')).to eq datetime.strftime('%r')
end
it 'should fill in a datetime input with a String' do
pending "Need to figure out what string format this will actually accept"
session.fill_in('form_datetime', with: datetime.iso8601)
session.click_button('awesome')
expect(Time.parse(extract_results(session)['datetime'])).to eq datetime
end
end
end
RSpec.describe Capybara::Selenium::Driver do
let(:driver) { described_class.new(TestApp, browser: :firefox, options: browser_options) }
describe '#quit' do
it 'should reset browser when quit' do
expect(driver.browser).to be_truthy
driver.quit
# access instance variable directly so we don't create a new browser instance
expect(driver.instance_variable_get(:@browser)).to be_nil
end
context 'with errors' do
let!(:original_browser) { driver.browser }
after do
# Ensure browser is actually quit so we don't leave hanging processe
RSpec::Mocks.space.proxy_for(original_browser).reset
original_browser.quit
end
it 'warns UnknownError returned during quit because the browser is probably already gone' do
allow(driver).to receive(:warn)
allow(driver.browser).to(
receive(:quit)
.and_raise(Selenium::WebDriver::Error::UnknownError, 'random message')
)
expect { driver.quit }.not_to raise_error
expect(driver.instance_variable_get(:@browser)).to be_nil
expect(driver).to have_received(:warn).with(/random message/)
end
it 'ignores silenced UnknownError returned during quit because the browser is almost definitely already gone' do
allow(driver).to receive(:warn)
allow(driver.browser).to(
receive(:quit)
.and_raise(Selenium::WebDriver::Error::UnknownError, 'Error communicating with the remote browser')
)
expect { driver.quit }.not_to raise_error
expect(driver.instance_variable_get(:@browser)).to be_nil
expect(driver).not_to have_received(:warn)
end
end
end
context 'storage' do
describe '#reset!' do
it 'clears storage by default' do
session = TestSessions::SeleniumFirefox
session.visit('/with_js')
session.find(:css, '#set-storage').click
session.reset!
session.visit('/with_js')
expect(session.driver.browser.local_storage.keys).to be_empty
expect(session.driver.browser.session_storage.keys).to be_empty
end
it 'does not clear storage when false' do
session = Capybara::Session.new(:selenium_firefox_not_clear_storage, TestApp)
session.visit('/with_js')
session.find(:css, '#set-storage').click
session.reset!
session.visit('/with_js')
expect(session.driver.browser.local_storage.keys).not_to be_empty
expect(session.driver.browser.session_storage.keys).not_to be_empty
end
end
end
context 'timeout' do
it 'sets the http client read timeout' do
expect(TestSessions::SeleniumFirefox.driver.browser.send(:bridge).http.read_timeout).to eq 31
end
end
end
RSpec.describe Capybara::Selenium::Node do
describe '#click' do
it 'warns when attempting on a table row' do
session = TestSessions::SeleniumFirefox
session.visit('/tables')
tr = session.find(:css, '#agent_table tr:first-child')
allow(tr.base).to receive(:warn)
tr.click
expect(tr.base).to have_received(:warn).with(/Clicking the first cell in the row instead/)
end
it 'should allow multiple modifiers', requires: [:js] do
session = TestSessions::SeleniumFirefox
session.visit('with_js')
# Firefox v62+ doesn't generate an event for control+shift+click
session.find(:css, '#click-test').click(:alt, :ctrl, :meta)
# it also triggers a contextmenu event when control is held so don't check click type
expect(session).to have_link('Has been alt control meta')
end
end
end
|