I'm not very sure I'm doing it right, but I have two models: House that has_one Address.
The Address model has:
class Address < ApplicationRecord
searchkick
belongs_to :house
end
I'm trying to test my house_controller with RSpec like this
RSpec.describe HousesController do
context 'GET #index' do
before { get :index }
it { is_expected.to render_template('index') }
it 'assigns #houses' do
h = create(:house)
expect(assigns(:houses).results).to eq([h])
end
...
Nevertheless I always get a result which is not the one I expect.
The code of my controller is the following:
def index
if params[:term].present?
#houses = House.search(params[:term])
else
#houses = House.search('*')
end
end
I'm not sure I understand it, but could it be that since I'm using FactoryBot, it is creating lots of houses, and then when getting in the index method, there's a bunch of houses there and not only and precisely h?
This is my failure:
Failures:
1) HousesController GET #index assigns #houses
Failure/Error: expect(assigns(:houses).results).to eq([h])
expected: [#<House id: 763, rent: 1173, deposit: 739, description: "Rerum cado curso curo alias.", preferred_ge...2018-11-26 21:40:43", available_at: "2018-12-17", user_id: 15945, lease_length: nil, built_in: nil>]
got: [#<House id: 215, rent: 0.839e3, deposit: 0.797e3, description: "Rerum aeneus taceo crepusculum aestu...2018-11-26 21:17:53", available_at: "2018-12-17", user_id: 15776, lease_length: nil, built_in: nil>]
(compared using ==)
Diff:
## -1,2 +1,5 ##
-[#<House id: 763, rent: 1173, deposit: 739, description: "Rerum cado curso curo alias.", preferred_gender: 0, created_at: "2018-11-26 21:40:43", updated_at: "2018-11-26 21:40:43", available_at: "2018-12-17", user_id: 15945, lease_length: nil, built_in: nil>]
+[#<House id: 215, rent: 0.839e3, deposit: 0.797e3, description: "Rerum aeneus taceo crepusculum aestus.", preferred_gender: 0, created_at: "2018-11-25 12:50:11", updated_at: "2018-11-25 12:50:11", available_at: "2018-12-16", user_id: 8065, lease_length: nil, built_in: nil>,
+ #<House id: 235, rent: 0.519e3, deposit: 0.642e3, description: "Cicuta totidem arbustum arcesso fugit tego.", preferred_gender: 0, created_at: "2018-11-25 12:54:28", updated_at: "2018-11-25 12:54:28", available_at: "2018-12-16", user_id: 8085, lease_length: nil, built_in: nil>,
+ #<House id: 648, rent: 0.668e3, deposit: 0.1104e4, description: "Corporis tametsi demens.", preferred_gender: 0, created_at: "2018-11-26 21:17:43", updated_at: "2018-11-26 21:17:43", available_at: "2018-12-17", user_id: 15775, lease_length: nil, built_in: nil>,
+ #<House id: 649, rent: 0.799e3, deposit: 0.611e3, description: "Ut ancilla tredecim.", preferred_gender: 0, created_at: "2018-11-26 21:17:53", updated_at: "2018-11-26 21:17:53", available_at: "2018-12-17", user_id: 15776, lease_length: nil, built_in: nil>]
# ./spec/controllers/houses_controller_spec.rb:12:in `block (3 levels) in <top (required)>'
I'm starting with RSpec now and it's really taking me effort and hours to try to grab the grasp of it, thanks a lot in advance!
Searchkick docs about disabling indexing for tests with RSpec.
You don't want to be updating your objects in Elasticsearch always while running tests. You want to do it only when you'll be explicitly testing your search functionality (or indexing/deleting from index). To do so, you will have to disable searchkick callbacks, define a custom tag for your tests and enable indexing only for these tests. You may have to handle cleaning your index after a test/groups of tests as well.
#vich's point is also important, you currently create your object too late, after the request.
I would change your setup to:
context 'GET #index', :search do
let!(:house) { create(:house) }
before { get :index }
it 'assigns #houses' do
expect(assigns(:houses).results).to eq([house])
end
end
Try creating your house in the before block:
context 'GET #index' do
before do
let!(:house) { create(:house) }
get :index
end
it { is_expected.to render_template('index') }
it 'assigns #houses' do
expect(assigns(:houses).results).to eq([house])
end
end
A couple of things to note:
As opposed to let, let! is immediately invoked (thus creating your record before the index action is hit)
Add a breakpoint (IDE) or use a debugger (byebug, pry, etc.) and put it before the get :index call to see what (if any) houses already exist.
Related
require 'rails_helper'
feature "comment" do
given(:current_user) do
create(:user)
end
given(:undertaking) do
create(:undertaking)
end
background do
login_as(current_user)
end
scenario "can create comment" do
#below two because undertaking = user_id:2 & asking_id:1
create(:user)
create(:asking)
p undertaking
p Asking.find(1)
p User.find(2)
p User.find(1)
p Undertaking.all
visit undertaking_path(undertaking)
expect(current_path).to eq undertaking_path(1)
within("form#undertake-form-test") do
fill_in "content" , with: "heyheyhey"
end
click_button 'Send'
expect(page).to have_content 'heyheyhey'
end
end
This is spec/features/comment_spec.rb.
and this below is result command rspec.
#<Undertaking id: 1, title: "MyString", content: "MyText", result: false, user_id: 2, asking_id: 1, created_at: "2016-12-13 15:07:08", updated_at: "2016-12-13 15:07:08">
#<Asking id: 1, content: "MyText", fromlang: "MyString", tolang: "MyString", usepoint: 1, finished: false, title: "MyString", deadline: nil, user_id: 1, created_at: "2016-12-13 15:07:08", updated_at: "2016-12-13 15:07:08">
#<User id: 2, email: "shiba.hayato2#docomo.ne.jp", created_at: "2016-12-13 15:07:08", updated_at: "2016-12-13 15:07:08", provider: nil, uid: nil, name: "Shiruba", occupation: "大学生", age: 10, sex: "男性", content: "heyheyheyeheyeheye", skill: "日本語検定3級", picture: "/assets/default_user.jpg", point: 500, country: "Japan", language1: "Japanese", language2: "Korea", language3: "English">
#<User id: 1, email: "shiba.hayato1#docomo.ne.jp", created_at: "2016-12-13 15:07:08", updated_at: "2016-12-13 15:07:08", provider: nil, uid: nil, name: "Shiruba", occupation: "大学生", age: 10, sex: "男性", content: "heyheyheyeheyeheye", skill: "日本語検定3級", picture: "/assets/default_user.jpg", point: 500, country: "Japan", language1: "Japanese", language2: "Korea", language3: "English">
#<ActiveRecord::Relation [#<Undertaking id: 1, title: "MyString", content: "MyText", result: false, user_id: 2, asking_id: 1, created_at: "2016-12-13 15:07:08", updated_at: "2016-12-13 15:07:08">]>
F
Failures:
1) comment can create comment
Failure/Error: <%= #undertaking.id %>
ActionView::Template::Error:
undefined method `id' for nil:NilClass
and this below is undertaking_controller.rb.
class UndertakingController < ApplicationController
def show
#undertaking=Undertaking.find(params[:id])
#comment=Comment.new do |c|
c.user=current_user
end
end
end
and this below is undertaking/show.html.erb.
<%= #undertaking.id %>
Why do I have the error? Why #undertaking is nil in view although Undertaking.first is not nil in spec/features/comment_spec.rb?Please help me.
I think it has to do with the naming used for your controller . The convention is undertakings/show.html.erb for the view instead of undertaking/show.html.erb . I would also use
class UndertakingsController < ApplicationController
instead of
class UndertakingController < ApplicationController
Finally I would check that all my routes also have the correct naming. Hope that helps. Good luck
I am trying to test the following controller action(Using Ruby on Rails, RSPEC, and FactoryGirl):
class ContactsController < ApplicationController
before_action :authenticate_user!
def index
#contacts = current_user.contacts
# #contacts = Contact.all
end
Here is my contacts_controller_spec.rb file:
require 'rails_helper'
describe ContactsController do
before do
#user = FactoryGirl.create(:user_with_contacts)
sign_in #user
end
describe "GET INDEX" do
it "assigns #contacts" do
expect(assigns(:contacts)).to eq(#user.contacts)
end
end
Failure/Error: expect(assigns(:contact)).to eq([contact])
expected: [#<Contact id: 295, first_name: "Loy", email: "leon#hegmannhintz.net", phone_number: "6044339393", created_at: "2015-09-12 19:13:42", updated_at: "2015-09-12 19:13:42", last_name: "Wyman", user_id: 343>]
got: #<Contact id: nil, first_name: nil, email: nil, phone_number: nil, created_at: nil, updated_at: nil, last_name: nil, user_id: nil>
And here is my users_spec.rb file:
FactoryGirl.define do
factory :user do
email { Faker::Internet.email }
password { "32423fdsfasf42" }
factory :user_with_contacts do
transient do
contacts_count 2
end
after(:create) do |user, evaluator|
create_list(:contact, evaluator.contacts_count, user: user)
end
end
end
end
Any Help please? I have been stuck on this for a long time.
If i call
puts #user.inspect
I get
#<User id: 340, email: "johnson_kaulke#brekke.com", encrypted_password: "$2a$04$Si5k6Q1eYERvhQITXKBoIOGEzPyK50E3IQ.yjRcqmDj...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2015-09-12 19:13:42", updated_at: "2015-09-12 19:13:42">
and
calling
puts #user.contacts.inspect
I get
#<ActiveRecord::Associations::CollectionProxy [#<Contact id: 289, first_name: "Fae", email: "ariane#johnston.net", phone_number: "6044339393", created_at: "2015-09-12 19:13:42", updated_at: "2015-09-12 19:13:42", last_name: "Spinka", user_id: 340>, #<Contact id: 290, first_name: "Marcellus", email: "chloe_deckow#buckridge.net", phone_number: "6044339393", created_at: "2015-09-12 19:13:42", updated_at: "2015-09-12 19:13:42", last_name: "Bashirian", user_id: 340>]>
Its just when i call the assigns(:contacts) that the problem happens!
I think you forgot to invoke the controller action. :)
Try adding get :index
it "assigns #contacts" do
get :index
expect(assigns(:contacts)).to eq(#user.contacts)
end
I use the gem ancestry to create comments.
Now, I can list all comments.
But I want to push serial number to each comment.
For example, if there were 3 comments, the first comment is annotated by 1, the next annotated by 2,..
I have no idea how to do it?
show.html.haml
- if notice
%p.alert.alert-success= notice
= nested_comments(#comment.subtree.arrange(:order => :created_at))
helper
def nested_comments(comments)
if comments.respond_to? :map
comments.map do |comment, sub_comments|
render(comment) + content_tag(:div, nested_comments(sub_comments), :class => "nested_comments")
end.join.html_safe
end
end
each_with_index won't work on recursive
if I have 4 comments, I want to show 0,1,2,3 for each comment
But each_with_index can not make it because it's a recursive call.
comments.each_with_index.map do |(comment, sub_comments), i|
comments
=> {#<Comment id: 2, user_id: 1, ip: nil, content: "I'm id2 the second floor VIVOTEK Releases New Vers...", commentable_id: nil, commentable_type: nil, created_at: "2014-11-07 03:59:38", updated_at: "2014-11-07 06:56:12", ancestry: nil>=>
{#<Comment id: 4, user_id: 1, ip: nil, content: "lala", commentable_id: nil, commentable_type: nil, created_at: "2014-11-07 05:22:41", updated_at: "2014-11-07 05:22:41", ancestry: "2">=>
{#<Comment id: 5, user_id: 1, ip: nil, content: "son of 4", commentable_id: nil, commentable_type: nil, created_at: "2014-11-07 06:38:04", updated_at: "2014-11-07 06:38:04", ancestry: "2/4">=>
{},
#<Comment id: 6, user_id: 1, ip: nil, content: "dild last 252", commentable_id: nil, commentable_type: nil, created_at: "2014-11-07 06:52:15", updated_at: "2014-11-07 06:52:15", ancestry: "2/4">=>
{}}}}
You can use with_index with map
comments.map.with_index do |comment, sub_comments, index|
Every enumerable instance in ruby has a method each_with_index, providing an_enumerator. So in your case I would suggest to use:
- comments.map do |comment, sub_comments|
+ comments.each_with_index.map do |idx, comment, sub_comments|
Hope it helps.
I don't know of an elegant solution. But you could pass a counter into your nested_comments function, and deal with the problem manually -- which might well mean without map at all. Ugly, I know.
To take a simpler example, should you need one:
def nested_foo(result, string, index)
index += 1
result << "\n#{index}: #{string}"
if index >= 10
return result
else
return nested_foo(result, string, index)
end
end
I'm ashamed to make this question but I can't find my error, I am once again doing the rails tutorial from Michael Hartl, since the first time I wasn't able to do the proper TDD, anyways I have managed to have working every single test but one! the thing is that I test it manually on rails' console and it worked, I tried to reset the db with rake db:reset and rake test:prepare and obviously re-populating the db rake db:populate ok, straight to the point... I have the following test
describe "status" do
let(:unfollowed_posts) do
FactoryGirl.create(:micropost, user: FactoryGirl.create(:user))
end
let(:followed_user) { FactoryGirl.create(:user) }
before do
#user.follow!(followed_user)
3.times { followed_user.microposts.create!(content: "Lorem Ipsum") }
end
its (:feed) { should include(newer_micropost) }
its (:feed) { should include(older_micropost) }
its (:feed) { should_not include(unfollowed_posts) }
its (:feed) do
followed_user.microposts.each do |micropost|
should include(micropost)
end
end
end
according to me, everything is ok, I test it manually on rails console, however when runing the spec with rpsec spec/models/user_spec.rb it comes up with the following error
Failures:
1) User micropost associations status feed
Failure/Error: should include(micropost)
expected #<ActiveRecord::Relation [#<Micropost id: 355, content: "Lorem ipsum", user_id: 702, created_at: "2014-05-10 03:34:47", updated_at: "2014-05-10 04:34:47">, #<Micropost id: 354, content: "Lorem ipsum", user_id: 702, created_at: "2014-05-09 04:34:47", updated_at: "2014-05-10 04:34:47">]> to include #<Micropost id: 358, content: "Lorem ipsum", user_id: *703*, created_at: "2014-05-10 04:34:47", updated_at: "2014-05-10 04:34:47">
Diff:
## -1,2 +1,3 ##
-[#<Micropost id: 358, content: "Lorem ipsum", user_id: *703*, created_at: "2014-05-10 04:34:47", updated_at: "2014-05-10 04:34:47">]
+[#<Micropost id: 355, content: "Lorem ipsum", user_id: 702, created_at: "2014-05-10 03:34:47", updated_at: "2014-05-10 04:34:47">,
+ #<Micropost id: 354, content: "Lorem ipsum", user_id: 702, created_at: "2014-05-09 04:34:47", updated_at: "2014-05-10 04:34:47">]
</code>
I don't understand why the user_id is changed if the code 3.times { followed_user.microposts.create!(content: "Lorem Ipsum") } doesn't touch followed_user at all, so... that's my headache now, why is this happening? is it a bogus behavior on rspec, thanks in advance, and sry for this dull question.
you need to change you feed method in user.rb file
from
def feed
Micropost.where("user_id = ?", user)
end
to
def feed
Micropost.from_users_followed_by(self)
end
as well as add method self.from_users_followed_by to your micropost.rb file
def self.from_users_followed_by(user)
followed_user_ids = "SELECT followed_id FROM relationships WHERE follower_id = :user_id"
where("user_id IN (#{followed_user_ids}) or user_id = :user_id", user_id: user.id)
end
Note: my app works just fine. I'm just unable to do the right rspec for it.
trash_controller.rb:
class TrashController < ApplicationController
before_action :set_slide, only: [ :show, :destroy, :restore ]
def set_slide
#trashed_slide = Slide.only_deleted.find(params[:id])
end
def show
end
trash_controller_spec.rb:
describe TrashController do
let(:album) { create(:album) }
let(:slide) { build(:slide) }
describe "GET #show" do
before do
slide.save
slide.destroy
get :show, id: slide.id
end
it { expect(assigns(:trashed_slide)).to match_array(Slide.only_deleted.to_a) }
end
error:
1) TrashController GET #show should contain exactly #<Slide id: 1, album_id: 1, description: "Brennon Prosacco", created_at: "2014-04-02 06:06:03", updated_at: "2014-04-02 06:06:03", photo_file_name: "sample_2.jpg", photo_content_type: "image/jpeg", photo_file_size: 204509, photo_updated_at: "2014-04-02 06:06:03", photo_fingerprint: "4dbd1870094527b8c4ddca6afd415eb9", deleted_at: "2014-04-02 06:06:03", photo_processing: false>
Failure/Error: it { expect(assigns(:trashed_slide)).to match_array(Slide.only_deleted.to_a) }
expected an array, actual collection was #<Slide id: 1, album_id: 1, description: "Brennon Prosacco", created_at: "2014-04-02 06:06:03", updated_at: "2014-04-02 06:06:03", photo_file_name: "sample_2.jpg", photo_content_type: "image/jpeg", photo_file_size: 204509, photo_updated_at: "2014-04-02 06:06:03", photo_fingerprint: "4dbd1870094527b8c4ddca6afd415eb9", deleted_at: "2014-04-02 06:06:03", photo_processing: false>
# ./spec/controllers/trash_controller_spec.rb:25:in `block (3 levels) in <top (required)>'
I don't get what it's about as both lines looks the same. Any ideas ?
I would not expect Slide.only_deleted.find(params[:id]) to return an array. find returns just one slide. Therefore I would change the expectation to:
expect(assigns(:trashed_slide)).to eq(Slide.only_deleted.first)