I've got the following Rspec tests that test whether a user can successfully update a scavenger hunt. I know the site will let the user do this, but my problem is that my tests aren't capturing that. Each time I run rspec, all the tests below fail. I'm hoping there's just one simple thing that I'm forgetting to put in there, but my eyes are bleary all the code's running together. When you look at these tests, does anything strike you as obviously wrong?
describe "PUT 'update'"
before(:each) do
#hunt = FactoryGirl.create(:hunt)
end
....
describe "as an admin user" do
before(:each) do
admin = FactoryGirl.create(:user, :email => "admin#example.com", :admin => true)
test_sign_in(admin)
end
....
describe "success" do
before(:each) do
#attr = { :name => "New Hunt" }
end
it "returns http success" do
get 'edit', :id => #hunt
response.should be_success
end
it "should change the hunt's name" do
put :update, :id => #hunt, :name => #attr
#hunt.reload
#hunt.name.should == #attr[:name]
end
it "should redirect to the hunt show page" do
put :update, :id => #hunt
response.should redirect_to(#hunt)
end
it "should have a flash message" do
put :update, :id => #hunt, :user => #attr
flash[:success].should =~ /updated/
end
end
...
end
Here's code from my controller.
def edit
#hunt = Hunt.find(params[:id])
#title = "Edit hunt"
end
def update
#hunt = Hunt.find(params[:id])
if #hunt.update_attributes(params[:hunt])
flash[:success] = "Hunt updated."
redirect_to hunts_path
else
#title = "Edit Hunt"
render 'edit'
end
end
And here's the feedback I'm getting form Rspec. It's all across the boards, but I'm hoping it's caused by a single problem and not four individual ones.
1) HuntsController PUT 'update' as an admin user failure should render the 'edit' page
Failure/Error: response.should render_template('edit')
expecting <"edit"> but rendering with <"">
# ./spec/controllers/hunts_controller_spec.rb:220:in `block (5 levels) in <top (required)>'
2) HuntsController PUT 'update' as an admin user failure should have the right title
Failure/Error: response.should have_selector("title", :content => "Edit hunt")
expected following output to contain a <title>Edit hunt</title> tag:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body>You are being redirected.</body></html>
# ./spec/controllers/hunts_controller_spec.rb:226:in `block (5 levels) in <top (required)>'
3) HuntsController PUT 'update' as an admin user success should change the hunt's name
Failure/Error: #hunt.name.should == #attr[:name]
expected: "New Hunt"
got: "Hunt 9" (using ==)
# ./spec/controllers/hunts_controller_spec.rb:244:in `block (5 levels) in <top (required)>'
4) HuntsController PUT 'update' as an admin user success should redirect to the hunt show page
Failure/Error: response.should redirect_to(#hunt)
Expected response to be a redirect to <http://test.host/hunts/649> but was a redirect to <http://test.host/hunts>
# ./spec/controllers/hunts_controller_spec.rb:249:in `block (5 levels) in <top (required)>'
Related
I'm trying to create a controller spec for a contact form. All I want is to test that the :new template is rendered when invalid attributes are submitted. I've tried various configurations of the factory, as well as changing it to a trait, instead of factory to no avail. The error message doesn't get very specific, just Invalid Factory. Any ideas would be appreciated!
# blog_app/spec/factories/inquiries.rb
FactoryGirl.define do
factory :inquiry do
name "TestName"
email "test#test.com"
phone "123-456-7890"
message "TestMessage"
end
factory :invalid_inquiry, parent: :inquiry do
name nil
end
end
#/app/controllers/inquiries_controller.rb
class InquiriesController < ApplicationController
def new
#inquiry = Inquiry.new
end
def create
#inquiry = Inquiry.new(params[:inquiry])
if #inquiry.deliver
render :thank_you
else
render :new
end
end
end
# spec/controllers/inquiries_controller_spec.rb
require 'spec_helper'
describe InquiriesController do
it "has a valid factory" do
FactoryGirl.build(:inquiry).should be_valid
end
describe "POST #create" do
context "with valid attributes" do
it "delivers inquiry" #pending
it "renders the :thank_you page template" do
post :create, inquiry: FactoryGirl.attributes_for(:inquiry)
response.should render_template :thank_you
end
end
context "with invalid attributes" do
it "does not deliver inquiry" do #pending
it "renders :new page template" do
post :create, inquiry: FactoryGirl.attributes_for(:invalid_inquiry)
response.should render_template :new
end
end
end
describe "GET #new" do
it "renders :new page template" do
get :new
response.should render_template :new
end
end
end
Finished in 0.31244 seconds
0 examples, 0 failures
/Users/.../.rvm/gems/ruby-2.0.0-p353/gems/factory_girl-4.4.0/lib/factory_girl.rb:73:in `lint': The following factories are invalid: (FactoryGirl::InvalidFactoryError)
* invalid_inquiry
from /Users/.../Documents/blog_app/spec/support/factory_girl.rb:8:in `block (2 levels) in <top (required)>'
from /Users/.../.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.13.1/lib/rspec/core/hooks.rb:21:in `instance_eval'
from /Users/.../.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.13.1/lib/rspec/core/hooks.rb:21:in `run'
from /Users/.../.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.13.1/lib/rspec/core/hooks.rb:66:in `block in run'
from /Users/.../.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.13.1/lib/rspec/core/hooks.rb:66:in `each'
from /Users/.../.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.13.1/lib/rspec/core/hooks.rb:66:in `run'
from /Users/.../.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.13.1/lib/rspec/core/hooks.rb:418:in `run_hook'
from /Users/.../.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.13.1/lib/rspec/core/command_line.rb:27:in `block in run'
from /Users/.../.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.13.1/lib/rspec/core/reporter.rb:34:in `report'
from /Users/.../.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.13.1/lib/rspec/core/command_line.rb:25:in `run'
from /Users/.../.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.13.1/lib/rspec/core/runner.rb:80:in `run'
from /Users/.../.rvm/gems/ruby-2.0.0-p353/gems/rspec-core-2.13.1/lib/rspec/core/runner.rb:17:in `block in autorun'
Does this work?
FactoryGirl.define do
factory :inquiry do
name "TestName"
email "test#test.com"
phone "123-456-7890"
message "TestMessage"
factory :invalid_inquiry do
name nil
end
end
end
Alternatively you might try replacing:
post :create, inquiry: FactoryGirl.attributes_for(:invalid_inquiry)
with:
post :create, inquiry: FactoryGirl.attributes_for(:inquiry, name: nil)
and getting rid of the invalid_inquiry factory altogether.
I am following Michael Hartl's tutorial, and trying to implement the reply twitter-like functionality, ie. "#122-john-smith: hello there" should be a reply to user 122.
I first tried filtering the "#XXX-AAA-AAA" part using a before_filter, but I decided to try it first in the very same Micropost#create action. So far I've got this MicropostController:
class MicropostsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
before_filter :correct_user, only: [:destroy]
#before_filter :reply_to_user, only: [:create]
def index
end
def create
#micropost=current_user.microposts.build(params[:micropost])
#Rails.logger.info "hoooola"
regex=/\A#(\d)+(\w|\-|\.)+/i
message=#micropost.content.dup
isResponse=message.match(regex)[0].match(/\d+/)[0]
#micropost.response=isResponse
if #micropost.save
flash[:success]="Micropost created!"
redirect_to root_path
else
#feed_items=[]
render 'static_pages/home'
end
end
def destroy
#micropost.destroy
redirect_to root_path
end
private
def correct_user
#micropost = current_user.microposts.find_by_id(params[:id])
redirect_to root_path if #micropost.nil?
end
def reply_to_user
regex=/\A#(\d)+(\w|\-|\.)+/i
#I use [0] cause the output of match is a MatchData class with lots of bs
mtch=params[:micropost][:content].match(regex)[0]
#puts mtch
##micropost=current_user.microposts.build(params[:micropost])
if mtch != nil
user_id=mtch.match(/\d+/)[0]
#replied_user=User.find(user_id)
#micropost.response=user_id unless #replied_user.nil?
end
end
end
And this is the snippet test I'm trying to pass:
require 'spec_helper'
describe "MicropostPages" do
subject { page }
let(:user) { FactoryGirl.create(:user) }
before { valid_signin user }
describe "micropost creation" do
before { visit root_path }
describe "with invalid information" do
it "should not create a micropost" do
expect { click_button "Post" }.should_not change(Micropost,
:count)
end
describe "error messages" do
before { click_button "Post" }
it { should have_content('error') }
end
end
describe "with valid information" do
before { fill_in 'micropost_content', with: "Lorem ipsum" }
it "should create a micropost" do
expect { click_button "Post" }.should change(Micropost,
:count).by(1)
end
end
end
...
end
If I run these tests I get the follwing error:
Failures:
1) MicropostPages micropost creation with invalid information should not create a micropost
Failure/Error: expect { click_button "Post" }.should_not change(Micropost, :count)
NoMethodError:
undefined method `[]' for nil:NilClass
# ./app/controllers/microposts_controller.rb:14:in `create'
# (eval):2:in `click_button'
# ./spec/requests/micropost_pages_spec.rb:11:in `block (5 levels) in <top (required)>'
# ./spec/requests/micropost_pages_spec.rb:11:in `block (4 levels) in <top (required)>'
2) MicropostPages micropost creation with invalid information error messages
Failure/Error: before { click_button "Post" }
NoMethodError:
undefined method `[]' for nil:NilClass
# ./app/controllers/microposts_controller.rb:14:in `create'
# (eval):2:in `click_button'
# ./spec/requests/micropost_pages_spec.rb:14:in `block (5 levels) in <top (required)>'
However if I modify the tests and comment out all the #XXX filtering in the Micropost#create action:
def create
#micropost=current_user.microposts.build(params[:micropost])
#Rails.logger.info "hoooola"
#regex=/\A#(\d)+(\w|\-|\.)+/i
#message=#micropost.content.dup
#isResponse=message.match(regex)[0].match(/\d+/)[0]
##micropost.response=isResponse
if #micropost.save
flash[:success]="Micropost created!"
redirect_to root_path
else
#feed_items=[]
render 'static_pages/home'
end
end
The tests pass just fine and the new Micropost is not a Nil object.
It can't seem to find an explanation here.
The error comes from this line:
isResponse=message.match(regex)[0].match(/\d+/)[0]
Check if your two match calls actually match correctly. If the pattern is not found in your string, nil is returned and the [0] call is made on nil. There's two instances in this line alone where this could happen.
Try to spread it out over several lines and check the return values of your matches or extend your Regex to properly check the pattern in one go.
I'm just starting to use RSpec with a new project (after being a minitest user for a while). I've created a single MVC, called contracts. Here is the model file:
class Contract < ActiveRecord::Base
attr_accessible :name, :number, :plannedStart, :actualStart, :plannedCompletion, :actualCompletion
end
I've got a basic factory defined for Contracts (it was slightly more complex earlier, using sequence to generate novel names and numbers, but I removed all of that to try to simplify squashing this bug):
FactoryGirl.define do
factory :contract do
end
end
Here are the specs (pretty much auto generated, except I added in the calls to the factory):
require File.dirname(__FILE__) + '/../spec_helper'
describe ContractsController do
render_views
it "index action should render index template" do
create(:contract)
get :index
response.should render_template(:index)
end
it "show action should render show template" do
create(:contract)
get :show, :id => Contract.first
response.should render_template(:show)
end
it "new action should render new template" do
get :new
response.should render_template(:new)
end
it "create action should render new template when model is invalid" do
Contract.any_instance.stubs(:valid?).returns(false)
post :create
response.should render_template(:new)
end
it "create action should redirect when model is valid" do
Contract.any_instance.stubs(:valid?).returns(true)
post :create
response.should redirect_to(contract_url(assigns[:contract]))
end
it "edit action should render edit template" do
create(:contract)
get :edit, :id => Contract.first
response.should render_template(:edit)
end
it "update action should render edit template when model is invalid" do
create(:contract)
Contract.any_instance.stubs(:valid?).returns(false)
put :update, :id => Contract.first
response.should render_template(:edit)
end
it "update action should redirect when model is valid" do
create(:contract)
create(:contract)
Contract.any_instance.stubs(:valid?).returns(true)
put :update, :id => Contract.first
response.should redirect_to(contract_url(assigns[:contract]))
end
it "destroy action should destroy model and redirect to index action" do
create(:contract)
contract = Contract.first
delete :destroy, :id => contract
response.should redirect_to(contracts_url)
Contract.exists?(contract.id).should be_false
end
end
When I run the spec, I get the following error message, but the number of these I get varies from run to run:
ActiveRecord::RecordInvalid: Validation failed:
./spec/controllers/contracts_controller_spec.rb:39:in `block (2 levels) in <top (required)>'
ActiveRecord::RecordInvalid: Validation failed:
./spec/controllers/contracts_controller_spec.rb:45:in `block (2 levels) in <top (required)>'
ActiveRecord::RecordInvalid: Validation failed:
./spec/controllers/contracts_controller_spec.rb:7:in `block (2 levels) in <top (required)>'
10 examples, 3 failures, 7 passed
Finished in 0.360139 seconds
/Users/jlee/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec ./spec/controllers/contracts_controller_spec.rb ./spec/models/contract_spec.rb failed
I've implemented Databasecleaner just to make sure this wasn't some odd behavior problem relating to using transactions during testing, but to no avail. Suggestions? I have no validations defined, so its hard to understand how I could be failing validation.
The stub for :valid? hangs around between tests, so I put the following in the before(:each) block: Contract.any_instance.unstub(:valid?), and it cleared everything up.
I have this projects controller brief action.
projects_controller.rb
def brief
##project before_filter_da ataniyor
if #project.user_allowed_to_view_brief?(current_user)
#brief_notes = #project.brief_notes.order(:id)
#project_files = #project.project_files
render :action => :written_brief if #project.project_type.brief_template == :written
else
render :action => :hidden_brief
end
end
And this is my projects_controller_spec.rb file
context 'get :brief' do
it 'should be loaded successfully' do
sign_in #creative
#project.stub(:user_allowed_to_view_brief?).with(#creative).and_return(false)
get :brief, :id => #project.to_param
response.should render_template("hidden_gallery")
end
end
and When I run this test, I encounter the error like that.
Failure/Error: response.should have_rendered("hidden_gallery")
expecting <"hidden_gallery"> but rendering with <"shared/_project_title, shared/_project_header, shared/_project_buttons, shared/_messages, projects/_brief, projects/brief, shared/_header, shared/_footer, layouts/application">
# ./spec/controllers/projects_controller_spec.rb:63:in `block (3 levels) in <top (required)>'
I think that the last line of your spec should instead read:
response.should render_template("hidden_brief")
I'm on section 10.3.1 "User Index" of Ruby on Rails 3 Tutorial. I have one test that refuses to pass and I have researched the error extensively and can't seem to get it to pass.
Here is the error:
1) UsersController GET 'index' for signed-in users should have an element for each user
Failure/Error: response.should have_selector("li", :content => user.name)
NoMethodError:
undefined method name' for nil:NilClass
# ./spec/controllers/users_controller_spec.rb:39:inblock (5 levels) in '
# ./spec/controllers/users_controller_spec.rb:38:in each'
# ./spec/controllers/users_controller_spec.rb:38:inblock (4 levels) in '
I have tried a test to ensure that the user is returning an object instead of an array...it is. I have checked my sign_in and test_sign_in methods. I can probably move on, but fails tests drive me crazy.
Here is my users_controller_spec.rb code:
describe "for signed-in users" do
before(:each) do
#user = test_sign_in(Factory(:user))
second = Factory(:user, :name => "Bob", :email => "another#example.com")
third = Factory(:user, :name => "Ben", :email => "another#example.net")
#users = [#users, second, third]
end
it "should be successful" do
get :index
response.should be_success
end
it "should have the right title" do
get :index
response.should have_selector("title", :content => "All users")
end
it "should have an element for each user" do
get :index
#users.each do |user|
response.should have_selector("li", :content => user.name)
end
end
end
end
Please help!!!
I actually just solved this. In my code for # users = [#user, second, third] I misspelled #user with # users