Pavan
Pavan

Reputation: 33542

Why are my tests failing with bad argument (expected URI object or URI string) error?

I have a scenario where I have to assign roles to the users based on the value of request.referrer(i.e, the URL of the page from where they are signing up). I've achieved it through below code

#application_controller.rb
 private

 def store_referrer_url
   session[:referrer] ||= URI(request.referer).path  if ((self.controller_name == 'registrations' || self.controller_name == 'users/omniauth_callbacks'))
 end

And I'm passing it as a value for a hidden_field in the form like below

<%= f.hidden_field :referrer_url, :value => session[:referrer] %>

Everything working good, but my tests are failing with the below error

2) Sign in user can sign up
     Failure/Error: sign_up(user.first_name, user.last_name, user.email, user.encrypted_password, user.encrypted_password)
     ArgumentError: bad argument (expected URI object or URI string
     ./app/controllers/application_controller.rb:100:in `store_referrer_url'

Below is my test code

#/spec/features/users/user_sign_up_spec.rb
include Warden::Test::Helpers
Warden.test_mode!

feature 'Sign up', :devise do

  scenario 'user can sign up' do
    user = FactoryGirl.create(:user)
    sign_up(user.first_name, user.last_name, user.email, user.encrypted_password, user.encrypted_password)
  end
end

#/spec/features/support/helpers/session_helpers.rb
module Features
  module SessionHelpers
    def sign_up(firstname, lastname, email, password, confirmation)
      visit new_user_registration_path
      fill_in 'first_name', with: firstname
      fill_in 'last_name', with: lastname
      fill_in 'email', with: email
      fill_in 'user_password', with: password, :match => :first
      fill_in 'user_password_confirmation', :with => confirmation
      find("#user_referrer_url").set("/")
      click_button 'Register'
    end
  end
end

#/spec/factories/users.rb
require 'faker'

FactoryGirl.define do
  factory :user do |f|
    f.first_name { Faker::Name.first_name }
    f.last_name { Faker::Name.last_name }
    f.email { Faker::Internet.email }
    f.encrypted_password { Faker::Lorem.characters(10) }
    f.password { Faker::Lorem.characters(10) }
    f.primary_phone { Faker::PhoneNumber.cell_phone }
    f.alternate_phone { Faker::PhoneNumber.phone_number }
    f.role [0,1].sample
    f.agree_tos true
    confirmed_at = Time.now
    f.referrer_url ["/", "/visitors/owner-faq"].sample
  end
end

Update:

I just noticed that request.referer returns for nil for sign_up scenario but it returns "http://www.example.com/" for other sign_in scenarios(which are omitted in the question).

What I'm doing wrong?

Upvotes: 3

Views: 3483

Answers (2)

jakeatwork
jakeatwork

Reputation: 497

Likely you're running into an issue with the headless browser from capybara not having a referrer because you 'opened' the browser directly to the new_user_registration_path resulting in a nil referrer. Imagine clicking on that url in a word doc and your computer opening chrome with that url...there would be no referrer.

So try something like replacing: visit new_user_registration_path with the following:

visit root_path
click_link('Sign Up')

Then maybe it will have a referrer and your test will pass.

Upvotes: 1

Yury Lebedev
Yury Lebedev

Reputation: 4005

You are passing the path as an argument to create a URL object.

To make it work you need to add host to your referrer value.

Upvotes: 0

Related Questions