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

269 lines
9.5 KiB
Ruby

# frozen_string_literal: true
RSpec.describe "Finish Installation" do
include OmniauthHelpers
let(:finish_installation_page) { PageObjects::Pages::FinishInstallation.new }
context "when has_login_hint is false" do
before { SiteSetting.has_login_hint = false }
it "denies access" do
finish_installation_page.visit_page
expect(finish_installation_page).to have_access_denied
end
end
context "when has_login_hint is true" do
before { SiteSetting.has_login_hint = true }
context "when DISCOURSE_SKIP_EMAIL_SETUP=1" do
before do
allow(ENV).to receive(:[]).and_call_original
allow(ENV).to receive(:[]).with("DISCOURSE_SKIP_EMAIL_SETUP").and_return("1")
end
context "when ID registration is successful" do
before do
GlobalSetting.stubs(:developer_emails).returns("dev1@example.com,dev2@example.com")
stub_request(:post, "https://id.discourse.com/challenge").to_return(
status: 200,
body: { domain: Discourse.current_hostname, token: "test_token" }.to_json,
)
stub_request(:post, "https://id.discourse.com/register").to_return(
status: 200,
body: { client_id: "test_client_id", client_secret: "test_client_secret" }.to_json,
)
end
it "enables Discourse ID and shows login button" do
finish_installation_page.visit_page
expect(finish_installation_page).to have_discourse_id_button
expect(finish_installation_page).to have_no_register_button
expect(finish_installation_page).to have_no_error_message
end
it "creates multiple admin users when multiple emails are configured" do
finish_installation_page.visit_page
finish_installation_page.click_login_with_discourse_id
user1 = User.find_by_email("dev1@example.com")
user2 = User.find_by_email("dev2@example.com")
expect(user1).to be_present
expect(user1.admin).to eq(true)
expect(user2).to be_present
expect(user2.admin).to eq(true)
expect(page.current_url).to include("id.discourse.com")
end
it "skips creating users that already exist" do
Fabricate(:user, email: "dev1@example.com", admin: false)
Fabricate(:user, email: "dev2@example.com", admin: false)
initial_user_count = User.count
finish_installation_page.visit_page
finish_installation_page.click_login_with_discourse_id
expect(User.count).to eq(initial_user_count)
end
it "lands the first admin user on wizard" do
OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:discourse_id] = OmniAuth::AuthHash.new(
provider: "discourse_id",
uid: "12345",
info: OmniAuth::AuthHash::InfoHash.new(email: "dev1@example.com", nickname: "dev1"),
)
finish_installation_page.visit_page
finish_installation_page.click_login_with_discourse_id
expect(page).to have_current_path("/wizard")
ensure
reset_omniauth_config(:discourse_id)
end
context "when installed in a subfolder" do
before do
set_subfolder "/discuss"
stub_request(:post, "https://id.discourse.com/challenge").to_return(
status: 200,
body: {
domain: Discourse.current_hostname,
path: Discourse.base_path,
token: "test_token",
}.to_json,
)
end
it "logs in the first admin user and lands them on the wizard" do
OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:discourse_id] = OmniAuth::AuthHash.new(
provider: "discourse_id",
uid: "12345",
info: OmniAuth::AuthHash::InfoHash.new(email: "dev1@example.com", nickname: "dev1"),
)
finish_installation_page.visit("/discuss/finish-installation")
finish_installation_page.click_login_with_discourse_id
expect(page).to have_current_path("/discuss/wizard")
ensure
reset_omniauth_config(:discourse_id)
end
end
end
context "when developer_emails is empty" do
before { GlobalSetting.stubs(:developer_emails).returns("") }
it "shows error message about missing allowed emails" do
finish_installation_page.visit_page
expect(finish_installation_page).to have_no_discourse_id_button
expect(finish_installation_page).to have_no_register_button
expect(finish_installation_page).to have_error_message
expect(finish_installation_page.error_message_text).to include(
I18n.t("finish_installation.discourse_id.no_allowed_emails"),
)
end
end
context "when ID registration fails with an error" do
before do
GlobalSetting.stubs(:developer_emails).returns("dev1@example.com,dev2@example.com")
failed_context = Service::Base::Context.new
failed_context.fail(error: "Failed to connect to Discourse ID")
allow(DiscourseId::Register).to receive(:call).and_return(failed_context)
end
it "shows error message and no login button" do
finish_installation_page.visit_page
expect(finish_installation_page).to have_no_discourse_id_button
expect(finish_installation_page).to have_no_register_button
expect(finish_installation_page).to have_error_message
end
end
end
context "when using local registration" do
before do
GlobalSetting.stubs(:developer_emails).returns("admin@example.com,other@example.com")
end
it "shows local register form button" do
finish_installation_page.visit_page
expect(finish_installation_page).to have_register_button
expect(finish_installation_page).to have_no_discourse_id_button
expect(finish_installation_page).to have_no_error_message
end
it "shows validation error when username is blank" do
finish_installation_page.visit_register.fill_password("supersecurepassword").submit
expect(finish_installation_page).to have_username_error
end
it "shows validation error when password is blank" do
finish_installation_page.visit_register.fill_username("newadmin").submit
expect(finish_installation_page).to have_password_error
end
it "shows validation error when password is too short" do
finish_installation_page
.visit_register
.fill_username("newadmin")
.fill_password("short")
.submit
expect(finish_installation_page).to have_password_error("too short")
end
it "registers admin and redirects to confirm email page" do
finish_installation_page
.visit_register
.select_email("admin@example.com")
.fill_username("newadmin")
.fill_password("supersecurepassword")
.submit
expect(finish_installation_page).to be_redirected_to_confirm_email
expect(User.find_by(username: "newadmin")).to have_attributes(
email: "admin@example.com",
trust_level: 1,
)
end
it "handles multiple developer emails" do
finish_installation_page
.visit_register
.select_email("other@example.com")
.fill_username("otheradmin")
.fill_password("supersecurepassword")
.submit
expect(finish_installation_page).to be_redirected_to_confirm_email
expect(User.find_by(username: "otheradmin")).to be_present
end
it "resends activation email when user already exists" do
Fabricate(:user, email: "admin@example.com")
expect {
finish_installation_page
.visit_register
.select_email("admin@example.com")
.fill_username("differentuser")
.fill_password("supersecurepassword")
.submit
}.to change { Jobs::CriticalUserEmail.jobs.size }.by(1)
expect(finish_installation_page).to be_redirected_to_confirm_email
end
it "does not send email when user is already active and confirmed" do
user = Fabricate(:user, email: "admin@example.com", active: true)
user.activate
expect {
finish_installation_page
.visit_register
.select_email("admin@example.com")
.fill_username("differentuser")
.fill_password("supersecurepassword")
.submit
}.not_to change { Jobs::CriticalUserEmail.jobs.size }
end
it "redirects to the wizard after admin confirms their email" do
Jobs.run_immediately!
finish_installation_page
.visit_register
.select_email("admin@example.com")
.fill_username("newadmin")
.fill_password("supersecurepassword")
.submit
expect(finish_installation_page).to be_redirected_to_confirm_email
user = User.find_by(username: "newadmin")
user.grant_admin!
mail = ActionMailer::Base.deliveries.first
expect(mail.to).to contain_exactly("admin@example.com")
activation_link = mail.body.to_s[%r{/u/activate-account/\S+}]
activate_account_page = PageObjects::Pages::ActivateAccount.new
visit activation_link
activate_account_page.click_activate_account
expect(page).to have_current_path("/wizard")
end
end
end
end