J'ai écrit la spécification de fonctionnalité suivante pour tester l'inscription, la connexion, la récupération de mot de passe et le comportement de verrouillage de compte dans une application Rails 4.2.8 avec Devise.Tester et vous connecter avec Capybara (Rails, RSpec, Devise)
Les tests fonctionnent. Cependant, je suis relativement nouveau à Capybara, donc je voudrais vos suggestions concernant la façon d'améliorer leur lisibilité, maintenabilité, DRYness, vitesse, réduire la fragilité, etc
Validations telles unicité de l'e-mail, la force du mot de passe et ainsi de suite effectuée à la spécification de modèle User
. Par conséquent, je n'ai pas re-testé ces comportements ici.
# spec/features/user_registration_spec.rb
require 'rails_helper'
def login_via_form(email, password)
expect(page).to have_current_url("https://stackoverflow.com/users/sign_in")
fill_in "Email", with: email
fill_in "Password", with: password
click_button "Sign in"
end
RSpec::Matchers.define :be_logged_in do |user_first_name|
match do |page|
expect(page).to have_current_path "/"
expect(page).to have_content "Hello #{user_first_name}"
end
failure_message do |actual|
"expected the current path to be /, actual path is #{page.current_path}" \
"\nexpected to find a 'Hello #{user_first_name}' in '#{page.text}'."
end
end
describe "User self-management", type: :feature, js: true do
let!(:user) { FactoryGirl.create(:user) }
let(:valid_attributes) { FactoryGirl.attributes_for(:user) }
it "registers a new user" do
visit "/"
click_link "Sign up"
fill_in "Email", with: valid_attributes[:email]
fill_in "Password", with: valid_attributes[:password]
fill_in "Password confirmation", with: valid_attributes[:password]
fill_in "First name", with: valid_attributes[:first_name]
fill_in "Last name", with: valid_attributes[:last_name]
select "United States", from: "Country"
select "New York", from: "State"
select "New York", from: "City"
fill_in "Sangha", with: "My Sangha"
fill_in "Phone number", with: "+1 212-555-0187"
fill_in "Facebook url", with: "http://www.facebook.com/johndoe"
click_button "Sign up"
# The user may only login *after* confirming her e-mail
expect(page).to have_content "A message with a confirmation link has been" \
" sent to your email address. Please follow the link to activate your" \
" account."
expect(page).to have_current_path "https://stackoverflow.com/users/sign_in"
# Find email sent to the given recipient and set the current_email variable
# Implemented by https://github.com/DockYard/capybara-email
open_email(valid_attributes[:email])
expect(current_email.subject).to eq "Confirmation instructions"
current_email.click_link "Confirm my account"
expect(page).to have_content "Your email address has been successfully " \
"confirmed."
login_via_form(valid_attributes[:email],
valid_attributes[:password])
expect(page).to have_content "Signed in successfully."
expect(page).to be_logged_in(valid_attributes[:first_name])
end
it "performs password recovery (creates a new password)" do
visit "https://stackoverflow.com/users/sign_in"
click_link "Forgot your password?"
fill_in "Email", with: user.email
click_button "Send me reset password instructions"
expect(page).to have_text "You will receive an email with instructions " \
"on how to reset your password in a few minutes."
# Find email sent to the given recipient and set the current_email variable
open_email(user.email)
expect(current_email.subject).to eq "Reset password instructions"
current_email.click_link "Change my password"
fill_in "New password", with: valid_attributes[:password]
fill_in "Confirm new password", with: valid_attributes[:password]
click_button "Change my password"
expect(page).to have_content "Your password has been changed " \
"successfully. You are now signed in."
expect(page).to be_logged_in(user.first_name)
open_email(user.email)
expect(current_email.subject).to eq "Password Changed"
expect(current_email.body). to have_text "We're contacting you to notify " \
"you that your password has been changed."
end
describe "resend confirmation e-mail" do
context "with an already confirmed e-mail address" do
it "warns the user and does not send a new confirmation e-mail" do
# Our factory creates users with confirmed e-mails
visit "https://stackoverflow.com/users/sign_in"
click_link "Didn't receive confirmation instructions?"
fill_in "Email", with: user.email
expect {
click_button "Resend confirmation instructions"
}.not_to change(ActionMailer::Base.deliveries, :count)
expect(page).to have_text "Email was already confirmed"
end
end
context "with an unconfirmed e-mail address" do
it "sends a new confirmation e-mail" do
# Unconfirm user (our factory creates users with confirmed e-mails)
user.update(confirmed_at: nil)
visit "https://stackoverflow.com/users/sign_in"
click_link "Didn't receive confirmation instructions?"
fill_in "Email", with: user.email
click_button "Resend confirmation instructions"
expect(page).to have_text "You will receive an email with " \
"instructions for how to confirm your email address in a few minutes."
open_email(user.email)
expect(current_email.subject).to eq "Confirmation instructions"
current_email.click_link "Confirm my account"
expect(page).to have_content "Your email address has been " \
"successfully confirmed."
login_via_form(user.email, user.password)
expect(page).to have_content "Signed in successfully."
expect(page).to be_logged_in(user.first_name)
end
end
end
it "locks the account after 5 failed login attempts" do
visit "https://stackoverflow.com/users/sign_in"
3.times do
login_via_form(user.email, "bogus")
expect(page).to have_text "Invalid Email or password."
end
login_via_form(user.email, "bogus")
expect(page).to have_text "You have one more attempt before your " \
"account is locked."
login_via_form(user.email, "bogus")
expect(page).to have_text "Your account is locked."
open_email(user.email)
expect(current_email.subject).to eq "Unlock instructions"
current_email.click_link "Unlock my account"
expect(page).to have_content "Your account has been unlocked " \
"successfully. Please sign in to continue."
login_via_form(user.email, user.password)
expect(page).to have_content "Signed in successfully."
expect(page).to be_logged_in(user.first_name)
end
context "account is locked, didn't receive unlocking instructions" do
it "sends a new unlocking instructions e-mail" do
user.update(locked_at: DateTime.now)
visit "https://stackoverflow.com/users/sign_in"
click_link "Didn't receive unlock instructions?"
fill_in "Email", with: user.email
click_button "Resend unlock instructions"
expect(page).to have_text "You will receive an email with instructions " \
"for how to unlock your account in a few minutes."
open_email(user.email)
expect(current_email.subject).to eq "Unlock instructions"
current_email.click_link "Unlock my account"
expect(page).to have_content "Your account has been unlocked " \
"successfully. Please sign in to continue."
login_via_form(user.email, user.password)
expect(page).to have_content "Signed in successfully."
expect(page).to be_logged_in(user.first_name)
end
end
context "account is not locked, attempts to re-send unlocking instructions" do
it "warns the user and does not send a new confirmation e-mail" do
# Our factory creates users with confirmed e-mails
visit "https://stackoverflow.com/users/sign_in"
click_link "Didn't receive unlock instructions?"
fill_in "Email", with: user.email
expect {
click_button "Resend unlock instructions"
}.not_to change(ActionMailer::Base.deliveries, :count)
expect(page).to have_text "Email was not locked"
end
end
end
Merci.
Remarque: Tout ce que vous attendez de ... {...} .not_to ... ne fait peut-être rien. C'est parce que click_button ne garantit pas que les actions déclenchées par le bouton click finiront. Pour corriger cela, déplacez l'attente 'have_text' suivante dans le bloc' expect {...}. Not_to change..'. –