Testing select_tag with Rspec. Rails - ruby-on-rails

I want to testing page, and I have some problem. The select matcher does not work.
rspec
let!(:hotel1) { create(:hotel) }
let!(:hotel2) { create(:hotel, status: 'rejected') }
it 'with params: status column and existing value' do
login_admin
visit admin_hotels_path
expect(page).to have_content hotel1.title
expect(page).to have_content hotel2.title
fill_in :search, with: 'rejected'
select 'status', from: :search_column
click_button 'Search'
expect(page).to have_content hotel2.title
expect(page).to_not have_content hotel1.title
end
index
=form_tag admin_hotels_path, method: 'get' do
=text_field_tag :search, params[:search]
=select_tag :search_column, options_for_select(Hotel.searchable_columns, params[:search_column])
=submit_tag 'Search'
controller
def index
#hotels = Hotel.search(params[:search], params[:search_column]).order(sort_column + ' ' + sort_direction)
end
The result of testing:
Failures:
1) hotels page check the Search with params: status column and existing value
Failure/Error: expect(page).to_not have_content hotel1.title
expected #has_content?("Hotel1") to return false, got true
But the search from status with this params return one object, because in the factories the status have approved value.
UPDATE
factory :hotel do
sequence(:title) { |i| "Hotel#{i}" }
description 'This is a some description for hotel'
breakfast true
price 20500
address { create(:address) }
user { create(:user) }
avatar { fixture_file_upload(Rails.root + 'spec/fixtures/images/example.jpg', "image/jpg") }
status 'approved'
end
UPDATE 2.0
hotel.rb
def self.search(keyword, column_name)
if self.column_names.include?(column_name.to_s)
where("#{column_name} LIKE ?", "#{keyword}")
else
scoped
end
end
def self.searchable_columns
wanted_columns = ['title', 'status' ]
self.column_names.select{ |column| wanted_columns.include?(column) }
end
end

Maybe your factory generates hotels with the same name.

Your select statement should be in the format of:
select(value, options = {})
e.g.,
select 'rejected', from: :search_column
Ref. this doc

Related

Rails RSpec (beginner): Why is this test sometimes passing and sometimes not?

