Testing page redirect in rails - ruby-on-rails

How can I test this in rails:
A student goes to a list of their groups, and when they click the link, it brings them to that group page.
I have the gist of it down, but how can I test that it went to a page? I was thinking something along the lines of:
expect(page).to eq()
but then I am not sure what to do from there. I don't want to just expect the page to have the name of the group, because that that would be on the overall list and the page the link would bring them to. Any advice?

You're looking for the redirect_to() method. So an example would be:
require 'spec_helper'
describe FoobarController do
describe "GET foo" do
it "redirects to bar" do
get :foo
expect(response).to redirect_to(bar_path)
end
end
end

Related

How to test if a page is rendered from rspec

I'm testing access to a page with a bunch of different types of users. I'm tyring to see which page is rendered for each type. I can't find the right syntax to do so. I'm also not sure if this should be in a views file rather than controller.
describe "GET show as admin" do
before(:each) do
session[:admin_user_id] = FactoryGirl.create(:admin_user).id
end
it "is available to view by admin" do
data_service = FactoryGirl.create(:published_data_service)
get :show, {:id => data_service.to_param}
assigns(:data_service).should eq(data_service)
response.should render_template('show')
end
end
render_template is returning as [].
Other note: Capybara is included in the Gemfile, and is being required in spec_helper

Rspec testing specific nodes in response

I'd like to isolate specific nodes to test on.
e.g. instead of
get :show
response.should have_content(#user.name)
it would be more descriptive/correct to be able to write something like
get :show
profile = response.find_selector("div.user-profile")
profile.should have_content(#user.name)
is it possible?
UPDATE
Got a bit further with this after reading Peter's answer but still not finding elements.
in app\views\users\index.html.erb
<h1>Users</h1>
<div id="test"></div>
in spec\controllers\users_controller_spec.rb
require 'spec_helper'
describe UsersController do
render_views
it "should should have header" do
get :index
response.should have_selector("h1", content: "Users")
end
it "should show user profile" do
get :index
node = page.find_by_id("test")
p node
end
end
The first test passes, the second test gives ElementNotFound error. I'm possibly just doing something stupid as this is my first go at Rails.
Yes, it is possible. Capybara doesn't have find_selector, but it does have find and derivatives which take a locator and behave as you imply above. See http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Finders
For example, instead of:
page.should have_selector('foo', text: 'bar')
you can say:
node = page.find('foo')
node.should have_content('bar')

Rails failing rspec

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

RSpec example group naming for webapps

This question is about how to best name RSpec example groups and examples in English.
I understand that in RSpec, describe, context (which are functionally equivalent) and it are supposed to give you complete sentences. So for example,
describe "Log-in controller" do
context "with logged-in user" do
it "redirects to root" do
...
end
end
end
reads Log-in controller with logged-in user redirects to root. Awesome.
But in my application, where I need to test all components on an ajaxy page (using Capybara), I tend to have example groups like this:
describe "blog post" do
describe "content" do
it "is displayed"
end
describe "comment" do
it "is displayed"
describe "editing" do
it "works" # successful comment editing
it "requires logged-in user" # error case 1
it "requires non-empty body" # error case 2
end
end
describe "comment form" do
it "works" # successful comment submission
it "requires valid email address" # error case 1
it "requires non-empty body" # error case 2
end
end
I see two anti-patterns here:
The nested describes don't read as sentences. Of course one could put an 's:
describe "blog post" do
describe "'s content" do
it "is displayed"
end
end
Or one could put a colon after "blog post:". Or ideally, I would write
describe "blog post" do
its "content" do
it "is displayed"
end
end
but that's not possible because its is about attribute access, and I just have strings here.
Is there a better way to deal with the "page components" problem?
For the functionality, the successful cases (for functionality like comment submission) are simply marked as it "works". At least this is concise and simple -- I find it slightly preferable to it "can be submitted and causes a comment to be added", because that just forces me to make up verbiage for something that is obvious. But is there a nicer, more "natural" way to do this?
Suggestions for how to restructure the example example-group ;) above would be appreciated!
You shouldn't really think about having examples be grammatically correct. It's fine if your test reads 'blog post content is displayed' without the 's. The test is readable and simple. What you really want is to be able to understand what is failing when a test doesn't work.
With regards to your second point, 'it works' is usually not descriptive enough. It doesn't let someone else know what you mean by 'works'. If you are actually testing many things it's best to split your examples up, for instance:
describe 'blog post' do
context 'creating a comment' do
it 'should require a logged-in user'
it 'should require a non-empty body'
it 'should require a valid email address'
it 'should create a new comment'
it 'should be submittable'
end
end

Dynamically test each method in a controller

I have an Ruby on Rails 3 admin_controller with the default set of CRUD, index and so on methods. I'd like to test each of these for certain assertions with rspec.
Like response.should render_template("layouts/some_layout") or tests that it should require login.
Copy-pasting that test into the group of tests for each method is a lot of duplication. IMO it makes little sense to have an
it 'should require login' do
Duplicated several times troughout that test.
Is there a simple way to run a test on a list of methods? Say defined_methods.each do |method| it 'should' .... of some sort?
Is this a good way in the first place? Or am I taking a wrong route in the first place?
Given that you really want all those assertions, have you considered shared example groups?
shared_examples_for "an action that requires authentication" do
it "should render successfuly" do
sign_in(user)
response.should be_success # or whatever
end
it "should deny access" do
# don't sign_in the user
# assert access was denied
end
end
shared_examples_for "another behaviour" do
# ...
end
let(:user) { create_user }
describe "#index" do
before(:each) { get :index }
it_behaves_like "an action that requires authentication"
it_behaves_like "another behaviour"
end
describe "#show" do
before(:each) { get :show }
it_behaves_like "an action that requires authentication"
end
# ...
Of course before writing large number of specs for a basic functionality you should always check if it isn't already tested by the library that is providing the functionality (e.g. checking for the rendered template, if it is handled by rails's implicit rendering, might be a bit overkill).
If you wanted to go down the route of iteratively testing each public method in the controller, you could do something like:
SomeController.public_instance_methods(false).each do |method|
it "should do something"
end
However, I think a shared example group (see about half way down this page: http://rspec.info/documentation/) would be prettier. If it were extracted so it could be used across all your controller specs, it'll be even nicer..
shared_examples_for "admin actions" do
it "should require login"
end
Then in each controller spec:
describe SomeController do
it_should_behave_like "admin actions"
end
Just add it to your test_helper.rb, something like:
def requires_login
...
end

Resources