mirror of
https://github.com/discourse/discourse.git
synced 2025-06-03 19:39:30 +08:00
UX: Streamline reset password page (#27341)
This commit includes various UX improvements to the reset password page: * Introduce a `hide-application-header-buttons` helper to do the following: * Hide Sign Up and Log In buttons, they are not necessary on this flow * Hide the sidebar, it is a distraction on this flow * Improve messaging when a 2FA confirmation is required first * Improve display of server-side ActiveRecord model validation errors in password form, e.g. instead of "is the same as your current password" we do "The password is the same as your current password" * Move password tip to next line below input and move caps lock hint inline with Show/Hide password toggle * Add system specs for 2FA flow on reset password page * Fixes a computed property conflict issue on the password reset page when toggling 2FA methods
This commit is contained in:
@ -192,6 +192,23 @@ RSpec.describe "Glimmer Header", type: :system do
|
||||
)
|
||||
end
|
||||
|
||||
context "when resetting password" do
|
||||
fab!(:current_user) { Fabricate(:user) }
|
||||
|
||||
it "does not show search, login, or signup buttons" do
|
||||
email_token =
|
||||
current_user.email_tokens.create!(
|
||||
email: current_user.email,
|
||||
scope: EmailToken.scopes[:password_reset],
|
||||
)
|
||||
|
||||
visit "/u/password-reset/#{email_token.token}"
|
||||
expect(page).not_to have_css("button.login-button")
|
||||
expect(page).not_to have_css("button.sign-up-button")
|
||||
expect(page).not_to have_css(".search-dropdown #search-button")
|
||||
end
|
||||
end
|
||||
|
||||
context "when logged in and login required" do
|
||||
fab!(:current_user) { Fabricate(:user) }
|
||||
|
||||
|
22
spec/system/legacy_widget_header_spec.rb
Normal file
22
spec/system/legacy_widget_header_spec.rb
Normal file
@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe "Legacy Widget Header", type: :system do
|
||||
before { SiteSetting.glimmer_header_mode = "disabled" }
|
||||
|
||||
context "when resetting password" do
|
||||
fab!(:current_user) { Fabricate(:user) }
|
||||
|
||||
it "does not show search, login, or signup buttons" do
|
||||
email_token =
|
||||
current_user.email_tokens.create!(
|
||||
email: current_user.email,
|
||||
scope: EmailToken.scopes[:password_reset],
|
||||
)
|
||||
|
||||
visit "/u/password-reset/#{email_token.token}"
|
||||
expect(page).not_to have_css("button.login-button")
|
||||
expect(page).not_to have_css("button.sign-up-button")
|
||||
expect(page).not_to have_css(".search-dropdown #search-button")
|
||||
end
|
||||
end
|
||||
end
|
@ -8,6 +8,19 @@ shared_examples "login scenarios" do
|
||||
|
||||
before { Jobs.run_immediately! }
|
||||
|
||||
def wait_for_email_link(user, type)
|
||||
wait_for(timeout: 5) { ActionMailer::Base.deliveries.count != 0 }
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
expect(mail.to).to contain_exactly(user.email)
|
||||
if type == :reset_password
|
||||
mail.body.to_s[%r{/u/password-reset/\S+}]
|
||||
elsif type == :activation
|
||||
mail.body.to_s[%r{/u/activate-account/\S+}]
|
||||
elsif type == :email_login
|
||||
mail.body.to_s[%r{/session/email-login/\S+}]
|
||||
end
|
||||
end
|
||||
|
||||
context "with username and password" do
|
||||
it "can login" do
|
||||
EmailToken.confirm(Fabricate(:email_token, user: user).token)
|
||||
@ -25,11 +38,7 @@ shared_examples "login scenarios" do
|
||||
expect(page).to have_css(".not-activated-modal")
|
||||
login_modal.click(".activation-controls button.resend")
|
||||
|
||||
wait_for(timeout: 5) { ActionMailer::Base.deliveries.count != 0 }
|
||||
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
expect(mail.to).to contain_exactly(user.email)
|
||||
activation_link = mail.body.to_s[%r{/u/activate-account/\S+}]
|
||||
activation_link = wait_for_email_link(user, :activation)
|
||||
visit activation_link
|
||||
|
||||
find("#activate-account-button").click
|
||||
@ -53,11 +62,8 @@ shared_examples "login scenarios" do
|
||||
login_modal.find("#modal-alert a").click
|
||||
find("button.forgot-password-reset").click
|
||||
|
||||
wait_for(timeout: 5) { ActionMailer::Base.deliveries.count != 0 }
|
||||
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
expect(mail.to).to contain_exactly(user.email)
|
||||
expect(mail.body).to match(%r{/u/password-reset/\S+})
|
||||
reset_password_link = wait_for_email_link(user, :reset_password)
|
||||
expect(reset_password_link).to be_present
|
||||
end
|
||||
|
||||
it "can reset password" do
|
||||
@ -66,15 +72,11 @@ shared_examples "login scenarios" do
|
||||
login_modal.forgot_password
|
||||
find("button.forgot-password-reset").click
|
||||
|
||||
wait_for(timeout: 5) { ActionMailer::Base.deliveries.count != 0 }
|
||||
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
expect(mail.to).to contain_exactly(user.email)
|
||||
reset_password_link = mail.body.to_s[%r{/u/password-reset/\S+}]
|
||||
reset_password_link = wait_for_email_link(user, :reset_password)
|
||||
visit reset_password_link
|
||||
|
||||
find("#new-account-password").fill_in(with: "newsuperpassword")
|
||||
find("form .btn-primary").click
|
||||
find(".change-password-form .btn-primary").click
|
||||
expect(page).to have_css(".header-dropdown-toggle.current-user")
|
||||
end
|
||||
end
|
||||
@ -85,11 +87,7 @@ shared_examples "login scenarios" do
|
||||
login_modal.fill_username("john")
|
||||
login_modal.email_login_link
|
||||
|
||||
wait_for(timeout: 5) { ActionMailer::Base.deliveries.count != 0 }
|
||||
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
expect(mail.to).to contain_exactly(user.email)
|
||||
login_link = mail.body.to_s[%r{/session/email-login/\S+}]
|
||||
login_link = wait_for_email_link(user, :email_login)
|
||||
visit login_link
|
||||
|
||||
find(".email-login-form .btn-primary").click
|
||||
@ -148,11 +146,7 @@ shared_examples "login scenarios" do
|
||||
login_modal.fill_username("john")
|
||||
login_modal.email_login_link
|
||||
|
||||
wait_for(timeout: 5) { ActionMailer::Base.deliveries.count != 0 }
|
||||
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
expect(mail.to).to contain_exactly(user.email)
|
||||
login_link = mail.body.to_s[%r{/session/email-login/\S+}]
|
||||
login_link = wait_for_email_link(user, :email_login)
|
||||
visit login_link
|
||||
|
||||
totp = ROTP::TOTP.new(user_second_factor.data).now
|
||||
@ -166,11 +160,7 @@ shared_examples "login scenarios" do
|
||||
login_modal.fill_username("john")
|
||||
login_modal.email_login_link
|
||||
|
||||
wait_for(timeout: 5) { ActionMailer::Base.deliveries.count != 0 }
|
||||
|
||||
mail = ActionMailer::Base.deliveries.last
|
||||
expect(mail.to).to contain_exactly(user.email)
|
||||
login_link = mail.body.to_s[%r{/session/email-login/\S+}]
|
||||
login_link = wait_for_email_link(user, :email_login)
|
||||
visit login_link
|
||||
|
||||
find(".toggle-second-factor-method").click
|
||||
@ -178,6 +168,42 @@ shared_examples "login scenarios" do
|
||||
find(".email-login-form .btn-primary").click
|
||||
expect(page).to have_css(".header-dropdown-toggle.current-user")
|
||||
end
|
||||
|
||||
it "can reset password with TOTP" do
|
||||
login_modal.open
|
||||
login_modal.fill_username("john")
|
||||
login_modal.forgot_password
|
||||
find("button.forgot-password-reset").click
|
||||
|
||||
reset_password_link = wait_for_email_link(user, :reset_password)
|
||||
visit reset_password_link
|
||||
|
||||
totp = ROTP::TOTP.new(user_second_factor.data).now
|
||||
find(".second-factor-token-input").fill_in(with: totp)
|
||||
find(".password-reset .btn-primary").click
|
||||
|
||||
find("#new-account-password").fill_in(with: "newsuperpassword")
|
||||
find(".change-password-form .btn-primary").click
|
||||
expect(page).to have_css(".header-dropdown-toggle.current-user")
|
||||
end
|
||||
|
||||
it "can reset password with a backup code" do
|
||||
login_modal.open
|
||||
login_modal.fill_username("john")
|
||||
login_modal.forgot_password
|
||||
find("button.forgot-password-reset").click
|
||||
|
||||
reset_password_link = wait_for_email_link(user, :reset_password)
|
||||
visit reset_password_link
|
||||
|
||||
find(".toggle-second-factor-method").click
|
||||
find(".second-factor-token-input").fill_in(with: "iAmValidBackupCode")
|
||||
find(".password-reset .btn-primary").click
|
||||
|
||||
find("#new-account-password").fill_in(with: "newsuperpassword")
|
||||
find(".change-password-form .btn-primary").click
|
||||
expect(page).to have_css(".header-dropdown-toggle.current-user")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
Reference in New Issue
Block a user