2015-04-08 16 views
11

Ambientedevise e rspec-rails - Come accedere l'utente nelle specifiche del tipo di richiesta (specifiche con il tag type:: request)?

Rails 4.2.0 
ruby-2.2.1 [ x86_64 ] 
devise   3.4.1 
rspec-core 3.2.2 
rspec-rails 3.2.1 

Nel mio /spec/rails_helper.rb Ho incluso Devise aiutanti per i file spec taggati con type: :controller e type: :request

spec/rails_helper.rb

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 = false 

    config.before(:suite) do 
    DatabaseCleaner.strategy = :transaction 
    DatabaseCleaner.clean_with(:truncation) 
    end 

    config.before(:suite) do 
    begin 
     DatabaseCleaner.start 
     FactoryGirl.lint 
    ensure 
     DatabaseCleaner.clean 
    end 
    end 

    config.around(:each) do |example| 
    DatabaseCleaner.cleaning do 
     example.run # ==================> L-60 
    end 
    end 

    config.include FactoryGirl::Syntax::Methods 

    # 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 
    # https://relishapp.com/rspec/rspec-rails/docs 
    config.infer_spec_type_from_file_location! 

    config.include Devise::TestHelpers, type: :controller 
    config.include Devise::TestHelpers, type: :request 

end 

Con tale configurazione attiva, le specifiche type: controller funzionano correttamente. Tuttavia quando si esegue type: request spec sto ottenendo seguente errore:

Failure/Error: Unable to find matching line from backtrace 
NoMethodError: 
    undefined method `env' for nil:NilClass 
# /home/.rvm/gems/[email protected]/gems/devise-3.4.1/lib/devise/test_helpers.rb:24:in `setup_controller_for_warden' 
# ./spec/rails_helper.rb:60:in `block (3 levels) in <top (required)>' 
# /home/.rvm/gems/[email protected]/gems/database_cleaner-1.4.1/lib/database_cleaner/generic/base.rb:15:in `cleaning' 
# /home/.rvm/gems/[email protected]/gems/database_cleaner-1.4.1/lib/database_cleaner/base.rb:92:in `cleaning' 
# /home/.rvm/gems/[email protected]/gems/database_cleaner-1.4.1/lib/database_cleaner/configuration.rb:86:in `block (2 levels) in cleaning' 
# /home/.rvm/gems/[email protected]/gems/database_cleaner-1.4.1/lib/database_cleaner/configuration.rb:87:in `call' 
# /home/.rvm/gems/[email protected]/gems/database_cleaner-1.4.1/lib/database_cleaner/configuration.rb:87:in `cleaning' 
# ./spec/rails_helper.rb:59:in `block (2 levels) in <top (required)>' 

https://github.com/plataformatec/devise/blob/master/lib/devise/test_helpers.rb#L24 seguendo

def setup_controller_for_warden #:nodoc: 
    @request.env['action_controller.instance'] = @controller # ==================> L-24 
end 

Sono consapevole che @request istanza non è disponibile per: spec richiesta di tipo e quindi l'errore.

Esistono degli helper disponibili che è possibile utilizzare per accedere a un utente in: richieste specifiche tipo quando si utilizza Devise?

ho trovato un problema simile https://github.com/plataformatec/devise/issues/1114, il reply al quale suggerisce seguente:

If you're doing integration tests, make sure to sign in your user in the tradicional way, by filling the sign in form and submitting.

ma vorrei passare dall'account di accesso effettivo per le specifiche che richiede un utente firmato-in.

Grazie.

risposta

23

Con l'aiuto di pochi post SO (si prega di fare riferimento alla sezione di seguito) Sono riuscito a ottenere la soluzione desiderata. Vi metto il mio codice di lavoro al di sotto, nel caso in cui esso può aiutare gli altri a guardare fuori per lo stesso:

spec/rails_helper.rb

RSpec.configure do |config| 
    .... 
    .... 
    config.include Devise::TestHelpers, type: :controller 
    config.include Warden::Test::Helpers, type: :request 
    end 

spec/shared_contexts.rb

RSpec.shared_context "api request global before and after hooks" do 
    before(:each) do 
     Warden.test_mode! 
    end 

    after(:each) do 
     Warden.test_reset! 
    end 
    end 

    RSpec.shared_context "api request authentication helper methods" do 
    def sign_in(user) 
     login_as(user, scope: :user) 
    end 

    def sign_out 
     logout(:user) 
    end 
    end 

/spec/requests/api/logout_spec.rb

require 'rails_helper' 
    require 'shared_contexts' 


    RSpec.describe "Api Logout", :type => :request do 
    include_context "api request authentication helper methods" 
    include_context "api request global before and after hooks" 

    let(:email) { '[email protected]' } 
    let(:password) { 'password' } 

    # Assumes you have FactoryGirl included in your application's test group. 
    let!(:user) { create(:user, email: email, password: password) } 

    context "DELETE /logout" do 
     it "responds with 204 and signs out the signed-in user" do 
     sign_in(user) 

     # Till not figured out how to assert Warden has successfully logged in the user like we can do in a Devise controller spec by asserting subject.current_user. If anybody knows a way to do it please share. 
     # expect(subject.current_user).to_not be_nil 

     delete "/logout" 

     expect(response).to have_http_status(204) 
     end 
    end 
    end 

Non ho ancora capito come affermare che Warden ha eseguito correttamente l'accesso all'utente come possiamo fare in una specifica del controller Devise asserendo expect(subject.current_user).to_not be_nil. Se qualcuno conosce un modo per farlo per favore condividi.

Riferimenti

Grazie,

Jiggnesh

+0

Hi Jiggneshh Gohel Sei hai qualche soluzione per: aspettarsi (subject.current_user) .to_not be_nil –

+0

@Viktor Leonets Scusa, non ho alcuna soluzione in questo momento perché non l'ho seguito in seguito. –

+0

Grazie! Stavo cercando una soluzione a questo per ore. Penso che ci siano altri modi per strutturare ciò che potrebbe funzionare meglio per me (credo che lo stesso effetto potrebbe essere ottenuto con gli helper e i macro di supporto per le specifiche della richiesta come ho visto fare con le specifiche del controller in alcuni di questi esempi) Ho ancora un problema quando ottengo "throw non avviato: Warden", ma devo risolvere il problema anche per le mie caratteristiche 1. – CJBrew