I have a Shopify Rails app and I am trying to test some of the functionality of my "pro" plan, but having trouble updating the test shop plan. I can login no problem, but when I try to update my shops plan via capybara, I get redirected to the login page.
I've done some troubleshooting, but I really have no idea where this issue is stemming from because it works fine when I try it manually in my browser. Maybe database_cleaner or caching issue?
Here's my cucumber steps (basically just login to the app, choose a plan):
Background:
Given I am a logged in user
When I am on the pro plan
Capybara:
When "I am a logged in user" do
step "I visit the login page"
step "I supply my shopify url"
step "I get taken to the app index page"
end
When /^I am on the (.+) plan$/ do |plan|
click_link_or_button "Settings & Notifications"
click_link_or_button "edit plan"
choose("shop_plan_#{plan}")
click_link_or_button "Update Plan"
click_link_or_button "Approve charge"
end
The driver successfully authenticates into the app, visits the edit plan page, visits the Shopify "approve charge" authorization page. But after clicking "approve charge", the browser is redirected to the login page instead of the action I am expecting.
When I try this manually in my own browser, I am redirected to the correct page.
Here's the actual controller action when a user updates their plan:
Step 1. User selects plan from settings page - posts to this action, which will redirect user to a page with embedded JS which redirects user to a Shopify authentication page (has to be done this way to escape the embedded app iframe).
def update_plan_step_1
@plan = shop_params[:plan]
redirect_url = current_shop.confirm_plan(@plan)
gon.authorization_url = redirect_url
render :redirect_to_shopify_auth
end
And here is the confirm_plan method. Basically this creates a new Shopify Charge object - Shopify is going to respond with a unique expiring URL for the user to confirm the charge. We need to provide the price, name, and return_url for Shopify to redirect the user after they approve the charge:
def confirm_plan(shopify_plan)
price = Plan.cost(shopify_plan)
name = shopify_plan + "Plan"
return_url = update_plan_step_2_url(:host => Figaro.env.root_uri)
response = ShopifyAPI::RecurringApplicationCharge.create({
:name => name,
:price => price,
:return_url => return_url,
:test=> !Rails.env.production?
})
response.confirmation_url
end
When I pry into this, I can see the return_url is set to the proper location: http://localhost:23456/shop/plans/update_plan_step_2
(shops#update_plan_step_2).
After user approves the charge on Shopify authentication page, they are supposed to be redirected to this action:
def update_plan_step_2
#some code to update our shop record
end
But when I pry into this action, I can see that it's not even being called in the Test, so I know the issue is happening before this.
To summarize, it looks like everything is working until the user is supposed to be redirected to http://localhost:23456/shop/plans/update_plan_step_2
. Instead, they are redirected to the authentication page.
Why would this happen in the test, but not when I try doing it manually? Any ideas on where the issue lies?
Logs:
Started GET "/shop/plans/update_plan_step_2?charge_id=12345" for 127.0.0.1 at 2015-10-30 11:09:58 -0700
Processing by ShopsController#update_plan_step_2 as HTML
Parameters: {"charge_id"=>"12345"}
Redirected to http://localhost:23456/login
So we can see user is being redirected to authenticate. Why would this be happening only in test? Could it be a caching issue where the shop session is not being stored in the test? And the session is destroyed when the user is taken off the app to the Shopify authentication page?
EDIT: I know exactly where it's being redirected (in an before action in the controller)
def shopify_session
if shop_session
begin
ShopifyAPI::Base.activate_session(shop_session)
yield
ensure
ShopifyAPI::Base.clear_session
end
else
redirect_to_login ## REDIRECTED HERE
end
end
Which means after user authenticates via Shopify, the shopify_session no longer exists.