0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-06 13:08:40 +08:00
discourse/spec/system/admin_customize_themes_spec.rb
Penar Musaraj 3baf375056
UX: Use English as language label where appropriate (#36762)
PR makes two changes: 

- replaces "English (US) with "English" everywhere
- in the language switcher dropdown, it replaces "English (UK)" with
"English" if that variant of English is the only one enabled

"English (US)" is needlessly geo-specific. Given it is the default
language, using "English" as the label is shorter and clearer. It still
differentiates from "English (UK)" when choosing the interface language
for users (or in admin UIs):

<img width="500" alt="CleanShot 2025-12-17 at 17 38 32@2x"
src="https://github.com/user-attachments/assets/abd7674c-2b72-4e5c-8543-050b7812c743"
/>

And the PR also strips `(UK)` from the language switcher list when
"English (UK)" is the only English variant enabled. This is a bit hacky,
but it lets us have cleaner UX (especially for countries like Canada,
Australia, where sites may opt for `en_GB` as their default) while
keeping the necessary technical separation between English and English
(UK) in admin and user preference screens.

---------

Co-authored-by: Natalie Tay <natalie.tay@gmail.com>
2025-12-18 13:10:23 -05:00

357 lines
13 KiB
Ruby
Vendored

# frozen_string_literal: true
describe "Admin Customize Themes", type: :system do
fab!(:color_scheme) do
Fabricate(:color_scheme, base_scheme_id: ColorScheme::NAMES_TO_ID_MAP["Light"])
end
fab!(:theme) { Fabricate(:theme, name: "Cool theme 1", user_selectable: true) }
fab!(:admin) { Fabricate(:admin, locale: "en") }
let(:theme_page) { PageObjects::Pages::AdminCustomizeThemes.new }
let(:themes_page) { PageObjects::Pages::AdminCustomizeThemesConfigArea.new }
let(:dialog) { PageObjects::Components::Dialog.new }
let(:sidebar) { PageObjects::Components::NavigationMenu::Sidebar.new }
before { sign_in(admin) }
describe "when visiting the page to customize a single theme" do
it "should keep sidebar navigation link active" do
theme_page.visit(theme)
expect(sidebar).to have_active_link("admin_themes_and_components")
end
it "should allow admin to update the light color scheme of the theme" do
theme_page.visit(theme)
color_scheme_settings = find(".theme-settings__light-color-scheme")
expect(color_scheme_settings).to have_no_css(".submit-light-edit")
expect(color_scheme_settings).to have_no_css(".cancel-light-edit")
color_scheme_settings.find(".color-palette-picker").click
color_scheme_settings.find(".color-palette-picker-row[data-value='#{color_scheme.id}']").click
color_scheme_settings.find(".submit-light-edit").click
expect(color_scheme_settings.find(".setting-value")).to have_content(color_scheme.name)
expect(color_scheme_settings).to have_no_css(".submit-light-edit")
expect(color_scheme_settings).to have_no_css(".cancel-light-edit")
expect(page).to have_link(
I18n.t("admin_js.admin.customize.theme.edit_colors"),
href: "/admin/config/colors/#{color_scheme.id}",
)
end
it "should allow admin to update the dark color scheme of the theme" do
theme_page.visit(theme)
color_scheme_settings = find(".theme-settings__dark-color-scheme")
expect(color_scheme_settings).not_to have_css(".submit-dark-edit")
expect(color_scheme_settings).not_to have_css(".cancel-dark-edit")
color_scheme_settings.find(".color-palette-picker").click
color_scheme_settings.find(".color-palette-picker-row[data-value='#{color_scheme.id}']").click
color_scheme_settings.find(".submit-dark-edit").click
expect(color_scheme_settings.find(".setting-value")).to have_content(color_scheme.name)
expect(color_scheme_settings).not_to have_css(".submit-dark-edit")
expect(color_scheme_settings).not_to have_css(".cancel-dark-edit")
expect(page).to have_link(
I18n.t("admin_js.admin.customize.theme.edit_colors"),
href: "/admin/config/colors/#{color_scheme.id}",
)
end
it "allows a theme to be deleted" do
theme_page.visit(theme).click_delete_button_and_confirm
expect(PageObjects::Components::Toasts.new).to have_success(
I18n.t("admin_js.admin.customize.theme.delete_success", theme: theme.name),
)
expect(page).to have_current_path("/admin/config/customize/themes")
expect(themes_page).to have_no_theme(theme.name)
end
end
describe "when editing a local theme" do
it "The saved value is present in the editor" do
theme.set_field(target: "common", name: "head_tag", value: "console.log('test')", type_id: 0)
theme.save!
visit("/admin/customize/themes/#{theme.id}/common/head_tag/edit")
expect(find(".ace_content")).to have_content("console.log('test')")
end
it "can edit the js field" do
visit("/admin/customize/themes/#{theme.id}/common/js/edit")
expect(find(".ace_content")).to have_content("// Your code here")
find(".ace_text-input", visible: false).fill_in(with: "console.log('test')\n")
find(".save-theme").click
expect(theme.theme_fields.find_by(target_id: Theme.targets[:extra_js])&.value).to start_with(
"console.log('test')\n",
)
# Check content is loaded from db correctly
theme
.theme_fields
.find_by(target_id: Theme.targets[:extra_js])
.update!(value: "console.log('second test')")
visit("/admin/customize/themes/#{theme.id}/common/js/edit")
expect(find(".ace_content")).to have_content("console.log('second test')")
end
end
it "cannot edit js, upload files or delete system themes" do
theme.update_columns(id: -10)
theme_page.visit(theme)
expect(page).to have_css(".system-theme-info")
expect(page).to have_css(".title button")
expect(page).to have_no_css(".title button svg")
expect(page).to have_no_css(".edit-code")
expect(page).to have_no_css("button.upload")
expect(page).to have_no_css(".delete")
end
it "hides unnecessary sections and buttons for system themes" do
theme.set_field(
target: :extra_js,
name: "discourse/api-initializers/test.js",
value: "console.log('second test')",
)
yaml = <<~YAML
enable_welcome_banner:
default: true
description: "Overrides the core `enable welcome banner` site setting"
YAML
theme.set_field(target: :settings, name: "yaml", value: yaml)
theme.save!
theme_page.visit(theme)
expect(page).to have_css(".created-by")
expect(page).to have_css(".export")
expect(page).to have_css(".extra-files")
expect(page).to have_css(".theme-settings")
expect(page).to have_no_css(".system-theme-info")
# Since we're only testing the one theme, we can stub the system? method
# for every theme to return true.
# This avoids needing to update the theme field data to point to a different theme id.
allow_any_instance_of(Theme).to receive(:system?).and_return(true)
theme_page.visit(theme)
expect(page).to have_css(".system-theme-info")
expect(page).to have_no_css(".created-by")
expect(page).to have_no_css(".export")
expect(page).to have_no_css(".extra-files")
expect(page).to have_css(".theme-settings")
end
it "shows both JS and SCSS extra files with canonical paths" do
theme.set_field(
target: :extra_js,
name: "discourse/api-initializers/canvas.js",
value: "console.log('extra js')",
)
theme.set_field(target: :extra_scss, name: "properties", value: ".custom { color: red; }")
theme.save!
theme_page.visit(theme)
extra_files = find(".extra-files")
extra_files.find("summary").click
expect(extra_files).to have_content("javascripts/discourse/api-initializers/canvas.js")
expect(extra_files).to have_content("stylesheets/properties.scss")
end
describe "when editing theme translations" do
it "should allow admin to edit and save the theme translations" do
theme.set_field(
target: :translations,
name: "en",
value: { en: { group: { hello: "Hello there!" } } }.deep_stringify_keys.to_yaml,
)
theme.save!
theme_page.visit(theme)
theme_translations_settings_editor =
PageObjects::Components::AdminThemeTranslationsSettingsEditor.new
theme_translations_settings_editor.fill_in("Hello World")
theme_translations_settings_editor.save
theme_page.visit(theme)
expect(theme_translations_settings_editor.get_input_value).to have_content("Hello World")
end
it "should allow admin to edit and save the theme translations from other languages" do
theme.set_field(
target: :translations,
name: "en",
value: { en: { group: { hello: "Hello there!" } } }.deep_stringify_keys.to_yaml,
)
theme.set_field(
target: :translations,
name: "fr",
value: { fr: { group: { hello: "Bonjour!" } } }.deep_stringify_keys.to_yaml,
)
theme.save!
theme_page.visit(theme)
theme_translations_settings_editor =
PageObjects::Components::AdminThemeTranslationsSettingsEditor.new
expect(theme_translations_settings_editor.get_input_value).to have_content("Hello there!")
theme_translations_picker = PageObjects::Components::SelectKit.new(".translation-selector")
theme_translations_picker.select_row_by_value("fr")
expect(page).to have_css(".translations")
expect(theme_translations_settings_editor.get_input_value).to have_content("Bonjour!")
theme_translations_settings_editor.fill_in("Hello World in French")
theme_translations_settings_editor.save
end
it "should match the current user locale translation" do
SiteSetting.allow_user_locale = true
SiteSetting.set_locale_from_accept_language_header = true
SiteSetting.default_locale = "fr"
theme.set_field(
target: :translations,
name: "en",
value: { en: { group: { hello: "Hello there!" } } }.deep_stringify_keys.to_yaml,
)
theme.set_field(
target: :translations,
name: "fr",
value: { fr: { group: { hello: "Bonjour!" } } }.deep_stringify_keys.to_yaml,
)
theme.save!
theme_page.visit(theme)
theme_translations_settings_editor =
PageObjects::Components::AdminThemeTranslationsSettingsEditor.new
expect(theme_translations_settings_editor.get_input_value).to have_content("Hello there!")
theme_translations_picker = PageObjects::Components::SelectKit.new(".translation-selector")
expect(theme_translations_picker.component).to have_content("English")
end
end
describe "when editing a theme's included components" do
fab!(:component) { Fabricate(:theme, component: true, name: "Cool component 145") }
it "can save the included components" do
theme_page.visit(theme.id)
theme_page.included_components_selector.expand
theme_page.included_components_selector.select_row_by_index(0)
theme_page.included_components_selector.collapse
theme_page.relative_themes_save_button.click
expect(theme_page).to have_reset_button_for_setting(".included-components-setting")
expect(ChildTheme.exists?(parent_theme_id: theme.id, child_theme_id: component.id)).to eq(
true,
)
end
end
context "when visiting a component's page" do
fab!(:component) { Fabricate(:theme, component: true, name: "Cool component 493") }
it "has a link to the components page" do
visit("/admin/customize/themes/#{component.id}")
expect(theme_page).to have_back_button_to_components_page
end
it "allows to add component to all themes" do
visit("/admin/customize/themes/#{component.id}")
expect(page.find(".relative-theme-selector .formatted-selection").text).to eq(
I18n.t("js.select_kit.default_header_text"),
)
theme_page.click_add_all_themes_button
expect(page.find(".relative-theme-selector .formatted-selection").text).to eq(
"#{theme.name}, Foundation, Horizon",
)
end
end
describe "editing theme site settings" do
it "shows all themeable site settings and allows editing values" do
theme_page.visit(theme.id)
SiteSetting.themeable_site_settings.each do |setting_name|
expect(theme_page).to have_theme_site_setting(setting_name)
end
theme_page.toggle_theme_site_setting("enable_welcome_banner")
expect(theme_page).to have_overridden_theme_site_setting("enable_welcome_banner")
expect(page).to have_content(
I18n.t("admin_js.admin.customize.theme.theme_site_setting_saved"),
)
expect(
ThemeSiteSetting.exists?(theme: theme, name: "enable_welcome_banner", value: "f"),
).to be_truthy
end
it "allows resetting themeable site setting values back to site setting default" do
Fabricate(
:theme_site_setting_with_service,
theme: theme,
name: "enable_welcome_banner",
value: false,
)
theme_page.visit(theme.id)
expect(theme_page).to have_overridden_theme_site_setting("enable_welcome_banner")
theme_page.reset_overridden_theme_site_setting("enable_welcome_banner")
expect(page).to have_content(
I18n.t("admin_js.admin.customize.theme.theme_site_setting_saved"),
)
expect(
ThemeSiteSetting.exists?(theme: theme, name: "enable_welcome_banner", value: "f"),
).to be_falsey
end
it "does not show the overridden indicator if the theme site setting value in the DB is the same as the default" do
Fabricate(
:theme_site_setting_with_service,
theme: theme,
name: "enable_welcome_banner",
value: true,
)
theme_page.visit(theme.id)
expect(theme_page).to have_theme_site_setting("enable_welcome_banner")
expect(theme_page).to have_no_overridden_theme_site_setting("enable_welcome_banner")
end
it "alters the UI via MessageBus when a theme site setting changes" do
SiteSetting.refresh!(refresh_site_settings: false, refresh_theme_site_settings: true)
banner = PageObjects::Components::WelcomeBanner.new
other_user = Fabricate(:user)
other_user.user_option.update!(theme_ids: [theme.id])
sign_in(other_user)
visit("/")
expect(banner).to be_visible
using_session(:admin) do
sign_in(admin)
theme_page.visit(theme.id)
theme_page.toggle_theme_site_setting("enable_welcome_banner")
end
try_until_success(reason: "Relies on MessageBus updates") { expect(banner).to be_hidden }
end
end
end