0

I'm trying to get into TDD and i'm currently struggling with this error message:

UsersController GET 'show' should find the right user
     Failure/Error: expect(user).to eq(@user)

       expected: #<User id: 1, email: "example@example.com", encrypted_password: "$2a$04$AVGGS0XU1Kjmbdc/iZ86iOq2f4k992boP7xfqcg2nl6...", 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: "2014-06-08 19:43:41", updated_at: "2014-06-08 19:43:41", name: "Test User", confirmation_token: nil, confirmed_at: "2014-06-08 19:43:41", confirmation_sent_at: nil, unconfirmed_email: nil, account_id: 1, notify: nil>
            got: nil

       (compared using ==)
     # ./spec/controllers/users_controller_spec.rb:28:in `block (3 levels) in <top (required)>'

Here's the particular test:

require 'rails_helper'
include Devise::TestHelpers

describe UsersController do

  before (:each) do
    @user = FactoryGirl.create(:user)
    sign_in @user
  end

  describe "GET 'show'" do

    it "should find the right user" do
      get :show, :id => @user.id
      puts "user = #{@user.inspect}"
      user = assigns(:user)
      #assigns(:user).should == @user
      puts "assigns user = #{assigns(:user)}"
      expect(user).to eq(@user)
    end

  end

end

Here's the controller:

class UsersController < ApplicationController
...
    def show
        authorize! :show, @user, :message => 'Not authorized as an administrator.'
        @user = current_account.users.find(params[:id])
    end

...
end

application_controller.rb:

class ApplicationController < ActionController::Base
    # Prevent CSRF attacks by raising an exception.
    # For APIs, you may want to use :null_session instead.
    protect_from_forgery with: :exception

    check_authorization :unless => :devise_controller?
    before_filter :authenticate_user!, :validate_subdomain
    helper_method :subdomain, :current_account
    layout :set_layout

# This will redirect the user to your 404 page if the account can not be found
    # based on the subdomain.  You can change this to whatever best fits your
    # application.
    def validate_subdomain
        current_account
    end

def current_account
        @current_account ||= Account.where(:subdomain => subdomain).first
        #puts @current_account

        if @current_account.nil?
            redirect_to('/accounts/invalid_site')
            return
        end

        @current_account
    end


def subdomain
        request.subdomain
    end

...
end

user factory:

FactoryGirl.define do
  factory :user do
    name 'Test User'
    account_id 1
    email 'example@example.com'
    password 'changeme'
    password_confirmation 'changeme'
    # required if the Devise Confirmable module is used
    confirmed_at Time.now
  end
end

How can I get around this error message? I have a feeling it has something to do with before_filters, but that's just a guess.

Catfish
  • 18,876
  • 54
  • 209
  • 353
  • Does FactoryGirl.create add the user to the user's table? else current_account.users.find(params[:id]) wont work..just a guess – sethi Jun 08 '14 at 19:56
  • I just added the user factory to the question. – Catfish Jun 08 '14 at 20:56
  • Use a debugger or add logging to see why the second line of `show` isn't setting the user. Look at the values of `current_account`, `current_account.users` and `params[:id]`. – Dave Schweisguth Jun 10 '14 at 20:47
  • `@current_account` contains the same `user` that i'm expecting. When I do `puts params = #{params]`, I get this error: `Failure/Error: puts "params = #{params}" NameError: undefined local variable or method params' for #` – Catfish Jun 11 '14 at 01:57
  • If i change `puts params = #{params]` to `puts params = #{controller.params]` I see some params. The test still fails though. – Catfish Jun 11 '14 at 02:06
  • Wait i lied, current_account is empty.. – Catfish Jun 11 '14 at 02:23

2 Answers2

0

Do you have before_filter on your users controller where you need authentication to use the show method? Your before block is making two calls, creating a user and then "sign_in", some kind of authentication. But your test is just to see if the user was created and the show method returns the correct user record with the passed id.

So I would break down your before block. Start by testing that your Factory is being created successfully:

it 'has a valid factory' do
    FactoryGirl.create(:user).should eq(true) # or should be_valid.. 
end

If that passes, I'd comment out any constraint on your users controller (temporarily) for the sign_in method, and test if show receives the id and returns the correct user.

If that passes, then add the constraint back in for validation on your users controller, and figure out how to test your sign_in method. :)

Andrew
  • 375
  • 2
  • 12
  • So would I put the `has a valid factory` test inside my before block or after it? If i put it after it, I get `email is already taken`. Also, the sign in method is devise's sign in method. – Catfish Jun 08 '14 at 20:59
  • The `has a valid factory` test passes just fine. I've tried commenting out all my before_filters in my application controller and all the can can authorization checks and it still does not work. – Catfish Jun 10 '14 at 03:00
0

Ok so i figured it out from debugging through the current_account not getting set. I found this answer Rails rspec set subdomain.

I guess i left out a major piece of the puzzle in my original question so i apologize about that as I had no idea that would affect my rspecs.

The trick was to

before(:each) do
  @account = FactoryGirl.create(:account)
  @request.host = "#{@account.subdomain}.example.com"
end
Community
  • 1
  • 1
Catfish
  • 18,876
  • 54
  • 209
  • 353