Method: Capybara::Node::Base#synchronize
- Defined in:
- lib/capybara/node/base.rb
#synchronize(seconds = nil, errors: nil) ⇒ Object
This method is Capybara's primary defence against asynchronicity problems. It works by attempting to run a given block of code until it succeeds. The exact behaviour of this method depends on a number of factors. Basically there are certain exceptions which, when raised from the block, instead of bubbling up, are caught, and the block is re-run.
Certain drivers, such as RackTest, have no support for asynchronous processes, these drivers run the block, and any error raised bubbles up immediately. This allows faster turn around in the case where an expectation fails.
Only exceptions that are ElementNotFound or any subclass
thereof cause the block to be rerun. Drivers may specify additional
exceptions which also cause reruns. This usually occurs when a node is
manipulated which no longer exists on the page. For example, the
Selenium driver specifies
Selenium::WebDriver::Error::ObsoleteElementError
.
As long as any of these exceptions are thrown, the block is re-run,
until a certain amount of time passes. The amount of time defaults to
Capybara.default_max_wait_time and can be overridden through the seconds
argument. This time is compared with the system time to see how much
time has passed. On rubies/platforms which don't support access to a monotonic process clock
if the return value of Time.now
is stubbed out, Capybara will raise Capybara::FrozenInTime
.
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 |
# File 'lib/capybara/node/base.rb', line 76 def synchronize(seconds = nil, errors: nil) return yield if session.synchronized seconds = .default_max_wait_time if [nil, true].include? seconds interval = .default_retry_interval session.synchronized = true timer = Capybara::Helpers.timer(expire_in: seconds) begin yield rescue StandardError => e session.raise_server_error! raise e unless catch_error?(e, errors) if driver.wait? raise e if timer.expired? sleep interval reload if .automatic_reload else old_base = @base reload if .automatic_reload raise e if old_base == @base end retry ensure session.synchronized = false end end |