Rspec redirect to testing - ruby-on-rails

In my controller when an user creates a new post, he/she is redirected to the page that contains the newly created post. I'm wanting to create a test in rspec to cover this redirect but am having trouble with it. Specifically, I want to know what to write in the refirst_to argument. Here is the controller code below..
def create
#micropost = Micropost.new(params[:micropost])
respond_to do |format|
if #micropost.save
format.html {redirect_to #micropost}
else
format.html {render action: 'edit'}
end
end
end
Here is the rspec test...
before do
#params = FactoryGirl.build(:micropost)
end
it "redirects to index" do
#clearly #params.id doesn't work. its telling me instead of a redirect im getting a
#200
#response.should redirect_to(#params.id)
end

Assuming that #params will create a valid Micropost (otherwise .save will fail and you'll be rendering :edit)...
it "redirects to index on successful save" do
post :create, :micropost => #params.attributes
response.should be_redirect
response.should redirect_to(assigns[:micropost])
end
it "renders :edit on failed save" do
post :create, :micropost => {}
response.should render ... # i don't recall the exact syntax...
end

Related

How to run minitest for controller methods?

post_controller file
class PostsController < ActionController::Base
before_action :authenticate_user!
def index
#post = current_user.posts.paginate(page: params[:page], per_page: 5)
respond_to do |format|
format.html
format.json { render json: #post }
end
end
def new
#post = Post.new
end
def create
#post = current_user.posts.build(post_param)
if #post.save
redirect_to action: 'index'
else
render 'new'
end
post_controller_test
require 'test_helper'
class PostsControllerTest < ActionController::TestCase
include Devise::TestHelpers
def setup
#user = users(:Bob)
#post = Post.new
end #passed
test 'logged in should get show' do
sign_in #user
get :index
assert_response :success
end #passed
test 'not authenticated should get redirect' do
get :index
assert_response :redirect
end #passed
test 'should get index' do
get :index
assert_response :success
assert_not_nil assigns(:posts)
end #failing
test "should destroy post" do
assert_difference('Post.count', -1) do
delete :destroy, id: #post
end
assert_redirected_to posts_path
end #failing
...
devise is setup and working fine but why I am getting 302 error in last two cases. Is it because I am not passing #user parameters to it? I did but it was still throwing the same error. I also checked out my routes file which is fine because post_controller is working fine in development mode.
What I am doing wrong here?
Edit-1
I tried to create test cases for create method
def setup
#user = users(:bob)
#p = posts(:one)
#post = Post.new
end
test 'should create post' do
sign_in #user
assert_difference('Post.count') do
post :create, post: { name: #p.name, value: #p.value}
end
end
I am getting ActionController::ParameterMissing: param is missing or the value is empty: post while in my controller class I do have
params.require(:post).permit(:name, :value, :user_id)
I also have all parameters in my .yml file i.e.
one:
name: 2
value: 3
It looks like you need to sign in before trying the index action. You're also testing the wrong instance variable name. You're testing #posts, but you've defined #post in the controller. Try this test instead:
test 'should get index' do
sign_in #user
get :index
assert_response :success
assert_not_nil assigns(:post)
end

ActionController::UnknownFormat: when using Rspec

I am creating a simple API to perform CRUD actions on contacts. :index, :show, :create and :update methods are working properly and they all pass their respective request rspec tests. The problem only arise in the :destroy method. The :destroy action looks like this:
class Api::V1::ContactsController < ApplicationController
def destroy
#contact = Contact.find(params[:id])
#contact.destroy
respond_to do |format|
format.json {render action: :index }
end
end
end
The spec to test DELETE request looks like this:
describe "DELETE /api/v1/contacts/:id" do
before(:each) do
#contact = FactoryGirl.create(:contact)
end
it "it should have a status code of 200" do
delete "/api/v1/contacts/#{#contact.id}"
expect(response.status).to eq(200)
end
it "It should delete a contact" do
expect{
delete "/api/v1/contacts/#{#contact.id}"
}.to change(Contact, :count).by(-1)
end
end
when i run the test i get this error message:
Failure/Error: delete "/api/v1/contacts/#{#contact.id}"
ActionController::UnknownFormat:
ActionController::UnknownFormat
# ./app/controllers/api/v1/contacts_controller.rb:67:in `destroy'
respond_to do |format| is line 67 in contacts_controller.rb
Try changing the format of your request to JSON, i.e. replace
delete "/api/v1/contacts/#{#contact.id}"
by
delete "/api/v1/contacts/#{#contact.id}.json"
that would allow the format logic to figure out that you want the reply rendered in JSON which it knows about.

Rspec POST controller create test fails but web based submission works

I have the following rspec test for create method in my
describe "with valid information" do
it "should respond with success" do
post 'create', :show_secretary_id => #show_secretary.id, :show => #show
response.should be_success
end
it "should incremenet the show count" do
expect do
post 'create', :show_secretary_id => #show_secretary.id, :show => #show
end.to change(Show,'count').by(1)
end
end
The test fails. However, when I try the create method in the browser, it works. Any ideas on what I am missing?
EDIT: My Controller Code
def create
#show_secretary = ShowSecretary.find_by_id(params[:show_secretary_id])
#show = #show_secretary.shows.build(params[:show])
if #show.save
flash[:notice] = "Successfully created show"
redirect_to show_path #show
else
render 'new'
end
end
EDIT: #show_secretary, #show
These two objects are ActiveRecords created and built by FactoryGirl respectively.
#show_secretary = FactoryGirl.create(:show_secretary_user).verifiable
#show = FactoryGirl.build(:show)
Replace
#show = FactoryGirl.build(:show)
with:
#show = FactoryGirl.attributes_for(:show)

testing "create" method in ruby with rspec

I have written this controller code in Ruby on Rails
class PostsController < ApplicationController
before_filter :authenticate_user!
def index
#posts = Post.all(:order => "created_at DESC")
respond_to do |format|
format.html
end
end
def create
#post = Post.create(:message => params[:message])
respond_to do |format|
if #post.save
format.html { redirect_to posts_path }
format.js
else
flash[:notice] = "Message failed to save."
format.html { redirect_to posts_path }
end
end
end
end
and corresponding to this I have written the following test case :-
require 'spec_helper'
describe PostsController do
describe "GET 'index'" do
it "returns http success" do
get 'index'
response.should be_success
end
end
describe "#create" do
it "creates a successful mesaage post" do
#post = Post.create(message: "Message")
#post.should be_an_instance_of Post
end
end
end
I am getting failures on both. Please take a look on the code and help me figure out.
I suspect you are not logged in since you are using Devise?
Maybe you need to include the devise testhelpers:
describe PostsController do
include Devise::TestHelpers
before(:each) do
#user = User.create(...)
sign_in #user
end
#assertions go here
end
As Tigraine states, it appears as though you probably are not logged in (with Devise) when the tests get executed. However, showing the failures would help in narrowing down the problem further.
On top of that, the second test isn't really an integration test and I would probably prefer something like the following to test the same condition. There are two types of test you could do:
# inside 'describe "#create"'
let(:valid_params) { {'post' => {'title' => 'Test Post'} }
it 'creates a new Post' do
expect {
post :create, valid_params
}.to change(Post, :count).by(1)
end
# and / or
it 'assigns a new Post' do
post :create, valid_params
assigns(:post).should be_a(Post)
assigns(:post).should be_persisted
end
Don't forget to add this line into your spec_helper.rb
require "devise/test_helpers"
include Devise::TestHelpers
Nevertheless, here is link for Devise wiki - How to test Controllers where you can find more info about this approach. I recommend writing the before method without (:each), what I remember it sometimes causes problems.
before do
#user = FactoryGirl.create(:user)
sign_in #user
end
Can always use:
puts response.inspect
To see how your response looks like.

Rspec testing templates being rendered

Im trying to test a condition where on successful signup a Success Template is rendered by the following controller code
def create
#user = User.new(params[:user])
if #user.save
render :template => "success"
else
flash[:notice] = "Oops Somethings not quite right! :("
render :action => "new"
end
end
I am using the following spec to test out this code
before(:each) do
#user = User.new
#user.attributes = valid_attributes
#params = valid_attributes
#user.stub!(:save).and_return(true)
end
def do_post
post :create
end
it "should create new user " do
count = User.count
do_post
user = User.new(#params)
user.save.should eql(true)
User.count.should eql(count + 1)
end
it "should render the success page on successful signup" do
do_post
#user.save
response.should render_template("success") if #user.save
end
But the example fails "it should render success page on successful signup" with this error message
1)
'UsersController handling POST /users should render the success page on successful signup' FAILED
expected "success", got "users/new.html.erb"
./spec/controllers/users_controller_spec.rb:67:
The success view is an template stored in the views/users/ without an action. Im guessing im making a very fundamental mistake and would like some help .
You are stubbing the #user variable in the test, but the controller will instantiate a new instance so the stub won't be in place.
It's not a good idea to use a stub in this case just to emulate a successful save call. Why don't you supply valid data instead and make sure the action is successful?
The following code is for RSpec > 2.1 and it uses the expect syntax.
before(:each) do
#params = valid_attributes
end
it "should create new user" do
#_before = User.count
post :create, :user => #params
expect(assigns(:user)).to_not be_new_record
expect(User.count).to eq(#_before + 1)
end
it "should render the success page on successful signup" do
post :create, :user => #params
expect(response).to be_successful
expect(response).to render_template("success")
end
Finally, change
render :template => "success"
to
render :action => "success"
For previous RSpec versions or if you have to use the should syntax, use
before(:each) do
#params = valid_attributes
end
it "should create new user" do
#_before = User.count
post :create, :user => #params
assigns(:user).should_not be_new_record
User.count.should == (#_before + 1)
end
it "should render the success page on successful signup" do
post :create, :user => #params
response.should be_successful
response.should render_template("success")
end

Resources