Why does my AR relation return empty in RSpec but returns objects in Rails Console?

This is my Spec:

it "assigns all the nodes that are tagged with the current_user email to local variable 'tagged_nodes'" do      
  get :index            

  u1 = create(:user)
  u2 = create(:user)
  n1 = create(:node, family_tree: family_tree)      
  n1.user_tag_list.add(u1.email, u2.email)

  expect(assigns(:tagged_nodes)).to include(n1)
end

That relates to my Dashboard#Index, where it is testing the assignment of @tagged_nodes per this line:

@tagged_nodes = nodes_that_are_tagged_with(current_user)

Here is the method that is doing the lookup, which I have stored in a Concern (which is properly included in the controller):

  def nodes_that_are_tagged_with(user)
    Node.includes(:user_tags).tagged_with(user.email)
  end

The error I am getting is this:

 1) DashboardController GET #index assigns all the nodes that are tagged with the current_user email to local variable 'tagged_nodes'
     Failure/Error: expect(assigns(:tagged_nodes)).to include(n1)
       expected #<ActiveRecord::Relation []> to include #<Node id: 21, name: "Miss Wendy McClure", family_tree_id: 38, user_id: nil, media_id: 21, media_type: "Video", created_at: "2015-05-07 22:56:09", updated_at: "2015-05-07 22:56:09", circa: "2015-05-25 00:00:00", is_comment: nil>
       Diff:
       @@ -1,2 +1,2 @@
       -[#<Node id: 21, name: "Miss Wendy McClure", family_tree_id: 38, user_id: nil, media_id: 21, media_type: "Video", created_at: "2015-05-07 22:56:09", updated_at: "2015-05-07 22:56:09", circa: "2015-05-25 00:00:00", is_comment: nil>]
       +[]

Notice that the relation being returned is empty.

When I try to run this Node.includes(:user_tags)... query at the command line, I get the proper results I would expect:

[17] pry(main)> n
=> #<Node id: 7, name: "Hercules", family_tree_id: 57, user_id: 57, media_id: 120, media_type: "Video", created_at: "2015-03-12 08:54:29", updated_at: "2015-03-31 21:48:05", circa: nil, is_comment: nil>
[18] pry(main)> n.user_tags
=> [#<ActsAsTaggableOn::Tag id: 4, name: "gerry@test.com", taggings_count: 2>, #<ActsAsTaggableOn::Tag id: 6, name: "danny@test.com", taggings_count: 1>]
[19] pry(main)> u
=> #<User id: 52, email: "gerry@test.com", encrypted_password: "$2a$10$KaX1kvtIw1.jGITnt9Czqeq3xTzhY3OM052NSHsL5Lf...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 5, current_sign_in_at: "2015-04-03 17:10:28", last_sign_in_at: "2015-04-03 00:38:24", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2015-03-05 01:36:31", updated_at: "2015-04-03 17:10:28", first_name: "Gerry ", confirmation_token: nil, confirmed_at: "2015-03-05 01:36:52", confirmation_sent_at: nil, unconfirmed_email: nil, invitation_relation: "uncle", avatar: nil, invitation_token: nil, invitation_created_at: "2015-03-05 01:36:31", invitation_sent_at: "2015-03-05 01:36:31", invitation_accepted_at: "2015-03-05 01:36:52", invitation_limit: nil, invited_by_id: 1, invited_by_type: "User", invitations_count: 0, bio: nil, last_name: "Atrick", gender: 0>
[20] pry(main)> u.email
=> "gerry@test.com"
[21] pry(main)> Node.includes(:user_tags).tagged_with(u.email)
  ActsAsTaggableOn::Tag Load (2.7ms)  SELECT "tags".* FROM "tags"  WHERE (LOWER(name) = LOWER('gerry@test.com'))
  Node Load (2.9ms)  SELECT "nodes".* FROM "nodes" JOIN taggings nodes_taggings_baebc90  ON nodes_taggings_baebc90.taggable_id = "nodes".id AND nodes_taggings_baebc90.taggable_type = 'Node' AND nodes_taggings_baebc90.tag_id = 4
  ActsAsTaggableOn::Tagging Load (2.5ms)  SELECT "taggings".* FROM "taggings"  WHERE "taggings"."context" = 'user_tags' AND "taggings"."taggable_type" = 'Node' AND "taggings"."taggable_id" IN (6, 7)
  ActsAsTaggableOn::Tag Load (1.0ms)  SELECT "tags".* FROM "tags"  WHERE "tags"."id" IN (4, 6)
=> [#<Node id: 6, name: "10PP Form Video", family_tree_id: 57, user_id: 57, media_id: 118, media_type: "Video", created_at: "2015-03-09 20:57:19", updated_at: "2015-04-03 00:25:38", circa: nil, is_comment: nil>,
 #<Node id: 7, name: "Hercules", family_tree_id: 57, user_id: 57, media_id: 120, media_type: "Video", created_at: "2015-03-12 08:54:29", updated_at: "2015-03-31 21:48:05", circa: nil, is_comment: nil>]

For the life of me, I can’t figure out why the spec is returning an empty relation.

Thoughts?

Hmm…one thought…assuming you’re using acts as taggable, from the readme it looks like you need to save as follows:

@another_user = User.new(:name => "Alice")
@another_user.skill_list.add("clowning")
@another_user.save

In the spec, you’re calling get :index before you’ve created any data.

In other words, instead of “setup, exercise, verify” you have “exercise, setup, verify”:

See The four phase test.

@treble37 This is actually a great suggestion. One of the few things I hadn’t tried before.

However, I just tried it and that doesn’t fix it :frowning:

Is there anyway for me to combine the add_tag line with the node creation line? i.e. I would love to combine these two:

  n1 = create(:node, family_tree: family_tree)      
  n1.user_tag_list.add(u1.email, u2.email)

I can’t figure out how to do that though.

@andyw8 - Yeh I tried that already but it doesn’t fix it either.

Are you sure?

You definitely need to move the get :index line to immediately before your expect line.

After you do that, can you paste the relevant contents of your test.log?

@benorenstein

I am not quite sure about how to read test.log properly. Or rather, how to sync it up with my spec.

So I think I have whittled it down to the most important/relevant bits for this particular it block, and have put it here:

Let me know if that is sufficient info. If not, I can provide more.

Thanks.

@benorenstein Another thing could be that current_user is not being set properly, hence why it is returning nil.

The issue is I am getting it to work properly in another spec elsewhere…so I don’t know.

I think this is exactly the problem.

You likely want to write a method to simulate logging in a user (it will probably set user_id in the session).

I thought I was doing that, the gist has the code where I did that. Specifically:

Along with this:

Where are you defining @user in the let blocks in dashboard_controller_spec.rb?

It appears that you may be trying to reference the logged-in user that’s created in your SpecAuthentication helper, but it won’t have been created yet because you’re calling login_user after the let blocks.

I might also refactor this Mystery Guest by explicitly creating the user in the test setup and passing it as an argument to login_user.

1 Like

I am defining that in the spec/support/devise.rb file, like so:

module SpecAuthentication
  def login_user
    @request.env["devise.mapping"] = Devise.mappings[:user]
    @user = FactoryGirl.create :user
    sign_in @user
  end
end
 
RSpec.configure do |config|
  config.include Devise::TestHelpers, type: :controller
  config.include SpecAuthentication, type: :controller
end

Does that look right?

Edit:

Note that I even re-arranged my dashboard_controller_spec.rb to put the login_user call before all the let blocks, but it still doesn’t work.