discourse/spec/models/site_setting_spec.rb
Martin Brennan b54c49cca7
DEV: Refactor admin search index into a service (#38959)
Move the AdminSearchController#index endpoint into a proper
service class since it does a few different things now.
2026-04-01 10:09:10 +10:00

489 lines
15 KiB
Ruby

# frozen_string_literal: true
RSpec.describe SiteSetting do
describe "topic_title_length" do
it "returns a range of min/max topic title length" do
expect(SiteSetting.topic_title_length).to eq(
SiteSetting.min_topic_title_length..SiteSetting.max_topic_title_length,
)
end
end
describe "post_length" do
it "returns a range of min/max post length" do
expect(SiteSetting.post_length).to eq(
SiteSetting.min_post_length..SiteSetting.max_post_length,
)
end
end
describe "first_post_length" do
it "returns a range of min/max first post length" do
expect(SiteSetting.first_post_length).to eq(
SiteSetting.min_first_post_length..SiteSetting.max_post_length,
)
end
end
describe "private_message_title_length" do
it "returns a range of min/max pm topic title length" do
expect(SiteSetting.private_message_title_length).to eq(
SiteSetting.min_personal_message_title_length..SiteSetting.max_topic_title_length,
)
end
end
describe "in test we do some judo to ensure SiteSetting is always reset between tests" do
it "is always the correct default" do
expect(SiteSetting.contact_email).to eq("")
end
it "sets a setting" do
SiteSetting.contact_email = "sam@sam.com"
end
end
describe "anonymous_homepage" do
it "returns latest" do
expect(SiteSetting.anonymous_homepage).to eq("latest")
end
end
describe "top_menu" do
describe "validations" do
it "always demands latest" do
expect do SiteSetting.top_menu = "categories" end.to raise_error(
Discourse::InvalidParameters,
)
end
it "does not allow random text" do
expect do SiteSetting.top_menu = "latest|random" end.to raise_error(
Discourse::InvalidParameters,
)
end
end
describe "items" do
let(:items) { SiteSetting.top_menu_items }
it "returns TopMenuItem objects" do
expect(items[0]).to be_kind_of(TopMenuItem)
end
end
describe "homepage" do
it "has homepage" do
SiteSetting.top_menu = "bookmarks|latest"
expect(SiteSetting.homepage).to eq("bookmarks")
end
end
end
describe "min_redirected_to_top_period" do
context "when has_enough_top_topics" do
before do
SiteSetting.topics_per_period_in_top_page = 2
SiteSetting.top_page_default_timeframe = "daily"
2.times { TopTopic.create!(daily_score: 2.5) }
TopTopic.refresh!
end
it "should_return_a_time_period" do
expect(SiteSetting.min_redirected_to_top_period(1.day.ago)).to eq(:daily)
end
end
context "when does_not_have_enough_top_topics" do
before do
SiteSetting.topics_per_period_in_top_page = 20
SiteSetting.top_page_default_timeframe = "daily"
TopTopic.refresh!
end
it "should_return_a_time_period" do
expect(SiteSetting.min_redirected_to_top_period(1.day.ago)).to eq(nil)
end
end
end
describe "scheme" do
before { SiteSetting.force_https = true }
it "returns http when ssl is disabled" do
SiteSetting.force_https = false
expect(SiteSetting.scheme).to eq("http")
end
it "returns https when using ssl" do
expect(SiteSetting.scheme).to eq("https")
end
end
describe ".shared_drafts_enabled?" do
it "returns false by default" do
expect(SiteSetting.shared_drafts_enabled?).to eq(false)
end
it "returns false when the category is uncategorized" do
SiteSetting.shared_drafts_category = SiteSetting.uncategorized_category_id
expect(SiteSetting.shared_drafts_enabled?).to eq(false)
end
it "returns true when the category is valid" do
SiteSetting.shared_drafts_category = Fabricate(:category).id
expect(SiteSetting.shared_drafts_enabled?).to eq(true)
end
end
describe "cached settings" do
it "should recalculate cached setting when dependent settings are changed" do
SiteSetting.blocked_attachment_filenames = "foo"
expect(SiteSetting.blocked_attachment_filenames_regex).to eq(/foo/)
SiteSetting.blocked_attachment_filenames = "foo|bar"
expect(SiteSetting.blocked_attachment_filenames_regex).to eq(/foo|bar/)
end
end
it "sanitizes the client settings when they are overridden" do
xss = "<b onmouseover=alert('Wufff!')>click me!</b><script>alert('TEST');</script>"
SiteSetting.global_notice = xss
expect(SiteSetting.global_notice).to eq("<b>click me!</b>alert('TEST');")
end
it "doesn't corrupt site settings with special characters" do
value = 'OX5y3Oljb+Qt9Bu809vsBQ==<>!%{}*&!@#$%..._-A'
settings = new_settings(SiteSettings::LocalProcessProvider.new)
settings.setting(:test_setting, "", client: true)
settings.test_setting = value
expect(settings.test_setting).to eq(value)
end
describe "#all_settings" do
it "does not include the `default_locale` setting if include_locale_setting is false" do
expect(SiteSetting.all_settings.map { |s| s[:setting] }).to include(:default_locale)
expect(
SiteSetting.all_settings(include_locale_setting: false).map { |s| s[:setting] },
).not_to include(:default_locale)
end
it "does not include the `default_locale` setting if filter_categories are specified" do
expect(
SiteSetting.all_settings(filter_categories: ["branding"]).map { |s| s[:setting] },
).not_to include(:default_locale)
end
it "does not include the `default_locale` setting if filter_plugin is specified" do
expect(
SiteSetting.all_settings(filter_plugin: "chat").map { |s| s[:setting] },
).not_to include(:default_locale)
end
it "includes only settings for the specified category" do
expect(SiteSetting.all_settings(filter_categories: ["required"]).count).to eq(12)
end
end
describe ".history_for" do
fab!(:admin)
it "returns an empty relation when no changes have been made" do
expect(SiteSetting.history_for(:title)).to be_empty
end
it "returns UserHistory records for the specified setting" do
StaffActionLogger.new(admin).log_site_setting_change(:title, "Old Title", "New Title")
StaffActionLogger.new(admin).log_site_setting_change(:title, "New Title", "Newer Title")
history = SiteSetting.history_for(:title)
expect(history.count).to eq(2)
expect(history.first.action).to eq(UserHistory.actions[:change_site_setting])
expect(history.first.subject).to eq("title")
expect(history.first.new_value).to eq("Newer Title")
expect(history.last.new_value).to eq("New Title")
end
it "returns only records for the specified setting" do
StaffActionLogger.new(admin).log_site_setting_change(:title, "Old", "New")
StaffActionLogger.new(admin).log_site_setting_change(
:contact_email,
"old@test.com",
"new@test.com",
)
history = SiteSetting.history_for(:title)
expect(history.count).to eq(1)
expect(history.first.subject).to eq("title")
end
it "returns records ordered by most recent first" do
StaffActionLogger.new(admin).log_site_setting_change(:title, "First", "Second")
StaffActionLogger.new(admin).log_site_setting_change(:title, "Second", "Third")
history = SiteSetting.history_for(:title)
expect(history.first.new_value).to eq("Third")
expect(history.last.new_value).to eq("Second")
end
end
describe "ImageQuality" do
describe "#png_to_jpg_quality" do
context "when set to zero" do
before { SiteSetting.png_to_jpg_quality = 0 }
it "falls back to unified image quality setting" do
expect(SiteSetting.ImageQuality.png_to_jpg_quality).to eq(SiteSetting.image_quality)
end
end
context "when set to any non-zero value" do
before { SiteSetting.png_to_jpg_quality = 42 }
it "uses the configured value" do
expect(SiteSetting.ImageQuality.png_to_jpg_quality).to eq(42)
end
end
end
describe "#recompress_original_jpg_quality" do
context "when set to zero" do
before { SiteSetting.recompress_original_jpg_quality = 0 }
it "falls back to unified image quality setting" do
expect(SiteSetting.ImageQuality.recompress_original_jpg_quality).to eq(
SiteSetting.image_quality,
)
end
end
context "when set to any non-zero value" do
before { SiteSetting.recompress_original_jpg_quality = 42 }
it "uses the configured value" do
expect(SiteSetting.ImageQuality.recompress_original_jpg_quality).to eq(42)
end
end
end
describe "#image_preview_jpg_quality" do
context "when set to zero" do
before { SiteSetting.image_preview_jpg_quality = 0 }
it "falls back to unified image quality setting" do
expect(SiteSetting.ImageQuality.image_preview_jpg_quality).to eq(
SiteSetting.image_quality,
)
end
end
context "when set to any non-zero value" do
before { SiteSetting.image_preview_jpg_quality = 42 }
it "uses the configured value" do
expect(SiteSetting.ImageQuality.image_preview_jpg_quality).to eq(42)
end
end
end
end
describe "creating upload references for type objects settings with upload fields" do
let(:provider) { SiteSettings::DbProvider.new(SiteSetting) }
fab!(:upload)
fab!(:upload2, :upload)
it "creates upload references for objects with upload fields" do
objects_value =
JSON.generate(
[
{ "name" => "object1", "upload_id" => upload.id },
{ "name" => "object2", "upload_id" => upload2.id },
],
)
expect {
provider.save(
"test_objects_with_uploads",
objects_value,
SiteSettings::TypeSupervisor.types[:objects],
)
}.to change { UploadReference.count }.by(2)
upload_references =
UploadReference.where(target: SiteSetting.find_by(name: "test_objects_with_uploads"))
expect(upload_references.pluck(:upload_id)).to contain_exactly(upload.id, upload2.id)
expect { provider.destroy("test_objects_with_uploads") }.to change {
UploadReference.count
}.by(-2)
end
it "creates upload references for objects with upload URLs" do
objects_value =
JSON.generate(
[
{ "name" => "object1", "upload_id" => upload.url },
{ "name" => "object2", "upload_id" => upload2.url },
],
)
expect {
provider.save(
"test_objects_with_uploads",
objects_value,
SiteSettings::TypeSupervisor.types[:objects],
)
}.to change { UploadReference.count }.by(2)
upload_references =
UploadReference.where(target: SiteSetting.find_by(name: "test_objects_with_uploads"))
expect(upload_references.pluck(:upload_id)).to contain_exactly(upload.id, upload2.id)
end
it "removes upload references when uploads are removed from objects" do
# First save with two uploads
objects_value =
JSON.generate(
[
{ "name" => "object1", "upload_id" => upload.url },
{ "name" => "object2", "upload_id" => upload2.url },
],
)
provider.save(
"test_objects_with_uploads",
objects_value,
SiteSettings::TypeSupervisor.types[:objects],
)
setting = SiteSetting.find_by(name: "test_objects_with_uploads")
expect(UploadReference.where(target: setting).count).to eq(2)
# Now save with only one upload - should remove the other reference
objects_value_updated = JSON.generate([{ "name" => "object1", "upload_id" => upload.url }])
expect {
provider.save(
"test_objects_with_uploads",
objects_value_updated,
SiteSettings::TypeSupervisor.types[:objects],
)
}.to change { UploadReference.count }.by(-1)
expect(UploadReference.where(target: setting).pluck(:upload_id)).to contain_exactly(upload.id)
end
it "removes all upload references when all uploads are removed from objects" do
# First save with uploads
objects_value =
JSON.generate(
[
{ "name" => "object1", "upload_id" => upload.url },
{ "name" => "object2", "upload_id" => upload2.url },
],
)
provider.save(
"test_objects_with_uploads",
objects_value,
SiteSettings::TypeSupervisor.types[:objects],
)
setting = SiteSetting.find_by(name: "test_objects_with_uploads")
expect(UploadReference.where(target: setting).count).to eq(2)
# Now save with no uploads - should remove all references
objects_value_empty = JSON.generate([{ "name" => "object1" }])
expect {
provider.save(
"test_objects_with_uploads",
objects_value_empty,
SiteSettings::TypeSupervisor.types[:objects],
)
}.to change { UploadReference.count }.by(-2)
expect(UploadReference.where(target: setting).count).to eq(0)
end
end
describe "Upload" do
before { setup_s3 }
describe "#use_dualstack_endpoint" do
context "when the s3 endpoint has been set" do
before { SiteSetting.s3_endpoint = "https://s3clone.test.com" }
it "returns false " do
expect(SiteSetting.Upload.use_dualstack_endpoint).to eq(false)
end
end
context "when enable_s3_uploads is false" do
before { SiteSetting.enable_s3_uploads = false }
it "returns false" do
expect(SiteSetting.Upload.use_dualstack_endpoint).to eq(false)
end
end
context "when enable_s3_uploads is true" do
before do
SiteSetting.enable_s3_uploads = true
SiteSetting.s3_endpoint = ""
end
it "returns false if the s3_region is in China" do
SiteSetting.s3_region = "cn-north-1"
expect(SiteSetting.Upload.use_dualstack_endpoint).to eq(false)
end
it "returns true if the s3_region is not in China" do
SiteSetting.s3_region = "us-west-1"
expect(SiteSetting.Upload.use_dualstack_endpoint).to eq(true)
end
end
end
end
describe ".content_localization_locales" do
it "returns configured supported locales" do
SiteSetting.content_localization_supported_locales = "es|fr|de"
SiteSetting.default_locale = "es"
expect(SiteSetting.content_localization_locales).to contain_exactly("es", "fr", "de")
end
it "includes default locale when not in supported locales" do
SiteSetting.content_localization_supported_locales = "es|fr"
SiteSetting.default_locale = "en"
expect(SiteSetting.content_localization_locales).to contain_exactly("es", "fr", "en")
end
it "does not duplicate default locale when already in supported locales" do
SiteSetting.content_localization_supported_locales = "en|es|fr"
SiteSetting.default_locale = "en"
expect(SiteSetting.content_localization_locales).to contain_exactly("en", "es", "fr")
end
it "returns only default locale when no supported locales configured" do
SiteSetting.content_localization_supported_locales = ""
SiteSetting.default_locale = "en"
expect(SiteSetting.content_localization_locales).to eq(["en"])
end
end
end