Ruby: Error in minitest to destroy user - ruby

I am a newbie to ruby and am just creating my first test suite.
When writing a minitest to destroy a user I get the following error:
ERROR["test_should_destroy_when_logged_in_as_a_admin", UsersControllerTest]
test_should_destroy_when_logged_in_as_a_admin#UsersControllerTest ActionController::UrlGenerationError:
No route matches {:action=>"/users/608331937", :controller=>"users"}
The test reads the following:
def setup
#user_destroy = users(:destroyme)
#user_admin = users(:admin)
end
test "should destroy when logged in as a admin" do
log_in_as(#user_admin)
assert #user_admin.admin?, "not admin"
assert_difference 'User.count', -1 do
delete user_path(#user_destroy)
end
end
and fixture:
admin:
name: Matthias Havenaar
email: my#mail.com
password_digest: <%= User.digest('password') %>
admin: true
destroyme:
name: Destroy Me
email: destroy#me.com
password_digest: <%= User.digest('password') %>
admin: true
It seems like something goes wrong with the user ID or user_path. Any idea what I am doing wrong here?

Try this, I hope this will work.
Replace
delete user_path(#user_destroy)
With
delete :destroy, id: #user_destroy

Related

Set Controller params in Rspec Testing

I want to write Capybara test for form but get an error on UI after submitting a form.
Field Position doesn't have a default value
But this field non-present on the new.html view, it present in the Controller and Edit.html. How should I pass "position" params to the controller in my TEST.
Controller:
#issue_position = params[:issue_position].presence.try(:to_i)
_edit.html.erb:
<%= hidden_field_tag 'issue_position', #issue_position if #issue_position %>
Test:
within("#issue-form") do
fill_in 'issue[subject]', with: 'Test_issue'
fill_in 'issue[description]', with: 'Test_description'
end
click_button 'Create'
Maybe in your test ,when you visit your page, you forgot to pass your issue_position params. Please add the code below:
visit your_page_path({issue_position: 1})
But as Thomas mention in comment the show up a weird behaviour of your app. Maybe you should display the input in you form when issue_params is empty in order to prévention this unfriendly behaviour for your user.
I just add the migration with "default value" to my Database table column and run migrations and Everything start working!
Thanks to everyone!
class AddDefaultValueToIssue < ActiveRecord::Migration
def up
change_column :issues, :position, :integer, default: 1
end
def down
change_column :issues, :position, :integer, default: nil
end
end

Rspec testing if text is pluralized (Hartl 10.5 Exercise 1)

Ruby 1.9.3, Rails 3.2.2
I'm trying to write an Rpsec (Capybara) to test if my page is properly pluralizing the word "Post". I get an error when running my Rspec that states:
c:/.../my_app/spec/requests/user_pages_spec.rb:58: in `block (3 levels) in ': undefined local variable or method 'user' for ... (NameError)
Here's the relevant test:
describe "profile page" do
let(:user){FactoryGirl.create(:user)}
let!(:m1){FactoryGirl.create(:micropost, user: user, content: "Food")}
let!(:m2){FactoryGirl.create(:micropost, user: user, content: "Bar")}
before {visit user_path(user)}
it {should have_selector('h1', text: user.name)}
it {should have_selector('title', text: user.name)}
describe "pagination" do
before(:all){40.times {FactoryGirl.create(:micropost, user: user, content: "Food")}}
after(:all){User.delete_all}
it {should have_selector('div.pagination')}
end
describe "microposts" do
it {should have_content(m1.content)}
it {should have_content(m2.content)}
it {should have_content(user.microposts.count)}
before do
sign_in user
visit root_path
User.delete_all
end
it "should pluralize post numbers" do
FactoryGirl.create(:micropost, user: user, content: "Food")
page.should have_content("1 micropost")
2.times {FactoryGirl.create(:micropost, user: user, content: "Food")}
page.should have_content("2 microposts")
end
I'm not sure if I'm going about testing for pluralization of posts the right way either, but I'm mainly stumped about why that block can't "see" the users object since the line right after my if statement can see it. if I comment out the if block everything runs fine.
Any code outside of it doesn't have access to the variables defined with before, let, etc. You need to place it inside an it call, say with a text argument that describes the total if/else test. Could you update this question to include the other code from your spec that's in scope?
Profile page doesn't have pluralization to test.
The test should be for static_pages#home.
describe 'Home page' do
describe 'for signed-in users' do
let(:user) { FactoryGirl.create(:user) }
before do
FactoryGirl.create(:micropost, user: user, content: 'Lorem ipsum')
FactoryGirl.create(:micropost, user: user, content: 'Dolor sit amet')
sign_in user
visit root_path
end
it { should have_content('micropost'.pluralize(user.microposts.count)) }
end
end

FactoryGirl and Rails 3.2 error

I have this in factories.rb:
FactoryGirl.create :user do |user|
user.name "test"
user.age "40"
end
and this in my test file:
require 'spec_helper'
describe "FirstTests" do
it "creates a user" do
user=Factory(:user)
end
end
Like always nothing works. Could somebody explain me why I am getting this?
/usr/local/rvm/gems/ruby-1.9.3-p194/gems/factory_girl-4.1.0/lib/factory_girl/registry.rb:24:in `find': Factory not registered: user (ArgumentError)
Everything is there. why I am getting this error?
You are using create instead of define
FactoryGirl.define do
factory :user do
name "test"
age "40"
end
end
and Factory(:user) instead of FactoryGirl.create(:user), or more simply create(:user)
https://github.com/thoughtbot/factory_girl/wiki/Usage

Reference user in Rails Fixtures

Is there any way to reference the ID of a user fixture in another fixture. I have a messages.yml fixture:
basic:
body: "Hey Barney, wanna go bowling tonight?"
sender: fred
recipient_ids: [users(:barney)]
type: Message
users.yml
barney:
first_name: Barney
last_name: Rubble
Yes, use ERB syntax:
recipient_id: <%= User.find_by_first_name('Barney').id %>
http://guides.rubyonrails.org/v5.0/testing.html#the-low-down-on-fixtures
This is a big reason why fixtures are not commonly used anymore. I'd recommend using a seeds file. Possibly with seed_fu. This will allow you to create fixtures/seeds in Ruby and do just about anything.

How can I access Sorcery in my RSpec tests?

Sorcery authentication gem: https://github.com/NoamB/sorcery
Sorcery's creator provides an example Rails app with Sorcery test helpers included in its Test::Unit functional tests: https://github.com/NoamB/sorcery-example-app/blob/master/test/functional/users_controller_test.rb
# Test::Unit functional test example
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
setup do
#user = users(:noam)
end
test "should show user" do
login_user
get :show, :id => #user.to_param
assert_response :success
end
But I can't figure out how to get login_user to work in my RSpec controller specs.
/gems/sorcery-0.7.5/lib/sorcery/test_helpers/rails.rb:7:in `login_user':
undefined method `auto_login' for nil:NilClass (NoMethodError)
Here's the relevant code in the Sorcery gem regarding the above error:
https://github.com/NoamB/sorcery/blob/master/lib/sorcery/test_helpers/rails.rb
module Sorcery
module TestHelpers
module Rails
# logins a user and calls all callbacks
def login_user(user = nil)
user ||= #user
#controller.send(:auto_login,user)
#controller.send(:after_login!,user,[user.send(user.sorcery_config.username_attribute_names.first),'secret'])
end
def logout_user
#controller.send(:logout)
end
end
end
end
UPDATE:
As per Sorcery's documentation "Testing in Rails 3", I have indeed added include Sorcery::TestHelpers::Rails to my spec_helper.rb.
The Sorcery test helper login_user acts on #controller, but I'm getting the error because #controller is nil in my controller spec. Here's my spec:
#spec/controllers/forums_controller_spec.rb
require 'spec_helper'
describe ForumsController do
render_views
describe 'GET new' do
describe 'when guest' do
it 'should deny and redirect' do
get :new
response.should redirect_to(root_path)
end
end
describe 'when admin' do
p #controller #=> nil
#user = User.create!(username: "Test", password: "secret", email: "test#test.com")
login_user # <--------------- where the error occurs
it 'should resolve' do
get :new
response.should render_template(:new)
end
end
end
end
FWIW, I spent a lot of time looking for an answer to this problem. I am using Capybara and RSpec. As it turns out, you need to login manually to using Sorcery to get the login to work.
I've created a Gist on creating integration tests with Sorcery/Rspec/Capybara here:
https://gist.github.com/2359120/9989c14af19a48ba726240d030c414b882b96a8a
You need to include the Sorcery test helpers in your spec_helper
include Sorcery::TestHelpers::Rails
See the sorcery wiki : https://github.com/NoamB/sorcery/wiki/Testing-rails-3
In the example rails app, this is done at https://github.com/NoamB/sorcery-example-app/blob/master/test/test_helper.rb#L13
Updated
Do you have any other Controller specs in the same folder which pass successfully ?
RSpec usually mixes in the required stuff for controller testing for the specs in "spec/controllers" folder.
You could try explicitly marking this as a controller spec by writing
describe ForumsController, :type => :controller do
You need to put your user creation and login into a before(:each) block as follows:
describe 'when admin' do
before(:each) do
#user = User.create!(username: "Test", password: "secret", email: "test#test.com")
login_user
end
it 'should resolve' do
get :new
response.should render_template(:new)
end
end
I've just experienced this dilemma myself and drawing from the input from danneu, diwalak and Birdlevitator (in this thead: rail3/rspec/devise: rspec controller test fails unless I add a dummy=subject.current_user.inspect) I think I can see a solution.
I've been working with a standard rails 3 rspec generated resource from the 'rails generate scaffold' command. Here's the controller rspec file after I modified it to work with a sorcery login:
require 'spec_helper'
# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to specify the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator. If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails. There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.
#
# Compared to earlier versions of this generator, there is very limited use of
# stubs and message expectations in this spec. Stubs are only used when there
# is no simpler way to get a handle on the object needed for the example.
# Message expectations are only used when there is no simpler way to specify
# that an instance is receiving a specific message.
describe RecordsController do
before(:each) do
#user = User.create!(forename: "Billy", surname: "Bob", username: "Test", password: "secret!1", email: "test#test.com")
login_user
end
# This should return the minimal set of attributes required to create a valid
# Record. As you add validations to Record, be sure to
# update the return value of this method accordingly.
def valid_attributes
{ :owner => 'Mr Blobby', :catagory => 'Index'}
end
# This should return the minimal set of values that should be in the session
# in order to pass any filters (e.g. authentication) defined in
# RecordsController. Be sure to keep this updated too.
def valid_session
{"warden.user.user.key" => session["warden.user.user.key"]}
end
describe "GET index" do
it "assigns all records as #records" do
record = Record.create! valid_attributes
get :index, {}, valid_session
assigns(:records).should eq([record])
end
end
describe "GET show" do
it "assigns the requested record as #record" do
record = Record.create! valid_attributes
get :show, {:id => record.to_param}, valid_session
assigns(:record).should eq(record)
end
end
describe "GET new" do
it "assigns a new record as #record" do
get :new, {}, valid_session
assigns(:record).should be_a_new(Record)
end
end
describe "GET edit" do
it "assigns the requested record as #record" do
record = Record.create! valid_attributes
get :edit, {:id => record.to_param}, valid_session
assigns(:record).should eq(record)
end
end
describe "POST create" do
describe "with valid params" do
it "creates a new Record" do
expect {
post :create, {:record => valid_attributes}, valid_session
}.to change(Record, :count).by(1)
end
it "assigns a newly created record as #record" do
post :create, {:record => valid_attributes}, valid_session
assigns(:record).should be_a(Record)
assigns(:record).should be_persisted
end
it "redirects to the created record" do
post :create, {:record => valid_attributes}, valid_session
response.should redirect_to(Record.last)
end
end
describe "with invalid params" do
it "assigns a newly created but unsaved record as #record" do
# Trigger the behavior that occurs when invalid params are submitted
Record.any_instance.stub(:save).and_return(false)
post :create, {:record => {}}, valid_session
assigns(:record).should be_a_new(Record)
end
it "re-renders the 'new' template" do
# Trigger the behavior that occurs when invalid params are submitted
Record.any_instance.stub(:save).and_return(false)
post :create, {:record => {}}, valid_session
response.should render_template("new")
end
end
end
describe "PUT update" do
describe "with valid params" do
it "updates the requested record" do
record = Record.create! valid_attributes
# Assuming there are no other records in the database, this
# specifies that the Record created on the previous line
# receives the :update_attributes message with whatever params are
# submitted in the request.
Record.any_instance.should_receive(:update_attributes).with({'these' => 'params'})
put :update, {:id => record.to_param, :record => {'these' => 'params'}}, valid_session
end
it "assigns the requested record as #record" do
record = Record.create! valid_attributes
put :update, {:id => record.to_param, :record => valid_attributes}, valid_session
assigns(:record).should eq(record)
end
it "redirects to the record" do
record = Record.create! valid_attributes
put :update, {:id => record.to_param, :record => valid_attributes}, valid_session
response.should redirect_to(record)
end
end
describe "with invalid params" do
it "assigns the record as #record" do
record = Record.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Record.any_instance.stub(:save).and_return(false)
put :update, {:id => record.to_param, :record => {}}, valid_session
assigns(:record).should eq(record)
end
it "re-renders the 'edit' template" do
record = Record.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Record.any_instance.stub(:save).and_return(false)
put :update, {:id => record.to_param, :record => {}}, valid_session
response.should render_template("edit")
end
end
end
describe "DELETE destroy" do
it "destroys the requested record" do
record = Record.create! valid_attributes
expect {
delete :destroy, {:id => record.to_param}, valid_session
}.to change(Record, :count).by(-1)
end
it "redirects to the records list" do
record = Record.create! valid_attributes
delete :destroy, {:id => record.to_param}, valid_session
response.should redirect_to(records_url)
end
end
end
And a run down of the important bits:
This bit does the programmatic login (ignore the forename and surname attributes, they're specific to the solution I'm building):
before(:each) do
#user = User.create!(forename: "Billy", surname: "Bob", username: "Test", password: "secret!1", email: "test#test.com")
login_user
end
This bit holds session info/key data:
def valid_session
{"warden.user.user.key" => session["warden.user.user.key"]}
end
As diwalak writes, we need to add this to the spec_help.rb file:
include Sorcery::TestHelpers::Rails
And that's it - worked for me anyhow :)

Resources