How to write rspec test cases to cover failure of object save - ruby-on-rails-4

I have following code
#support_report.notes = params[:support_report][:notes]
if #support_report.save
redirect_to admins_support_reports_path, notice: t('admins.support_reports.add_notes.successfully')
else
redirect_to admins_support_reports_path, alert: t('admins.support_reports.add_notes.no_change')
end
In this am just updating 'notes' attribute which is not having any validation.
I have to cover 'else' part inside rspec coverage.
How can I do it, please suggest some way

it "should re-render new template on failed save" do
SupportReport.any_instance.stubs(:valid?).returns(false)
post 'create'
assigns[:support_report].should be_new_record
response.should render_template('new')
end

Related

custom message for rails 4 sorcery brute force protection sub-module

I'm using the sorcery gem brute force protection sub-module in my rails app. When the user has exceeded the allowed number of attempts to sign in, I'd like to provide a custom message. I haven't been able to find anything in the documentation or online that allows the messages to be configured.
Here's how I handled it - not sure its the best way so any comments welcome.
sessions_controller.rb
def create
if login(params[:email], params[:password])
redirect_to preorders_by_campaign_path
else
if is_locked?
flash[:warning] = "my custom message"
else
flash[:warning] = "Invalid email or password"
end
render :new
end
end
def is_locked?
User.where(email: params[:email]).first.locked?
end

UnknownFormat in rails spec

I'm fairly new to rails and I'm trying to return a javascript file from a controller action. In TDD fashion I'm trying to write a failing test first and although I've fixed a bunch of reasons it's failed since starting, I'm now up against an error that I'm not sure how to fix. If I run it in a browser, it works. But running the spec I get an error "ActionController::UnknownFormat" pointing to the respond_to do |format| line.
Here's the controller action...
def job_board
respond_to do |format|
format.js
end
end
And my spec
require 'rails_helper'
RSpec.describe ApiController, :type => :controller do
describe "when using an invalid url/api key" do
it "should return error" do
get :job_board
expect(response).to have_http_status(400) #bad request
end
end
end
And finally my routes.
Rails.application.routes.draw do
get 'api/job_board' => 'api#job_board', defaults: { format: 'js'}
end
Any idea why the spec is throwing this error? Thanks.
Got it figured out. I had to change the
get :job_board
in the spec to
get :job_board, format: :js

undefined method `model_name' for #<User:XXXXXXXX>

I have a dashboard containing 2 partials. One partial works fine and does what its suppose to (bill). The other partial is setup similar to bill but wont work(request). When I look at my log it shows that the tenant(user) is being queried, also, the 1st partial is queried but the 2nd partial doesn't query. when I went to my dashboard controller and changed the instance of the partial to (Request.new) it works but I can't seem to get it to work right thru the controller. I don't want to have the method in the model. I am using mongoid.
SO here is my render in the dashboard...
<%= render partial: "request", locals: {request: #request} %>
In the partial I have...
<%= form_for [:tenants, request] do |f| %>
And on the dashboard controller I have...
def show
#dashboard = current_tenant
#bill = current_tenant.bill || current_tenant.build_bill
#request = current_tenant.request || current_tenant.build_request
end
(if I change #request = Request.new it works fine but I know that's not right)
The bill partial works and the dashboard finds the tenant but I keep getting
"undefined method `request' for #
Any idea of what I am missing? I compared the bill controller to the request controller and I cant find any differences. When I put the Model.new into the dashboard controller it works but I know this isn't right, its as if the app wont recognize the Request controller...
The error is saying it doesn't recognize "request" method.
Also here is my controller for request...
class Tenants::RequestsController < ApplicationController
before_filter :authenticate_tenant!
def index
#requests = Request.all
end
def show
#request = Request.find(params[:id])
end
def create
if #request = current_tenant.create_request(authorization_params)
redirect_to tenants_dashboard_path, :notice => "#{request.manager_name} has been Authorized!"
else
redirect_to tenants_dashboard_path, :error => "#{request.manager_name} has NOT been Authorized, please try again."
end
end
def edit
end
def update
if current_tenant.request.update_attributes(authorization_params)
redirect_to tenants_dashboard_path, :notice => "You have approved #{request.manager_name} to review your report"
else
redirect_to tenants_dashboard_path, :notice => "#{request.manager_name} is NOT allowed to review your report"
end
end
def destroy
#request = Request.find(params[:request_id])
name = #request.name
if #request.destroy
flash[:notice] = "\"#{name}\" was successfully removed from your profile."
redirect_to #dashboard
else
flash[:error] = "There was an error deleting this managers access."
render :show
end
end
Well it looks like
current_tenant.request has an issue. That means that the method is not available. Assuming you're not trying to access the http request , then you have an issue with the request method.
So your issue is with how you defined the request method (maybe in your model). e.g. is it a class method or a instance method etc.
Without knowing your goal, that's the general answer I can give you. Creating a Request.new could be right depending on your goal, but if your goal is to call the request method, you must make it available to current_tenant
One controller shouldn't be calling your other controller as you have suggested...

