Search code examples
ruby-on-railsrspecdevisecapybarafactory-bot

How to send in a random variable from Rails Rspec test to application controller? (devise, factorybot, capybara)


I need a way to Rspec various redirects to specific pages based on the ip/location of people coming to the splash page.

scenario "User from asdf sees ASDF page" do

    create_user_from_asdf

    visit root_path
    
    expect(page).to have_css("#egativenay_onyay_erqway_ehyay")

  end

Creating a factorybot user from asdf is redundant, as there is no user until they sign in (devise), otherwise I could create a user with some random attribute to trigger code in the application controller etc.

Normally, the redirects to the various splash pages is filtered using request.host or request.location.country

While performing the Rspec tests, when visiting root_path, the request.host is capybara's standard "www.example.com", and the request.location.country is "Reserved".

how do I edit this?

or how do I somehow notify the application controller, from an Rspec example/scenerio test, that certain code is to be initiated to modify the path to ASDF page?

... how do i send in a random variable from Rspec that is accessible from the application controller?


Solution

  • You could mock the Request object methods that you care about...

    This would mock the request.host:

    scenario "User from 'host' sees HOST page" do
      allow_any_instance_of(ActionDispatch::Request).to receive(:host).and_return("host")
    
      visit root_path    
    
      expect(page).to have_css("#host")
    end
    

    And, this would mock the request.location.country:

    scenario "User from country sees COUNTRY page" do
      location = instance_double("location", country: "country")
      allow_any_instance_of(ActionDispatch::Request).to receive(:location).and_return(location)
    
      visit root_path    
    
      expect(page).to have_css("#country")
    end
    

    Note: To preempt the inevitable comments about allow_any_instance_of being an anti-pattern, it's necessary in this case in order to get a handle on the instance of the Request class spun up by Rails.

    Note 2: There may also be a different way of going about this by using Rack::Test, which gives you access to set request headers.