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.
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.
I've been trying to use FactoryGirl for tests on my Rails application, but I'm running into difficulty with it.
I feel as if there must be something fairly obvious I'm doing wrong, but after much searching I haven't been able to figure out the cause.
I'm trying to run a test to confirm the 'show' action is successful on one of my controllers.
Here's the error message I'm getting:
Failure/Error: get 'show'
ActionController::UrlGenerationError:
No route matches {:action=>"show", :controller=>"simple_requests"}
Below are the relevant code snippets leading to this outcome.
/spec/controllers/simple_requests_controller_spec.rb
require 'spec_helper'
describe SimpleRequestsController do
describe "GET 'show'" do
before do
#simple_request = build(:simple_request)
end
it "should be successful" do
get 'show'
expect(response).to be_success
end
end
end
/factories/simple_requests_controller_spec.rb
FactoryGirl.define do
factory :simple_request do
id 123
full_name "Testie McTesterson"
company "Test Company"
role "Analyst"
email "foobar#foobs.com"
phone "000888"
message "Test question?"
end
end
/controllers/simple_requests_controller.rb
def show
authorize SimpleRequest #For pundit
#simple_request = SimpleRequest.find(params[:id])
end
I have two hypotheses as to why this may be happening:
1) Rspec is looking for an id for the 'show' action, but somehow can't find it. (Although there is one in the Factory, and I've yet to figure out how it wouldn't be flowing through.)
2) Pundit is causing issues, since the show action may require authorization (although commenting out the 'authorize' line makes no difference at present)
Any and all thoughts welcome :)
EDIT
Pasting below the output of rake routes | grep simple_requests
simple_requests GET /simple_requests(.:format) simple_requests#index
POST /simple_requests(.:format) simple_requests#create
new_simple_request GET /simple_requests/new(.:format) simple_requests#new
edit_simple_request GET /simple_requests/:id/edit(.:format) simple_requests#edit
simple_request GET /simple_requests/:id(.:format) simple_requests#show
PATCH /simple_requests/:id(.:format) simple_requests#update
PUT /simple_requests/:id(.:format) simple_requests#update
DELETE /simple_requests/:id(.:format) simple_requests#destroy
Edit 2 - Adding ID parameter
I have now also attempted to add an id as follows:
it "should be successful" do
get 'show', id: #simple_request.id
expect(response).to be_success
end
This time I received the following error message
ActiveRecord::RecordNotFound: Couldn't find SimpleRequest with 'id'=123
'123' is the ID in my /factories - I think I must be missing something to get this working, but can't figure out what yet.
Your SimpleRequest does not have an Id. You need to use create instead of build
before do
#simple_request = create(:simple_request)
end
it "should be successful" do
get 'show', id: #simple_request.id
expect(response).to be_success
end
Try this:
before do
#simple_request = create :simple_request
end
it "should be successful" do
get 'show', id: #simple_request.id
expect(response).to be_success
end
It's a show view, so you'll have to supply your request with an ID and you'll have to actually create a record with create instead of build in your before block.
I am trying to check the title of a page, but it is failing with:
rspec ./spec/controllers/pages_controller_spec.rb:13 # PagesController GET 'home' should have the right title
Here is what pages_controller_spec.erb looks like:
render_views
describe "GET 'home'" do
it "returns http success" do
get 'home'
response.should be_success
end
it "should have the right title" do
get 'home'
response.should have_selector("title",:content => "Home")
end
end
According to this, I think you need :text not :content:
http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Finders#all-instance_method
I hope that helps.
rspec controller tests stub the view so you can test the controller in isolation
https://www.relishapp.com/rspec/rspec-rails/v/2-12-2/docs/controller-specs/views-are-stubbed-by-default
if you check the response object it probably contains a blank string
the idea being you should test
if the correct template rendered
if the controller redirected correctly
if the controller called the correct models, etc...
that being said, if you want the test to render the view, use render_views in the describe block
https://www.relishapp.com/rspec/rspec-rails/v/2-2/docs/controller-specs/render-views
Building off of what house9 says, you should test the title of your views somewhere else, and not in your controller specs. For instance, you can create a "requests" directory within your spec directory and test page features there. For more information on request specs:
http://railscasts.com/episodes/257-request-specs-and-capybara?view=asciicast
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
Does anyone know how to make rspec follow a redirect (in a controller spec)? (e.g test/unit has follow_redirect!)
I have tried "follow_redirect!" and "follow_redirect" but only get
undefined method `follow_redirect!' for #<Spec::Rails::Example::ControllerExampleGroup::Subclass_1:0xb6df5294>
For example:
When I create an account the page is redirected to accounts page and my new account should be at the top of the list.
it "should create an account" do
post :create, :name => "My New Account"
FOLLOW_REDIRECT!
response.code.should == "200"
accounts = assigns[:accounts]
accounts[0].name.should == "My New Account"
end
But FOLLOW_REDIRECT! needs to be changed to something that actually works.
I think this is the default behavior for rspec-rails controller tests, in the sense that you can set an expectation on the response status and/or path, and test for success.
For example:
it "should create an account" do
post :create
response.code.should == "302"
response.should redirect_to(accounts_path)
end
You can access the redirect location with
response.headers['Location']
you could then request that directly.
If you want to test the redirect you are moving outside of the rspec-rails domain.
You can use Webrat or some other integration-test framework to test this.
The easiest way to solve this without resorting to integration testing is probably to mock out the method that is causing the redirect.
The spec is out of scope, if you want to follow a redirect use request spec, the equivalent of integration test in Test::Unit.
In request specs follow_redirect! works as well as in Test::Unit.
Or if you want to redirect inmediately use _via_redirect as suffix for the verb, example:
post_via_redirect :create, user: #user
Try to use integration/request tests. They are using web-like acces through routing to controllers.
For example:
I have for Rails 2 app in file /spec/integration/fps_spec.rb
require 'spec_helper'
describe "FinPoradci" do
it "POST /fps.html with params" do
fp_params={:accord_id => "FP99998", :under_acc => "OM001", :first_name => "Pavel", :last_name => "Novy"}
fp_test=FinPoradce.new(fp_params)
#after create follow redirection to show
post_via_redirect "/fps", {:fp => fp_params}
response.response_code.should == 200 # => :found , not 302 :created
new_fp=assigns(:fp)
new_fp.should_not be_empty
new_fp.errors.should be_empty
flash[:error].should be_empty
flash[:notice].should_not be_empty
response.should render_template(:show)
end
end
and it works. Until you want to send headers (for basic http authorization).
env={'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user,password)}
post_via_redirect "/fps", {:fp => fp_params}, env
is fine for create, but after redirection it returns 401 and needs new authorization.
SO I have to split it in 2 tests: creation and show on result of creation.
For RSpec / Capybara + Rails
response_headers['Location']
But it works only if there is no delay before redirect.
If it is there, then it's harder to follow the logic.