RSpec request example failing - ruby-on-rails

I'm trying to do a really simple request spec for testing my API methods in my application. Right now I'm getting 302 message when I should be getting 200 with this test.
The spec:
require 'spec_helper'
describe UsersController do
describe "#create" do
it "creates a new user " do
post '/users', user: FactoryGirl.attributes_for(:user)
expect(response.status).to eq 200
end
end
end
The factory:
FactoryGirl.define do
factory :user do
sequence(:name) { |n| "Person #{n}" }
sequence(:username) { |n| "Person#{n}" }
sequence(:email) { |n| "person_#{n}#example.com"}
password "foobar"
password_confirmation "foobar"
end
end
The controller method:
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
What am I missing?

So you need to make the asynchronous post request, it should be something like below,
it "creates a new user " do
xhr :post, '/users', user: FactoryGirl.attributes_for(:user)
expect(response.status).to eq 200
end
Try this, it might work

To solve the issue I need to add the ACCEPT header to my request, like so:
post "/users", { user: #user } , { accept: 'application/json' }
Doing this fixed the issue which was the server not interpreting the request as expecting json in return.

Related

Rspec test fails while rendering

For my user controller, while running the test cases I am facing render issue. It is redirecting to http://test.host/sign_in instead of rendering new.
Controller code
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
UserMailer.registration_confirmation(#user).deliver_now
session[:user_id] = #user.id
format.html { redirect_to sign_in_path, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
spec/users_controller_spec.rb
describe '#create' do
it 'User created' do
new_user = FactoryBot.build :user
post :create, params: {
user: {
id: new_user.id,
firstname: new_user.firstname,
email: new_user.email,
password: "s",
password_confirmation:"s"
}
}
expect(response).to render_template("new")
end
end
While running this test case I am facing this error!
Error
Failures:
1) UsersController controller test cases #create User created
Failure/Error: expect(response).to render_template("new")
expecting <"new"> but was a redirect to <http://test.host/sign_in>
# ./spec/controllers/users_controller_spec.rb:30:in `block (4 levels) in <top (required)>'
How do I resolve this?
According to your controller code, you redirect to sign_in when the save is successful :
format.html { redirect_to sign_in_path, notice: 'User was successfully created.' }
Your failing test is saying :
expecting <"new"> but was a redirect to <http://test.host/sign_in>
It comes from expect(response).to render_template("new"). You might want to change this line to expect(subject).to redirect_to(sign_in_path).
The behaviour render_template("new") might be relevant when #user.save is false

RSPEC test of #update cannot update some parameters

I try testing my #UPDATE method in my Users Controller. The update of my fields (firstname, lastname, email, phone_number) works totally fine on my localhost but I can't make my test pass. Here is my code
I have this in my Users Controller :
def update
#user = User.find(params[:id])
authorize(#user)
#user.skip_reconfirmation! if #user.is_a_customer?
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to user_account_path, notice:
I18n.t('User_was_successfully_updated') }
format.json { render json: #user, status: :ok}
else
format.html { render :edit }
format.json { render json: #user.errors, status:
:unprocessable_entity }
end
end
and here is my RSPEC test :
RSpec.describe UsersController, type: :controller do
describe "PATCH update" do
let(:user) { create(:customer_user) }
before :each do
sign_in user
end
it "update the user information" do
allow(User).to receive(:find_by).and_return(user)
new_attributes = {
firstname: 'Roger',
lastname: 'Rabbit',
email: 'roger.rabbit#lapin.fr',
mobile_phone_number: '0606060606',
gender: 'female',
}
patch :update, params: { locale: I18n.locale,
id: user.id,
user: new_attributes
}
expect(user.firstname).to eq(new_attributes['firstname'])
expect(user.lastname).to eq(new_attributes['lastname'])
expect(user.email).to eq(new_attributes[:email])
expect(user.mobile_phone_number).to
eq(new_attributes[:mobile_phone_number])
end
Finally, here is the error message :
0) UsersController PATCH update user is a user update the user information
Failure/Error: expect(user.email).to eq(new_attributes[:email])
expected: "roger.rabbit#lapin.fr"
got: "customer#ecity.fr"
(compared using ==)
# ./spec/controllers/users_controller_spec.rb:29:in `block (4 levels) in <top (required)>'
Two more things :
- the test pass for firstname and lastname
- new_attributes['email'] and new_attributes['mobile_phone_number'] return nils ; that's why I symbolized key for the two last expectations
You need to reload the user object.
patch :update, ...
user.reload # ⇐ THIS
expect(user.firstname).to ...
Without reloading you have the stale object in your test and Rails has no ability to magically understand the object in the database has changed.

Cancancan gem while using Rspec

I have problem with my feature test for users creating new content. It passes only when I comment or delete this line in my controller. It looks like factory :user doesn't have ability to create new content. I checked factory using seperate test to check if it has ability to create new word and it has. What can be problem here?
authorize! :create, #word, :message => "Musisz się zalogować, aby dodać nowe słówko."
words_controller.rb
def create
authorize! :create, #word, :message => "Musisz się zalogować, aby dodać nowe słówko."
#user = current_user
#word = #user.words.build(word_params)
respond_to do |format|
if #word.save
format.html {
redirect_to new_word_path
flash[:notice] = 'Słówko zostało prawidłowo zapisane. Dodaj następne!'
}
format.json { render :show, status: :created, location: #word }
else
format.html { render :new }
format.json { render json: #word.errors, status: :unprocessable_entity }
end
end
end
user_creates_word_spec.rb
require 'spec_helper'
feature 'User creates word' do
before(:all) do
category = FactoryGirl.create(:category)
10.times { word = FactoryGirl.create(:word) }
sign_in
expect(page).to have_content 'Wyloguj się'
visit game_words_path
click_link('Dodaj słówko')
end
scenario 'with valid input' do
fill_in 'Angielski', with: 'house'
fill_in 'Polski', with: 'dom'
find(:css, ".check_boxes[value='1']").set(true)
click_button 'Zapisz'
expect(page).to have_content 'Słówko zostało prawidłowo zapisane.'
end
end
test to check if user factory has ability to create new word
it "can create new word" do
user = FactoryGirl.create(:user)
ability = Ability.new(user)
word = Word.new(user: user)
expect { ability.should be_able_to(:create, word)}
end
I changed this lines:
authorize! :create, #word, :message => "Musisz się zalogować, aby dodać nowe słówko."
#user = current_user
#word = #user.words.build(word_params)
to:
#user = current_user
#word = #user.words.build(word_params)
authorize! :create, #word, :message => "Musisz się zalogować, aby dodać nowe słówko."
And it works fine. In the previous version variable #word was definied after authorize! method, so it doesn't work properly.

Not able to call a controller action in Rspec

I have been trying to implement an RSpec for a Controller called "Estimate controller" to test whether my mailing functionality (sending estimate) working properly or not. But I'm not able to call the controller action from my RSpec. I need to set some values (to, subject, message, cc, current_user, attachments) in a hash and send that hash to Estimate controller.Here is what I tried..
estimates_controller_spec.rb
describe "post 'send_estimate'" do
it "should send estimate " do
#estimate = Fabricate(:estimate, id: Faker::Number.number(10), validity: "12/12/2014", total_value: 1222.00, user_id:#user.id, project_id: #project_id)
est_params = {
to: "rspec#rails.com",
subject: "Estimate",
message: "Check out the Estiamte details",
cc: "respec#rails.com",
current_user: #user,
attachments: ""
}
expect{
post :send_estimate, estimate: est_params
}.to change { ActionMailer::Base.deliveries.count }.by(1)
end
end
estimates_controller.rb
def send_estimate
respond_to do |format|
if #estimate.send_email(params[:to], params[:subject], params[:message], params[:cc], current_user, params[:attachments])
#estimate.create_activity :send_estimate, owner: current_user, recipient: #estimate.project
format.html { redirect_to lead_path(#estimate.project), notice: "Email sent Successfully"}
format.json { head :no_content, status: :ok}
else
format.json { render json: #estimate.errors }
format.html { redirect_to contacts_path, notice: 'Something went wrong' }
end
end
end

How to use strong parameters with foreign keys

I am having an issue with foreign keys being permitted in my new Rails 4 application.
Lets say you have a user create form, where you can create a user and assign a user type though a dropdown.
The user model will then have a foreign key: user_type_id.
I have a RSpec test which uses FactoryGirl, and if I debug and look at params the user_type has the value 2, but if my permit params look like this:
private
def user_params
params.require(:user).permit(:name, :password, :user_type_id)
end
I won't get any user_type out. I have also tried with:
private
def user_params
params.require(:user).permit(:name, :password, user_type_attributes: [:user_type_id])
end
but without any luck.
What is the way to permit it in my post action in my User controller?
Update:
I don't have a UI yet, I try to do this the TDD way, so basically it is my RSpec-tests which fails.
The create user action looks like this:
def create
#user = User.new(user_params)
authorize #user
respond_to do |format|
if #user.save
format.html { render json: #user, status: :created, location: #user }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render json: #user, status: :unprocessable_entity, location: #user }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
and the RSpec test looks like this:
it 'should create a user' do
expect {
post :create, { :user => FactoryGirl.attributes_for(:User) }
}.to change(User, :count).by(1)
end
The FactoryGirl for my user looks like this:
FactoryGirl.define do
factory :User do |f|
f.email { Faker::Internet.email }
f.password { '12345678' }
f.password_confirmation { '12345678' }
f.user_type { FactoryGirl.create(:UserType) }
end
end
If I debug my #user object it doesn't have a user_type added, but if I debug the params object, it does, contain a user_type: 2
Any ideas?
You are not creating an Id in the Factory. You are creating the new associated object. You will have to retrieve the ID in the params passed to the controller.
I suggest:
FactoryGirl.define do
factory :User do |f|
f.email { Faker::Internet.email }
f.password { '12345678' }
f.password_confirmation { '12345678' }
f.user_type 999
end
end
In your spec:
before(:each) do
type = FactoryGirl.create(:UserType, id: 999)
end
And then:
it 'should create a user' do
expect { :create, { :user => FactoryGirl.attributes_for(:User)}
}.to change(User, :count).by(1)
end
And remove the association from the FactoryGirl action.
EDIT:
If the user type is mandatory, and assuming that you have them in the database, you just need to insert in the factory the user_id you want for that user type. And you won't need to merge the params after.

Resources