<true> expected to be != to <true>. test failure - ruby-on-rails

My test is the following:
test "should post make_admin" do
user = FactoryGirl.create(:user, admin: true)
sign_in(user)
before_value = user.admin
post :make_admin, id: user.id
after_value = user.admin
assert_not_equal before_value, after_value
assert_response :redirect
end
and the controller looks like this:
def make_admin
user = User.find_by_id(params[:id])
user.toggle!(:admin)
redirect_to static_pages_user_index_path
end
and yet I keep getting this error:
Failure:
test_should_post_make_admin(StaticPagesControllerTest) [..../functional/static_pages_controller_test.rb:48]:
<true> expected to be != to
<true>.
Any ideas on what I'm doing wrong?

I'd replace:
after_value = user.admin
with:
after_value = user.reload.admin

Related

Unable to pass session variables to RSpec controller

I'm testing confirmation method from a controller using RSpec, it seems like tests crush because I can't pass session variables when addressing the method.
Here's my spec:
RSpec.describe OauthCallbacksController, type: :controller do
describe 'POST #confirm_email' do
before do
request.env["devise.mapping"] = Devise.mappings[:user]
end
context 'confirms_email' do
let(:email) { 'test-email#test.ru' }
let(:confirm_email) { post :confirm_email, params: { email: email }, session: { auth: { uid: '12345', provider: 'facebook' } } }
it 'redirects to new_user_session_path' do
confirm_email
expect(response).to redirect_to new_user_session_path
end
it 'sends an email' do
expect { confirm_email }.to change{ ActionMailer::Base.deliveries.count }.by(1)
end
end
end
end
Method confirm_email:
def confirm_email
puts params[:email]
pending_user = User.find_or_init_skip_confirmation(params[:email])
if pending_user
aut = Authorization.where(provider: session[:auth]['provider'], uid: session[:auth]['uid'], linked_email: params[:email])
.first_or_initialize do |auth|
auth.user = pending_user
auth.confirmation_token = Devise.friendly_token[0, 20],
auth.confirmation_sent_at = Time.now.utc
end
if aut.save
OauthMailer.send_confirmation_letter(aut).deliver_now
redirect_to root_path, notice: "Great! Now confirm your email, we've sent you a letter!"
else
redirect_to root_path, alert: "Something went wrong. Please try again later or use another sign in method"
end
end
end
When I try to display session variables they are nil, In test.log it's obvious that there should be session variables are NULL-s.
[34mSELECT "authorizations".* FROM "authorizations" WHERE "authorizations"."provider" IS NULL AND "authorizations"."uid" IS NULL AND "authorizations"."linked_email" = $1 ORDER BY "authorizations"."id" ASC LIMIT $2[0m [["linked_email", "test-email#test.ru"], ["LIMIT", 1]]
I use Rails 5.2.2.1 and RSpec 3.8.
I've read that in Rails 5 there's a problem accessing sessions, I've already tried setting it with controller.session[:auth]['uid'] or
request.session[:auth]['uid'] but nothing
Something strange is happening in rails or rack but with a nested session, the keys are available as symbols. This should work
Authorization.where(provider: session[:auth][:provider], uid: session[:auth][:uid], linked_email: params[:email])
I managed to pass session parameters using request.env["omniauth.auth"] = mock_auth_hash(:facebook) and when instead of passing hash I've passed request to the session. It did the job.
Now my spec looks like this.
describe 'POST #confirm_email' do
before do
request.env["devise.mapping"] = Devise.mappings[:user]
request.env["omniauth.auth"] = mock_auth_hash(:facebook)
get :facebook
end
let(:confirm_email) { post :confirm_email, params: { email: 'mockuser#test.com'}, session: { auth: request.env["omniauth.auth"] } }
it 'redirects to root_path' do
confirm_email
expect(response).to redirect_to root_path
end
it 'sends an email' do
request.env["devise.mapping"] = Devise.mappings[:user]
request.env["omniauth.auth"] = mock_auth_hash(:facebook)
get :facebook
expect { confirm_email }.to change{ ActionMailer::Base.deliveries.count }.by(1)
end
end

What could be possible test cases for this controller action and how can i handle if else conditions. Using minitest framework in RubyonRails

I am new to writing test cases and I cant figure out the scenarios of writing tests. For example there are too many if else conditions in controller how would I write cases for these conditions. Below is my registration controller. I am using rails minitest framework for rails 3.2.1 version.
def create
invitation_token = params["invitation_token"]
#Check if the user exists yet based on their e-mail address.
user = User.find_by_email(params[:user][:email])
omni = session[:omniauth] || params[:omniauth]
theme_id = nil
theme_layout_id = nil
theme_style_id = nil
begin
omni = JSON.parse omni if omni
rescue => e
# if we got here, the omni is invalid!!
return redirect_to '/login'
end
#Did we find a user yet? If not, perform the following.
if user.nil? && !invitation_token.present?
client = Client.find_or_create_by_name(name: params[:user][:username])
#p client.errors
if client.present?
user = User.new
app_url = ApplicationUrl.find_by_domain_url(request.host_with_port)
user.apply_omniauth(omni)
user.email = params[:user][:email]
user.username = params[:user][:username]
user.client_id = client.id
#Assign the user/client the Free plan by default.
plan = ClientPlan.find_or_create_by_client_id(client_id: client.id, plan_id: 1, plan_billing_cycle_id: 1, start_date: Date.today, is_paid: 1, isactive: 1)
#Set the client settings to the defaults for a Free (non business plan) user.
ClientSetting.create(client_id: client.id, is_billboard_enabled: 0, is_tweetback_enabled: 0, is_conversations_enabled: 0)
#Set the client environment link.
ClientsEnvironment.create(environment_id: environment.id, client_id: client.id)
unless params[:user][:theme_id].nil?
theme_id = params[:user][:theme_id]
puts "theme id: " + theme_id.to_s
end
unless params[:user][:theme_layout_id].nil?
theme_layout_id = params[:user][:theme_layout_id]
puts "theme layout id: " + theme_layout_id.to_s
end
unless params[:user][:theme_style_id].nil?
theme_style_id = params[:user][:theme_style_id]
puts "theme style id: " + theme_style_id.to_s
end
#Create an application for the client.
Application.find_or_create_by_client_id(
client_id: client.id,
name: params[:user][:username],
callback_url: "#{request.host_with_port}",
application_url_id: app_url.id
)
#Create the default feed for the client.
Feed.find_or_create_by_client_id(
client_id: client.id,
name: 'My Feed',
token: SecureRandom.uuid,
theme_id: theme_id,
theme_style_id: theme_style_id,
theme_layout_id: theme_layout_id
)
if user.save
#Remember me?
if params[:remember_me]
user.remember_me!
end
client = user.client
client.update_attribute(:owner_user_id, user.id)
schedule_reminder_email(user)
#Create the users Profile
Profile.find_or_create_by_user_id(
user_id: user.id,
fullname: params[:user][:fullname],
username: params[:user][:username]
)
record_event_profile(user,params[:user][:fullname],params[:remember_me])
end
end
elsif user.nil? && invitation_token.present?
user = User.new
invite = Invite.find_by_token(invitation_token)
if invite.present?
client = invite.client
user.apply_omniauth(omni)
user.email = params[:user][:email]
user.username = params[:user][:username]
user.client_id = client.id
user.can_curate = false
user.can_publish = false
if user.save
#Remember me?
if params[:remember_me]
user.remember_me!
end
#Create the users Profile
Profile.find_or_create_by_user_id(
user_id: user.id,
fullname: params[:user][:fullname],
username: params[:user][:username]
)
record_event_profile(user,params[:user][:fullname],params[:remember_me])
invite.update_attributes({invite_accepted_at: Time.now, name: user.profile.try(:fullname)})
end
else
return redirect_to root_path
end
else
#If a user already exists for the email address then this must just be a new social network account for this user.
token = omni['credentials']['token']
token_secret = ""
user.relatednoise_authentications.create!(
provider: omni['provider'],
uid: omni['uid'],
token: token,
token_secret: token_secret
) if user.present?
end
#Create an entry in Socialnetworkaccounts for this user to associate them to their social login/account.
create_sna(omni, user)
#SignupNotifier.init_notify(user).deliver
begin
ApiConnector.new("#{API_URL}/notify_us/#{user.id}")
rescue => e
Airbrake.notify_or_ignore(e, {})
end
unless user.new_record?
session[:omniauth] = nil
session[:omniauth_auth] = nil
#reset_invite_token
end
session[:user_id] = user.id
record_event_signup(user)
back_if_coming_from_wix(params[:wix_appid], user)
sign_in_and_redirect user if !params[:wix_appid].present?
end
so far i have written this. Not sure if this is the way to write test cases.
require 'test_helper'
class RegistrationsControllerTest < ActionController::TestCase
fixtures :users
def setup
#params = {"omniauth"=>"{\"provider\":\"twitter\",\"uid\":\"167003011\",\"credentials\":{\"token\":\"167003011-ZqnlBsCZlFjymanQ6gQ2ggD7a2tAESuUVlygw0WN\",\"secret\":\"idVWQgR79HOKmZfuNtVtxvzWzGH5plJlxdEksxyuHgH5S\"}}","user"=>{"fullname"=>"Tommy", "email"=>"Tom#moody.com", "username"=>"tommy", "theme_id"=>"", "theme_style_id"=>"", "theme_layout_id"=>""}}
#invite = invites(:arvind_invite)
end
def test_new
get :new
assert_response :success
end
def test_create_for_client_plan
assert_difference ->{ ClientPlan.count }, +1 do
post :create, #params
end
end
def test_create_for_client_setting
assert_difference ->{ ClientSetting.count }, +1 do
post :create, #params
end
end
def test_create_for_client_environment
assert_difference -> {ClientsEnvironment.count}, +1 do
post :create, #params
end
end
def test_create_for_application
assert_difference -> {Application.count}, +1 do
post :create, #params
end
end
def test_create_for_user
assert_difference -> {User.count}, +1 do
post :create, #params
end
end
def test_create_for_feed
assert_difference -> {Feed.count}, +1 do
post :create, #params
end
end
def test_create_for_profile
assert_difference -> {Profile.count}, +1 do
post :create, #params
end
end
def test_create_for_sna
assert_difference -> {Socialnetworkaccount.count}, +1 do
post :create, #params
end
end
def test_create_for_user_with_invitation
assert_difference -> {User.count}, +1 do
post :create, #params.merge({invitation_token: #invite.token})
end
end
end
This is my test helper file.
ENV["RAILS_ENV"] = "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
class ActiveSupport::TestCase
include Devise::TestHelpers
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
#
# Note: You'll currently still have to declare fixtures explicitly in integration tests
# -- they do not yet inherit this setting
fixtures :all
def host_with_port
#request.host_with_port = "localhost:3000"
end
# Add more helper methods to be used by all tests here...
end

Rspec testing a controller using from to?

Tested in browser and works fine. Test error says "expected result to have changed from 0 to 1, but did not change". Is this a factory issue or rspec issue? Why is it not changing?
Error:
Failures:
1) ShortLinksController Short links controller Clicking a short link increments the click counter by 1
Failure/Error: expect{ get :url_dispatch, { id: short_link.short_link } }.to change{short_link.click_counter}.from(0).to(1)
expected result to have changed from 0 to 1, but did not change
# ./spec/controllers/short_links_controller_spec.rb:34:in `block (4 levels) in <top (required)>'
Rspec:
it "increments the click counter by 1" do
short_link = create(:short_link)
expect{ get :url_dispatch, { id: short_link.short_link } }.to change{short_link.click_counter}.from(0).to(1)
end
Controller:
def url_dispatch
id = params[:id]
record = ShortLink.where(["short_link = ?", id]).first
if record.update(click_counter: record.click_counter + 1)
redirect_to record.redirect_to
else
render '/not_found'
end
end
Factory:
FactoryGirl.define do
factory :short_link do
redirect_to "http://google.com"
title "This is the google page"
short_link "xGh7u"
click_counter 0
owner Owner.create!(first_name: "Bob", last_name: "Diller", email: "bdiller#example.com")
end
end
per Fab's request, here is how I'm currently working around the issue.
context 'save invocations' do
before(:each) do
#org = create(:organization)
user = create(:user, organization: #org, is_admin: true)
sign_in user
end
it 'valid scenario' do
user2 = create(:user, organization: #org, is_admin: false)
put :update, id: user2, user: { is_admin: true }
user2.reload
expect(response).to have_http_status(204)
expect(user2.is_admin).to eq true
end
end
Here I'm calling user2.reload in order to get the updated attributes from the user2 factory.
I don't know why the expect{} syntax doesn't work for factories but you could refactor your code like this:
it "increments the click counter by 1" do
short_link = create(:short_link)
count = short_link.click_counter
get :url_dispatch, { id: short_link.short_link }
short_link.reload
expect(short_link.click_counter).to eq count + 1
end
Again I'm not saying this is best practice, I just couldn't find anything in the FactoryGirl documentation regarding RSpec 3 expect syntax in controllers that update attributes.

Creating new case using Capybara

I am new to ror and I'm stuck with writing tests in Capybara .
What I need to do is to test the creation of a new Case
by user clicks the button . But when I check if the glasses did not see created .
require 'spec_helper'
feature "User can create new case" to
background do
# user = FactoryGirl.create (: sysadmin_user) # user.make_current
#plan = FactoryGirl.create(:plan)
# account = FactoryGirl.create (: account, plan: #plan, user: #user)
#trial = FactoryGirl.create trial (:trial, account: #account)
# trial.make_current
# trial_phase = FactoryGirl.create (: trial_phase, trial: #trial)
login (# user.email, # user.password)
end
scenario 'create new case' to
Case.where puts ("created_by =?", # user.id).count #returns 0
fill_in 'case_subject_identifier', with 'MyNewTest'
expect {click_button ('Create New Case')}.to change(Case,:count).by(1)
Case.where puts ("created_by =?", # user.id).count #returns 0
end
end
And this is controller :
POST /cases as HTML
def create`
#case = Case.where("subject_identifier = ? && trial_id = ?", params[:case]
[:subject_identifier], #current_trial.id).first
if #case || params[:case][:subject_identifier].blank?
respond_to :js
else`
params[:case][:subject_identifier]
=sanitize_value(params[:case[:subject_identifier])
if params[:case]
#case = Case.create(params[:case])``
if current_user.trial_member?(#current_trial, current_user)
#case.update_attributes(:location_id => current_user.default_location_id)
else
#case.update_attributes(:location_id => Location.find_by_name("None").id)
end
#case.update_attributes(:trial_phase_id
=>TrialPhase.find_by_name("None").id,:access
=> "None")
#redirect_to "/trial/#{#current_trial.id.to_s}/cases/#{#case.id.to_s}/case_view"
respond_to do |format|
format.js { render :js => %(window.location.pathname='#{'/trial
/'+#current_trial.id.to_s+'/cases/'+#case.id.to_s+'/case_view'}') }
end
end
end

Why is my rspec test failing with ActionController::RoutingError:?

Basically I'm stumped as to why this particular test is failing. The page works fine when I go in and test it out by hand but the test keeps failing. First off, here's the error.
2) Setlist Pages Edit page adding a song
Failure/Error: click_button submit
ActionController::RoutingError:
No route matches {:action=>"edit", :controller=>"setlists", :id=>nil}
# ./app/controllers/allocations_controller.rb:15:in `create'
# (eval):2:in `click_button'
# ./spec/requests/setlist_pages_spec.rb:79:in `block (4 levels) in <top (required)>'
I realise that the id is set to nil but I know that when the test initially visits the page it renders because tests for content pass. I'm not sure why it points to the create controller when I'm testing the edit action as well? The test is shown below:
before do
#setlist = Setlist.create(date: Date.today, morning: true)
end
...
describe "Edit page" do
let(:admin) { FactoryGirl.create(:admin) }
let(:submit){ "Add Song" }
before do
#secondSong = FactoryGirl.create(:song)
sign_in admin
visit edit_setlist_path(#setlist)
end
it{ should have_content("Edit a Setlist")}
describe "adding a song" do
before do
select("#{#secondSong.title} by #{#secondSong.artist}", from: 'Songs')
click_button submit
end
it{ should have_selector('div.alert.alert-success')}
it "should create a new allocation" do
expect{click_button submit}.to change(Allocation, :count).by(1)
end
end # end adding a song
end # end edit test
Controller code as requested:
def create
#setlist = Setlist.new(params[:setlist])
if #setlist.save
#success!
flash[:success] = "Setlist saved"
##setlist.allocations.build produce invalid allocation with nil id
redirect_to setlist_path(#setlist)
else
#FAIL!
render 'new'
end
end
def edit
#songs= Song.search(params[:search])
##songs = Song.all(order: 'title')
#setlist = Setlist.find(params[:id])
#allocations = #setlist.allocations
#allocation = Allocation.new
#selections = Song.all.collect {|s| [ [s.title, s.artist].join(" by "), s.id ]}
end
def update
#setlist = Setlist.find(params[:id])
#selections = Song.all.collect {|s| [ [s.title, s.artist].join(" by "), s.id] }
#allocations = #setlist.allocations
#allocation = Allocation.new
#Allocation parameters
#allocation.song_id = params[:allocation][:song_id]
#allocation.setlist_id = #setlist.id
#allocation.songPosition = #setlist.songs.count + 1
if #setlist.update_attributes(params[:setlist])
if #allocation.save
flash[:success] = "SETLIST SAVED!"
redirect_to edit_setlist_path(#setlist)
else
flash[:fail] = "Sorry there was an error adding songs to the setlist"
render 'edit'
end
else
flash[:fail] = "Invalid Set"
render 'edit'
end
end
Any pointers would be much appreciated!

Resources