J'essaie de créer une spécification pour un flux de déconnexion en utilisant factorygirl pour créer un utilisateur, puis en utilisant sign_in
méthode pour authentifier l'utilisateur, puis utilisez capybara pour cliquer sur le lien "Déconnexion".
Je reçois (ce qui me semble être) une étrange erreur lorsque j'exécute la spécification:
Failures:
1) Sign out flow successfully redirects to the welcome index (root)
Failure/Error: Unable to find matching line from backtrace
NoMethodError:
undefined method `env' for nil:NilClass
# /home/vagrant/.rvm/gems/Ruby-2.0.0-p576/gems/devise-3.4.1/lib/devise/test_helpers.rb:24:in `setup_controller_for_warden'
Finished in 0.00226 seconds (files took 3.32 seconds to load)
1 example, 1 failure
Voici la spécification:
require 'Rails_helper'
describe "Sign out flow" do
include Devise::TestHelpers
describe "successfully" do
it "redirects to the welcome index (root)" do
user = create(:user)
sign_in user
within '.user-info' do
click_link 'Sign Out'
end
expect(current_path).to eq root_path
end
end
end
Et mon user.rb
usine:
FactoryGirl.define do
factory :user do
name "Fake User"
sequence(:email, 100) { |n| "person#{n}@example.com" }
password "helloworld"
password_confirmation "helloworld"
confirmed_at Time.now
end
end
L'erreur semble être déclenchée simplement à partir de la ligne include Devise::TestHelpers
, car j'ai essayé de commenter tout le contenu de la spécification et j'obtiens toujours la même erreur.
Je pensais que les assistants de test Devise fonctionneraient hors de la boîte; ai-je manqué une configuration? Merci.
Apparemment, il y a des problèmes avec Devise::TestHelpers
et les tests d'intégration, c'est peut-être le problème ici.
https://github.com/plataformatec/devise (mentionné dans README, Issues, etc.; voir également les SO questions connexes):
Ces assistants ne vont pas travailler pour des tests d'intégration pilotés par Capybara ou Webrat. Ils sont destinés à être utilisés uniquement avec des tests fonctionnels. Remplissez plutôt le formulaire ou définissez explicitement l'utilisateur en session;
Dans Rails 5, vous devez inclure Devise::Test::IntegrationHelpers
au lieu Devise::Test::ControllerHelpers
:
# Rails_helper.rb
config.include Devise::Test::IntegrationHelpers, type: :feature
Voir plus:
FWIW, il semble que les problèmes aient été corrigés, mais j'ai rencontré le problème après avoir mal lu la documentation.
C'était notre code:
RSpec.configure do |config|
...
config.include Devise::TestHelpers
...
end
Cela signifie que chaque test comprendra les assistants de test, y compris les modèles. Cela s'est avéré être le problème pour nous. Si nous avions lu la documentation de plus près, nous aurions remarqué que Devise suggère de la limiter aux seuls contrôleurs avec:
RSpec.configure do |config|
...
config.include Devise::TestHelpers, type: :controller
...
end
Cela a résolu le problème pour nous. Tous les tests réussissent :)
Voici ma solution:
class ActiveSupport::TestCase
# all the normal stuff
end
class ActionController::TestCase
include Devise::TestHelpers
end
Je rencontre la même erreur sur Rails 5. Voici ma solution
RSpec.configure do |config|
config.include Devise::TestHelpers, type: :controller
config.include Devise::TestHelpers, type: :view
config.include Warden::Test::Helpers
end
RSpec.describe YourController, type: :controller do
before(:all) do
user = FactoryGirl.create(:user)
login_as user, scope: :user
end
it "#index" do
get "index"
expect(response).to render_template(:index)
expect(response).to have_http_status(200)
end
Run options: include {:focus=>true}
DashboardController
#index
Finished in 3.9 seconds (files took 3.5 seconds to load)
1 example, 0 failures
Comme d'autres l'ont déjà dit, vous incluez le Devise::TestHelpers
. C'est pour tester les contrôleurs . Si vous souhaitez toujours vous connecter automatiquement à un utilisateur de test dans vos tests d'intégration, consultez l'officiel Concevoir des instructions pour l'utiliser avec Capybara.
Fondamentalement, ce que vous devez faire est d'abord activer le mode de test de Warden:
include Warden::Test::Helpers
Warden.test_mode!
Ensuite, (créez et) connectez votre utilisateur:
user = FactoryGirl.create(:user)
login_as(user, scope: :user)
# spec/features/survey_spec.rb
require 'Rails_helper'
feature 'survey app' do
include Warden::Test::Helpers
let(:user) { create(:user) }
let(:survey) { create(:survey_with_questions) }
before do
# Sign the User in
Warden.test_mode!
login_as(user, scope: user)
end
it 'renders the survey' do
visit survey_show_path(survey)
expect(page).to have_content(survey.title)
end
end
Pour être complet, avec Rails 5 et RSpec, j'ai rencontré des problèmes similaires lors de l'utilisation des derniers assistants, car ils doivent être définis explicitement avec le type lorsqu'ils ne sont pas utilisés en tant que superclasse.
Donc, si vous vous retrouvez à recevoir des erreurs dans vos tests de modèle, il y a de fortes chances que le type ne soit pas défini.
Voici ce que j'utilise dans le spec_helper:
config.include Devise::Test::ControllerHelpers, type: :controller
config.include Devise::Test::ControllerHelpers, type: :view
config.include Devise::Test::IntegrationHelpers, type: :feature
Je sais que les documents le mentionnent, mais il peut arriver que vous rencontriez un ancien blog qui vous donne une approche plus ancienne ou une mise à niveau à partir d'une ancienne configuration, et la prochaine chose que vous savez, c'est que cela se produit.
La syntaxe correcte pour Rails 5/Devise (4.2.0) est
RSpec.configure do |config|
config.include Devise::Test::ControllerHelpers, :type => :controller
end
Devise::TestHelpers
sont obsolètes, utilisez donc Devise::Test::ControllerHelpers
:type => :controller
- pour limiter uniquement les contrôleurs et non les modèles par exemple.Ma version Devise est 4.2.0 donc je viens de l'inclure
config.include Devise::Test::ControllerHelpers, type: :controller
dans mon Rails helper file.
Alternativement, vous pouvez utiliser le même dans vos spécifications que
include Devise::Test::ControllerHelpers
J'avais ce problème en essayant de sign_in
un utilisateur dans un hook avant:
before(:context) do
create(:skill, name: 'Google Maps API'.downcase)
user = create(:user)
sign_in user
end
Placement sign_in
à l'intérieur du crochet avant conduit à:
Failure/Error: sign_in user
NoMethodError:
undefined method `env' for nil:NilClass
Mais le placer dans un exemple fonctionne très bien:
shared_examples_for('an authenticated resource.') do
describe 'An authenticated request' do
it "responds with HTTP status OK" do
user = create(:user)
sign_in user
make_request
expect(response).to have_http_status(:ok)
end
end
end
Mais cela peut être amélioré, en plaçant le signe_in dans un avant (: exemple) qui fonctionnera également:
context 'allow search by keyword' do
let!(:skill){ create(:skill, name: 'Google Maps API'.downcase) }
let!(:user) { create(:user) }
before(:example) { sign_in user }
it 'finds matching records' do
get :search, name: "Google Maps API", format: :json
expect(assigns(:skills).size).to be(1)
end
it 'finds records that start with keyword'
it 'finds records that end with keyword'
it 'finds records that contains keyword'
end