discourse/spec/components/js_locale_helper_spec.rb
Sam Saffron 4ea21fa2d0 DEV: use #frozen_string_literal: true on all spec
This change both speeds up specs (less strings to allocate) and helps catch
cases where methods in Discourse are mutating inputs.

Overall we will be migrating everything to use #frozen_string_literal: true
it will take a while, but this is the first and safest move in this direction
2019-04-30 10:27:42 +10:00

202 lines
6.4 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
require 'mini_racer'
describe JsLocaleHelper do
module StubLoadTranslations
def set_translations(locale, translations)
@loaded_translations ||= HashWithIndifferentAccess.new
@loaded_translations[locale] = translations
end
def clear_cache!
@loaded_translations = nil
@loaded_merges = nil
end
end
JsLocaleHelper.extend StubLoadTranslations
after do
I18n.locale = :en
JsLocaleHelper.clear_cache!
end
describe "#output_locale" do
it "doesn't change the cached translations hash" do
I18n.locale = :fr
expect(JsLocaleHelper.output_locale('fr').length).to be > 0
expect(JsLocaleHelper.translations_for('fr')['fr'].keys).to contain_exactly("js", "admin_js", "wizard_js")
end
end
context "message format" do
def message_format_filename(locale)
Rails.root + "lib/javascripts/locale/#{locale}.js"
end
def setup_message_format(format)
filename = message_format_filename('en')
compiled = JsLocaleHelper.compile_message_format(filename, 'en', format)
@ctx = MiniRacer::Context.new
@ctx.eval('MessageFormat = {locale: {}};')
@ctx.load(filename)
@ctx.eval("var test = #{compiled}")
end
def localize(opts)
@ctx.eval("test(#{opts.to_json})")
end
it 'handles plurals' do
setup_message_format('{NUM_RESULTS, plural,
one {1 result}
other {# results}
}')
expect(localize(NUM_RESULTS: 1)).to eq('1 result')
expect(localize(NUM_RESULTS: 2)).to eq('2 results')
end
it 'handles double plurals' do
setup_message_format('{NUM_RESULTS, plural,
one {1 result}
other {# results}
} and {NUM_APPLES, plural,
one {1 apple}
other {# apples}
}')
expect(localize(NUM_RESULTS: 1, NUM_APPLES: 2)).to eq('1 result and 2 apples')
expect(localize(NUM_RESULTS: 2, NUM_APPLES: 1)).to eq('2 results and 1 apple')
end
it 'handles select' do
setup_message_format('{GENDER, select, male {He} female {She} other {They}} read a book')
expect(localize(GENDER: 'male')).to eq('He read a book')
expect(localize(GENDER: 'female')).to eq('She read a book')
expect(localize(GENDER: 'none')).to eq('They read a book')
end
it 'can strip out message formats' do
hash = { "a" => "b", "c" => { "d" => { "f_MF" => "bob" } } }
expect(JsLocaleHelper.strip_out_message_formats!(hash)).to eq("c.d.f_MF" => "bob")
expect(hash["c"]["d"]).to eq({})
end
it 'handles message format special keys' do
JsLocaleHelper.set_translations('en', "en" => {
"js" => {
"hello" => "world",
"test_MF" => "{HELLO} {COUNT, plural, one {1 duck} other {# ducks}}",
"error_MF" => "{{BLA}",
"simple_MF" => "{COUNT, plural, one {1} other {#}}"
},
"admin_js" => {
"foo_MF" => "{HELLO} {COUNT, plural, one {1 duck} other {# ducks}}"
}
})
ctx = MiniRacer::Context.new
ctx.eval("I18n = { pluralizationRules: {} };")
ctx.eval(JsLocaleHelper.output_locale('en'))
expect(ctx.eval('I18n.translations["en"]["js"]["hello"]')).to eq("world")
expect(ctx.eval('I18n.translations["en"]["js"]["test_MF"]')).to eq(nil)
expect(ctx.eval('I18n.messageFormat("test_MF", { HELLO: "hi", COUNT: 3 })')).to eq("hi 3 ducks")
expect(ctx.eval('I18n.messageFormat("error_MF", { HELLO: "hi", COUNT: 3 })')).to match(/Invalid Format/)
expect(ctx.eval('I18n.messageFormat("missing", {})')).to match(/missing/)
expect(ctx.eval('I18n.messageFormat("simple_MF", {})')).to match(/COUNT/) # error
expect(ctx.eval('I18n.messageFormat("foo_MF", { HELLO: "hi", COUNT: 4 })')).to eq("hi 4 ducks")
end
it 'load pluralizations rules before precompile' do
message = JsLocaleHelper.compile_message_format(message_format_filename('ru'), 'ru', 'format')
expect(message).not_to match 'Plural Function not found'
end
end
it 'performs fallbacks to english if a translation is not available' do
JsLocaleHelper.set_translations('en', "en" => {
"js" => {
"only_english" => "1-en",
"english_and_site" => "3-en",
"english_and_user" => "5-en",
"all_three" => "7-en",
}
})
JsLocaleHelper.set_translations('ru', "ru" => {
"js" => {
"only_site" => "2-ru",
"english_and_site" => "3-ru",
"site_and_user" => "6-ru",
"all_three" => "7-ru",
}
})
JsLocaleHelper.set_translations('uk', "uk" => {
"js" => {
"only_user" => "4-uk",
"english_and_user" => "5-uk",
"site_and_user" => "6-uk",
"all_three" => "7-uk",
}
})
expected = {
"none" => "[uk.js.none]",
"only_english" => "1-en",
"only_site" => "2-ru",
"english_and_site" => "3-ru",
"only_user" => "4-uk",
"english_and_user" => "5-uk",
"site_and_user" => "6-uk",
"all_three" => "7-uk",
}
SiteSetting.default_locale = 'ru'
I18n.locale = :uk
ctx = MiniRacer::Context.new
ctx.eval('var window = this;')
ctx.load(Rails.root + 'app/assets/javascripts/locales/i18n.js')
ctx.eval(JsLocaleHelper.output_locale(I18n.locale))
ctx.eval('I18n.defaultLocale = "ru";')
expect(ctx.eval('I18n.translations.en.js').keys).to contain_exactly("only_english")
expect(ctx.eval('I18n.translations.ru.js').keys).to contain_exactly("only_site", "english_and_site")
expect(ctx.eval('I18n.translations.uk.js').keys).to contain_exactly("all_three", "english_and_user", "only_user", "site_and_user")
expected.each do |key, expect|
expect(ctx.eval("I18n.t(#{"js.#{key}".inspect})")).to eq(expect)
end
end
LocaleSiteSetting.values.each do |locale|
it "generates valid date helpers for #{locale[:value]} locale" do
js = JsLocaleHelper.output_locale(locale[:value])
ctx = MiniRacer::Context.new
ctx.eval('var window = this;')
ctx.load(Rails.root + 'app/assets/javascripts/locales/i18n.js')
ctx.eval(js)
end
it "finds moment.js locale file for #{locale[:value]}" do
content = JsLocaleHelper.moment_locale(locale[:value])
if (locale[:value] == 'en')
expect(content).to eq('')
else
expect(content).to_not eq('')
end
end
end
end