RSpec, wrong parametrs in method post - ruby-on-rails

I test password recovery, but there are errors.
Rspec study recently.
code (User Controller)
def forgot
if request.post?
user = User.find_by_email(params[:user][:email])
if user
user.create_reset_code
end
flash[:notice] = t('helpers.notice_email')
render :template => "sessions/new"
end
end
rspec test
it "POST 'reset page'" do
User.should_receive(:find_by_email).with({:email => #user.email})
post :forgot, :user => {"email" => #user.email}
end
What am I doing wrong in the test?

User.should_receive(:find_by_email).with(#user.email)

Related

Devise sign_in for api causing RSpec test to fail

I'm building an API using Rails and Devise. My sessions controller inherits from the following base controller
api/base_controller.rb
module Api
class BaseController < ApplicationController
skip_before_filter :verify_authenticity_token
before_filter :authenticate_user_from_token!
respond_to :json
private
def authenticate_user_from_token!
user_token = params[:auth_token].presence
user = user_token && User.find_by_authentication_token(user_token)
if user
sign_in user, store: false
else
render :json => {:success => false, :message => "Error with your credentials", :status => 401}
end
end
end
end
My sessions controller's destroy action below:
api/sessions_controller.rb
before_filter :authenticate_user_from_token!, :except => [:create]
def destroy
current_user.reset_authentication_token
render :json => {
:success => true,
:status => 200
}
end
This works perfectly when testing the api via curl. But, I can't get my Rspec tests for the destroy action to pass. From Rspec the sign_in user call is failing, so the response is a redirect. I haven't had any success trying to stub the sign_in method.
Rspec test:
describe "DELETE destroy" do
before(:each) do
#user1 = User.create!(:email => 'example#gmail.com', :password => 'helloworld', :password_confirmation => 'helloworld')
end
it "should render success json" do
delete :destroy, :auth_token => #user1.authentication_token
json = JSON.parse(response.body)
json.should include('success' => true, 'status' => 200)
end
###this fails because the response is a redirect to the sign_in page
end
How should I go about mocking the sign_in method called from within the base controller?
Add a spec/support/devise.rb file with this content:
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
end
Also, check in your test.log wether it's actually using the json format. I had a similar problem and found out that I had to force the format :json in my spec call parameters.
Andreamazz pointed me to the test.logs which revealed that the user I had created was confirmed (I'm using Devise confirmable). I use user.confirm! in the before(:each) and everything is passing.
describe "DELETE destroy" do
before(:each) do
#user1 = User.create!(:email => 'example#gmail.com', :password => 'helloworld', :password_confirmation => 'helloworld')
#user1.confirm!
end
it "should render success json" do
delete :destroy, :auth_token => #user1.authentication_token
json = JSON.parse(response.body)
json.should include('success' => true, 'status' => 200)
end
end
Thanks!

Integration test rails not working login

I have such tests:
class LockableFlowTest < ActionDispatch::IntegrationTest
context 'A user' do
setup do
#organization = Factory(:organization)
#user = Factory(:user, :organization => #organization)
end
should "login after 4 attempts" do
4.times do
post_via_redirect '/users/sign_in', 'user[username]' => #user.username, 'user[password]' => "bad_password"
assert_equal '/users/sign_in', path
assert_equal 'Invalid email or password.', flash[:alert]
end
post_via_redirect '/users/sign_in', 'user[username]' => #user.username, 'user[password]' => "password"
assert_equal "/registrations/#{#user.id}/edit", path
assert_nil flash[:alert]
end
It doesn't work but the application is okay. I would like to test attempts to login into the application. After 4 attempts it should be possible to login.
The code controller:
class SessionsController < Devise::SessionsController
after_filter :log_failed_login, :only => :new
private
def log_failed_login
if request.filtered_parameters["user"]
user = User.find_by_username(request.filtered_parameters["user"]["username"])
if user
if user.first_failed_attempt.nil?
user.first_failed_attempt = Time.now
else
if user.first_failed_attempt + 15.minutes <= Time.now
user.failed_attempts = 1
user.first_failed_attempt = Time.now
end
end
user.save
end
end
end
def failed_login?
(options = env["warden.options"]) && options[:action] == "unauthenticated"
end
end
What's the counting mechanism to let the application know that it already executed four tries?
Cookies? Cookies do not persist in Rspec on rails 3.1

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

An RSpec2 error by the biggest newb in New Jersey :( | factory_girl, authlogic, rails3

I'm writing an rspec scenario thats failing with:
(#<User:0x1056904f0>).update_attributes(#<RSpec::Mocks::ArgumentMatchers::AnyArgMatcher:0x105623648>)
expected: 1 time
received: 0 times
users_controller_spec.rb:
describe "Authenticated examples" do
before(:each) do
activate_authlogic
#user = Factory.create(:valid_user)
UserSession.create(#user)
end
describe "PUT update" do
it "updates the requested user" do
User.stub!(:current_user).and_return(#user)
#user.should_receive(:update_attributes).with(anything()).and_return(true)
put :update, :id => #user , :current_user => {'email' => 'Trippy'}
puts "Spec Object Id : " + "#{#user.object_id}"
end
users_controller.rb:
def update
#user = current_user
puts "Controller Object ID is : " + "#{#user.object_id}"
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to(root_url, :notice => 'Successfully updated profile.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
user.rb - factories
Factory.define :valid_user, :class => User do |u|
u.username "Trippy"
u.password "password"
u.password_confirmation "password"
u.email "elephant#gmail.com"
u.single_access_token "k3cFzLIQnZ4MHRmJvJzg"
u.id "37"
end
Authlogic's standard helper methods like current_user don't call User.find directly. I believe it does current_user_session.user, where current_user_session calls UserSession.find, so you're not calling User.find directly. You could do some fancy chain stubbing there, but my suggestion is just to add this to your controller spec instead of what you're currently stubbing:
stub!(:current_user).and_return(#user)
In RSpec2 you might have to do
controller.stub!(:current_user).and_return(#user)
Edit: This should be your whole spec file:
describe "Authenticated examples" do
before(:each) do
activate_authlogic
#user = Factory.create(:valid_user)
UserSession.create(#user)
end
describe "PUT update" do
describe "with valid params" do
it "updates the requested user" do
stub!(:current_user).and_return(#user)
#user.should_receive(:update_attributes).with(anything()).and_return(true)
put :update, :id => #user , :current_user => {'email' => 'Trippy'}
end
end
I think you're confusing stubs with message expectations. The line
User.should_receive(:find)
tells Rspec to expect the User model to receive a find message. Whereas:
User.stub!(:find)
replaces the find method so that the test can pass. In your example the thing you're testing is whether update_attributes is called successfully, so that ought to be where the message expectation goes, and the job of all the other testing code is just to set up the prerequisites.
Try replacing that line with:
User.stub!(:find).and_return(#user)
Note that find returns the object, not just its id. Also, note that stubbing out find here serves only to speed things up. As written the example gets through should_receive(:find) successfully, and that is happening because you're using Factories to create users in the test database. You could take the stub out and the test should still work, but at the cost of hitting the database.
Another tip: if you're trying to figure out why a controller test isn't working, sometimes it's helpful to know if it is being blocked by before filters. You can check for this with:
controller.should_receive(:update)
If that fails, the update action is not being reached, probably because a before filter has redirected the request.

Stubbing a before_filter with RSpec

I'm having trouble understanding why I can't seem to stub this controller method :load_user, since all of my tests fail if I change the actual implementation of :load_user to not return and instance of #user.
Can anybody see why my stub (controller.stub!(:load_user).and_return(#user)) seems to fail to actually get called when RSpec makes a request to the controller?
require 'spec_helper'
describe TasksController do
before(:each) do
#user = Factory(:user)
sign_in #user
#task = Factory(:task)
User.stub_chain(:where, :first).and_return(#user)
controller.stub!(:load_user).and_return(#user)
end
#GET Index
describe "GET Index" do
before(:each) do
#tasks = 7.times{Factory(:task, :user => #user)}
#user.stub!(:tasks).and_return(#tasks)
end
it "should should find all of the tasks owned by a user" do
#user.should_receive(:tasks).and_return(#tasks)
get :index, :user_id => #user.id
end
it "should assign all of the user's tasks to the view" do
get :index, :user_id => #user.id
assigns[:tasks].should be(#tasks)
end
end
#GET New
describe "GET New" do
before(:each) do
#user.stub_chain(:tasks, :new).and_return(#task)
end
it "should return a new Task" do
#user.tasks.should_receive(:new).and_return(#task)
get :new, :user_id => #user.id
end
end
#POST Create
describe "POST Create" do
before(:each) do
#user.stub_chain(:tasks, :new).and_return(#task)
end
it "should create a new task" do
#user.tasks.should_receive(:new).and_return(#task)
post :create, :user_id => #user.id, :task => #task.to_s
end
it "saves the task" do
#task.should_receive(:save)
post :create, :user_id => #user.id, :task => #task
end
context "when the task is saved successfully" do
before(:each) do
#task.stub!(:save).and_return(true)
end
it "should set the flash[:notice] message to 'Task Added Successfully'"do
post :create, :user_id => #user.id, :task => #task
flash[:notice].should == "Task Added Successfully!"
end
it "should redirect to the user's task page" do
post :create, :user_id => #user.id, :task => #task
response.should redirect_to(user_tasks_path(#user.id))
end
end
context "when the task isn't saved successfully" do
before(:each) do
#task.stub(:save).and_return(false)
end
it "should return to the 'Create New Task' page do" do
post :create, :user_id => #user.id, :task => #task
response.should render_template('new')
end
end
end
it "should attempt to authenticate and load the user who owns the tasks" do
context "when the tasks belong to the currently logged in user" do
it "should set the user instance variable to the currently logged in user" do
pending
end
end
context "when the tasks belong to another user" do
it "should set the flash[:notice] to 'Sorry but you can't view other people's tasks.'" do
pending
end
it "should redirect to the home page" do
pending
end
end
end
end
class TasksController < ApplicationController
before_filter :load_user
def index
#tasks = #user.tasks
end
def new
#task = #user.tasks.new
end
def create
#task = #user.tasks.new
if #task.save
flash[:notice] = "Task Added Successfully!"
redirect_to user_tasks_path(#user.id)
else
render :action => 'new'
end
end
private
def load_user
if current_user.id == params[:user_id].to_i
#user = User.where(:id => params[:user_id]).first
else
flash[:notice] = "Sorry but you can't view other people's tasks."
redirect_to root_path
end
end
end
Can anybody see why my stub doesn't work? Like I said, my tests only pass if I make sure that load_user works, if not, all my tests fail which makes my think that RSpec isn't using the stub I created.
Stubbing out load_user breaks your tests because stubbing the method neuters it. When the controller calls load_user, it is no longer running your original code. It's now just returning whatever you specify in and_return(...) (which is getting returned to the ActionController callback stack, which ignores anything other than false).
Your controller code isn't using the return value of that method; it's using the variable instantiated within it. Since the original code for the load_user method isn't being run, the #user instance variable is never instantiated. (The #user variable in your tests is only visible to your tests.)
But with all the other stubs you have, I don't see any reason why you should need to stub out load_user at all. As long as you're stubbing current_user to return #user (which I assume is being done in the sign_in method), then there shouldn't be any need.
you can also try to verify that the stub works by doing an assertion like
controller.current_user.should == #user

Resources