From 5d6038f17f746102c93e4096b736227632510a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Thu, 19 Sep 2019 21:57:09 +0200 Subject: [PATCH] Add model tests for globalizable concern These tests are much faster than feature tests, so we're going to use them to test translatable models. --- spec/models/concerns/globalizable.rb | 178 ++++++++++++++++++++++++--- 1 file changed, 164 insertions(+), 14 deletions(-) diff --git a/spec/models/concerns/globalizable.rb b/spec/models/concerns/globalizable.rb index c730aa275..08d5f81cf 100644 --- a/spec/models/concerns/globalizable.rb +++ b/spec/models/concerns/globalizable.rb @@ -1,22 +1,160 @@ require "spec_helper" shared_examples_for "globalizable" do |factory_name| - let(:record) { create(factory_name) } + let(:record) { create(:factory_name) } let(:fields) { record.translated_attribute_names } - let(:attribute) { fields.sample } + let(:required_fields) do + fields.reject do |field| + record.translations.first.dup.tap { |duplicate| duplicate.send(:"#{field}=", "") }.valid? + end + end + let(:attribute) { required_fields.sample || fields.sample } + + before do + record.update_attribute(attribute, "In English") + + I18n.with_locale(:es) do + record.update(required_fields.map { |field| [field, "En español"] }.to_h) + record.update_attribute(attribute, "En español") + end + + record.reload + end + + describe "Add a translation" do + it "Maintains existing translations" do + record.update(translations_attributes: [ + { locale: :fr }.merge(fields.map { |field| [field, "En Français"] }.to_h) + ]) + record.reload + + expect(record.send(attribute)).to eq "In English" + I18n.with_locale(:es) { expect(record.send(attribute)).to eq "En español" } + I18n.with_locale(:fr) { expect(record.send(attribute)).to eq "En Français" } + end + + it "Works with non-underscored locale name" do + record.update(translations_attributes: [ + { locale: :"pt-BR" }.merge(fields.map { |field| [field, "Português"] }.to_h) + ]) + record.reload + + expect(record.send(attribute)).to eq "In English" + I18n.with_locale(:es) { expect(record.send(attribute)).to eq "En español" } + I18n.with_locale(:"pt-BR") { expect(record.send(attribute)).to eq "Português" } + end + + it "Does not create invalid translations in the database" do + skip("cannot have invalid translations") if required_fields.empty? + + record.update(translations_attributes: [{ locale: :fr }]) + + expect(record.translations.map(&:locale)).to match_array %i[en es fr] + + record.reload + + expect(record.translations.map(&:locale)).to match_array %i[en es] + end + + it "Does not automatically add a translation for the current locale" do + record.translations.destroy_all + record.reload + + record.update(translations_attributes: [ + { locale: :de }.merge(fields.map { |field| [field, "Deutsch"] }.to_h) + ]) + + record.reload + + expect(record.translations.map(&:locale)).to eq [:de] + end + end + + describe "Update a translation" do + it "Changes the existing translation" do + record.update(translations_attributes: [ + { id: record.translations.find_by(locale: :es).id, attribute => "Actualizado" } + ]) + record.reload + + expect(record.send(attribute)).to eq "In English" + I18n.with_locale(:es) { expect(record.send(attribute)).to eq "Actualizado" } + end + + it "Does not save invalid translations" do + skip("cannot have invalid translations") if required_fields.empty? + + record.update(translations_attributes: [ + { id: record.translations.find_by(locale: :es).id, attribute => "" } + ]) + + I18n.with_locale(:es) { expect(record.send(attribute)).to eq "" } + + record.reload + + I18n.with_locale(:es) { expect(record.send(attribute)).to eq "En español" } + end + + it "Does not automatically add a translation for the current locale" do + record.translations.find_by(locale: :en).destroy + record.reload + + record.update(translations_attributes: [ + { id: record.translations.first.id }.merge(fields.map { |field| [field, "Cambiado"] }.to_h) + ]) + + record.reload + + expect(record.translations.map(&:locale)).to eq [:es] + end + end + + describe "Remove a translation" do + it "Keeps the other languages" do + record.update(translations_attributes: [ + { id: record.translations.find_by(locale: :en).id, _destroy: true } + ]) + record.reload + + expect(record.translations.map(&:locale)).to eq [:es] + end + + it "Does not remove all translations" do + skip("cannot have invalid translations") if required_fields.empty? + + record.update(translations_attributes: [ + { id: record.translations.find_by(locale: :en).id, _destroy: true }, + { id: record.translations.find_by(locale: :es).id, _destroy: true } + ]) + + expect(record).not_to be_valid + + record.reload + + expect(record.translations.map(&:locale)).to match_array %i[en es] + end + + it "Does not remove translations when there's invalid data" do + skip("cannot have invalid translations") if required_fields.empty? + + record.update(translations_attributes: [ + { id: record.translations.find_by(locale: :es).id, attribute => "" }, + { id: record.translations.find_by(locale: :en).id, _destroy: true }, + ]) + + expect(record).not_to be_valid + + record.reload + + expect(record.translations.map(&:locale)).to match_array %i[en es] + end + end describe "Fallbacks" do before do - record.update_attribute(attribute, "In English") - - { es: "En español", de: "Deutsch" }.each do |locale, text| - Globalize.with_locale(locale) do - fields.each do |field| - record.update_attribute(field, record.send(field)) - end - - record.update_attribute(attribute, text) - end + I18n.with_locale(:de) do + record.update(required_fields.map { |field| [field, "Deutsch"] }.to_h) + record.update_attribute(attribute, "Deutsch") end end @@ -24,7 +162,7 @@ shared_examples_for "globalizable" do |factory_name| allow(I18n.fallbacks).to receive(:[]).and_return([:fr, :es]) Globalize.set_fallbacks_to_all_available_locales - Globalize.with_locale(:fr) do + I18n.with_locale(:fr) do expect(record.send(attribute)).to eq "En español" end end @@ -33,9 +171,21 @@ shared_examples_for "globalizable" do |factory_name| allow(I18n.fallbacks).to receive(:[]).and_return([:fr]) Globalize.set_fallbacks_to_all_available_locales - Globalize.with_locale(:fr) do + I18n.with_locale(:fr) do expect(record.send(attribute)).to eq "Deutsch" end end + + it "Falls back to the first available locale after removing a locale" do + Globalize.set_fallbacks_to_all_available_locales + + expect(record.send(attribute)).to eq "In English" + + record.update(translations_attributes: [ + { id: record.translations.find_by(locale: :en).id, _destroy: true } + ]) + + expect(record.send(attribute)).to eq "Deutsch" + end end end