I have a book database where books can have different book formats (hardcover, softcover etc).
I have factories with factory_bot.
The following spec just run through with an error - and then when I run it the second time, it worked. I have no idea where I need to start searching....
The error was:
1) BookFormat displays the proper book format for a book with that format
Failure/Error: expect(#book.book_format.name).to eq('Hardcover')
expected: "Hardcover"
got: "Not defined"
Here is the full spec:
require 'rails_helper'
RSpec.describe BookFormat, type: :model do
before(:all) do
#book = create(:hobbit)
#book_format_default = create(:not_defined)
end
it 'displays the proper book format for a book with that format' do
expect(#book.book_format.name).to eq('Hardcover')
end
it 'should reassign to the fallback book_format if their book_format is deleted' do
format = #book.book_format
format.destroy
expect(#book.reload.book_format.id).to eq(#book_format_default.id)
end
it 'should not let the fallback format be deleted' do
format = #book_format_default
format.destroy
expect(format).to be_truthy
end
end
Here is the corresponding factor for the book :hobbit:
factory :hobbit, class: Book do
title { 'The Hobbit' }
year { 1937 }
rating { 5 }
condition { 4 }
synopsis { "<p>#{Faker::Lorem.paragraphs(number: 30).join(' ')}</p>" }
association :book_format, factory: :hardcover
association :user, factory: :me
genres { [ create(:fiction) ] }
after(:build) do |hobbit|
hobbit.cover.attach(
# rubocop:disable Rails/FilePath
io: File.open(Rails.root.join('db', 'sample', 'images', 'cover-1.jpg')),
# rubocop:enable Rails/FilePath
filename: 'cover.jpg',
content_type: 'image/jpeg'
)
end
end
And here are the factories for book_formats:
FactoryBot.define do
factory :not_defined, class: BookFormat do
name { 'Not defined'}
fallback { true }
end
factory :hardcover, class: BookFormat do
name { 'Hardcover' }
end
factory :softcover, class: BookFormat do
name { 'Softcover' }
end
end

Trouble with Paperclip + Rspec ( Paperclip::AdapterRegistry::NoHandlerError: No handler found for )

I'm having some problems when i'm trying to run some tests with rspec and paperclip.
i'm getting this message:
Failure/Error: #event = Event.new(event_params)
Paperclip::AdapterRegistry::NoHandlerError:
No handler found for "/events/rails.png?1453566649"
Here is my test class:
context "user creates a new event" do
describe "with valid fields" do
before(:each) do
#image = Rack::Test::UploadedFile.new(Rails.root.join('spec/images/rails.png'), 'image/png')
end
it "must persist the event" do
event = build(:event, photo: nil, photo_attachment: nil)
event.photo_attachment = #image
post :create, event: {title: event.title, description: event.description, place: event.place, address: event.address, opening_date: event.opening_date, category: event.category, price: event.price, photo_attachment: event.photo_attachment, hour: event. hour}
expect(assigns(:event).id.nil?).to be false
end
Here is my controller:
class EventsController < ApplicationController
def new
#event = Event.new
end
def create
#event = Event.new(event_params)
if #event.save
redirect_to "success"
end
end
private
def event_params
params.require(:event).permit(:title, :description, :photo, :place, :address, :opening_date, :ending_date, :category, :price, :photo_attachment, :hour)
end
end
And here is my factory ( I'm using factory girl ):
FactoryGirl.define do
factory :event do
title { Faker::Name.name }
description 'A simples description'
photo { Faker::Bitcoin.address }
place 'Anywhere'
address { Faker::Address.street_address }
opening_date Date.today
ending_date Faker::Date.forward(2)
category 'any category'
price 1.99
photo_attachment {File.new("#{Rails.root}/spec/images/rails.png")}
hour '00:00'
end
trait :soccer_game do
title 'Soccer Game'
place 'Maracana Stadium'
opening_date Date.today
hour '14:00'
end
end
Could you help me with this ?

Issue with apipie gem and rspec in rails 4

i'm writing the code to get my Rspec tests to pass on my api. I'm using the apipie gem to generate documentation and it seems that my tests are failing because thy are expecting a number and it's funny because this is exactly what I want to test.
The page fails when the :bpm parameter is not a number. is there any way of going around this ?
context "when is not created" do
before(:each) do
user = FactoryGirl.create :user
#invalid_lesson_attributes = { title: "California Dreamin",
bpm: "Hello"
}
request.headers['Authorization'] = user.auth_token
post :create, { user_id: user.id, lesson: #invalid_lesson_attributes }
end
it "renders an errors json" do
lesson_response = json_response
expect(lesson_response).to have_key(:errors)
end
it "renders the json errors on why the user could not be created" do
lesson_response = json_response
expect(lesson_response[:errors][:bpm]).to include "is not a number"
end
it { should respond_with 422 }
end
end
Update spec:
context "when is not updated" do
before(:each) do
patch :update, { user_id: #user.id, id: #lesson.id,
lesson: { bpm: "ten" }, format: :json }
end
it "renders an errors json" do
lesson_response = json_response
expect(lesson_response).to have_key(:errors)
end
it "renders the json errors on why the user could not be updated" do
lesson_response = json_response
expect(lesson_response[:errors][:bpm]).to include "is not a number"
end
it { should respond_with 422 }
end
in my users_controller:
api :POST, '/teachers/:user_id/lessons/', "Create lesson"
param :lesson, Hash, desc: 'Lesson information', :required => true do
param :title, String, desc: 'Title of the lesson', :required => true
param :bpm, :number, desc: 'tempo of the lesson (beats per second)', :required => true
end
error :code => 422, :desc => "Unprocessable Entity"
my error when I run my rspec tests :
Apipie::ParamInvalid: Invalid parameter 'bpm' value "Hello": Must be a number.
Adds format json to post request
post :create, { user_id: user.id, lesson: #invalid_lesson_attributes, format: :json }
That worked for me.

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.

How to test Rspec in controller

In controller,
def admin_search
#admins = User.find(:all,:joins=>[:roles],:conditions=>["name IN (?) and email like '#{params[:email]}%'",["content team","ops team"]]).paginate(:page => params[:page], :per_page => 10)
end
please suggest me some code in rspec
First of all, it's better to extract find(:all, ...) call to User model. Call it search, for instance.
class User < ActiveRecord::Base
scope :search_by_email, lambda { |email|
joins(:roles).where(["name IN (?) and email like '#{email}%'",["content team","ops team"]])
}
end
Use it in the controller then:
def admin_search
#admins = User.search_by_email(params[:email]).paginate(:page => params[:page], :per_page => 10)
end
Now, you can test the search_by_email method in isolation - check, that it returns result for "content team" and "ops team" only, correctly works with empty email string and so on.
I don't think you have to test paginate method, as it should be already tested in kaminari, will_paginate or whatever you use. But if you want to be sure, that it is being called, than you can use mock expectations (should_receive) in the controller specs.
EDIT: How the specs could look like
describe User do
describe ".search_by_email" do
let(:content_team) { Role.create! name: "content team" }
let(:ops_team) { Role.create! name: "ops team" }
let(:another_team) { Role.create! name: "another team" }
it "should search in content team" do
content_team_user = User.create! email: "joe.black#example.com", roles: [content_team]
User.search_by_email("black").should == [content_team_user]
end
it "should search in ops team" do
ops_team_user = User.create! email: "joe.black#example.com", roles: [ops_team]
User.search_by_email("black").should == [ops_team_user]
end
it "should not search in other teams" do
other_team_user = User.create! email: "joe.black#example.com", roles: [another_team]
User.search_by_email("black").should == []
end
it "should not search by empty string" do
content_team_user = User.create! email: "joe.black#example.com", roles: [content_team_user]
User.search_by_email("").should == []
User.search_by_email(nil).should == []
end
# more specs for search...
end
end
describe UsersController do
describe "admin search" do
let(:admin_user) { double(:admin_user).as_null_object }
let(:search_string) { 'joe' }
it "should search for admin users" do
User.should_receive(:search_by_email).with(search_string).and_return([admin_user])
get :admin_search, email: search_string
assigns(:admins).should == [admin_user]
end
end
end

Resources