class Capybara::Node::Base
A {Capybara::Node::Base} represents either an element on a page through the subclass {Capybara::Node::Element} or a document through {Capybara::Node::Document}.
Both types of Node
share the same methods, used for interacting with the elements on the page. These methods are divided into three categories, finders, actions and matchers. These are found in the modules {Capybara::Node::Finders}, {Capybara::Node::Actions} and {Capybara::Node::Matchers} respectively.
A {Capybara::Session} exposes all methods from {Capybara::Node::Document} directly:
session = Capybara::Session.new(:rack_test, my_app) session.visit('/') session.fill_in('Foo', with: 'Bar') # from Capybara::Node::Actions bar = session.find('#bar') # from Capybara::Node::Finders bar.select('Baz', from: 'Quox') # from Capybara::Node::Actions session.has_css?('#foobar') # from Capybara::Node::Matchers
Attributes
Public Class Methods
Source
# File lib/capybara/node/base.rb, line 32 def initialize(session, base) @session = session @base = base end
Public Instance Methods
Source
# File lib/capybara/node/base.rb, line 106 def find_css(css, **options) if base.method(:find_css).arity == 1 base.find_css(css) else base.find_css(css, **options) end end
@api private
Source
# File lib/capybara/node/base.rb, line 115 def find_xpath(xpath, **options) if base.method(:find_xpath).arity == 1 base.find_xpath(xpath) else base.find_xpath(xpath, **options) end end
@api private
Source
# File lib/capybara/node/base.rb, line 38 def reload self end
overridden in subclasses, e.g. Capybara::Node::Element
Source
# File lib/capybara/node/base.rb, line 124 def session_options session.config end
@api private
Source
# File lib/capybara/node/base.rb, line 76 def synchronize(seconds = nil, errors: nil) return yield if session.synchronized seconds = session_options.default_max_wait_time if [nil, true].include? seconds interval = session_options.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 session_options.automatic_reload else old_base = @base reload if session_options.automatic_reload raise e if old_base == @base end retry ensure session.synchronized = false end end
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 {Capybara::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`.
@param [Integer] seconds (current sessions default_max_wait_time) Maximum number of seconds to retry this block @param [Array<Exception>] errors (driver.invalid_element_errors +
[Capybara::ElementNotFound]) exception types that cause the block to be rerun
@return [Object] The result of the given block @raise [Capybara::FrozenInTime] If the return value of ‘Time.now` appears stuck
Protected Instance Methods
Source
# File lib/capybara/node/base.rb, line 134 def catch_error?(error, errors = nil) errors ||= (driver.invalid_element_errors + [Capybara::ElementNotFound]) errors.any? { |type| error.is_a?(type) } end