RSpec and weird tests results - ruby-on-rails-3

I'm trying to make a simple app. When Im testing it in browser everytyhing works just fine. Howerver, when I try to run some tests with RSpec (2.5) it fails when it comes to :create test for controller.
Here's my create method:
def create
#website = Website.new(params[:website])
if #website.save
flash[:notice] = "Website created."
redirect_to(:action => 'list')
else
render('new')
end
end
The controller test:
describe WebsitesController do
render_views
.
.
.
describe "POST 'create'" do
before(:each) do
#attr = { :adres => "www.excc.pl", :opis => "aaa "*22, :tagi => "aaa aaa aaa",
:preview => File.new(Rails.root + 'spec/fixtures/rails.png'),
:preview_mini => File.new(Rails.root + 'spec/fixtures/rails.png')}
end
describe "success" do
it "should have the right title" do
response.should have_selector("title", :content=>"Lista witryn w portfolio")
end
end
.
.
.
The result of this test:
1) WebsitesController POST 'create' should have the right title
Failure/Error: response.should have_selector("title", :content=>"Lista witryn w portfolio")
expected following output to contain a <title>Lista witryn w portfolio</title> tag:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# ./spec/controllers/websites_controller_spec.rb:34:in `block (4 levels) in
websites_controller_spec.rb:34 refers to create method
However, this test is passed correctly (for incorrect data it should be redirected back to 'new' site with specified title):
it "should have the right title" do
post :create, :website => #attr.merge(:adres => "")
response.should have_selector("title", :content=>"Dodaj stronÄ™ WWW")
end
The second problem is...
There was a time when I've got a test result like this:
<html><body>You are being redire cted.</body></html>
... which was causing me to pull my hair out for some time until I've done sth (I don't really know what) and it was gone. Yet, it makes me scared like hell when I think that it can come back in future an ruin my happiness.
Any thoughts on this would be greatly appreciated.

