2012-01-16 13 views
12

Sto usando rspec/capybara/devise per condurre test di integrazione in un'app. Una delle caratteristiche dell'app è la "Registrazione account" sempre popolata utilizzando una funzione di conferma (ad esempio, registrati - ricevi un'email di conferma - fai clic sul link - l'account è convalidato).Test "Conferma account" con rails/rspec/capybara/devise

require 'spec_helper' 

describe "User Authentication" do 
    describe "New user" do 
    before(:each) do 
     @user = Factory.build(:user) 
    end 

    it "can confirm account by clicking on confirmation link" do 
     visit root_path 
     click_link "Register" 
     page.should have_content "Register for an account" 
     fill_in "user_email", :with => @user.email 
     fill_in "user_password", :with => @user.password 
     fill_in "user_password_confirmation", :with => @user.password 
     fill_in "user_first_name", :with => @user.first_name 
     fill_in "user_last_name", :with => @user.last_name 
     fill_in "user_city", :with => @user.city 
     fill_in "user_province", :with => @user.province 
     fill_in "user_country", :with => @user.country 
     fill_in "user_expertise", :with => @user.expertise 
     choose "user_experience_professional" 
     click_button "Go!" 
     last_email.to.should include(@user.email) 
    end 
    end 
end 

qui sono i miei aiutanti:

collegamento
module MailerMacros 
    def last_email 
    ActionMailer::Base.deliveries.last 
    end 
end 

La conferma è nella e-mail HTML generato. Sarebbe bello poter fare qualcosa del genere (assumendo "Conferma il mio account") è il link per la convalida dell'account.

last_email.body.find_link("Confirm My Account").click_link 

Qualcuno ha qualche suggerimento in essere in grado di identificare i link in un'email che potrebbe andare in un request_spec?

Grazie

risposta

4

"Conferma Il mio account" viene generato automaticamente, e di solito si basa su una sorta di un token che viene salvato nel database.

È possibile fare asserzione che il token per quell'utente sia incluso nel link di conferma che è stato inviato a quell'utente. Oppure puoi prendere quel collegamento dalla posta e usare il metodo di supporto visit, che viene fornito con rspec. E poi controlla se l'utente è confermato.

6

