New version of globalize uses RequestStore gem to store I18n.locale and Globalize.fallbacks in a per request basis to avoid collissions between different requests. This gem update broke Globalize.fallback results because it tries to fetch fallbacks from RequestStore, where there is no locale fallbacks definition.
380 lines
10 KiB
Ruby
380 lines
10 KiB
Ruby
shared_examples "translatable" do |factory_name, path_name, input_fields, textarea_fields = {}|
|
|
let(:language_texts) do
|
|
{
|
|
es: "en español",
|
|
en: "in English",
|
|
fr: "en Français",
|
|
"pt-BR": "Português"
|
|
}
|
|
end
|
|
|
|
let(:translatable_class) { build(factory_name).class }
|
|
|
|
let(:input_fields) { input_fields } # So it's accessible by methods
|
|
let(:textarea_fields) { textarea_fields } # So it's accessible by methods
|
|
let(:path_name) { path_name } # So it's accessible by methods
|
|
|
|
let(:fields) { input_fields + textarea_fields.keys }
|
|
|
|
let(:attributes) do
|
|
fields.product(%i[en es]).map do |field, locale|
|
|
[:"#{field}_#{locale}", text_for(field, locale)]
|
|
end.to_h
|
|
end
|
|
|
|
let(:optional_fields) do
|
|
fields.select do |field|
|
|
translatable.translations.last.dup.tap { |duplicate| duplicate.send(:"#{field}=", "") }.valid?
|
|
end
|
|
end
|
|
|
|
let(:required_fields) do
|
|
fields - optional_fields
|
|
end
|
|
|
|
let(:user) { create(:administrator).user }
|
|
let(:translatable) do
|
|
if factory_name == "budget_phase"
|
|
budget = create(:budget)
|
|
budget.phases.first.update attributes
|
|
budget.phases.first
|
|
else
|
|
create(factory_name, attributes)
|
|
end
|
|
end
|
|
let(:path) { send(path_name, *resource_hierarchy_for(translatable)) }
|
|
|
|
before do
|
|
login_as(user)
|
|
translatable.update(author: user) if front_end_path_to_visit?(path_name)
|
|
end
|
|
|
|
context "Manage translations" do
|
|
before do
|
|
if translatable_class.name == "I18nContent"
|
|
skip "Translation handling is different for site customizations"
|
|
end
|
|
end
|
|
|
|
scenario "should show first available fallback when current locale translation does not exist", :js do
|
|
attributes = fields.product(%i[fr]).map do |field, locale|
|
|
[:"#{field}_#{locale}", text_for(field, locale)]
|
|
end.to_h
|
|
translatable.update(attributes)
|
|
visit path
|
|
|
|
select "English", from: :translation_locale
|
|
click_link "Remove language"
|
|
select "Español", from: :translation_locale
|
|
click_link "Remove language"
|
|
click_button update_button_text
|
|
|
|
expect(page).to have_content "en Français"
|
|
end
|
|
|
|
scenario "Add a translation", :js do
|
|
visit path
|
|
|
|
select "Français", from: "translation_locale"
|
|
fields.each { |field| fill_in_field field, :fr, with: text_for(field, :fr) }
|
|
click_button update_button_text
|
|
|
|
visit path
|
|
field = fields.sample
|
|
|
|
expect_page_to_have_translatable_field field, :en, with: text_for(field, :en)
|
|
|
|
click_link "Español"
|
|
expect_page_to_have_translatable_field field, :es, with: text_for(field, :es)
|
|
|
|
click_link "Français"
|
|
expect_page_to_have_translatable_field field, :fr, with: text_for(field, :fr)
|
|
end
|
|
|
|
scenario "Add an invalid translation", :js do
|
|
skip("can't have invalid translations") if required_fields.empty?
|
|
|
|
field = required_fields.sample
|
|
|
|
visit path
|
|
|
|
select "Français", from: "translation_locale"
|
|
fill_in_field field, :fr, with: ""
|
|
click_button update_button_text
|
|
|
|
expect(page).to have_css "#error_explanation"
|
|
|
|
click_link "Français"
|
|
|
|
expect_page_to_have_translatable_field field, :fr, with: ""
|
|
end
|
|
|
|
scenario "Update a translation", :js do
|
|
visit path
|
|
|
|
click_link "Español"
|
|
field = fields.sample
|
|
updated_text = "Corrección de #{text_for(field, :es)}"
|
|
|
|
fill_in_field field, :es, with: updated_text
|
|
|
|
click_button update_button_text
|
|
|
|
visit path
|
|
|
|
expect_page_to_have_translatable_field field, :en, with: text_for(field, :en)
|
|
|
|
select("Español", from: "locale-switcher")
|
|
|
|
expect_page_to_have_translatable_field field, :es, with: updated_text
|
|
end
|
|
|
|
scenario "Update a translation with invalid data", :js do
|
|
skip("can't have invalid translations") if required_fields.empty?
|
|
|
|
field = required_fields.sample
|
|
|
|
visit path
|
|
click_link "Español"
|
|
|
|
expect_page_to_have_translatable_field field, :es, with: text_for(field, :es)
|
|
|
|
fill_in_field field, :es, with: ""
|
|
click_button update_button_text
|
|
|
|
expect(page).to have_css "#error_explanation"
|
|
|
|
click_link "Español"
|
|
|
|
expect_page_to_have_translatable_field field, :es, with: ""
|
|
end
|
|
|
|
scenario "Update a translation not having the current locale", :js do
|
|
translatable.translations.destroy_all
|
|
|
|
translatable.translations.create(
|
|
fields.map { |field| [field, text_for(field, :fr)] }.to_h.merge(locale: :fr)
|
|
)
|
|
|
|
visit path
|
|
|
|
expect(page).not_to have_link "English"
|
|
expect(page).to have_link "Français"
|
|
|
|
click_button update_button_text
|
|
|
|
expect(page).not_to have_css "#error_explanation"
|
|
|
|
path = updated_path_for(translatable)
|
|
visit path
|
|
|
|
expect(page).not_to have_link "English"
|
|
expect(page).to have_link "Français"
|
|
end
|
|
|
|
scenario "Remove a translation", :js do
|
|
visit path
|
|
|
|
click_link "Español"
|
|
click_link "Remove language"
|
|
|
|
expect(page).not_to have_link "Español"
|
|
|
|
click_button update_button_text
|
|
|
|
visit path
|
|
expect(page).not_to have_link "Español"
|
|
end
|
|
|
|
scenario "Remove a translation with invalid data", :js do
|
|
skip("can't have invalid translations") if required_fields.empty?
|
|
|
|
field = required_fields.sample
|
|
|
|
visit path
|
|
|
|
click_link "Español"
|
|
click_link "Remove language"
|
|
|
|
click_link "English"
|
|
fill_in_field field, :en, with: ""
|
|
click_button update_button_text
|
|
|
|
expect(page).to have_css "#error_explanation"
|
|
expect_page_to_have_translatable_field field, :en, with: ""
|
|
expect(page).not_to have_link "Español"
|
|
|
|
visit path
|
|
click_link "Español"
|
|
|
|
expect_page_to_have_translatable_field field, :es, with: text_for(field, :es)
|
|
end
|
|
|
|
scenario "Change value of a translated field to blank", :js do
|
|
skip("can't have translatable blank fields") if optional_fields.empty?
|
|
|
|
field = optional_fields.sample
|
|
|
|
visit path
|
|
expect_page_to_have_translatable_field field, :en, with: text_for(field, :en)
|
|
|
|
fill_in_field field, :en, with: ""
|
|
click_button update_button_text
|
|
|
|
visit path
|
|
expect_page_to_have_translatable_field field, :en, with: ""
|
|
end
|
|
|
|
scenario "Add a translation for a locale with non-underscored name", :js do
|
|
visit path
|
|
|
|
select "Português brasileiro", from: "translation_locale"
|
|
fields.each { |field| fill_in_field field, :"pt-BR", with: text_for(field, :"pt-BR") }
|
|
click_button update_button_text
|
|
|
|
visit path
|
|
|
|
select("Português brasileiro", from: "locale-switcher")
|
|
|
|
field = fields.sample
|
|
expect_page_to_have_translatable_field field, :"pt-BR", with: text_for(field, :"pt-BR")
|
|
end
|
|
end
|
|
|
|
context "Globalize javascript interface" do
|
|
scenario "Highlight current locale", :js do
|
|
visit path
|
|
|
|
expect(find("a.js-globalize-locale-link.is-active")).to have_content "English"
|
|
|
|
select("Español", from: "locale-switcher")
|
|
|
|
expect(find("a.js-globalize-locale-link.is-active")).to have_content "Español"
|
|
end
|
|
|
|
scenario "Highlight selected locale", :js do
|
|
visit path
|
|
|
|
expect(find("a.js-globalize-locale-link.is-active")).to have_content "English"
|
|
|
|
click_link "Español"
|
|
|
|
expect(find("a.js-globalize-locale-link.is-active")).to have_content "Español"
|
|
end
|
|
|
|
scenario "Show selected locale form", :js do
|
|
visit path
|
|
field = fields.sample
|
|
|
|
expect_page_to_have_translatable_field field, :en, with: text_for(field, :en)
|
|
|
|
click_link "Español"
|
|
|
|
expect_page_to_have_translatable_field field, :es, with: text_for(field, :es)
|
|
end
|
|
|
|
scenario "Select a locale and add it to the form", :js do
|
|
visit path
|
|
|
|
select "Français", from: "translation_locale"
|
|
|
|
expect(page).to have_link "Français"
|
|
|
|
click_link "Français"
|
|
|
|
expect_page_to_have_translatable_field fields.sample, :fr, with: ""
|
|
end
|
|
end
|
|
end
|
|
|
|
def updated_path_for(resource)
|
|
send(path_name, *resource_hierarchy_for(resource.reload))
|
|
end
|
|
|
|
def text_for(field, locale)
|
|
I18n.with_locale(locale) do
|
|
"#{translatable_class.human_attribute_name(field)} #{language_texts[locale]}"
|
|
end
|
|
end
|
|
|
|
def field_for(field, locale, visible: true)
|
|
if translatable_class.name == "I18nContent"
|
|
"contents_content_#{translatable.key}values_#{field}_#{locale}"
|
|
else
|
|
within(".translatable-fields[data-locale='#{locale}']") do
|
|
find("input[id$='_#{field}'], textarea[id$='_#{field}']", visible: visible)[:id]
|
|
end
|
|
end
|
|
end
|
|
|
|
def fill_in_field(field, locale, with:)
|
|
if input_fields.include?(field)
|
|
fill_in field_for(field, locale), with: with
|
|
else
|
|
fill_in_textarea(field, textarea_fields[field], locale, with: with)
|
|
end
|
|
end
|
|
|
|
def fill_in_textarea(field, textarea_type, locale, with:)
|
|
if textarea_type == :markdownit
|
|
click_link class: "fullscreen-toggle"
|
|
fill_in field_for(field, locale), with: with
|
|
click_link class: "fullscreen-toggle"
|
|
elsif textarea_type == :ckeditor
|
|
fill_in_ckeditor field_for(field, locale, visible: false), with: with
|
|
end
|
|
end
|
|
|
|
def expect_page_to_have_translatable_field(field, locale, with:)
|
|
if input_fields.include?(field)
|
|
if translatable_class.name == "I18nContent" && with.blank?
|
|
expect(page).to have_field field_for(field, locale)
|
|
else
|
|
expect(page).to have_field field_for(field, locale), with: with
|
|
end
|
|
else
|
|
textarea_type = textarea_fields[field]
|
|
|
|
if textarea_type == :markdownit
|
|
click_link class: "fullscreen-toggle"
|
|
expect(page).to have_field field_for(field, locale), with: with
|
|
click_link class: "fullscreen-toggle"
|
|
elsif textarea_type == :ckeditor
|
|
within("div.js-globalize-attribute[data-locale='#{locale}'] .ckeditor [id$='#{field}']") do
|
|
within_frame(textarea_fields.keys.index(field)) { expect(page).to have_content with }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
# FIXME: button texts should be consistent. Right now, buttons don't
|
|
# even share the same colour.
|
|
def update_button_text
|
|
case translatable_class.name
|
|
when "Milestone"
|
|
"Update milestone"
|
|
when "AdminNotification"
|
|
"Update notification"
|
|
when "Poll"
|
|
"Update poll"
|
|
when "Budget"
|
|
"Update Budget"
|
|
when "Poll::Question", "Poll::Question::Answer", "ActivePoll"
|
|
"Save"
|
|
when "SiteCustomization::Page"
|
|
"Update Custom page"
|
|
when "Widget::Card"
|
|
"Save card"
|
|
when "Budget::Group"
|
|
"Save group"
|
|
when "Budget::Heading"
|
|
"Save heading"
|
|
else
|
|
"Save changes"
|
|
end
|
|
end
|
|
|
|
def front_end_path_to_visit?(path)
|
|
path[/admin|managment|valuation/].blank?
|
|
end
|