It's hard to know what is being asked here, but I believe the issue is that you are not setting the conditions for success/failure. If I understand correctly, when you pass in an blank :adres attribute, the save should fail and the page should render the list action. So you want to stub the create method and return true or false depending on the expected result:
it "succeeds" do
#website = mock_model(Website,:save=>true)
Website.stub(:new) { #website }
post :create, :website => {}
# redirects
response.should have_selector("etc etc")
end
it "fails" do
#website = mock_model(Website,:save=>false)
Website.stub(:new) { #website }
post :create, :website => {}
# renders 'new'
response.should_not have_selector("etc etc")
end
Testing of the validity of the parameters should be performed in the model spec:
#website = Website.new(:adres=>"")
#website.should_not be_valid

Related

Rspec testing in rails3

I have a Queues controller and and QueueItems controller in my rails
application. In routes I have defined as below
match 'queues/:queue_id/next', :to=> 'queueitems#next'
In my QueueItems Controller I have a next action and it assigns an
instance variable.
def next
#queue = "Regular"
#other stuffs related to regular
end
How do I test this in Rspec. I am pretty very new to Rspec. Please help.
I tried like the below
describe QueuesController do
describe "next " do
it "routes /queues/:queue_id/next" do
{ :get => "/queues/regular_queue/next" }.should route_to(
:controller => "queue_items",
:action => "next",
:queue_id => "regular_queue",
:format => "json"
)
assigns(:queue).should_not be_nil
expect(response).to be_success
end
end
But it is not at all coming inside my next action in controller.
Update #2
spec/controllers/queue_items_controller_spec.rb
require 'spec_helper'
describe QueueItemsController do
describe 'GET next' do
it 'assigns #queue' do
get :next, format: :json
expect(assigns[:queue]).to eq('regular')
end
end
end
queue_items_controller.rb
def next
puts "Inside next action..."
#queue = "regular"
end
routes.rb
get '/queues/:queue_id/next', :to => 'queue_items#next', :format=>'json'
rake routes
GET /queues/:queue_id/next(.:format) queue_items#next {:format=>"json"}
/queues/:queue_id/delete(.:format) queue_items#delete {:method=>:delete, :format=>"json"}
/queues/:queue_id/clear(.:format) queue_items#clear {:format=>"json"}
First of all change match to get or post - it is better to use exactly verb. Let's say it is get.
Action next is in QueueItemsController so test should be in this queue_items_controller_spec.rb file (and in folder spec/controlers).
and test might be similar to
describe QueueItemsController do
describe "GET next " do
it "responses json" do
get :next, format: :json
expect(response).to be_success
end
it "does not response html" do
get :next, format: :html
expect(response).not_to be_success # or define more exactly response
end
it 'assigns #queue' do
get :next, format: :json
expect(assigns[:queue]).to eq('Regular')
end
end
end
if you would like to test your routes you should follow this articles:
https://www.relishapp.com/rspec/rspec-rails/v/2-14/docs/routing-specs
https://www.relishapp.com/rspec/rspec-rails/docs/routing-specs/route-to-matcher

Stubbing out save methodin rails with rspec

I have the following action in my controller:
def create
#user = current_user
#vin = #user.vins.new(params[:vin])
if #vin.save
# waiting for implementation
logger.debug("here we are")
else
redirect_to(vins_path)
end
end
I'd like to test with with rspec. However, I want to stub out the save operation to simulate a failure:
it "should send user to vins_path if there is a problem creating the VIN" do
#vin.stub!(:save).and_return(false)
post 'create', :vin => { :name => "Test 1", :vin => "test" }
response.should redirect_to(vins_path)
end
However, the stub doesn't seem to work as the save operation is always successful. What am I doing wrong?
Thanks
Try this:
Vin.any_instance.stub(:save).and_return(false)

Rails testing, how to specify path for post? (No route matches error)

I try to test one of my REST api controllers which is placed at "controllers/api/v1/bookings_controller.rb". The controller only responds_to json at the moment as you can see here:
class Api::V1::BookingsController < ApplicationController
respond_to :json
before_filter :authenticate_user!
before_filter :get_user
def create
...
end
end
My functional test is located at "test/functional/api/v1/bookings_controller_test.rb" and looks like following:
require 'test_helper'
class Api::V1::BookingsControllerTest < ActionController::TestCase
include Devise::TestHelpers
setup do
#booking = bookings(:one)
#user = users(:one)
sign_in #user
end
test "should return a bad request" do
post :create, :booking => { }, :format => 'json'
assert_response :bad_request
end
end
The post path for creating a booking looks like this (and works, tested with HTTP Client):
api_v1_user_bookings
GET /api/v1/users/:user_id/bookings(.:format) api/v1/bookings#index
POST /api/v1/users/:user_id/bookings(.:format) api/v1/bookings#create
However when I run the test it seems that it uses some default route (see error message below), how can i specify the correct route in my test? Or is there some other mistake I do not see here?
test_should_return_a_bad_request(Api::V1::BookingsControllerTest):
ActionController::RoutingError: No route matches {:booking=>{}, :format=>"js
on", :controller=>"api/v1/bookings", :action=>"create"}
Your route expects a user_id parameter. Add it to your post:
post :create, :user_id => #user.id, :booking => {}, :format => :json
Ok, I think I figured it out now. I just had to add the user-id, otherwise it seems that rails does not select the right route. So the correct test method looks like this:
test "should return a bad request" do
post :create, :user_id => #user.id, :booking => { }, :format => 'json'
assert_response :bad_request
end

Testing Nested Resources Controller with RSpec - count doesn't change by 1

I have nested resources:
resources :portfolios do
resources :asset_actions
end
And following RSpec Controller: asset_actions_controller_spec.rb
before(:each) do
#portfolio = Factory(:portfolio)
end
describe "POST create" do
describe "with valid params" do
it "creates a new AssetAction" do
expect {
post :create, :asset_action => valid_attributes, :portfolio_id => #portfolio.id
##portfolio.asset_actions.create! valid_attributes #WORKS correctly, but this is Model
}.to change(#portfolio.asset_actions, :count).by(1)
end
end
end
While running Spec I got the following error:
Failure/Error: expect {
count should have been changed by 1, but was changed by 0
I can't find the reason for this failure. Any suggestions?
Notes: Rails 3.1.3, Ruby 1.9.3p5, RSpec 2.8.0
I think the problem is that #portfolio hasn't changed because it is a local variable. It's stored in memory and you've made changes to the database. So, you need to reload #portfolio to see it change. Try something like this:
describe "POST create" do
describe "with valid params" do
it "creates a new AssetAction" do
post :create, :asset_action => valid_attributes, :portfolio_id => #portfolio.id
expect { #portfolio.reload }.to change(#portfolio.asset_actions, :count).by(1)
end
end
end

I am having trouble testing my controller's update action using Rspec, what am I doing wrong?

I am trying to test the failing branch of the update action on my controller but I am having trouble with the test. This is what I have and it fails on the last
describe "PUT 'article/:id'" do
.
.
.
describe "with invalid params" do
it "should find the article and return the object" do
Article.stub(:find).with("1").and_return(#article)
end
it "should update the article with new attributes" do
Article.stub(:update_attributes).and_return(false)
end
it "should render the edit form" do
response.should render_template("edit")
end
end
end
Any ideas as to why the last part fails to render the template?
You're splitting up the parts of your test incorrectly. Each it call is actually a new example and the state is reset before/after each one.
What you should be doing is:
describe "with invalid params" do
before do
#article = Article.create(valid_params_go_here)
end
it "should find the article and return the object" do
put :update, { :id => #article.id, :article => { :title => "" } }
response.should render_template("edit")
end
end
By doing it this way, the #article is set up before hand (although you could use a mock one if you really wanted to) and the request to the update action and the assertion that it actually renders the edit template all happen in the one example.
For people who are coming here in 2018, some updates(pun not intended) have been made. It's important to include "params" before listing the params. Additionally, you should use expect and not "should" since it will be deprecated in Rails 6.0.
describe "with invalid params" do
before(:each) do
#article = Article.create(valid_params_go_here)
end
describe "PATCH update/:id" do
it "should find the article and return the object" do
put :update, params: { id: #article.id, article: { title: "" } }
expect(response).to be_redirect
end
end