Testing Rails Shopify App with Authenticated Graphql Controller

cosoare
Shopify Partner
9 1 2

Hello, I am new to building Shopify apps and I have started a project using a Rails 6 app with the shopify_app gem (v18.x) and a graphql controller.

I'm trying to write a request spec which uses the setup described in this issue to mock Oauth and provide the login helper to login the shop, in order to test my GraphQL mutations.

 

The problem I am facing as it stands is in my login method I set the shopify_domain on the session object and expect to have it available as part of the session object in my graphql controller, so I can pass it to the context param and make it available to any Query or Mutation.

 

This is the helper login method inspired by the github issue:

 

 

# spec/support/shopify_helpers.rb

module ShopifyHelpers
  def shopify_login(shop)
    # https://github.com/Shopify/shopify_app/issues/1266
    # standard for Shopify tests, cookie or JWT
    ShopifyApp.configuration.embedded_app = false
    # standard for OmniAuth tests of all kinds
    OmniAuth.config.test_mode = true
    # recommended to enable /auth/shopify and bypass devise override
    OmniAuth.config.allowed_request_methods = [:get]
    # silences omniauth noise telling me that the above line opens us up to vulnerabilities
    OmniAuth.config.silence_get_warning = true
    # standard implementation for mocking out the shopify omniauth provider structure
    OmniAuth.config.add_mock(
      :shopify, 
      provider: 'shopify', 
      uid: shop.shopify_domain,
      credentials: { token: shop.shopify_token }
    )
    # the next 4 lines are technically setting `request.env['key']` on a request that has not yet been made
    Rails.application.env_config['omniauth.auth'] = OmniAuth.config.mock_auth[:shopify]
    Rails.application.env_config['omniauth.params'] = { shop: shop.shopify_domain }
    Rails.application.env_config['jwt.shopify_domain'] = shop.shopify_domain
    Rails.application.env_config['jwt.shopify_user_id'] = 'test-shopify-user'

    get '/auth/shopify'
    follow_redirect!
    @request.session[:shop_id] = shop.id
    @request.session[:shopify_domain] = shop.shopify_domain

    request.headers.merge!('Authorization': "Bearer "blah")
  end
end

RSpec.configure do |config|
  config.include ShopifyHelpers, type: :request
end

 

 

 

 

In the GraphQL controller, I set the shopify_domain from the session:

 

 

class GraphqlController < AuthenticatedController
  def execute
    ...
    # Session gets set HERE
    context = {
      current_shopify_domain: session[:shopify_domain],
    }
    result = Schema.execute(query, variables: variables, context: context, operation_name: operation_name)
    ...
  end

 

 

 

Then I setup my RSpec suite as follows:

 

 

module Mutations
  module Model
    RSpec.describe CreateModel, type: :request do
      let(:shop) { create(:shop) }
      let(:model) { build(:model, shop: shop) }

      before(:each) do 
        shopify_login(shop)
        session[:shop_id] = shop.id
        session[:shopify_domain] = shop.shopify_domain
      end

      describe '.resolve' do
        it 'creates a model' do
          expect do
            # session[:shopify_domain] exists here
            post '/graphql', params: { 
              query: query(...)
            }
          end.to change { Model.count }.by(1)
        end
       ...
end

 

 

The problem I am seeing is session[:shopify_domain] is nil inside the GraphqlController#execute method, the key seems to get unset for some reason before the post /graphql request happens in the test suite. 

 

Has anyone encountered this issue and would be able to help?

 

Thank you very much 🙂 

cosoare
Replies 0 (0)