discourse/spec/system/email_change_spec.rb
2026-03-20 00:39:52 +01:00

165 lines
4.7 KiB
Ruby

# frozen_string_literal: true
describe "Changing email" do
fab!(:password) { "mysupersecurepassword" }
fab!(:user) { Fabricate(:user, active: true, password: password) }
let(:new_email) { "newemail@example.com" }
let(:user_preferences_security_page) { PageObjects::Pages::UserPreferencesSecurity.new }
let(:user_preferences_page) { PageObjects::Pages::UserPreferences.new }
before { Jobs.run_immediately! }
def generate_confirm_link
visit "/my/preferences/account"
email_dropdown = PageObjects::Components::SelectKit.new(".email-dropdown")
expect(email_dropdown.visible?).to eq(true)
email_dropdown.select_row_by_value("updateEmail")
find("#change-email").fill_in with: "newemail@example.com"
find(".save-button button").click
wait_for(timeout: Capybara.default_max_wait_time * 2) do
ActionMailer::Base.deliveries.count === 1
end
if user.admin?
get_link_from_email(:old)
else
get_link_from_email(:new)
end
end
def get_link_from_email(type)
mail = ActionMailer::Base.deliveries.last
expect(mail.to).to contain_exactly(type == :new ? new_email : user.email)
mail.body.to_s[%r{/u/confirm-#{type}-email/\S+}, 0]
end
it "allows regular user to change their email" do
sign_in user
visit generate_confirm_link
find(".confirm-new-email .btn-primary").click
expect(page).to have_css(".dialog-body", text: I18n.t("js.user.change_email.confirm_success"))
find(".dialog-footer .btn-primary").click
expect(user.reload.primary_email.email).to eq(new_email)
end
it "works when user has totp 2fa", dump_threads_on_failure: true do
SiteSetting.hide_email_address_taken = false
second_factor = Fabricate(:user_second_factor_totp, user: user)
sign_in user
visit generate_confirm_link
find(".confirm-new-email .btn-primary").click
find(".second-factor-token-input").fill_in with: second_factor.totp_object.now
find("button[type=submit]").click
expect(user.reload.primary_email.email).to eq(new_email)
end
it "works when user has webauthn 2fa" do
with_security_key(user) do
sign_in user
visit generate_confirm_link
find(".confirm-new-email .btn-primary").click
find("#security-key-authenticate-button").click
try_until_success(
reason: "Something about webauthn.js that we can't seem to track properly",
) { expect(user.reload.primary_email.email).to eq(new_email) }
end
end
it "does not require login to confirm email change" do
second_factor = Fabricate(:user_second_factor_totp, user: user)
sign_in user
confirm_link = generate_confirm_link
Capybara.reset_sessions! # log out
visit confirm_link
find(".confirm-new-email .btn-primary").click
find(".second-factor-token-input").fill_in with: second_factor.totp_object.now
find("button[type=submit]:not([disabled])").click
expect(user.reload.primary_email.email).to eq(new_email)
end
it "makes admins verify old email" do
user.update!(admin: true)
sign_in user
confirm_old_link = generate_confirm_link
# Confirm old email
visit confirm_old_link
find(".confirm-old-email .btn-primary").click
expect(page).to have_css(
".dialog-body",
text: I18n.t("js.user.change_email.authorizing_old.confirm_success"),
)
find(".dialog-footer .btn-primary").click
# Confirm new email
wait_for(timeout: Capybara.default_max_wait_time * 2) do
ActionMailer::Base.deliveries.count === 2
end
confirm_new_link = get_link_from_email(:new)
visit confirm_new_link
find(".confirm-new-email .btn-primary").click
expect(page).to have_css(".dialog-body", text: I18n.t("js.user.change_email.confirm_success"))
find(".dialog-footer .btn-primary").click
expect(user.reload.primary_email.email).to eq(new_email)
end
it "allows admin to verify old email while logged out" do
user.update!(admin: true)
sign_in user
confirm_old_link = generate_confirm_link
Capybara.reset_sessions! # log out
# Confirm old email
visit confirm_old_link
find(".confirm-old-email .btn-primary").click
expect(page).to have_css(
".dialog-body",
text: I18n.t("js.user.change_email.authorizing_old.confirm_success"),
)
find(".dialog-footer .btn-primary").click
# Confirm new email
wait_for(timeout: Capybara.default_max_wait_time * 2) do
ActionMailer::Base.deliveries.count === 2
end
confirm_new_link = get_link_from_email(:new)
visit confirm_new_link
find(".confirm-new-email .btn-primary").click
expect(page).to have_css(".dialog-body", text: I18n.t("js.user.change_email.confirm_success"))
find(".dialog-footer .btn-primary").click
expect(user.reload.primary_email.email).to eq(new_email)
end
end