si può semplicemente farlo usando rspec, capybara, gem 'email_spec' e `gem 'action_mailer_cache_delivery'.

click_button "Go!" 
email = open_email(@user.email) 
email.should deliver_to(@user.email) 
click_link "Confirm My Account" 
sleep 2 
+0

appena realizzato questa è una domanda vecchio anno. – PriyankaK

+1

Ancora mi ha aiutato. Mettimi nella gemma email_spec che è fantastica! Puoi anche utilizzare 'click_first_link_in_email email' in email_spec – mattvv

+0

@mattvv Ho provato '' 'click_first_link_in_email''', ma non ha funzionato per me.Grazie per la risposta! – PriyankaK

1

metodo simile a quello descritto da @socjopata.

lo faccio attraverso la definizione di un aiutante in su delle/supporto file * Specifiche/che estrarranno il token generato da devise:

def extract_token_from_email(token_name) 
    mail_body = last_email.body.to_s 
    mail_body[/#{token_name.to_s}_token=([^"]+)/, 1] 
end 

e quindi utilizzare da:

visit whatever_path({ some_token: token_name }) 

I ho rubato quel codice da un GitHub Gist da qualche parte ma non riesco a trovarlo per fare riferimento, quindi non posso prendere pieno credito.

16

Mi rendo conto che questa domanda ha un anno, ma mi ha indirizzato verso una soluzione che gli altri potrebbero trovare utili, quindi ho pensato di postarla comunque.

Non ho completamente esplorato la gemma email_spec menzionata sopra in modo che possa essere un approccio molto più elegante, ma questo funziona abbastanza bene per il mio caso. Nella mia app abbiamo elaborato modifiche per consentire agli utenti di registrarsi solo con un indirizzo email, quindi devono confermare il proprio account e vengono richieste ulteriori informazioni. Quindi ho dovuto verificare che le conferme funzionino.

Il mio file caratteristica assomiglia a questo:

Scenario: Confirm new account 
    Given I have registered for an account as "[email protected]" 
    When I follow the confirmation link in the confirmation email 
    Then I should be able to set a password 

In primo luogo, ho aggiunto il last_email aiuto al mio indice sostegno cetriolo come mailer_helper.rb:

def last_email 
    ActionMailer::Base.deliveries.last 
end 

In secondo luogo, ho scritto le mie definizioni passo in questo modo:

Given(/^I have registered for an account as "(.*?)"$/) do |user_email| 
    visit root_path 
    click_link 'register' 
    fill_in('Email', with: user_email) 
    click_button 'Sign up' 
    user = User.find_by_email(user_email) 
    user.should_not be_nil 
    user.confirmation_token.should_not be_nil 
end 

When(/^I follow the confirmation link in the confirmation email$/) do 
    ctoken = last_email.body.match(/confirmation_token=\w*/) 
    visit "https://stackoverflow.com/users/confirmation?#{ctoken}" 
end 

Then(/^I should be able to set a password$/) do 
    fill_in('user[password]', with: 'passw0rd') 
    fill_in('user[password_confirmation]', with: 'passw0rd') 
    fill_in('user[first_name]', with: 'John') 
    fill_in('user[last_name]', with: 'Doe') 
    click_button 'Activate' 
    page.should have_content('Your account was successfully confirmed. You are now signed in.') 
    page.should have_css('div#flash_notice.alert.alert-success') 
end 
+0

Potrebbe essere solo per me, ma penso che l'URL di conferma dovrebbe essere "/ utente/...", anche se so che devise fornisce un helper confirm_url, che non ho potuto ottenere lavorando. –

+1

Per farlo funzionare dovevo fare email.body.parts [0] .body.decoded.match (/ confirmation_token = [^ \ n] * /) nel mio caso invio una posta multipart, quindi estraggo il token da la versione testuale, e so che ho messo una newline dopo il link. –

+0

In 'rspec', ho usato' confirmation_token = $ 1 se ActionMailer :: Base.deliveries.last.body.raw_source = ~/confirm_token = ([^ '"] +) /' – ghayes

3

Nel caso in cui sia necessario farlo in RSpec co ntroller spec senza introdurre gemme aggiuntive:

# in spec/support/controllers/mailer_helper.rb 
module Controllers 
    module MailerHelpers 
    def last_email 
     ActionMailer::Base.deliveries.last 
    end 

    def extract_confirmation_token(email) 
     email && email.body && email.body.match(/confirmation_token=(.+)">/x)[1] 
    end 
    end 
end 

# in spec_helper.rb in RSpec.configure block 
config.include Controllers::MailerHelpers, type: :controller 

# in spec/controllers/confirmations_controller_spec.rb 
describe ConfirmationsController do 
    it "confirms registered user" do 
     user.confirmation_token 
     token = extract_confirmation_token last_email 
     get :show, confirmation_token: token 

     # fill in your expectation here 
     expect(user...).to be[...] 
    end 
end 

Spero che questo aiuti.

0

seguito la risposta di demisx, non riuscivo a farlo funzionare senza realmente richiamare il metodo send_confirmation_instructions e ricaricare l'oggetto user:

require 'rails_helper' 

RSpec.describe Users::ConfirmationsController, type: :controller do 

    describe 'ConfirmationsController' do 
    before(:each) do 
     @user = FactoryGirl.build(:user) 
     @request.env["devise.mapping"] = Devise.mappings[:user] 
    end 

    it "confirms registered user" do 
     @user.send_confirmation_instructions 
     token = extract_confirmation_token last_email 
     get :show, confirmation_token: token 

     expect(@user.reload.confirmed?).to be(true) 
    end 
    end 

end