Reputation: 12520
I am trying to write Rspec tests in Rails, using Devise helper methods for signing in and out. The sign_in method is not working. However, it had been working earlier, before a slew of changes to the app.
Things I have tried:
So far, no dice. What do I need to do differently to test my controllers with a signed-in user?
Error message:
OrderItemsController GET #index renders the :index view
Failure/Error: sign_in :admin
NoMethodError:
undefined method `sign_in' for # <RSpec::ExampleGroups::OrderItemsController_2::GETIndex:0x00000102c002d0>
# ./spec/controllers/order_items_controller_spec.rb:6:in `block (2 levels) in <top (required)>'
Controller Spec
require 'spec_helper'
describe OrderItemsController do
before (:each) do
admin = create(:admin)
sign_in :admin
end
describe "GET #index" do
it "renders the :index view" do
get :index
expect( response ).to render_template :index
end
end
end
spec_helper.rb
require 'rspec/rails'
require 'capybara/rspec'
RSpec.configure do |config|
config.include ApplicationHelper
config.include ControllersHelper
config.include UsersHelper
config.include Devise::TestHelpers, type: :controller
config.include FactoryGirl::Syntax::Methods
end
Gemfile
group :development, :test do
gem 'rspec-rails', '~> 3.0.0.beta'
gem 'capybara'
gem 'factory_girl_rails'
gem 'faker'
gem 'dotenv-rails'
gem 'guard'
gem 'guard-annotate'
gem 'guard-rspec', require: false
gem 'guard-livereload', require: false
gem 'foreman'
end
factories/user.rb
FactoryGirl.define do
factory :user do
first { Faker::Name.first_name }
last { Faker::Name.last_name }
email { Faker::Internet.email }
admin false
password "secrets1"
password_confirmation "secrets1"
confirmed_at Date.today
factory :admin do
admin true
end
end
end
Thanks in advance.
Upvotes: 39
Views: 24083
Reputation: 31
You can use login_as method instead like this:
# rails_helper.rb
RSpec.configure do |config|
config.include Warden::Test::Helpers
end
In your spec file use:
#spec/integration/user_flow_spec.rb
before :each do
employee = create(:employee)
login_as employee, scope: :user
end
Upvotes: -1
Reputation: 2288
If you need the sign_in
method in a request spec file, then you should include this:
config.include Devise::Test::IntegrationHelpers, type: :request
Upvotes: 9
Reputation: 371
For Rails 5 and Rspec 3 you need to add this into your spec_helper.rb
config.include Devise::Test::ControllerHelpers, type: :controller
Upvotes: 2
Reputation: 2354
You can use the Devise helper in the file spec/spec_helper.rb:
RSpec.configure do |config|
config.include Devise::TestHelpers, type: :controller
end
Upvotes: 7
Reputation: 11990
Did you recently upgrade to RSpec 3 like I did? This is from the RSpec 3 documentation:
Automatically Adding Metadata RSpec versions before 3.0.0 automatically added metadata to specs based on their location on the filesystem. This was both confusing to new users and not desirable for some veteran users.
In RSpec 3, this behavior must be explicitly enabled:
# spec/rails_helper.rb RSpec.configure do |config| config.infer_spec_type_from_file_location! end
Since this assumed behavior is so prevalent in tutorials, the default configuration generated by rails generate rspec:install enables this.
If you follow the above listed canonical directory structure and have configured infer_spec_type_from_file_location!, RSpec will automatically include the correct support functions for each type.
After I add that configuration snippet, I no longer have to specify the spec type (e.g. type: :controller
).
Upvotes: 31
Reputation: 12520
I figured out a solution. I explicitly defined the controller's Describe block as a controller type.
describe OrderItemsController, :type => :controller do
I still don't understand why this code worked earlier but now needs this (seemingly redundant) explicit declaration. Regardless, I'd appreciate learning what happened here. Thanks!
Upvotes: 8
Reputation: 808
I can provide you an example (works for me - rspec / capybara / simplecov etc..)
spec/spec_helper.rb
require 'capybara/rspec'
require 'capybara/rails'
RSpec.configure do |config|
config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.include FactoryGirl::Syntax::Methods
config.include Devise::TestHelpers, type: :controller
config.include Capybara::DSL
config.include Warden::Test::Helpers
config.include Rails.application.routes.url_helpers
end
spec/integration/user_flow_spec.rb
require 'spec_helper'
feature 'Verify contract' do
# Create employee
let(:employee) { create(:employee) }
let (:book) { create(:book) }
# Sign in employee before each test!
before :each do
login_as employee, scope: :user
end
scenario 'create book' do
# Visit Index and click to create
visit employee_books_path
click_link 'Create'
expect(current_path).to eq(employee_books_path)
end
end
I hope it will be ok :) I think your problem is missing Warden test helpers...
Upvotes: 7