RSpec: Test my own controllers

667 views
Skip to first unread message

Swibge

unread,
Jul 25, 2014, 12:33:59 PM7/25/14
to spree...@googlegroups.com
Hi,

I just wanted to know what to do for test my own controllers.
I created them in the Spree namespace... everything working well.

But when I want to use RSpec... even if I put my files into the path:

/spec/controllers/spree/api/custom_products_controller.rb

runing with:

bundle exec rspec spec/controllers/spree/api/custom_products_controller.rb

It's failing with:

Failure/Error: get :index
     ActionController::UrlGenerationError:
       No route matches {:action=>"index", :controller=>"spree/api/custom_products"}

If I try with the "api_get" method, like into the Spree RSpec files, it's not working because the method is undefined...

I really don't know how to fix it.
Here's the beginning of my RSpec file:

require 'rails_helper'

module Spree
describe Spree::Api::CustomProductsController, type: :controller do
  let(:shipping_category) { Spree::ShippingCategory.create!(name: 'default') }

  before do
    Spree::Customization.create!(reference: '01', price: 10)
    Spree::Customization.create!(reference: '02', price: 20)
  end

  describe 'GET #index' do

    context 'with existing custom products' do
      before do
        Spree::Product.create!(name: 'Product1', price: 5, shipping_category_id: shipping_category.id) # normal product
        Spree::Product.create!(name: 'CustomProduct1', price: 10, shipping_category_id: shipping_category.id, perso_id: 1) # custom products
        Spree::Product.create!(name: 'CustomProduct2', price: 20, shipping_category_id: shipping_category.id, perso_id: 2)
        api_get :index
      end

      it 'responds with 200' do
        expect(response).to be_success
        expect(response).to have_http_status(200)
      end

      it 'return 2 resources' do
        resources = JSON.parse(response.body)
        expect(resources.length).to eq(2)
      end
  end
end


Regards,
Swibge

Martin Tomov

unread,
Jul 25, 2014, 4:16:33 PM7/25/14
to spree...@googlegroups.com
Hi Swibge,

I think you need to make use of the module ControllerHacks, which defines the `api_get`. As Spree is mounted as an Engine, you will need to prefix all Spree routes with spree like this: `spree.route_path`


I guess one way is to copy it directly into your spec/support directory, another to require it in your spec_helper.rb or directly in your controller spec.

Martin

Swibge

unread,
Jul 28, 2014, 4:10:19 AM7/28/14
to spree...@googlegroups.com
Hi Martin,

Thanks for your help.
I just did the trick..:

# spec/rails_helper.rb
require 'spree/api/support/controller_hacks'

RSpec.configure do |config|
  [...]
  config.include Spree::API::Support::ControllerHacks, :type => :controller
end

But it's now telling me that:
/Library/Ruby/Gems/2.0.0/gems/polyglot-0.3.5/lib/polyglot.rb:65:in `require': cannot load such file -- spree/api/support/controller_hacks (LoadError)

I tried to find an issue related to that... but nothing,
Hope you can help me again ;)

Regards,
Swibge

Martin Tomov

unread,
Jul 28, 2014, 4:47:55 AM7/28/14
to spree...@googlegroups.com
Hi Swibge,


I think that you cannot require the file directly like this, because it is not on your relative paths. I think you need to go with an absolute path

require File.join(Rails.root, 'spree/api/support/controller_hacks')

and adjust it to your app.

Martin

Swibge

unread,
Jul 28, 2014, 5:25:13 AM7/28/14
to spree...@googlegroups.com
Thanks for all Martin,
Is working...

Antoher question, because I need authentication to test my API controller...
If you know how to use the method:
stub_authentication!
as it's done in
https://github.com/spree/spree/blob/2-3-stable/api/spec/controllers/spree/api/products_controller_spec.rb

module Spree
 
...
  before
do
    stub_authentication
!
 
end
 
...
end

Again, hope you can help,
and thanks for your tips ;)

Swibge

Swibge

unread,
Jul 28, 2014, 5:34:23 AM7/28/14
to spree...@googlegroups.com
Sorry, I forgot the "error" message, maybe this could help...

Failure/Error: expect(response).to be_success
       expected `#<ActionController::TestResponse:0x007fb4113fc4e8 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x007fb41176b930>, @stream=#<ActionDispatch::Response::Buffer:0x007fb4114b1668 @response=#<ActionController::TestResponse:0x007fb4113fc4e8 ...>, @buf=["{\"exception\":\"undefined method `authenticate' for nil:NilClass\"}"],

It seems that the method "authenticate" doesn't exist...
But where to "include" it... this is the problem.
I didn't find something related to it into other API controllers.

Thanks, regards,
Swibge

Swibge

unread,
Jul 28, 2014, 5:37:26 AM7/28/14
to spree...@googlegroups.com
And again sorry, for spam...

