Search code examples
ruby-on-railsrspeccapybarapoltergeist

How to ensure that request has completed before testing headers?


I am trying to test that when a user clicks a link, a PDF file is downloaded.

it 'downloads a PDF', :js do
  find("a.btn", text: %r{Download}i).trigger 'click'
  expect( page.response_headers['Content-Type'] ).to eq "application/pdf"
end

This is failing with

expected: "application/pdf"
got: "text/html; charset=utf-8"

If I add sleep 20 before the expectation, the test passes.

Is there a better/ more efficient way to write this?

For some reason, the following passes intermittently (even with longer wait durations):

expect( page.response_headers['Content-Type'] ).to have_text("application/pdf", wait: 20)

Solution

  • have_text is a matcher that uses a page element (Capybara::Node::Element). When you use it with a string the string gets parsed into an HTML document and then text nodes from that document are compared, but won't have any retrying behavior because it doesn't know how to reload the string (page elements store the query used to find them in the object so they can be reloaded - strings do not). In order to get a waiting behavior on the string from the response_headers you'd need to use something a matcher that takes a block and retries. https://github.com/abotalov/waiting_rspec_matchers is one gem that provides that sort of functionality, but there are a few others too.