capybara-webkit
capybara-webkit copied to clipboard
No response headers when body is empty and status code is not 200
If an Ajax request is made and the response has:
- status code != 200 (e.g. == 404), and
- empty body Then the request headers in javascript are empty and the status code is 0.
If the body contains something (e.g. a single character) or the status code is 200, then things work as they should.
To reproduce:
# routes:
match '/test' => 'test#test'
# test_controller.rb:
class TestController < ActionController::Base
def test
if params[:status]
response.status = params[:status]
render text: params[:content] || ''
else
render :inline => <<-EHTML
<html><head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</head><body><script>
var opt = {complete: function(xhr){
jQuery('body').append(xhr.status + "|" + xhr.getAllResponseHeaders());
}};
jQuery.ajax('/test?status=200', opt);
jQuery.ajax('/test?status=403&content=x', opt);
jQuery.ajax('/test?status=404', opt);
</script></body></html>
EHTML
end
end
end
# spec:
visit '/test'
page.should have_content '200|Connection:'
page.should have_content '403|Connection:'
page.should have_content '404|Connection:'
The test fails with:
Failure/Error: page.should have_content '404|Connection:'
expected there to be content "404|Connection:" in "200|Connection: close X-Request-Id: 4a8610c53c3814aea253cc67718ce4e9 X-UA-Compatible: IE=Edge,chrome=1 X-Runtime: 0.028846 Server: thin 1.3.1 codename Triple Espresso Content-Type: text/html; charset=utf-8 Cache-Control: no-cache 0|403|Connection: close X-Request-Id: 01fe49609c2395c25acf87d50817aaad X-UA-Compatible: IE=Edge,chrome=1 X-Runtime: 0.002853 Server: thin 1.3.1 codename Triple Espresso Content-Type: text/html; charset=utf-8 Cache-Control: no-cache"
Response will vary, but notice the "0|" which indicated a status code of 0 (instead of 404) and no headers whatsoever.
The text shows correctly in Chrome, Firefox and Safari.
Using capybara-webkit (0.12.1) on OS X
This is sort of complicated, but I think your application is actually returning a response code of 0.
The default setting for the Rails test environment is to raise exceptions instead of rescuing and displaying them (this is the config.action_dispatch.show_exceptions setting). This is useful in single-threaded test setups like controller specs and rack-test, but it means that the exception is sent to the application server (webrick or thin) on multithreaded setups like capybara-webkit and selenium. The invalid responses that result from these exceptions are interpreted by capybara-webkit as response code zero.
There's been some work in capybara (https://github.com/jnicklas/capybara/pull/660) to improve this situation. For now, I'd recommend turning show_exceptions to true or using @allow-rescue from cucumber-rails, which will allow capybara-webkit to actually see errors like 404s and 500s.
Thanks for the reply, but have you looked at the code I submitted?
There are no exceptions involved. The status code 404 is generated by me, manually. It could be some other code, like 403.
Also, when tested in a real browser, things work as they should and you get the 403/404 or whatever status that was generated.
Finally, nothing in your explanation addresses why there is a difference between an empty body and a non empty one.
@marcandre sorry, I missed that. I'll try to reproduce this when I can. If you get a chance to put together a failing test, that would help speed things up.
There is a failing test at the end...
@marcandre sorry - to be clear, I meant a failing spec in capybara-webkit.
Hmmm, I don't have the time, and it should be much easier for someone who knows the codebase, based on my very simple example. Thanks
We've long since reworked our connection handling code. Headers and status codes are handled completely differently, resolving this issue. Please reopen if you're still having issues in the latest version.
Still happening with * capybara-webkit (1.7.1)
Resolved with
render json: { blacklisted: true }, status: :unprocessable_entity
instead of
head :unprocessable_entity
in my controller
@delphaber is there a minimal test case you could put together to reproduce the issue?
@jferris this is a demo that I just prepared with latest version of suspenders and angular. See the README.md for more information. I hope this could help!
I managed to put together a failing test in d6c72bcd33fb9be77940eebe3b5149cb1fba13a1 that reproduces the issue.
I'm not sure if this is an issue in QtWebKit or related to how we handle requests.
I love this; we're running into the same problem but with redirects. Would be great to get this resolved.
Still affected on Capybara 2.17.0, but I'm not using capybara-webkit. Is this a Capybara issue?
@mdesantis It's an issue with whatever driver you are using. If you're not using capybara-webkit then I'm guessing Poltergeist since PhantomJS (used by poltergeist) is built on the same era of QtWebkit as capybara-webkit builds against.