I've created a test with
rails g integration_test index --webrat
This creates the file:
require 'spec_helper'
describe "Indices" do
describe "GET /indices" do
it "works! (now write some real specs)" do
visit indices_path
response.status.should be(200)
end
end
end
That's all fine, but the only problem is that this test fails even though indices_path exists:
Failure/Error: response.status.should be(200)
NoMethodError:
undefined method `status' for nil:NilClass
So it seems like response is nil.
I can still use page (e.g. page.should have_content works perfectly), but not response. I'd really just like to know that the response status was 200. Can I use something other than response?
If page is available, it looks like you may have capybara instead of webrat. You can try this:
page.status_code.should be 200
Related
I want to test if my root path renders proper view:
require 'rails_helper'
RSpec.describe "Statics", type: :request do
describe "GET root path" do
it "returns http success" do
get "/"
expect(response).to have_http_status(:success)
end
it 'routes GET / to static#landing_page' do
expect('/').to render_template('static#landing_page')
end
end
end
The second test fails. In order to find out the reasone behind it I type the second command manually with byebug. Then I receive this error message:
*** NoMethodError Exception: assert_template has been extracted to a gem. To continue using it,
add gem 'rails-controller-testing' to your Gemfile.
For some reasone I am not quite sure rspec confuses render_template with assert_template method and fails. How can I fix it to pass this test?
As RSpec docs state:
The render_template matcher is used to specify that a request renders
a given template or layout. It delegates to assert_template
It is available in controller specs (spec/controllers) and request
specs (spec/requests).
NOTE: use redirect_to(:action => 'new') for redirects, not
render_template.
So, no confusion here.
The setup is the following. For each http request the manager sends his credentials in the header(name,pw). These get checked against the entries in the db and if they succeed return the desired user object. How is it possible to implement basic http_auth in the request tests? I would like to add only the password and username and test the return value? Which is the goal of request tests,right? I tried the following without much success:
I created an AuthHelper module in spec/support/auth_helper.rb with
module AuthHelper
def http_login
user = 'test'
pw = 'test'
request.ENV['HTTP_AUTHORIZATION'] =ActionController::HttpAuthentication::Basic.encode_credentials(user,pw)
end
end
and use it in the requests/api/user_spec.rb as follows
include AuthHelper
describe "User API get 1 user object" do
before(:each) do
http_login
end
but i receive this error message. How can i fix this and enable my tests to pass http_auth? I read lot of similar topis and questions also here but
they apply mostly to older versions of rspec and rails and are not applying to my case
Thanks in advance!
Failure/Error: request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user,pw)
NoMethodError:
undefined method `env' for nil:NilClass# ./spec/support
# ./spec/support/auth_helper.rb:5:in `http_login'
# ./spec/requests/api/user_spec.rb:8:in `block (2 levels) in <top (required)>'
Update
I moved the header generation inside a request. I looked up the Auth verb, so i think the assignment should work. I tested the ActionController call in rails console and received a string. I suppose this is also correct.My whole test now looks like this:
describe "User API get 1 user object", type: :request do
it 'Get sends back one User object ' do
headers = {
"AUTHORIZATION" =>ActionController::HttpAuthentication::Basic.encode_credentials("test","test")
# "AUTHORIZATION" =>ActionController::HttpAuthentication::Token.encode_credentials("test","test")
}
FactoryGirl.create(:user)
get "/api/1/user", headers
#json = JSON.parse(response.body)
expect(response).to be_success
# expect(response.content_type).to eq("application/json")
end
end
receiving the following error:
which incudles the line #buf=["HTTP Basic: Access denied.\n"] so access is still denied.
Failure/Error: expect(response).to be_success
expected `#<ActionDispatch::TestResponse:0x000000070d1d38 #mon_owner=nil, #mon_count=0, #mon_mutex=#<Thread::Mutex:0x000000070d1c98>, #stream=#<ActionDispatch::Response::Buffer:0x000000070d1c48 #response=#<ActionDispatch::TestResponse:0x000000070d1d38 ...>,
#buf=["HTTP Basic: Access denied.\n"], #closed=false>, #header={"X-Frame-Options"=>"SAMEORIGIN", "X-XSS-Protection"=>"1; mode=block", "X-Content-Type-Options"=>"nosniff", "WWW-Authenticate"=>"Basic realm=\"Application\"", "Content-Type"=>"text/html; charset=utf-8", "Cache-Control"=>"no-cache", "X-Request-Id"=>"9c27d4e9-84c0-4ef3-82ed-cccfb19876a0", "X-Runtime"=>"0.134230", "Content-Length"=>"27"}, #status=401, #sending_file=false, #blank=false,
#cv=#<MonitorMixin::ConditionVariable:0x000000070d1bf8 #monitor=#<ActionDispatch::TestResponse:0x000000070d1d38 ...>, #cond=#<Thread::ConditionVariable:0x000000070d1bd0>>, #committed=false, #sending=false, #sent=false, #content_type=#<Mime::Type:0x00000002af78f8 #synonyms=["application/xhtml+xml"], #symbol=:html, #string="text/html">, #charset="utf-8", #cache_control={:no_cache=>true}, #etag=nil>.success?`
to return true, got false
SOLUTION
This test is not polished (yet) but at least it passes now.
describe "User API get 1 user object", type: :request do
it 'Get sends back one User object ' do
#env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user,pw)
FactoryGirl.create(:user)
get "/api/1/user", {}, #env
JSON.parse(response.body)
expect(response).to be_success
expect(response.status).to eq 200
end
end
Read the error carefully: undefined method `env' for nil:NilClass means request is nil. Are you trying to set the header before a test while you are defining the request later on in the test?
You might want to look at the documentation for an example on how to set headers.
If you're still stuck, post one of your tests as well.
This line looks suspicious:
request.ENV['HTTP_AUTHORIZATION'] =ActionController::HttpAuthentication::Basic.encode_credentials(user,pw)
Are you sure that "ENV" should be capitalized? I think it should be written like "env".
Below is my rspec. Notice that three lines are commented out. This rspec passes.
describe "/my_api_endpoint" do
it 'Blah Blah Blah' do
post "/my_api_endpoint", #params
# expect(response).to be_success
# json = JSON.parse(response.body)
# puts "json = #{json}"
last_response.should be_ok
end
end
However, not only do I need to know that the POST returned success, I also need to examine the JSON it returns. Somehow I cannot do this. When I comment those three lines back in, I get the following error
NameError: undefined local variable or method `response' for <RSpec::Core::ExampleGroup::Nested_1::Nested_9:0x007f84c58c31f0>`
How do I examine the results of the post?
My work colleague provided me this answer:
For Sinatra apps the response is in last_response not in response.
I am trying to test my rails app with rspec 2.10.0 + capybara 1.1.2. Here is my test file
require 'spec_helper'
describe AdminPanelController do
describe "index" do
it "should have return code 200" do
visit '/admin'
page.should have_content "hello"
#response.status.should be(200)
end
end
end
And here are test result
Failure/Error: page.should have_content "hello"
Capybara::ElementNotFound:
Unable to find xpath "/html"
I google about this issue but find only information that webrat can be a problem however i do not have this gem installed. Thanks for any suggestions.
Wrong type of test. This looks like a controller test, which does tests with methods like get and post and is in the spec/controllers folder. Request specs, which use capybara, reside in spec/requests. Run $ rails generate scaffold SomeModel to see how they each should look.
If you understood the above but would still like to use capybara for your controller test, modify your describe block:
describe AdminPanelController, :type => :request do
...
end
I have a user_controller_spec.rb that is failing, and I'm not sure why.
require 'spec_helper'
describe UsersController do
describe "GET 'index'" do
it "should be successful" do
get 'index'
response.should be_success
end
end
end
When I run rspec it says:
Failures:
1) UsersController GET 'index' should be successful
Failure/Error: response.should be_success
expected success? to return true, got false
# ./spec/controllers/users_controller_spec.rb:8
Finished in 0.17047 seconds
1 example, 1 failure
Going to the /home/ page in the browser works fine.
Is there a way to get a more detailed reason why it is failing?
Note:
This is rails3, and I am using rspec.
I also have the capybara gem, and searching my solution shows the only reference to capybara is in my gem and gem.lock file.
You can try outputting the response body to see what the message is. Could be anything from the user you're logged in as not having the correct permissions (or visiting a page anonymously that you must be logged in to see) to a strange view error in test environment.
get 'index'
puts response.body.inspect
puts response.status.inspect
...
response.should be_success
response.body will contain the HTML output of the response, so you should be able to tell why it's not a success (hopefully it will have a stack trace or be a redirect or something). Also keep in mind redirecting is not "success". If I remember correctly be_success makes sure the HTTP status code is one of the 200s, redirects are usually 302 or 304 so do not count. If a redirect is intended, try response.should be_redirect.
It could be that you do not just render the page, but redirect. To check on what may be wrong, i would do in my spec something like :
response.should == 1
in order to see what the actual response is. This would give you a good clue on what is happening.