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
Related
My controller and my test file are bellow.
controllers/reports_controller.rb:
def index
#reports = Report.all
end
specs/controllers/reports_controller_spec.rb:
RSpec.describe ReportsController, type: :controller do
let(:test_report) {
2.times.map {
create(:report, student: create(:student), report_options_attributes: [
{option: create(:option), note: "ole" }
])
}
}
describe "GET #index" do
before(:each) do
get :index
end
it "should be success" do
expect(response).to be_success
end
it "should render index template" do
expect(response).to render_template(:index)
end
it "should load all reports" do
expect(assigns(:report)).to match_array test_report
end
end
The last test is not working, but it should work. What is wrong with it?
index test is empty..you need to assert something to pass.
can you add.. assert_response :success in index function.
Your var is different from the controller. Use reports instead of report like this:
it "should load all reports" do
expect(assigns(:reports)).to match_array test_report
end
It should work.
I tried to write some tests for the "show" action in Rails API
require 'rails_helper'
RSpec.describe AirlinesController, type: :controller do
describe "GET #show" do
before(:each) do
#airline = FactoryGirl.create(:airline)
get :show, id: #airline.id
end
it "should return the airline information" do
airline_response = json_response
expect(airline_response[:name]).to eql #airline.name
end
it {should respond_with :ok}
end
end
The test passed. However, when I try to use let and subject like this
require 'rails_helper'
RSpec.describe AirlinesController, type: :controller do
describe "GET #show" do
let(:airline) {FactoryGirl.create(:airline)}
subject {airline}
before(:each) do
get :show, id: airline.id
end
it "should return the airline information" do
airline_response = json_response
expect(airline_response[:name]).to eql airline.name
end
it {should respond_with :ok}
end
end
It showed "NoMethodError undefined method `response' for ..."
This makes me confused!
Don't set the subject. The subject of a controller spec is the controller, not a model object. Just remove the line that sets subject and you shouldn't get that error any more.
it {should respond_with :ok}
I assume this line takes the subject and makes a response call.
The recommended syntax is:
it "returns 200" do
expect(response).to be_success
end
Or maybe your json_response helper method is using subject.response instead of response.
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
I have a controller and tests it through rspec:
describe "GET 'index'" do
subject { get :index }
it { expect(subject).to render_template(:index) }
My controller generates instance variables passed to views, smth. like that:
#specifications = current_user.specifications
How can I test that controller pass instance variables correct?
Something like that:
it { expect(subject).assign(:contractors).to match_array(my_array) }
You can use controller helper test method
describe TetsController do
let(:user) { build_stubbed :user }
before do
controller.stub authenticate_user!: true,
current_user: user
end
describe 'GET index' do
let(:plans) { double :plans }
before do
expect(Plan).to receive(:all).and_return(plans)
end
it 'response success' do
get :index
expect(response).to be_success
end
it 'assign plans' do
get :index
expect(assigns(:plans)).to eq plans
end
end
end
Small example. controller has instance variable #plans. It's accessed as assigns(:plans)
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.