skip to Main Content

My project is a Rails 5.2 app, running Ruby 2.6, and uses the shopify_gem and factory_bot_rails.

I have a controller that inherits from ShopifyController. My unit tests for controllers are stuck at a 302. I’m unable to figure out how to get past authentication…

I’ve tried these tutorials and other links, but no luck:

My controller test is below

require 'rails_helper'

describe OnboardingController, type: :controller do

  before do
    shop = FactoryBot.create(:shop)

    request.env['rack.url_scheme'] = 'https'
    @request.session[:shopify] = shop.id
    @request.session[:shopify_domain] = shop.shopify_domain
  end

   it 'onboards correctly', :focus do
    get :onboard_completed
    expect(response).to have_http_status(:success)
   end

end

I was also playing with this code, but it failed (errors in comments):

module ShopifyHelper

  def login(shop)
    OmniAuth.config.test_mode = true
    OmniAuth.config.add_mock(:shopify,
      provider: 'shopify',
      uid: shop.shopify_domain,
      credentials: { token: shop.shopify_token })
    Rails.application.env_config["omniauth.auth"] = OmniAuth.config.mock_auth[:shopify]

    get "/auth/shopify" # this leads to a UrlGenerationError
    follow_redirect! # this is an undefined method. Seems to be a MiniTest thing

  end

end

3

Answers


  1. Chosen as BEST ANSWER

    This ended up being the working solution

    
    require 'rails_helper'
    
    describe WizardController, type: :controller do
    
      before do
        shop = FactoryBot.create(:shop)
    
        request.env['rack.url_scheme'] = 'https'
        allow(shop).to receive(:wizard_completed?).and_return(false)
        allow(Shop).to receive(:current_shop).and_return(shop)
    
        # @note: my original code had "session[:shopify]" of "session[:shop]", which was the error
        session[:shop_id] = shop.id
        session[:shopify_domain] = shop.shopify_domain
      end
    
      it 'enter test here', :focus do
        get :wizard
        expect(response).to have_http_status(:success)
      end
    
    end
    
    

  2. require 'rails_helper'
    
    RSpec.describe "Home", type: :request do
      def login(shop)
        OmniAuth.config.test_mode = true
        OmniAuth.config.add_mock(:shopify,
          provider: 'shopify',
          uid: shop.shopify_domain,
          credentials: { token: shop.shopify_token })
        Rails.application.env_config["omniauth.auth"] = OmniAuth.config.mock_auth[:shopify]
    
        get "/auth/shopify"
        follow_redirect!
    
        @request.session[:shopify] = shop.id
        @request.session[:shopify_domain] = shop.shopify_domain
      end
    
      describe "GET /" do
        it "works!" do
    
          shop = Shop.first || create(:shop)
    
          login(shop)
          get root_path
    
          shop.with_shopify!
    
          expect(assigns(:products)).to eq ShopifyAPI::Product.find(:all, params: { limit: 10 })
          expect(response).to render_template(:index)
          expect(response).to have_http_status(200)
        end
      end
    end
    

    Something like this works for me, your getting the errors in your function probably because you do not have get and follow_redirect! functions defined in your ShopifyHelper module context.

    Reference: http://www.codeshopify.com/blog_posts/testing-shopify-authenticated-controllers-with-rspec-rails

    Login or Signup to reply.
  3. This worked for me:

    # File: spec/support/request_helper.rb
    def shopify_login(shop)
    
      OmniAuth.config.test_mode = true
      OmniAuth.config.add_mock(:shopify, provider: 'shopify', uid: shop.myshopify_domain,
                                       credentials: { token: shop.api_token })
      Rails.application.env_config['omniauth.auth'] = OmniAuth.config.mock_auth[:shopify]
      get "/auth/shopify/callback?shop=#{shop.myshopify_domain}"
      follow_redirect!
    
      @request.session[:shopify] = shop.shopify_id
      @request.session[:shop_id] = shop.id
      @request.session[:shopify_domain] = shop.myshopify_domain
    end
    

    Btw, testing controllers are deprecated in favour of requests.

    RSpec.describe 'ShopsController', type: :request do
      let(:shop) { FactoryBot.build :shop }
      let(:plan) { FactoryBot.build :enterprise_plan }
      let(:subscription) { FactoryBot.create :subscription, shop: shop, plan: plan }
    
     describe 'GET#product_search' do
      it 'returns a successful 200 response for listing action do' do
        VCR.use_cassette('shop-search-product', record: :new_episodes) do
        new_subscrip = subscription
        shopify_login(new_subscrip.shop)
    
        get product_search_path, { params: { query: 'bike' } }
        json = JSON.parse(response.body)
    
        expect(response).to be_successful
        expect(json.length).to eq(7)
       end
      end
    end
    

    Remember to setup "admin { true }" in your shop’s FactoryBot if you are using the ‘shopify_app’ gem.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search