-
Notifications
You must be signed in to change notification settings - Fork 678
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Testing controllers that inherit from ShopifyApp::AuthenticatedController #445
Comments
Great question. In Rails 5 Integration Tests are just as fast as controller tests but cover more area so controller tests were removed. This does mean that some kinds of mocking like you described don't work anymore. The solution is fairly intuitive but easy to miss if you're used to controller tests. Every test starts by calling a helper which follows the authentication flow which internally sets the session for you. Then make the desired second request to test in your test. def login_to_shopify
get '/auth/shopify'
follow_redirect!
# session is available now. You could look up the Shop model here and return it if you want
end Of course this isn't enough since this request gets directed to a 3rd party. This is where Omniauth test mode comes in: OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:shopify] = # shop object |
@kevinhughes27 could you elaborate on this line? OmniAuth.config.mock_auth[:shopify] = # shop object I am guessing this has to be an EDIT: def login(shop)
OmniAuth.config.test_mode = true
OmniAuth.config.add_mock(:shopify,
uid: shop.shopify_domain,
credentials: { token: shop.shopify_token })
# And because I am using RSpec (don't know if Minitest needs this):
Rails.application.env_config["omniauth.auth"] = OmniAuth.config.mock_auth[:shopify]
get "/auth/shopify"
end
# Then in my test
shop = FactoryGirl.create(:shop) # or whatever way you like to create test data
login(shop) Still not sure if this is the right way to do it though, so any feedback would be welcome 👍 |
That looks correct to me! Also I've always wanted to include some test helpers in this gem if you want to PR it :) |
@kevinhughes27 the biggest problem is, that you need to trigger the authorization differently depending on the usecase... For example in a capybara test, you would need to do |
Fair enough! I've run into that as well and I'm not sure the cleanest way to solve it either. |
@Ninigi How did you get that working? I face an error when trying to do above. So I have # spec/controllers/admin/dashboards_controller_spec.rb
require 'rails_helper'
RSpec.describe Admin::DashboardsController, type: :controller do
fixtures :shops
describe "#show" do
let!(:shop) { shops(:a_shop) }
before do
login(shop)
end
it "passes" do
expect(true).to be
end
end
end # spec/support/admin_controller_test_helpers.rb
module AdminControllerTestHelpers
def login(shop)
OmniAuth.config.test_mode = true
OmniAuth.config.add_mock(:shopify, uid: shop.shopify_domain, credentials: { token: shop.shopify_token })
Rails.application.env_config["omniauth.auth"] = OmniAuth.config.mock_auth[:shopify]
get "/auth/shopify"
end
end And the error is:
This has something to do with how rspec works. It assumes |
@waseem It is 1:30 AM for me right now and I really do not recall this issue very well, so please forgive me for giving spongy advice... It looks like you are trying to execute the login at a time, where not all the necessary data is available, as in the method I described heavily relies on an rspec controller/request context. |
No tests because of Shopify/shopify_app#445 (comment)
I ran into same issues, with not matching route. I suspect rspec only setting up the controller under test routes. Has anyone a working example that could be posted? |
require 'test_helper'
class AssetsControllerTest < ActionDispatch::IntegrationTest
def login(shop)
OmniAuth.config.test_mode = true
OmniAuth.config.add_mock(
:shopify,
provider: 'shopify',
uid: shop.shopify_domain,
credentials: { token: shop.shopify_token }
)
get "/auth/shopify"
follow_redirect!
ShopifyAPI::Shop.stubs(:current).returns(shop)
end
setup do
login(shops(:regular_shop))
end
test "associate should return the corresponding asset if it exists" do
assert_no_difference('Asset.count') do
get assets_associate_url
end
assert_response :ok
end
end |
This was initially posted on the Shopify forums, but was recommended to post it here.
I am using Minitest for testing. My controllers inherit from
ShopifyApp::AuthenticatedController
, and so in order to test them I need to somehow stub/mock a Shopify session. Previously withActionController::TestCase
there was a simple solution to this:But with the move to
ActionDispatch::IntegrationTest
, there is no longer any access to the@request
instance variable when testing controllers.What are the best practices for testing controllers that inherit from
ShopifyApp::AuthenticatedController
in Rails 5?The text was updated successfully, but these errors were encountered: