我編寫了以下功能規範,以測試在使用Devise的Rails 4.2.8應用程序中註冊,登錄,密碼恢復和帳戶鎖定行爲。測試註冊並使用Capybara(Rails,RSpec,Devise)登錄
測試工作。但是,我對水豚相對來說比較陌生,所以我想就如何提高他們的可讀性,可維護性,乾燥度,速度,降低脆弱性等方面提出建議。
驗證此類郵件的唯一性,密碼強度等在User
型號規格上執行。因此,我沒有在這裏重新測試這些行爲。
# 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
謝謝。
注意:所有'期望{...}。不要改變...'可能實際上並沒有做任何事情。這是因爲'click_button'不能保證等待由按鈕點擊觸發的操作完成。爲了解決這個問題,可以在'expect {...}。not_to change..'塊中加入以下'have_text'期望值。 –