My Rails project's 'spec' folder contains the following:
1) a 'controllers' subfolder with:
a) a 'pages_controller' spec file (with corresponding "describe PagesController do" statement):
require 'spec_helper'
describe PagesController do
render_views
before(:each) do
#base_title = "Ruby on Rails Tutorial Sample App | "
end
describe "GET 'home'" do
it "should be successful" do
get 'home'
response.should be_success
end
it "should have the right title" do
get 'home'
response.should have_selector("title", content: #base_title+"Home")
end
end
describe "GET 'contact'" do
it "should be successful" do
get 'contact'
response.should be_success
end
it "should have the right title" do
get 'contact'
response.should have_selector("title", content: #base_title+"Contact")
end
end
describe "GET 'about'" do
it "should be successful" do
get 'about'
response.should be_success
end
it "should have the right title" do
get 'about'
response.should have_selector("title", content: #base_title+"About")
end
end
describe "GET 'help'" do
it "should be successful" do
get 'help'
response.should be_success
end
it "should contain the right title" do
get 'help'
response.should have_selector("title", content: #base_title+"Help")
end
end
end
b) a 'users_controller' spec file (with corresponding "describe UsersController do" statement):
require 'spec_helper'
describe UsersController do
render_views
describe "GET '/new'" do
it "should be successful" do
get 'new'
response.should be_success
end
it "should have the right title" do
get 'new'
response.should have_selector("title", content: "Sign up")
end
end
end
2) a 'requests' subfolder with the following 'layout_links' spec file:
require 'spec_helper'
describe "LayoutLinks" do
it "should have a Home page at '/'" do
get '/'
response.should have_selector('title', content: 'Home')
end
it "should have a Contact page at '/content'" do
get '/contact'
response.should have_selector('title', content: 'Contact')
end
it "should have an About page at '/about'" do
get '/about'
response.should have_selector('title', content: 'About')
end
it "should have a Help page at '/help'" do
get '/help'
response.should have_selector('title', content: 'Help')
end
it "should have a signup page at '/signup'" do
get '/signup'
response.should have_selector("title", content: "Sign up")
end
end
I initially added the following code to my "users_controller" file:
it "should have a signup page at '/signup'" do
get '/signup'
response.should have_selector("title", content: "Sign up")
end
The test failed when I ran it, but when I added it to the 'layout_links' spec file, it passed. This tells me that I am missing some fundamental aspect of RSpec and/or integration testing. Am happy to re-word this question to make it more universal, if necessary.
Your hunch is correct, there is some convention over configuration going on here.
Controller tests will work off the controller specified. So your PagesController test will work off...well, the PagesController. So the get 'home' line will try to get the home action in your Pages controller, the Pages controller is assume for all of those tests. Unless your Pages controller has a signup action it will error.
The requests type tests are for integration tests and don't assume a controller.
Related
so I'm writing a Test for my UserController, and the associated Devise dependency.
I'm trying to write a test that verify's userA can't access the show page of userB, but is redirected to the root_path instead. I'm guessing syntax errors are my issue, but I'd love another pair of eyes on it!
require 'rails_helper'
describe UsersController, :type => :controller do
# create test user
before do
#userA = User.create!(email: "test#example.com", password: "1234567890")
#userB = User.create!(email: "test2#example.com", password: "1234567890")
end
describe "GET #show" do
before do
sign_in(#userA)
end
context "Loads correct user details" do
get :show
expect(response).to have_http_status(200)
expect(assigns(:user)).to eq #userA
end
context "No user is logged in" do
it "redirects to login" do
get :show, id: #userA.id
expect(response).to redirect_to(root_path)
end
end
end
describe "GET Unauthorized page" do
before do
sign_in(#userA)
end
context "Attempt to access show page of UserB" do
it "redirects to login" do
get :show, id: #userB.id
expect(response).to have_http_status(401)
expect(response).to redirect_to(root_path)
end
end
end
end
You're missing an "it" block in
context "Loads correct user details" do
get :show
expect(response).to have_http_status(200)
expect(assigns(:user)).to eq #userA
end
How do I do the following in RSpec?
test "should get home" do
get :home
assert_response :success
get :home, { mobile: 1 }
assert_response :success
end
Note that my mobile views have a different mime-type (i.e. .mobile.erb )
Failed attempt:
render_views
describe "GET home" do
it "renders the index view" do
get :home
expect(response).to render_template("home")
get :home, { mobile: 1 }
expect(response).to render_template("home")
end
end
This test doesn't fail if I break the mobile view.
To check that the request was successful you can use:
it { is_expected.to respond_with 200 }
As the best practice is to have single expectation per test, I would refactor your example to something like this:
describe "GET home" do
render_views
context 'with regular view' do
before do
get :home
end
it { is_expected.to respond_with 200 }
it "renders the index view" do
expect(page).to have_content 'some header'
end
end
context 'with mobile view' do
before do
get :home, { mobile: 1 }
end
it { is_expected.to respond_with 200 }
it "renders the index view" do
expect(page).to have_content 'some header'
end
end
end
That's just an idea for you to start.
You can try this:
expect(response).to be_success
I'm upgrading a site to use devise and I have the following specs to test SitesController:
describe SitesController do
let(:user) { FactoryGirl.create(:user) }
let(:admin) { FactoryGirl.create(:user, :admin) }
shared_examples "disallow get index" do
get :index
response.should_not be_success
end
context "with user signed in" do
before(:each) { sign_in user }
it "disallowes / with GET" do
get :index
response.should_not be_success
end
it_behaves_like "disallow get index"
end
context "with admin signed in" do
before(:each) { sign_in admin }
it "allowes / with GET" do
get :index
response.should be_success
end
end
end
I want to add a context where no user is signed in and use the shared example disallow get index to specify that you can't do that if you're not signed in. BUT, when I add it_behaves_like "disallow get index" I get this undefined method error:
sites_controller_spec.rb:8:in `block (2 levels) in <top (required)>': undefined method `get' for #<Class:0x00000101746718> (NoMethodError)
So, why does this work when I explicitly call get :index but not in a shared example group?
Turned out to be a very simple fix. I was using shared_examples to replace an it block like this:
shared_examples "disallow get index" do
get :index
response.should_not be_success
end
When shared_examples is really a "replacement" for a context block. So, you need to have it blocks inside your shared_examples:
shared_examples "disallow get index" do
it "fails on index" do
get :index
response.should_not be_success
end
end
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Rspec test should pass but fails
Why am I getting this error?
C:\Sites\sample_app>rspec
?[32m.?[0m?[31mF?[0m?[32m.?[0m?[31mF?[0m?[32m.?[0m?[31mF?[0m
Failures:
1) PagesController GET 'home' should have the right title
?[31mFailure/Error:?[0m ?[31mresponse.should have_selector("title",?[0m
?[31mNoMethodError:?[0m
?[31mundefined method has_selector?' for #<ActionController::TestResponse:0x4162ce0>?[0m
?[36m # ./spec/controllers/pages_controller_spec.rb:14:inblock (3 levels) in '?[0m
2) PagesController GET 'contact' should have the right title
?[31mFailure/Error:?[0m ?[31mresponse.should have_selector("title",?[0m
?[31mNoMethodError:?[0m
?[31mundefined method has_selector?' for #<ActionController::TestResponse:0x3eab898>?[0m
?[36m # ./spec/controllers/pages_controller_spec.rb:27:inblock (3 levels) in '?[0m
3) PagesController GET 'about' should have the right title
?[31mFailure/Error:?[0m ?[31mresponse.should have_selector("title",?[0m
?[31mNoMethodError:?[0m
?[31mundefined method has_selector?' for #<ActionController::TestResponse:0x3f1ccb0>?[0m
?[36m # ./spec/controllers/pages_controller_spec.rb:41:inblock (3 levels) in '?[0m
Finished in 5.15 seconds
?[31m6 examples, 3 failures?[0m
Failed examples:
?[31mrspec ./spec/controllers/pages_controller_spec.rb:12?[0m ?[36m# PagesController GET 'home' should have the right title?[0m
?[31mrspec ./spec/controllers/pages_controller_spec.rb:25?[0m ?[36m# PagesController GET 'contact' should have the right title?[0m
?[31mrspec ./spec/controllers/pages_controller_spec.rb:39?[0m ?[36m# PagesController GET 'about' should have the right title?[0m
Randomized with seed 501
Application_helper.rb
module ApplicationHelper
# Retrun a title on a per-page basic.
def title
base_title = "Ruby on Railys tut sample app"
if #title.nil?
base_title
else
"#{base_title} | #{#title}"
end
end
end
Pages_controller_spec.rb
require 'spec_helper'
describe PagesController do
render_views
describe "GET 'home'" do
it "should be successful" do
get 'home'
response.should be_success
end
it "should have the right title" do
get 'home'
response.should have_selector("title",
:content => "Ruby on Rails Tutorial Sample App | Home")
end
end
describe "GET 'contact'" do
it "should be successful" do
get 'contact'
response.should be_success
end
it "should have the right title" do
get 'contact'
response.should have_selector("title",
:content =>
"Ruby on Rails Tutorial Sample App | Contact")
end
end
describe "GET 'about'" do
it "should be successful" do
get 'about'
response.should be_success
end
it "should have the right title" do
get 'about'
response.should have_selector("title",
:content =>
"Ruby on Rails Tutorial Sample App | About")
end
end
end
If you need something else just add and thanks
You need the base_title method to return the exact string you are testing for. In this case "Ruby on Rails Tutorial Sample App". Currently you have it setting the title as "Ruby on Railys tut sample app".
Hey all this is where I'm at:
$ spec spec/
Finished in 0.002031 seconds
0 examples, 0 failures
HOWEVER. I've got my first few tests I've written and placed them in /spec/controllers/citations_controller_spec.rb
and added a puts in the above spec to verify that its actually being executed on the use of:
spec spec/
here are the contents of citations_controller_spec.rb ( it has existing tests ) :
require 'spec_helper'
describe CitationsController do
describe "GET 'home'" do
it "should be successful" do
get 'home'
response.should be_success
end
it "should have the right title" do
get 'home'
response.should have_tag("title",
"Ruby on Rails Tutorial Sample App | Home")
end
end
describe "GET 'contact'" do
it "should be successful" do
get 'contact'
response.should be_success
end
it "should have the right title" do
get 'contact'
response.should have_tag("title",
"Ruby on Rails Tutorial Sample App | Contact")
end
end
describe "GET 'about'" do
it "should be successful" do
get 'about'
response.should be_success
end
it "should have the right title" do
get 'about'
response.should have_tag("title",
"Ruby on Rails Tutorial Sample App | About")
end
end
end
But as shown in the first code bit ...
0 examples, 0 failures
.. so anyone happen to know whats going on here?
Try
spec spec/controllers/citations_controller_spec.rb
to run one test file. Or
rake test
to run all tests. Do you see any test dots or examples now?