Nick
Nick

Reputation: 3090

How to adjust test helper to account for from which model the test user is (metaprogramming)

I've followed Hartl's chapter 8 to develop a log_in_as test helper. Now I wanted to do some metaprogramming by adding type as a parameter. Type specifies which model the user is from. There are two models (Member and Organization) each of which can log in using the same page / create method (through if-else statement).

However, for an integration test the test is not working. The test always sees the user as coming from the model Organization and never from Member. What am I doing wrong?

I have the following test helper:

  def log_in_as(type, user, options = {})
    password    = options[:password]    || 'password'
    remember_me = options[:remember_me] || '1'
    ### Additional if-else statement needed for type? ###
    if integration_test?
      post login_path, session: { email:       user.email,
                                  password:    password,
                                  remember_me: remember_me }
    else
      if type == "mem_ber"
        session[:member_id] = user.id
      elsif type == "org_anization"
        session[:organization_id] = user.id
      end
    end
  end

  def is_logged_in_member?
    !session[:member_id].nil?
  end

  def is_logged_in_organization?
    !session[:organization_id].nil?
  end

  private
    # Returns true inside an integration test.
    def integration_test?
      defined?(post_via_redirect)
    end

The integration test:

require 'test_helper'
class SiteLayoutTest < ActionDispatch::IntegrationTest
  def setup
    @admin         = members(:michael)
    @non_admin     = members(:archer)
    @org_admin     = organizations(:one)
    @org_nonadmin  = organizations(:two)
  end

  test "ff" do
    log_in_as("mem_ber", @admin)
    puts "member: #{is_logged_in_member?}"
    puts "organization: #{is_logged_in_organization?}"
    delete logout_path

    log_in_as("mem_ber", @non_admin)
    puts "member: #{is_logged_in_member?}"
    puts "organization: #{is_logged_in_organization?}"
    delete logout_path

    log_in_as("org_anization", @org_admin)
    puts "member: #{is_logged_in_member?}"
    puts "organization: #{is_logged_in_organization?}"
    delete logout_path

    log_in_as("org_anization", @org_nonadmin)
    puts "member: #{is_logged_in_member?}"
    puts "organization: #{is_logged_in_organization?}"
    delete logout_path
  end
end

Def create in the sessions controller is:

  def create
    @organization = Organization.find_by(email: params[:session][:email].downcase)
    @member = Member.find_by(email: params[:session][:email].downcase)
    if @organization && @organization.authenticate(params[:session][:password])
      if @organization.activated?
        log_in("org_anization", @organization)
        params[:session][:remember_me] == '1' ? remember("org_anization", @organization) : forget("org_anization", @organization)
        redirect_back_or @organization
      else
        message  = "Account not activated. "
        message += "Check your email for the activation link."
        flash[:warning] = message
        redirect_to root_url
      end
    elsif @member && @member.authenticate(params[:session][:password])
      if @member.activated?
        log_in("mem_ber", @member)
        params[:session][:remember_me] == '1' ? remember("mem_ber", @member) : forget("mem_ber", @member)
        redirect_back_or @member
      else
        message  = "Account not activated. "
        message += "Check your email for the activation link."
        flash[:warning] = message
        redirect_to root_url
      end
    else
      flash.now[:danger] = 'Invalid email/password combination'
      render 'new'
    end
  end

For all four log_in_as tests in the test file, it says is_logged_in_member? false and is_logged_in_organization? true, so also if it is actually a fixture coming from members.yml. I've also tried adding

  self.set_fixture_class organizations: Organization
  self.set_fixture_class members: Member

to the test helper, but that made no difference.

If I remove organizations from the test (in def setup as well as remove 2 of the four tests) it still produces the same result in that it sees the member users as organizations. Only when I also empty the organizations fixtures file, it sees the members as members.

Upvotes: 0

Views: 92

Answers (2)

Nick
Nick

Reputation: 3090

I found the cause: it turned out that in both fixtures files there was an instance with the same email address.

Upvotes: 0

Rob Mulholand
Rob Mulholand

Reputation: 899

In test_helper.rb:

self.set_fixture_class usertype1: Usertype1
self.set_fixture_class usertype2: Usertype2

Upvotes: 0

Related Questions