It seems to be related to:
How can I include all "supports" file for my spec...

Regards,
Swibge

Martin Tomov

unread,
Jul 28, 2014, 7:43:54 AM7/28/14
to spree...@googlegroups.com
That is all right. Have a look at the API spec_helper.rb.


Just copy some of the lines to your spec_helper.rb
require 'spree/api/testing_support/helpers'



RSpec.configure do |config|
 config
.include Spree::Api::TestingSupport::Helpers, :type => :controller
end


The testing support helpers are already on your relative path, so you can just require them with the line above.

Martin


Swibge

unread,
Jul 29, 2014, 10:45:06 AM7/29/14
to spree...@googlegroups.com
Hi Martin,

I just done what you said... and to be sure also add the spree testing_support setup file...
This change nothing.

If you want, this is my configuration:
# /spec/rails_helper.rb

# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require 'spec_helper'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'

require '/Users/Swibge/.bundler/ruby/2.0.0/spree-b6fba810ec20/api/spec/support/controller_hacks'
require 'spree/api/testing_support/helpers'
require 'spree/api/testing_support/setup'

# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }

# Checks for pending migrations before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = true

  # RSpec Rails can automatically mix in different behaviours to your tests
  # based on their file location, for example enabling you to call `get` and
  # `post` in specs under `spec/controllers`.
  #
  # You can disable this behaviour by removing the line below, and instead
  # explicitly tag your specs with their type, e.g.:
  #
  #     RSpec.describe UsersController, :type => :controller do
  #       # ...
  #     end
  #
  # The different available types are documented in the features, such as in
  config.infer_spec_type_from_file_location!

  config.include ControllerHacks, :type => :controller
  config.include Spree::Api::TestingSupport::Helpers, :type => :controller
  config.extend Spree::Api::TestingSupport::Setup, :type => :controller
end


It's included in my spec/controllers/spree/api/custom_products_controller.rb.
Continues to tell me that the method 'authenticate' doesn't exist.

I will continue my search on internet.
If you have another idea, I'm here ;)

Thanks again for your time,
Swibge

Swibge

unread,
Jul 30, 2014, 5:40:20 AM7/30/14
to spree...@googlegroups.com
Hi,

I after some research and experiences... I finally can make it "work".
I added some gem to my Gemfile, as:

group :test do
  gem 'factory_girl'
  gem 'capybara'
  gem 'faker'
end

Here my rails_helper file:
/spec/rails_helper.rb
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require 'spec_helper'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'

# == Load core factories and other testing support libreries from Spree core
require 'spree/testing_support/factories'
require 'spree/testing_support/preferences'

# == Load API helpers
require 'spree/api/testing_support/helpers'
require 'spree/api/testing_support/setup'

# == Load Controller hacks helper (api_get, api_post...)
require '/Users/Swibge/.bundler/ruby/2.0.0/spree-b6fba810ec20/api/spec/support/controller_hacks'
  config.include FactoryGirl::Syntax::Methods
  config.include Spree::Api::TestingSupport::Helpers, :type => :controller
  config.extend Spree::Api::TestingSupport::Setup, :type => :controller
  config.include Spree::TestingSupport::Preferences, :type => :controller
  config.include Devise::TestHelpers, :type => :controller
  config.extend ControllerMacros, :type => :controller
end


And it's done.

But now I got another question...
I want to use the method "stub_authentication!"... or something from Spree to authenticate as an admin or a normal user.
For that, I see that the "stub_authentication!" is defined into the 'spree/api/testing_support/helpers' file.
If I want to use it, I need to call it into a "before" block:
before do
  stub_authentication!
end
... the method exist, no problem, just I don't think that it's authenticate me, because I have a "huge" error, as my "rspec test" can't access "data".

So I created a "ControllerMacro" has it's recommended on the Devise github:
#spec/support/controller_macros.rb
module ControllerMacros
  def login_admin
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:admin]
      sign_in FactoryGirl.create(:admin_user) # Using factory girl as an example
    end
  end

  def login_user
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:user]
      user = FactoryGirl.create(:user)
      user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the "confirmable" module
      sign_in user
    end
  end
end

And in my spec controller, I call the method "login_admin"... TADA is working well!

---

My question is, how use Spree stub_authentication!? Is is the right "service"?

Thanks again for your tips,
and your time.

Swibge

Martin Tomov

unread,
Jul 31, 2014, 4:49:13 AM7/31/14
to spree...@googlegroups.com
Swibge,

Great that you have found a way through. Indeed stub_authentication! is only stubbing authentication for API requests. You cannot use it to login to the backend or frontend of Spree. For that you will need the Controller Macros that you have found.

No problem : ) Glad I was able to help.
Reply all
Reply to author
Forward
0 new messages