Strange Behaviour with .errors on Factory Girl Stubbed Object

I am using factory_girl_rails (4.2.1) and rspec-rails (2.14.0) to test a simple controller on Rails 4. When testing an error case, I use FactoryGirl.build to build an invalid User object. However, the resulting object does not contain any error in #user.errors; yet expect(assigns(:user)).to have(1).errors_on(:email) in the test case still passes. Why doesn't the FactoryGirl generated object has any error, and how does rspec see the error?
Here are the details and code.
The controller simply creates a User object, then redirect to a verification page if creation was successful or render the form again if there is any error.
class RegistrationController < ApplicationController
def new
end
def create
#user = User.create(params.required(:user).permit(:email, :password, :password_confirmation))
if #user.errors.empty?
redirect_to verify_registration_path
else
render :new
end
end
end
In my error case test, I create a User without 'email' using FactoryGirl. It is expected to create an error entry in #user.errors for the 'email' field AND renders the :new template.
describe RegistrationController do
#... Some other examples ...
describe 'GET create' do
def post_create(user_params)
allow(User).to receive(:create).with(ActionController::Parameters.new({user: user_params})[:user]).and_return(FactoryGirl.build(:user, user_params))
post :create, user: user_params
end
context 'without email' do
before { post_create email: '', password: 'testing', password_confirmation: 'testing' }
subject { assigns(:user) }
it 'build the User with error' do
expect(subject).to have(1).errors_on(:email)
end
it 'renders the registration form' do
expect(response).to render_template('new')
end
end
end
end
However, when I ran the test case, only the 'renders the registration form' example failed, but not the other one.
Failures:
1) RegistrationController GET create without email renders the registration form
Failure/Error: expect(response).to render_template('new')
expecting <"new"> but rendering with <[]>
# ./spec/controllers/registration_controller_spec.rb:51:in `block (4 levels) in <top (required)>'
Finished in 0.25726 seconds
6 examples, 1 failure
Failed examples:
rspec ./spec/controllers/registration_controller_spec.rb:50 # RegistrationController GET create without email renders the registration form
What is strange here is that rspec seems to be able to see an error in #user (hence the first test case passes) but for some unknown reason #user.error.empty? returns true in controller causing it to redirect instead of rendering the :new template (hence the failed second test case). I also confirmed in debugger that #user.error was indeed empty.
Is it something wrong with how FactoryGirl handles error, or am I using it wrong?
Thanks
Two things I want to mention here are:
1. Probably You want to use "Post create" instead of "Get create".
2. Whether email is missing or not is the model's concern, not controller's.
I suggest you use stub to return false for the case that email is missing.
The easiest way is:
User.any_instance.stub(:create).and_return(false)
And maybe you want to change some other things in the controller, like "if #user.errors.empty?"
EDIT: Sorry, "create" actually doesn't return false.
So in your controller
#user = User.new(.....)
if #user.save
...
else
render :new
And in your test use
User.any_instance.stub(:save).and_return(false)

How to write a functional test case in rails 3.1 and unit:test

i am new to rails testing and i am using unit:test. I have an action in my controller
def save_campaign
unless params[:app_id].blank?
#app = TestApp.find(params[:app_id])
if params[:test_app]
#app.update_attributes(params[:test_app])
end
flash[:notice] = "Your Registration Process is completed"
redirect_to "/dashboard"
else
redirect_to root_path
end
end
and my test case is as following
test "should save campagin " do
assert_difference('TestApp.count', 0) do
post :save_campaign, test_app: #test_app.attributes
end
assert_redirected_to "/dashboard"
end
end
This method is a post method. While running this test, it is failing and showing me a message
"should save campagin (0.07s)
Expected response to be a redirect to http://test.host/dashboard but was a redirect to http://test.host/
/home/nouman/.rvm/gems/ruby-1.9.2-p290#global/gems/actionpack-3.1.3/lib/action_dispatch/testing/assertions/response.rb:67:in `assert_redirected_to'
My guess is that i am not giving it right assertion to check params
params[:app_id] and #app = TestApp.find(params[:app_id]).
How can i write such an assertion to check these attributes, check wether a parameter is blank. How can 1 find an object with a given id.
For functional test, you should not care about testing the model, that is in your case, you should remove:
assert_difference('TestApp.count', 0) do
..
end
What you want to know in a functional test is that if the page is loaded, redirected correctly.
In your controller, you have a condition check for params, so for each of the outcome of the check, you write a test each, that is you have to write two functional tests:
test "if app_id param is empty, #save_campaign redirect to root" do
post :save_campaign, :app_id => nil
assert_redirected_to root_path
end
test "#save_campaign" do
post :save_campaign, :app_id => app_fixture_id, :test_app => #test_app.attributes.to_params
assert_redirected_to '/dashboard'
end
The trick to prepare the post params is to use method to_params method.
Hope this help.
UPDATE: If you just want to check if params[:app_id] GET param is in the URL, you should just check for this presence instead of checking if it is blank or not:
if params[:app_id]
else
end