mirror of
https://github.com/discourse/discourse.git
synced 2024-11-30 13:16:43 +08:00
7ef482a292
* FIX: Use pluralized string * REFACTOR: Fix misuse of pluralized string * REFACTOR: Fix misuse of pluralized string * DEV: Remove linting of `one` key in MessageFormat string, it doesn't work * REFACTOR: Fix misuse of pluralized string This also ensures that the URL works on subfolder and shows the site setting link only for admins instead of staff. The string is quite complicated, so the best option was to switch to MessageFormat. * REFACTOR: Fix misuse of pluralized string * FIX: Use pluralized string This also ensures that the URL works on subfolder and shows the site setting link only for admins instead of staff. * REFACTOR: Correctly pluralize reaction tooltips in chat This also ensures that maximum 5 usernames are shown and fixes the number of "others" which was off by 1 if the current user reacted on a message. * REFACTOR: Use translatable string as comma separator * DEV: Add comment to translation to clarify the meaning of `%{identifier}` * REFACTOR: Use translatable comma separator and use explicit interpolation keys * REFACTOR: Don't interpolate lowercase channel status * REFACTOR: Fix misuse of pluralized string * REFACTOR: Don't interpolate channel status * REFACTOR: Use %{count} interpolation key * REFACTOR: Fix misuse of pluralized string * REFACTOR: Correctly pluralize DM chat channel titles
889 lines
28 KiB
Ruby
889 lines
28 KiB
Ruby
# frozen_string_literal: true
|
||
|
||
RSpec.describe Admin::SiteTextsController do
|
||
fab!(:admin) { Fabricate(:admin) }
|
||
fab!(:moderator) { Fabricate(:moderator) }
|
||
fab!(:user) { Fabricate(:user) }
|
||
let(:default_locale) { I18n.locale }
|
||
|
||
after do
|
||
TranslationOverride.delete_all
|
||
I18n.reload!
|
||
end
|
||
|
||
describe "#index" do
|
||
context "when logged in as an admin" do
|
||
before { sign_in(admin) }
|
||
|
||
it "returns json" do
|
||
get "/admin/customize/site_texts.json", params: { q: "title", locale: default_locale }
|
||
expect(response.status).to eq(200)
|
||
expect(response.parsed_body["site_texts"]).to include(include("id" => "title"))
|
||
end
|
||
|
||
it "sets has_more to true if more than 50 results were found" do
|
||
get "/admin/customize/site_texts.json", params: { q: "e", locale: default_locale }
|
||
expect(response.status).to eq(200)
|
||
expect(response.parsed_body["site_texts"].size).to eq(50)
|
||
expect(response.parsed_body["extras"]["has_more"]).to be_truthy
|
||
end
|
||
|
||
it "works with pages" do
|
||
texts = Set.new
|
||
|
||
get "/admin/customize/site_texts.json", params: { q: "e", locale: default_locale }
|
||
response.parsed_body["site_texts"].each { |text| texts << text["id"] }
|
||
expect(texts.size).to eq(50)
|
||
|
||
get "/admin/customize/site_texts.json", params: { q: "e", page: 1, locale: default_locale }
|
||
response.parsed_body["site_texts"].each { |text| texts << text["id"] }
|
||
expect(texts.size).to eq(100)
|
||
end
|
||
|
||
it "works with locales" do
|
||
get "/admin/customize/site_texts.json", params: { q: "yes_value", locale: default_locale }
|
||
value =
|
||
response.parsed_body["site_texts"].find { |text| text["id"] == "js.yes_value" }["value"]
|
||
expect(value).to eq(I18n.t("js.yes_value", locale: default_locale))
|
||
|
||
get "/admin/customize/site_texts.json", params: { q: "yes_value", locale: "de" }
|
||
value =
|
||
response.parsed_body["site_texts"].find { |text| text["id"] == "js.yes_value" }["value"]
|
||
expect(value).to eq(I18n.t("js.yes_value", locale: :de))
|
||
end
|
||
|
||
it "returns an error on invalid locale" do
|
||
get "/admin/customize/site_texts.json", params: { locale: "?" }
|
||
expect(response.status).to eq(400)
|
||
end
|
||
|
||
it "returns an error on empty locale" do
|
||
get "/admin/customize/site_texts.json"
|
||
expect(response.status).to eq(400)
|
||
end
|
||
|
||
it "normalizes quotes during search" do
|
||
value = "“That’s a ‘magic’ sock.”"
|
||
put "/admin/customize/site_texts/title.json",
|
||
params: {
|
||
site_text: {
|
||
value: value,
|
||
locale: default_locale,
|
||
},
|
||
}
|
||
|
||
[
|
||
"That's a 'magic' sock.",
|
||
"That’s a ‘magic’ sock.",
|
||
"“That's a 'magic' sock.”",
|
||
%q|"That's a 'magic' sock."|,
|
||
"«That's a 'magic' sock.»",
|
||
"„That’s a ‚magic‘ sock.“",
|
||
].each do |search_term|
|
||
get "/admin/customize/site_texts.json", params: { q: search_term, locale: default_locale }
|
||
expect(response.status).to eq(200)
|
||
expect(response.parsed_body["site_texts"]).to include(
|
||
include("id" => "title", "value" => value),
|
||
)
|
||
end
|
||
end
|
||
|
||
it "normalizes ellipsis" do
|
||
value = "Loading Discussion…"
|
||
put "/admin/customize/site_texts/embed.loading.json",
|
||
params: {
|
||
site_text: {
|
||
value: value,
|
||
locale: default_locale,
|
||
},
|
||
}
|
||
|
||
["Loading Discussion", "Loading Discussion...", "Loading Discussion…"].each do |search_term|
|
||
get "/admin/customize/site_texts.json", params: { q: search_term, locale: default_locale }
|
||
expect(response.status).to eq(200)
|
||
expect(response.parsed_body["site_texts"]).to include(
|
||
include("id" => "embed.loading", "value" => value),
|
||
)
|
||
end
|
||
end
|
||
|
||
it "does not return overrides for keys that do not exist in English" do
|
||
SiteSetting.default_locale = :ru
|
||
TranslationOverride.create!(
|
||
locale: :ru,
|
||
translation_key: "missing_plural_key.one",
|
||
value: "ONE",
|
||
)
|
||
TranslationOverride.create!(
|
||
locale: :ru,
|
||
translation_key: "another_missing_key",
|
||
value: "foo",
|
||
)
|
||
|
||
get "/admin/customize/site_texts.json",
|
||
params: {
|
||
q: "missing_plural_key",
|
||
locale: default_locale,
|
||
}
|
||
expect(response.status).to eq(200)
|
||
expect(response.parsed_body["site_texts"]).to be_empty
|
||
|
||
get "/admin/customize/site_texts.json",
|
||
params: {
|
||
q: "another_missing_key",
|
||
locale: default_locale,
|
||
}
|
||
expect(response.status).to eq(200)
|
||
expect(response.parsed_body["site_texts"]).to be_empty
|
||
end
|
||
|
||
it "returns site text from fallback locale if current locale doesn't have a translation" do
|
||
TranslationOverride.upsert!(
|
||
:en,
|
||
"js.summary.description_time_MF",
|
||
"description_time_MF override",
|
||
)
|
||
TranslationOverride.upsert!(:en, "education.new-topic", "education.new-topic override")
|
||
|
||
get "/admin/customize/site_texts.json",
|
||
params: {
|
||
q: "js.summary.description_time_MF",
|
||
locale: "en_GB",
|
||
}
|
||
expect(response.status).to eq(200)
|
||
value =
|
||
response.parsed_body["site_texts"].find do |text|
|
||
text["id"] == "js.summary.description_time_MF"
|
||
end[
|
||
"value"
|
||
]
|
||
expect(value).to eq("description_time_MF override")
|
||
|
||
get "/admin/customize/site_texts.json",
|
||
params: {
|
||
q: "education.new-topic",
|
||
locale: "en_GB",
|
||
}
|
||
expect(response.status).to eq(200)
|
||
value =
|
||
response.parsed_body["site_texts"].find { |text| text["id"] == "education.new-topic" }[
|
||
"value"
|
||
]
|
||
expect(value).to eq("education.new-topic override")
|
||
end
|
||
|
||
it "returns only overridden translations" do
|
||
TranslationOverride.upsert!(:en, "education.new-topic", "education.new-topic override")
|
||
|
||
get "/admin/customize/site_texts.json", params: { locale: "en", overridden: true }
|
||
expect(response.status).to eq(200)
|
||
|
||
site_texts = response.parsed_body["site_texts"]
|
||
expect(site_texts.size).to eq(1)
|
||
|
||
value = site_texts.find { |text| text["id"] == "education.new-topic" }["value"]
|
||
expect(value).to eq("education.new-topic override")
|
||
end
|
||
|
||
context "with plural keys" do
|
||
before do
|
||
I18n.backend.store_translations(
|
||
:en,
|
||
colour: {
|
||
one: "%{count} colour",
|
||
other: "%{count} colours",
|
||
},
|
||
)
|
||
end
|
||
|
||
shared_examples "finds correct plural keys" do
|
||
it "finds the correct plural keys for the locale" do
|
||
SiteSetting.default_locale = locale
|
||
|
||
get "/admin/customize/site_texts.json", params: { q: "colour", locale: locale }
|
||
expect(response.status).to eq(200)
|
||
|
||
json = ::JSON.parse(response.body, symbolize_names: true)
|
||
expect(json).to be_present
|
||
|
||
site_texts = json[:site_texts]
|
||
expect(site_texts).to be_present
|
||
|
||
expected_search_result =
|
||
expected_translations.map do |key, value|
|
||
overridden =
|
||
defined?(expected_overridden) ? expected_overridden[key] || false : false
|
||
{
|
||
id: "colour.#{key}",
|
||
value: value,
|
||
can_revert: overridden,
|
||
overridden: overridden,
|
||
}
|
||
end
|
||
|
||
expect(site_texts).to match_array(expected_search_result)
|
||
end
|
||
end
|
||
|
||
context "with English" do
|
||
let(:locale) { :en }
|
||
let(:expected_translations) { { one: "%{count} colour", other: "%{count} colours" } }
|
||
|
||
include_examples "finds correct plural keys"
|
||
end
|
||
|
||
context "with language with different plural keys and missing translations" do
|
||
let(:locale) { :ru }
|
||
let(:expected_translations) do
|
||
{
|
||
one: "%{count} colour",
|
||
few: "%{count} colours",
|
||
many: "%{count} colours",
|
||
other: "%{count} colours",
|
||
}
|
||
end
|
||
|
||
include_examples "finds correct plural keys"
|
||
end
|
||
|
||
context "with language with different plural keys and partial translation" do
|
||
before do
|
||
I18n.backend.store_translations(
|
||
:ru,
|
||
colour: {
|
||
few: "%{count} цвета",
|
||
many: "%{count} цветов",
|
||
},
|
||
)
|
||
end
|
||
|
||
let(:locale) { :ru }
|
||
let(:expected_translations) do
|
||
{
|
||
one: "%{count} colour",
|
||
few: "%{count} цвета",
|
||
many: "%{count} цветов",
|
||
other: "%{count} colours",
|
||
}
|
||
end
|
||
|
||
include_examples "finds correct plural keys"
|
||
end
|
||
|
||
context "with overridden translation not in original translation" do
|
||
before do
|
||
I18n.backend.store_translations(
|
||
:ru,
|
||
colour: {
|
||
few: "%{count} цвета",
|
||
many: "%{count} цветов",
|
||
},
|
||
)
|
||
TranslationOverride.create!(locale: :ru, translation_key: "colour.one", value: "ONE")
|
||
TranslationOverride.create!(locale: :ru, translation_key: "colour.few", value: "FEW")
|
||
end
|
||
|
||
let(:locale) { :ru }
|
||
let(:expected_translations) do
|
||
{ one: "ONE", few: "FEW", many: "%{count} цветов", other: "%{count} colours" }
|
||
end
|
||
let(:expected_overridden) { { one: true, few: true } }
|
||
|
||
include_examples "finds correct plural keys"
|
||
end
|
||
end
|
||
end
|
||
|
||
shared_examples "site texts inaccessible" do
|
||
it "denies access with a 404 response" do
|
||
get "/admin/customize/site_texts.json", params: { q: "title", locale: default_locale }
|
||
|
||
expect(response.status).to eq(404)
|
||
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
|
||
end
|
||
end
|
||
|
||
context "when logged in as a moderator" do
|
||
before { sign_in(moderator) }
|
||
|
||
include_examples "site texts inaccessible"
|
||
end
|
||
|
||
context "when logged in as a non-staff user" do
|
||
before { sign_in(user) }
|
||
|
||
include_examples "site texts inaccessible"
|
||
end
|
||
end
|
||
|
||
describe "#show" do
|
||
context "when logged in as an admin" do
|
||
before { sign_in(admin) }
|
||
|
||
it "returns a site text for a key that exists" do
|
||
get "/admin/customize/site_texts/js.topic.list.json", params: { locale: default_locale }
|
||
expect(response.status).to eq(200)
|
||
|
||
json = response.parsed_body
|
||
|
||
site_text = json["site_text"]
|
||
|
||
expect(site_text["id"]).to eq("js.topic.list")
|
||
expect(site_text["value"]).to eq(I18n.t("js.topic.list"))
|
||
end
|
||
|
||
it "returns a site text for a key with ampersand" do
|
||
get "/admin/customize/site_texts/js.emoji_picker.food_&_drink.json",
|
||
params: {
|
||
locale: default_locale,
|
||
}
|
||
expect(response.status).to eq(200)
|
||
|
||
json = response.parsed_body
|
||
|
||
site_text = json["site_text"]
|
||
|
||
expect(site_text["id"]).to eq("js.emoji_picker.food_&_drink")
|
||
expect(site_text["value"]).to eq(I18n.t("js.emoji_picker.food_&_drink"))
|
||
end
|
||
|
||
it "returns not found for missing keys" do
|
||
get "/admin/customize/site_texts/made_up_no_key_exists.json",
|
||
params: {
|
||
locale: default_locale,
|
||
}
|
||
expect(response.status).to eq(404)
|
||
end
|
||
|
||
it "returns overridden = true if there is a translation_overrides record for the key" do
|
||
key = "js.topic.list"
|
||
put "/admin/customize/site_texts/#{key}.json",
|
||
params: {
|
||
site_text: {
|
||
value: I18n.t(key, locale: default_locale),
|
||
locale: default_locale,
|
||
},
|
||
}
|
||
expect(response.status).to eq(200)
|
||
|
||
get "/admin/customize/site_texts/#{key}.json", params: { locale: default_locale }
|
||
expect(response.status).to eq(200)
|
||
json = response.parsed_body
|
||
expect(json["site_text"]["overridden"]).to eq(true)
|
||
|
||
TranslationOverride.destroy_all
|
||
|
||
get "/admin/customize/site_texts/#{key}.json", params: { locale: default_locale }
|
||
expect(response.status).to eq(200)
|
||
json = response.parsed_body
|
||
expect(json["site_text"]["overridden"]).to eq(false)
|
||
end
|
||
|
||
it "returns a site text in the given locale" do
|
||
get "/admin/customize/site_texts/js.topic.list.json", params: { locale: "es" }
|
||
expect(response.status).to eq(200)
|
||
|
||
json = response.parsed_body
|
||
site_text = json["site_text"]
|
||
|
||
expect(site_text["id"]).to eq("js.topic.list")
|
||
expect(site_text["value"]).to eq(I18n.t("js.topic.list", locale: :es))
|
||
end
|
||
|
||
it "fails if locale is not given" do
|
||
get "/admin/customize/site_texts/js.topic.list.json"
|
||
expect(response.status).to eq(400)
|
||
end
|
||
|
||
it "returns site text from fallback locale if current locale doesn't have a translation" do
|
||
TranslationOverride.upsert!(
|
||
:en,
|
||
"js.summary.description_time_MF",
|
||
"description_time_MF override",
|
||
)
|
||
TranslationOverride.upsert!(:en, "education.new-topic", "education.new-topic override")
|
||
|
||
get "/admin/customize/site_texts/js.summary.description_time_MF.json",
|
||
params: {
|
||
locale: "en_GB",
|
||
}
|
||
expect(response.status).to eq(200)
|
||
|
||
json = response.parsed_body
|
||
site_text = json["site_text"]
|
||
|
||
expect(site_text["id"]).to eq("js.summary.description_time_MF")
|
||
expect(site_text["value"]).to eq("description_time_MF override")
|
||
|
||
get "/admin/customize/site_texts/education.new-topic.json", params: { locale: "en_GB" }
|
||
expect(response.status).to eq(200)
|
||
|
||
json = response.parsed_body
|
||
site_text = json["site_text"]
|
||
|
||
expect(site_text["id"]).to eq("education.new-topic")
|
||
expect(site_text["value"]).to eq("education.new-topic override")
|
||
end
|
||
|
||
context "with plural keys" do
|
||
before do
|
||
I18n.backend.store_translations(
|
||
:en,
|
||
colour: {
|
||
one: "%{count} colour",
|
||
other: "%{count} colours",
|
||
},
|
||
)
|
||
end
|
||
|
||
shared_examples "has correct plural keys" do
|
||
it "returns the correct plural keys for the locale" do
|
||
expected_translations.each do |key, value|
|
||
id = "colour.#{key}"
|
||
|
||
get "/admin/customize/site_texts/#{id}.json", params: { locale: locale }
|
||
expect(response.status).to eq(200)
|
||
|
||
json = response.parsed_body
|
||
expect(json).to be_present
|
||
|
||
site_text = json["site_text"]
|
||
expect(site_text).to be_present
|
||
|
||
expect(site_text["id"]).to eq(id)
|
||
expect(site_text["value"]).to eq(value)
|
||
end
|
||
end
|
||
end
|
||
|
||
context "with English" do
|
||
let(:locale) { :en }
|
||
let(:expected_translations) { { one: "%{count} colour", other: "%{count} colours" } }
|
||
|
||
include_examples "has correct plural keys"
|
||
end
|
||
|
||
context "with language with different plural keys and missing translations" do
|
||
let(:locale) { :ru }
|
||
let(:expected_translations) do
|
||
{ one: "%{count} colour", few: "%{count} colours", other: "%{count} colours" }
|
||
end
|
||
|
||
include_examples "has correct plural keys"
|
||
end
|
||
|
||
context "with language with different plural keys and partial translation" do
|
||
before { I18n.backend.store_translations(:ru, colour: { few: "%{count} цвета" }) }
|
||
|
||
let(:locale) { :ru }
|
||
let(:expected_translations) do
|
||
{ one: "%{count} colour", few: "%{count} цвета", other: "%{count} colours" }
|
||
end
|
||
|
||
include_examples "has correct plural keys"
|
||
end
|
||
end
|
||
end
|
||
|
||
shared_examples "site text inaccessible" do
|
||
it "denies access with a 404 response" do
|
||
get "/admin/customize/site_texts/js.topic.list.json", params: { locale: default_locale }
|
||
|
||
expect(response.status).to eq(404)
|
||
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
|
||
end
|
||
end
|
||
|
||
context "when logged in as a moderator" do
|
||
before { sign_in(moderator) }
|
||
|
||
include_examples "site text inaccessible"
|
||
end
|
||
|
||
context "when logged in as a non-staff user" do
|
||
before { sign_in(user) }
|
||
|
||
include_examples "site text inaccessible"
|
||
end
|
||
end
|
||
|
||
describe "#update & #revert" do
|
||
context "when logged in as an admin" do
|
||
before { sign_in(admin) }
|
||
|
||
it "returns 'not found' when an unknown key is used" do
|
||
put "/admin/customize/site_texts/some_key.json",
|
||
params: {
|
||
site_text: {
|
||
value: "foo",
|
||
locale: default_locale,
|
||
},
|
||
}
|
||
|
||
expect(response.status).to eq(404)
|
||
|
||
json = response.parsed_body
|
||
expect(json["error_type"]).to eq("not_found")
|
||
end
|
||
|
||
it "works as expected with correct keys" do
|
||
put "/admin/customize/site_texts/js.emoji_picker.animals_%26_nature.json",
|
||
params: {
|
||
site_text: {
|
||
value: "foo",
|
||
locale: default_locale,
|
||
},
|
||
}
|
||
|
||
expect(response.status).to eq(200)
|
||
|
||
json = response.parsed_body
|
||
site_text = json["site_text"]
|
||
|
||
expect(site_text["id"]).to eq("js.emoji_picker.animals_&_nature")
|
||
expect(site_text["value"]).to eq("foo")
|
||
end
|
||
|
||
it "does not update restricted keys" do
|
||
put "/admin/customize/site_texts/user_notifications.confirm_old_email.title.json",
|
||
params: {
|
||
site_text: {
|
||
value: "foo",
|
||
locale: default_locale,
|
||
},
|
||
}
|
||
|
||
expect(response.status).to eq(403)
|
||
|
||
json = response.parsed_body
|
||
expect(json["error_type"]).to eq("invalid_access")
|
||
expect(json["errors"].size).to eq(1)
|
||
expect(json["errors"].first).to eq(I18n.t("email_template_cant_be_modified"))
|
||
end
|
||
|
||
it "returns the right error message" do
|
||
I18n.backend.store_translations(SiteSetting.default_locale, some_key: "%{first} %{second}")
|
||
|
||
put "/admin/customize/site_texts/some_key.json",
|
||
params: {
|
||
site_text: {
|
||
value: "hello %{key} %{omg}",
|
||
locale: default_locale,
|
||
},
|
||
}
|
||
|
||
expect(response.status).to eq(422)
|
||
|
||
body = response.parsed_body
|
||
|
||
expect(body["message"]).to eq(
|
||
I18n.t(
|
||
"activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys",
|
||
keys: "key, omg",
|
||
count: 2,
|
||
),
|
||
)
|
||
end
|
||
|
||
it "logs the change" do
|
||
original_title = I18n.t(:title)
|
||
|
||
put "/admin/customize/site_texts/title.json",
|
||
params: {
|
||
site_text: {
|
||
value: "yay",
|
||
locale: default_locale,
|
||
},
|
||
}
|
||
expect(response.status).to eq(200)
|
||
|
||
log = UserHistory.last
|
||
|
||
expect(log.previous_value).to eq(original_title)
|
||
expect(log.new_value).to eq("yay")
|
||
expect(log.action).to eq(UserHistory.actions[:change_site_text])
|
||
|
||
delete "/admin/customize/site_texts/title.json", params: { locale: default_locale }
|
||
expect(response.status).to eq(200)
|
||
|
||
log = UserHistory.last
|
||
|
||
expect(log.previous_value).to eq("yay")
|
||
expect(log.new_value).to eq(original_title)
|
||
expect(log.action).to eq(UserHistory.actions[:change_site_text])
|
||
end
|
||
|
||
it "updates and reverts the key" do
|
||
orig_title = I18n.t(:title)
|
||
|
||
put "/admin/customize/site_texts/title.json",
|
||
params: {
|
||
site_text: {
|
||
value: "hello",
|
||
locale: default_locale,
|
||
},
|
||
}
|
||
expect(response.status).to eq(200)
|
||
|
||
json = response.parsed_body
|
||
|
||
site_text = json["site_text"]
|
||
|
||
expect(site_text["id"]).to eq("title")
|
||
expect(site_text["value"]).to eq("hello")
|
||
|
||
# Revert
|
||
delete "/admin/customize/site_texts/title.json", params: { locale: default_locale }
|
||
expect(response.status).to eq(200)
|
||
|
||
json = response.parsed_body
|
||
|
||
site_text = json["site_text"]
|
||
|
||
expect(site_text["id"]).to eq("title")
|
||
expect(site_text["value"]).to eq(orig_title)
|
||
end
|
||
|
||
it "returns site texts for the correct locale" do
|
||
locale = :ru
|
||
|
||
ru_title = "title ru"
|
||
ru_mf_text = "ru {NUM_RESULTS, plural, one {1 result} other {many} }"
|
||
|
||
put "/admin/customize/site_texts/title.json",
|
||
params: {
|
||
site_text: {
|
||
value: ru_title,
|
||
locale: locale,
|
||
},
|
||
}
|
||
expect(response.status).to eq(200)
|
||
put "/admin/customize/site_texts/js.topic.read_more_MF.json",
|
||
params: {
|
||
site_text: {
|
||
value: ru_mf_text,
|
||
locale: locale,
|
||
},
|
||
}
|
||
expect(response.status).to eq(200)
|
||
|
||
get "/admin/customize/site_texts/title.json", params: { locale: locale }
|
||
expect(response.status).to eq(200)
|
||
json = response.parsed_body
|
||
expect(json["site_text"]["value"]).to eq(ru_title)
|
||
|
||
get "/admin/customize/site_texts/js.topic.read_more_MF.json", params: { locale: locale }
|
||
expect(response.status).to eq(200)
|
||
json = response.parsed_body
|
||
expect(json["site_text"]["value"]).to eq(ru_mf_text)
|
||
|
||
en_locale = :en
|
||
|
||
get "/admin/customize/site_texts/title.json", params: { locale: en_locale }
|
||
expect(response.status).to eq(200)
|
||
json = response.parsed_body
|
||
expect(json["site_text"]["value"]).to_not eq(ru_title)
|
||
|
||
get "/admin/customize/site_texts/js.topic.read_more_MF.json", params: { locale: en_locale }
|
||
expect(response.status).to eq(200)
|
||
json = response.parsed_body
|
||
expect(json["site_text"]["value"]).to_not eq(ru_mf_text)
|
||
end
|
||
|
||
context "when updating a translation override for a system badge" do
|
||
fab!(:user_with_badge_title) { Fabricate(:active_user) }
|
||
let(:badge) { Badge.find(Badge::Regular) }
|
||
|
||
before do
|
||
BadgeGranter.grant(badge, user_with_badge_title)
|
||
user_with_badge_title.update(title: "Regular")
|
||
end
|
||
|
||
it "updates matching user titles to the override text in a job" do
|
||
expect_enqueued_with(
|
||
job: :bulk_user_title_update,
|
||
args: {
|
||
new_title: "Terminator",
|
||
granted_badge_id: badge.id,
|
||
action: Jobs::BulkUserTitleUpdate::UPDATE_ACTION,
|
||
},
|
||
) do
|
||
put "/admin/customize/site_texts/badges.regular.name.json",
|
||
params: {
|
||
site_text: {
|
||
value: "Terminator",
|
||
locale: default_locale,
|
||
},
|
||
}
|
||
end
|
||
|
||
# Revert
|
||
expect_enqueued_with(
|
||
job: :bulk_user_title_update,
|
||
args: {
|
||
granted_badge_id: badge.id,
|
||
action: Jobs::BulkUserTitleUpdate::RESET_ACTION,
|
||
},
|
||
) do
|
||
delete "/admin/customize/site_texts/badges.regular.name.json",
|
||
params: {
|
||
locale: default_locale,
|
||
}
|
||
end
|
||
end
|
||
|
||
it "does not update matching user titles when overriding non-title badge text" do
|
||
expect_not_enqueued_with(job: :bulk_user_title_update) do
|
||
put "/admin/customize/site_texts/badges.regular.long_description.json",
|
||
params: {
|
||
site_text: {
|
||
value: "Terminator",
|
||
locale: default_locale,
|
||
},
|
||
}
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
shared_examples "site text update not allowed" do
|
||
it "prevents updates with a 404 response" do
|
||
put "/admin/customize/site_texts/js.emoji_picker.animals_%26_nature.json",
|
||
params: {
|
||
site_text: {
|
||
value: "foo",
|
||
locale: default_locale,
|
||
},
|
||
}
|
||
|
||
expect(response.status).to eq(404)
|
||
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
|
||
end
|
||
end
|
||
|
||
context "when logged in as a moderator" do
|
||
before { sign_in(moderator) }
|
||
|
||
include_examples "site text update not allowed"
|
||
end
|
||
|
||
context "when logged in as a non-staff user" do
|
||
before { sign_in(user) }
|
||
|
||
include_examples "site text update not allowed"
|
||
end
|
||
end
|
||
|
||
context "when reseeding" do
|
||
before do
|
||
staff_category = Fabricate(:category, name: "Staff EN", user: Discourse.system_user)
|
||
SiteSetting.staff_category_id = staff_category.id
|
||
|
||
guidelines_topic =
|
||
Fabricate(
|
||
:topic,
|
||
title: "The English Guidelines",
|
||
category: @staff_category,
|
||
user: Discourse.system_user,
|
||
)
|
||
Fabricate(:post, topic: guidelines_topic, user: Discourse.system_user)
|
||
SiteSetting.guidelines_topic_id = guidelines_topic.id
|
||
end
|
||
|
||
describe "#get_reseed_options" do
|
||
context "when logged in as an admin" do
|
||
before { sign_in(admin) }
|
||
|
||
it "returns correct json" do
|
||
get "/admin/customize/reseed.json"
|
||
expect(response.status).to eq(200)
|
||
|
||
expected_reseed_options = {
|
||
categories: [
|
||
{
|
||
id: "uncategorized_category_id",
|
||
name: I18n.t("uncategorized_category_name"),
|
||
selected: true,
|
||
},
|
||
{ id: "staff_category_id", name: "Staff EN", selected: true },
|
||
],
|
||
topics: [{ id: "guidelines_topic_id", name: "The English Guidelines", selected: true }],
|
||
}
|
||
|
||
expect(JSON.parse(response.body, symbolize_names: true)).to eq(expected_reseed_options)
|
||
end
|
||
end
|
||
|
||
shared_examples "reseed options inaccessible" do
|
||
it "denies access with a 404 response" do
|
||
get "/admin/customize/reseed.json"
|
||
|
||
expect(response.status).to eq(404)
|
||
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
|
||
end
|
||
end
|
||
|
||
context "when logged in as a moderator" do
|
||
before { sign_in(moderator) }
|
||
|
||
include_examples "reseed options inaccessible"
|
||
end
|
||
|
||
context "when logged in as a non-staff user" do
|
||
before { sign_in(user) }
|
||
|
||
include_examples "reseed options inaccessible"
|
||
end
|
||
end
|
||
|
||
describe "#reseed" do
|
||
context "when logged in as an admin" do
|
||
before { sign_in(admin) }
|
||
|
||
it "reseeds categories and topics" do
|
||
SiteSetting.default_locale = :de
|
||
|
||
post "/admin/customize/reseed.json",
|
||
params: {
|
||
category_ids: ["staff_category_id"],
|
||
topic_ids: ["guidelines_topic_id"],
|
||
}
|
||
expect(response.status).to eq(200)
|
||
|
||
expect(Category.find(SiteSetting.staff_category_id).name).to eq(
|
||
I18n.t("staff_category_name", locale: :de),
|
||
)
|
||
expect(Topic.find(SiteSetting.guidelines_topic_id).title).to eq(
|
||
I18n.t("guidelines_topic.title", locale: :de),
|
||
)
|
||
end
|
||
end
|
||
|
||
shared_examples "reseed not allowed" do
|
||
it "prevents reseeds with a 404 response" do
|
||
post "/admin/customize/reseed.json",
|
||
params: {
|
||
category_ids: ["staff_category_id"],
|
||
topic_ids: ["guidelines_topic_id"],
|
||
}
|
||
|
||
expect(response.status).to eq(404)
|
||
expect(response.parsed_body["errors"]).to include(I18n.t("not_found"))
|
||
end
|
||
end
|
||
|
||
context "when logged in as a moderator" do
|
||
before { sign_in(moderator) }
|
||
|
||
include_examples "reseed not allowed"
|
||
end
|
||
|
||
context "when logged in as a non-staff user" do
|
||
before { sign_in(user) }
|
||
|
||
include_examples "reseed not allowed"
|
||
end
|
||
end
|
||
end
|
||
end
|