capybara: Hang in `within_frame`, specifically `driver.switch_to_frame(:parent)` in nested iframes

Meta

Capybara Version: 3.31.0 Driver Information (and browser if relevant): chrome=80.0.3987.116

Expected Behavior

within_frame(...) should not hang.

Actual Behavior

within_frame(...) hangs.

Steps to reproduce

We had a spec that started failing recently.

def authorize_3d_secure(approve = true)
  # authorisation iframes are really hard to locate in the DOM
  outer_iframe_selector = "iframe[src*='authorize'], iframe[src*='three-ds-2-challenge']"
  # and on top of that, they have nested iframes?!
  inner_iframe_selector = "iframe"
  
  using_wait_time(15) do
    if has_selector?(outer_iframe_selector)
      within_frame(:css, outer_iframe_selector) do
        sleep 1
        
        if has_selector?(inner_iframe_selector)
          within_frame(:css, inner_iframe_selector) do
            
            if approve
              click_button("Complete")
            else
              click_button("Fail")
            end
          end
        end
      end
    end
  end
end

It has to navigate credit card “3D Secure” iframes which are two layers deep.

The code works fine, we navigate to the button. But it hangs when executing the ensure block of within_frame, specifically the line

driver.switch_to_frame(:parent)

I guess that at that point, the parent iframe is already gone, so it hangs indefinitely.

cc @madleech

Backtrace

selenium-webdriver-3.142.7/lib/selenium/webdriver/remote/response.rb:72 in `assert_ok'
selenium-webdriver-3.142.7/lib/selenium/webdriver/remote/response.rb:34 in `initialize'
selenium-webdriver-3.142.7/lib/selenium/webdriver/remote/http/common.rb:88 in `new'
selenium-webdriver-3.142.7/lib/selenium/webdriver/remote/http/common.rb:88 in `create_response'
selenium-webdriver-3.142.7/lib/selenium/webdriver/remote/http/default.rb:114 in `request'
selenium-webdriver-3.142.7/lib/selenium/webdriver/remote/http/common.rb:64 in `call'
selenium-webdriver-3.142.7/lib/selenium/webdriver/remote/bridge.rb:167 in `execute'
selenium-webdriver-3.142.7/lib/selenium/webdriver/remote/w3c/bridge.rb:567 in `execute'
selenium-webdriver-3.142.7/lib/selenium/webdriver/remote/w3c/bridge.rb:177 in `window_handle'
selenium-webdriver-3.142.7/lib/selenium/webdriver/common/driver.rb:197 in `window_handle'
capybara-3.31.0/lib/capybara/selenium/driver.rb:170 in `current_window_handle'
capybara-3.31.0/lib/capybara/selenium/driver.rb:155 in `switch_to_frame'
capybara-3.31.0/lib/capybara/session.rb:398 in `switch_to_frame'
capybara-3.31.0/lib/capybara/session.rb:431 in `within_frame'
capybara-3.31.0/lib/capybara/dsl.rb:58 in `block (2 levels) in <module
my_spec.rb in `block in authorize_3d_secure'
capybara-3.31.0/lib/capybara/session.rb:796 in `using_wait_time'
capybara-3.31.0/lib/capybara/dsl.rb:28 in `using_wait_time'

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 26 (13 by maintainers)

Most upvoted comments

Possibly, or it may only throw an error if you try and interact with elements in the now deleted frame and let you cleanly go back up 2 levels like 79 used to let you

No it’s not possible to recreate the parent frame it would be a different element so the context would be different

It might be worth implementing scopes snapshotting type behavior in order to allow resetting to a previous position - will need to think about that.