Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable rack_test driver to reload nodes if stale #2159

Merged
merged 1 commit into from
Feb 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions lib/capybara/node/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,18 @@ def synchronize(seconds = nil, errors: nil)
yield
rescue StandardError => err
session.raise_server_error!
raise err unless driver.wait? && catch_error?(err, errors)
raise err if timer.expired?
raise err unless catch_error?(err, errors)

sleep(0.01)
reload if session_options.automatic_reload
if driver.wait?
raise err if timer.expired?

sleep(0.01)
reload if session_options.automatic_reload
else
old_base = @base
reload if session_options.automatic_reload
raise err if old_base == @base
end
retry
ensure
session.synchronized = false
Expand Down
4 changes: 4 additions & 0 deletions lib/capybara/rack_test/driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,8 @@ def post(*args, &block); browser.post(*args, &block); end
def put(*args, &block); browser.put(*args, &block); end
def delete(*args, &block); browser.delete(*args, &block); end
def header(key, value); browser.header(key, value); end

def invalid_element_errors
[ Capybara::RackTest::Errors::StaleElementReferenceError ]
end
end
6 changes: 6 additions & 0 deletions lib/capybara/rack_test/errors.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

module Capybara::RackTest::Errors
class StaleElementReferenceError < StandardError
end
end
21 changes: 18 additions & 3 deletions lib/capybara/rack_test/node.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require 'capybara/rack_test/errors'

class Capybara::RackTest::Node < Capybara::Driver::Node
BLOCK_ELEMENTS = %w[p h1 h2 h3 h4 h5 h6 ol ul pre address blockquote dl div fieldset form hr noscript table].freeze

Expand Down Expand Up @@ -106,18 +108,27 @@ def path
native.path
end

def find_xpath(locator)
def find_xpath(locator, **_hints)
native.xpath(locator).map { |el| self.class.new(driver, el) }
end

def find_css(locator)
def find_css(locator, **_hints)
native.css(locator, Capybara::RackTest::CSSHandlers.new).map { |el| self.class.new(driver, el) }
end

self.public_instance_methods(false).each do |meth_name|
alias_method "unchecked_#{meth_name}", meth_name
private "unchecked_#{meth_name}"
define_method meth_name do |*args|
stale_check
send("unchecked_#{meth_name}", *args)
end
end

def ==(other)
native == other.native
end

protected

# @api private
Expand All @@ -141,6 +152,10 @@ def displayed_text(check_ancestor: true)

private

def stale_check
raise Capybara::RackTest::Errors::StaleElementReferenceError unless native.document == driver.dom
end

def deselect_options
select_node.find_xpath('.//option[@selected]').each { |node| node.native.remove_attribute('selected') }
end
Expand Down
6 changes: 3 additions & 3 deletions lib/capybara/selenium/extensions/find.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ def es_context
def is_displayed_atom # rubocop:disable Naming/PredicateName
@@is_displayed_atom ||= begin
browser.send(:bridge).send(:read_atom, 'isDisplayed')
rescue StandardError
# If the atom doesn't exist or other error
""
rescue StandardError
# If the atom doesn't exist or other error
''
end
end
end
Expand Down
23 changes: 23 additions & 0 deletions lib/capybara/spec/session/within_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,29 @@
end
expect(@session).to have_content('Bar')
end

it 'should reload the node if the page is changed' do
@session.within(:css, '#for_foo') do
@session.visit('/with_scope_other')
expect(@session).to have_content('Different text')
end
end

it 'should reload multiple nodes if the page is changed' do
@session.within(:css, '#for_bar') do
@session.within(:css, 'form[action="/redirect"]') do
@session.refresh
expect(@session).to have_content('First Name')
end
end
end

it 'should error if the page is changed and a matching node no longer exists' do
@session.within(:css, '#for_foo') do
@session.visit('/')
expect { @session.text }.to raise_error(StandardError)
end
end
end

context 'with XPath selector' do
Expand Down
6 changes: 6 additions & 0 deletions lib/capybara/spec/views/with_scope_other.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

<h1>This page is used for testing various scopes</h1>

<p id="for_foo">
Different text same wrapper id
</p>