module Capybara::Lockstep
Constants
- ERROR_ALERT_OPEN
- ERROR_NAVIGATED_AWAY
- ERROR_PAGE_MISSING
- ERROR_SNIPPET_MISSING
- VERSION
Attributes
synchronizing[RW]
synchronizing?[RW]
Public Class Methods
auto_synchronize(**options)
click to toggle source
# File lib/capybara-lockstep/lockstep.rb, line 40 def auto_synchronize(**options) if mode == :auto synchronize(**options) end end
synchronize(lazy: false, log: nil)
click to toggle source
# File lib/capybara-lockstep/lockstep.rb, line 26 def synchronize(lazy: false, log: nil) if (lazy && synchronized?) || synchronizing? || mode == :off return end # Allow passing a log message that is only logged # when we're actually synchronizing. if log self.log(log) end synchronize_now end
synchronized=(value)
click to toggle source
# File lib/capybara-lockstep/lockstep.rb, line 22 def synchronized=(value) page.instance_variable_set(:@lockstep_synchronized, value) end
synchronized?()
click to toggle source
# File lib/capybara-lockstep/lockstep.rb, line 15 def synchronized? value = page.instance_variable_get(:@lockstep_synchronized) # We consider a new Capybara session to be synchronized. # This will be set to false after our first visit(). value.nil? ? true : value end
Private Class Methods
current_seconds()
click to toggle source
# File lib/capybara-lockstep/lockstep.rb, line 150 def current_seconds Process.clock_gettime(Process::CLOCK_MONOTONIC) end
ignoring_alerts(&block)
click to toggle source
# File lib/capybara-lockstep/lockstep.rb, line 144 def ignoring_alerts(&block) block.call rescue ::Selenium::WebDriver::Error::UnexpectedAlertOpenError # no-op end
page()
click to toggle source
# File lib/capybara-lockstep/lockstep.rb, line 128 def page Capybara.current_session end
synchronize_now()
click to toggle source
# File lib/capybara-lockstep/lockstep.rb, line 48 def synchronize_now self.synchronizing = true self.synchronized = false log 'Synchronizing' start_time = current_seconds begin with_max_wait_time(timeout) do message_from_js = evaluate_async_script(<<~JS) let done = arguments[0] let synchronize = () => { if (window.CapybaraLockstep) { CapybaraLockstep.synchronize(done) } else { done(#{ERROR_SNIPPET_MISSING.to_json}) } } let protocol = location.protocol if (protocol === 'data:' || protocol == 'about:') { done(#{ERROR_PAGE_MISSING.to_json}) } else if (document.readyState === 'complete') { // WebDriver always waits for the `load` event after a visit(), // unless a different page load strategy was configured. synchronize() } else { window.addEventListener('load', synchronize) } JS case message_from_js when ERROR_PAGE_MISSING log(message_from_js) when ERROR_SNIPPET_MISSING log(message_from_js) else log message_from_js end_time = current_seconds ms_elapsed = ((end_time.to_f - start_time) * 1000).round log "Synchronized successfully [#{ms_elapsed} ms]" self.synchronized = true end end rescue ::Selenium::WebDriver::Error::ScriptTimeoutError timeout_message = "Could not synchronize within #{timeout} seconds" log timeout_message if timeout_with == :error raise Timeout, timeout_message else # Don't raise an error, this may happen if the server is slow to respond. # We will retry on the next Capybara synchronize call. end rescue ::Selenium::WebDriver::Error::UnexpectedAlertOpenError log ERROR_ALERT_OPEN # Don't raise an error, this will happen in an innocent test. # We will retry on the next Capybara synchronize call. rescue ::Selenium::WebDriver::Error::JavascriptError => e # When the URL changes while a script is running, my current selenium-webdriver # raises a Selenium::WebDriver::Error::JavascriptError with the message: # "javascript error: document unloaded while waiting for result". # We will retry on the next Capybara synchronize call, by then we should see # the new page. if e.message.include?('unload') log ERROR_NAVIGATED_AWAY else unhandled_synchronize_error(e) end rescue StandardError => e unhandled_synchronize_error(e) ensure self.synchronizing = false end end
unhandled_synchronize_error(e)
click to toggle source
# File lib/capybara-lockstep/lockstep.rb, line 123 def unhandled_synchronize_error(e) log "#{e.class.name} while synchronizing: #{e.message}" raise e end
with_max_wait_time(seconds, &block)
click to toggle source
# File lib/capybara-lockstep/lockstep.rb, line 134 def with_max_wait_time(seconds, &block) old_max_wait_time = Capybara.default_max_wait_time Capybara.default_max_wait_time = seconds begin block.call ensure Capybara.default_max_wait_time = old_max_wait_time end end