Open
Description
Reproduction
This code uses Capybara's synchronize
inside of within
. The code inside synchronize
always fails, but that's a simplification from the real application. The page has JavaScript that fully replaces the #parent
element that contains the#child
element, which is what Capybara is looking for.
Gemfile
# frozen_string_literal: true
source "https://rubygems.org"
gem "cuprite", "~> 0.14.3"
gem "capybara", "~> 3.39"
repro.rb
require 'capybara'
require 'capybara/dsl'
require 'capybara/cuprite'
include Capybara::DSL
Capybara.javascript_driver = :cuprite
Capybara.register_driver(:cuprite) do |app|
Capybara::Cuprite::Driver.new(app)
end
Capybara.current_driver = :cuprite
Capybara.app_host = 'http://[::1]:8888'
Capybara.run_server = false
class DummyError < StandardError; end
visit('/')
within('#parent') do
ok_errors = page.driver.invalid_element_errors + [DummyError]
page.document.synchronize(Capybara.default_max_wait_time, errors: ok_errors) do
page.all('#child', count: 1)
# We always fail this test. If everything is working correctly,
# this program should report this exception.
raise DummyError
end
end
index.html
<!doctype html>
<html>
<head>
<title>Reproduction</title>
</head>
<body>
<div id="parent">
<div id="child">Child 1</div>
</div>
</body>
<script type="text/javascript">
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function main() {
await sleep(1000);
const parent = document.getElementById('parent');
const body = parent.parentElement;
parent.remove();
const newParent = document.createElement('div');
newParent.id = 'parent';
const newChild = document.createElement('div');
newChild.id = 'child';
newChild.innerText = 'Child 2';
newParent.appendChild(newChild);
body.appendChild(newParent);
}
main()
</script>
</html>
Steps
- Serve the page via
python3 -m http.server --bind '::1' 8888
- Run the test via
bundle exec ruby repro.rb
Output
gems/cuprite-0.14.3/lib/capybara/cuprite/node.rb:23:in `rescue in command': The element you are trying to interact with is either not part of the DOM, or is not currently visible on the page (perhaps display: none is set). It is possible the element has been replaced by another element and you meant to interact with the new element. If so you need to do a new find in order to get a reference to the new element. (Capybara::Cuprite::ObsoleteNode)
from gems/cuprite-0.14.3/lib/capybara/cuprite/node.rb:20:in `command'
from gems/cuprite-0.14.3/lib/capybara/cuprite/node.rb:48:in `find'
from gems/cuprite-0.14.3/lib/capybara/cuprite/node.rb:44:in `find_css'
from gems/capybara-3.39.2/lib/capybara/node/base.rb:108:in `find_css'
from gems/capybara-3.39.2/lib/capybara/queries/selector_query.rb:253:in `find_nodes_by_selector_format'
from gems/capybara-3.39.2/lib/capybara/queries/selector_query.rb:166:in `block in resolve_for'
from gems/capybara-3.39.2/lib/capybara/node/base.rb:77:in `synchronize'
from gems/capybara-3.39.2/lib/capybara/queries/selector_query.rb:165:in `resolve_for'
from gems/capybara-3.39.2/lib/capybara/node/finders.rb:265:in `block in all'
from gems/capybara-3.39.2/lib/capybara/node/base.rb:77:in `synchronize'
from gems/capybara-3.39.2/lib/capybara/node/finders.rb:264:in `all'
from gems/capybara-3.39.2/lib/capybara/session.rb:773:in `all'
from repro.rb:25:in `block (2 levels) in <main>'
from gems/capybara-3.39.2/lib/capybara/node/base.rb:84:in `synchronize'
from repro.rb:24:in `block in <main>'
from gems/capybara-3.39.2/lib/capybara/session.rb:365:in `within'
from gems/capybara-3.39.2/lib/capybara/dsl.rb:52:in `call'
from gems/capybara-3.39.2/lib/capybara/dsl.rb:52:in `within'
from repro.rb:20:in `<main>'
gems/ferrum-0.13/lib/ferrum/browser/client.rb:88:in `raise_browser_error': No node with given id found (Ferrum::NodeNotFoundError)
from gems/ferrum-0.13/lib/ferrum/browser/client.rb:49:in `command'
from gems/ferrum-0.13/lib/ferrum/page.rb:276:in `command'
from gems/cuprite-0.14.3/lib/capybara/cuprite/browser.rb:74:in `find_within'
from gems/cuprite-0.14.3/lib/capybara/cuprite/node.rb:21:in `command'
from gems/cuprite-0.14.3/lib/capybara/cuprite/node.rb:48:in `find'
from gems/cuprite-0.14.3/lib/capybara/cuprite/node.rb:44:in `find_css'
from gems/capybara-3.39.2/lib/capybara/node/base.rb:108:in `find_css'
from gems/capybara-3.39.2/lib/capybara/queries/selector_query.rb:253:in `find_nodes_by_selector_format'
from gems/capybara-3.39.2/lib/capybara/queries/selector_query.rb:166:in `block in resolve_for'
from gems/capybara-3.39.2/lib/capybara/node/base.rb:77:in `synchronize'
from gems/capybara-3.39.2/lib/capybara/queries/selector_query.rb:165:in `resolve_for'
from gems/capybara-3.39.2/lib/capybara/node/finders.rb:265:in `block in all'
from gems/capybara-3.39.2/lib/capybara/node/base.rb:77:in `synchronize'
from gems/capybara-3.39.2/lib/capybara/node/finders.rb:264:in `all'
from gems/capybara-3.39.2/lib/capybara/session.rb:773:in `all'
from repro.rb:25:in `block (2 levels) in <main>'
from gems/capybara-3.39.2/lib/capybara/node/base.rb:84:in `synchronize'
from repro.rb:24:in `block in <main>'
from gems/capybara-3.39.2/lib/capybara/session.rb:365:in `within'
from gems/capybara-3.39.2/lib/capybara/dsl.rb:52:in `call'
from gems/capybara-3.39.2/lib/capybara/dsl.rb:52:in `within'
from repro.rb:20:in `<main>'
Observations
-
If I add
puts page.has_selector?('#child', text: 'Child 2')
before thesynchronize
block, it will print outtrue
and the program will (correctly) exit withDummyError
. -
If I replace
cuprite
withapparition
, the program will (correctly) exit withDummyError
.
Metadata
Metadata
Assignees
Labels
No labels