etaiso
etaiso

Reputation: 2746

Capybara not waiting on expect

I have a page with a link that opens a bootstrap modal with a simple input field. I'm having a hard time understanding why Capybara doesn't wait for the modal to open, and fails immediately.

I added expect(page).to have_content('Did you') so capybara will wait a few seconds until the modal is shown. But for some reason it's not waiting and raises Capybara::ExpectationNotMet: expected to find text "Did you" in ...."

If I put a sleep of 1 second it will then find the modal, but it's not good enough because then a DB clean callback found in my spec_helper.rb is called:

config.after(:each) do
  DatabaseCleaner.clean
end

This is the spec:

RSpec.describe "follower button", type: :request do
  it "sends email #15B to owner", :js do
    using_wait_time 20 do
      FactoryGirl.create(:apartment_with_event)

      visit apartment_path(Apartment.last)
      click_on 'follow-events'
      expect(page).to have_content('Did you')
      within('#follow-events-modal') do
        fill_in 'follower-email-signup-mail', with: '[email protected]'
        click_button 'follower-signup-submit'
      end

      expect(page).to have_content(I18n.t("followers.create.title_success"))
      expect(Follower.all.count).to eq(1)
    end
  end
end

I also set Capybara.default_max_wait_time = 10 in spec_helper.rb, even though it should wait for 20 seconds for this example.

Forgot to mention, I'm using Capybara-wekbit as the driver.

I really spent hours trying to discover why it's happening, while other examples run just fine.

UPDATE: Adding full backtrace of failure.

Failures:

  1) leeron's button sends email #15B to owner
     Failure/Error: raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"

     ActionController::RoutingError:
       No route matches [GET] "/images/slider/missing.png"
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/rollbar-1.2.13/lib/rollbar/middleware/rails/show_exceptions.rb:22:in `call_with_rollbar'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/railties-4.2.4/lib/rails/rack/logger.rb:38:in `call_app'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/railties-4.2.4/lib/rails/rack/logger.rb:20:in `block in call'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/railties-4.2.4/lib/rails/rack/logger.rb:20:in `call'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/request_store-1.2.0/lib/request_store/middleware.rb:8:in `call'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/rack-1.6.4/lib/rack/methodoverride.rb:22:in `call'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/rack-1.6.4/lib/rack/runtime.rb:18:in `call'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/rack-1.6.4/lib/rack/lock.rb:17:in `call'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/rack-1.6.4/lib/rack/sendfile.rb:113:in `call'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/railties-4.2.4/lib/rails/engine.rb:518:in `call'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/railties-4.2.4/lib/rails/application.rb:165:in `call'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/rack-1.6.4/lib/rack/urlmap.rb:66:in `block in call'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/rack-1.6.4/lib/rack/urlmap.rb:50:in `each'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/rack-1.6.4/lib/rack/urlmap.rb:50:in `call'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/capybara-2.7.1/lib/capybara/server.rb:43:in `call'
     # /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/rack-1.6.4/lib/rack/handler/webrick.rb:88:in `service'
     # ------------------
     # --- Caused by: ---
     # Capybara::ExpectationNotMet:
     #   expected to find text "Did you" in "...(REMOVED BY ME TO SAVE SPACE)..."
     #   /Users/etaiso/.rbenv/versions/2.2.3/gemsets/dorbel/gems/capybara-2.7.1/lib/capybara/node/matchers.rb:527:in `block in assert_text'

Finished in 3.87 seconds (files took 9.79 seconds to load)
1 example, 1 failure

Upvotes: 0

Views: 1514

Answers (1)

Thomas Walpole
Thomas Walpole

Reputation: 49850

From the callback we can see that the actual exception is a routing error from the app. While Capybara is retrying/waiting on finders and expectations it checks for server thrown errors and if Capybara.raise_server_errors is true it will raise them in the test thread so they are visible to tests. A side-effect of the re-raising of exceptions from the app thread in the test thread is that any current exception in the test thread (such as ExpectationNotMet) which would normally be handled and retried by Capybara gets set by ruby as the nested cause of the apps exception. It isn't really the cause but we can't because of the way Capybara re-raises the server error it shows up there. You can either set Capybara.raise_server_errors = false or better yet, fix the missing image.

Upvotes: 2

Related Questions