cuprite: Capybara::Cuprite::BrowserError Cannot find context with specified id

Getting intermittent BrowserError with cannot find context with specified id.

Some searches led me down a similar issue in puppeteer which was solved by adding a waitFor networkidle2 (network almost finished requests). I’m wondering if this error is caused by attempting to interact with the page too early, and we should wait for this networkidle2 event.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 1
  • Comments: 66 (25 by maintainers)

Most upvoted comments

I’ve taken another look at this after I found a way for a test to fail consistently.

Situation:

  • page contains a remote form

  • test contains something like:

     click_button "submit" # no problem
     expect(page).to have_content(…)
    

Solution:

The expect call lets cuprite insert a javascript snippet in the page just before the ajax call. Thus losing the context once the ajax call gets executed and the page redirects (in the example I worked on). The system cannot recover from such a problem without re-inserting the same snippet again. That’s why the original solution doesn’t work.

This solution tries to do just that and seems to work for me: https://github.com/caifara/cuprite/tree/missing-context

In a couple of days there will be new release, it should fix this issue and other possible dead locks

@route I’m still seeing this error occasionally, but only in a part of our test suite that opens iframes as popups and then tries to interact with the content of the popups. Adding a sleep before starting interaction reliably makes the error go away. Using selenium also prevents the error, so it seems to be specific to cuprite.

Just mentioning that here in case you see a way to update your patch to also take into account freshly opened iframes.

@samstickland As I said before, @caifara’s patch only deals with Browser#find_all. It’s a proof-of-concept (applied to one particular code path) that just hints at what needs to be done. There are other code paths that can also hit this bug. e.g. Your test calls visible? (whether directly or indirectly), which also hits this same problem but was not patched.

I don’t have enough of a big-picture of the code base to know where to patch this globally, but I did want to give feedback to @route that @caifara is indeed onto something.

I’ve been running into this as well, when submitting a form and setting an expectation about css or content on the page after a reload.

If I add a loop, waiting until the capybara session’s body contains a target value, before checking that expectation, bypassing the capybara synchronize + cuprite find/wait that should be doing this already, my tests pass. ex:

myform.submit
expect(Capybara.current_session).to have_content('something')

will fail with the Cannot find context with specified id error while

myform.submit
until Capybara.current_session.html =~ /something/ do
  sleep 0.1
end
expect(Capybara.current_session).to have_content('something')

will succeed.

I think this fixed it for us, simply increasing timeouts https://github.com/rubycdp/cuprite/issues/122#issuecomment-724117040 - I guess some code is being cut short resulting in confusing errors. Just today I increased timeouts as a Chrome update seems to have made this worse, not sure it’s totally fixed it this time.

Had same issues with Capybara::Cuprite::BrowserError and was solved by using @caifara missing-context-2 branch. Is it possible to merge those changes to cuprite repository and make new release?

@nmagedman while @caifara patch https://github.com/caifara/cuprite/commit/e8efad9f48f86058995fb848bfae9c54491652b8 works it only does so for find_all method, in fact such issues with missing context or node can happen in between even internal calls of Cuprite. For example Runtime#evaluate or #evaluate_on it may send a few commands to Chrome in order to get the value and node may disappear in between.

The raise is not that meaningless because in some cases capybara takes care of such issues automatically. For instance https://github.com/machinio/cuprite/blob/master/lib/capybara/cuprite/node.rb#L21 and https://github.com/machinio/cuprite/blob/master/lib/capybara/cuprite/driver.rb#L296 When Obsolete node error occurs capybara knows it has to stop pulling for such node and starts executing other code.

My branch needs some polishing definitely and it should work afterwards. If you have a failing test you can try to adjust the code and I’ll happily merge your work.

I can confirm that using gem "cuprite", github: "caifara/cuprite", branch: "missing-context" solved the issue for me.