We have an app that uses current_visit
as a stand-in user model when a user is not authenticated. We allow a user to "trial" the application, then request they register an account to continue after completing our wizard once. We then associate resources from current_visit
with current_user
using the Devise after_sign_in
method. We also use Pundit, and have a UserContext
object, but I don't think that's relevant for this particular question.
I am trying to write system tests and want to be able to instantiate a visit to a certain state. For example, we have two resources a user could optionally have and I'd like to be able to instantiate a visit into these states:
Visitor could have associated resource B but not A, but this is not common, nor possible via the UI (which is the focus of this system test).
I have added an edit below about an additional approach using mocks.
I am able to instantiate a visitor in my system tests, and they are successfully created in the system test. Using the debugger, I can confirm that the visitor responds to the right methods as I expect, as I can call expect(visitor.reload.resource_a.size).to eq(1)
and pass the spec
However, it seems that this visitor is not associated with the current_visit
on the backend in the system test, as even though the instance of visitor
has the traits I want, the frontend does not display this instantiated visit.
I have tried to initiate a tracker in my system test:
let(:visitor) { create(:ahoyvisit, :with_resources) }
let(:tracker) { Ahoy::Tracker.new(visitor_token: visitor.token) }
But this doesn't seem to work to associate the created visitor to current_visit
in the controller. I am generally unsure how I should properly bridge this gap in my system testing.
[edit]
It was suggested to me to try using a mock, but that also didn't seem to work:
allow_any_instance_of(Ahoy::Tracker).to receive(:visit).and_return(visitor)
Using a mock was the way to go. I simply had to make sure I was mocking the right method and response before visiting my route like so:
it "shows the right thing" do
allow_any_instance_of(ApplicationController).to receive(:current_visit).and_return(visitor)
visit resource_path
expect(page).to have_text(visitor.resource.first.title)
end