diff --git a/app/models/admin_post.rb b/app/models/admin_post.rb index 416efc4e585..99aed3d42a6 100644 --- a/app/models/admin_post.rb +++ b/app/models/admin_post.rb @@ -18,21 +18,20 @@ class AdminPost < ApplicationRecord has_many :admin_post_taggings has_many :tags, through: :admin_post_taggings, source: :admin_post_tag - validates_presence_of :title - validates_length_of :title, - minimum: ArchiveConfig.TITLE_MIN, - too_short: ts("must be at least %{min} characters long.", min: ArchiveConfig.TITLE_MIN) + validates :title, presence: true, + length: { minimum: ArchiveConfig.TITLE_MIN, + maximum: ArchiveConfig.TITLE_MAX } - validates_length_of :title, - maximum: ArchiveConfig.TITLE_MAX, - too_long: ts("must be less than %{max} characters long.", max: ArchiveConfig.TITLE_MAX) + validates :content, presence: true, + length: { minimum: ArchiveConfig.CONTENT_MIN, + maximum: ArchiveConfig.CONTENT_MAX } - validates_presence_of :content - validates_length_of :content, minimum: ArchiveConfig.CONTENT_MIN, - too_short: ts("must be at least %{min} characters long.", min: ArchiveConfig.CONTENT_MIN) - - validates_length_of :content, maximum: ArchiveConfig.CONTENT_MAX, - too_long: ts("cannot be more than %{max} characters long.", max: ArchiveConfig.CONTENT_MAX) + # rubocop:disable Rails/UniqueValidationWithoutIndex + validates :translated_post_id, + uniqueness: { scope: :language_id, + message: :translation_already_exists }, + allow_nil: true + # rubocop:enable Rails/UniqueValidationWithoutIndex validate :translated_post_must_exist @@ -93,7 +92,7 @@ def tags def translated_post_must_exist if translated_post_id.present? && AdminPost.find_by(id: translated_post_id).nil? - errors.add(:translated_post_id, "does not exist") + errors.add(:translated_post_id, :does_not_exist) end end @@ -101,7 +100,7 @@ def translated_post_language_must_differ return if translated_post.blank? return unless translated_post.language == language - errors.add(:translated_post_id, "cannot be same language as original post") + errors.add(:translated_post_id, :same_language_as_original) end def translated_post_must_be_posted_first diff --git a/config/locales/models/en.yml b/config/locales/models/en.yml index a5d48d4358e..2d5cd5cc52e 100644 --- a/config/locales/models/en.yml +++ b/config/locales/models/en.yml @@ -100,8 +100,18 @@ en: comment_permissions: format: "%{message}" invalid_permissions: Comment permissions are invalid. + content: + too_long: cannot be more than %{count} characters long. + too_short: must be at least %{count} characters long. + title: + too_long: must be less than %{count} characters long. + too_short: must be at least %{count} characters long. translated_post_id: - must_be_posted_first: cannot be posted before the original post + does_not_exist: Translated post does not exist + format: "%{message}" + must_be_posted_first: Translated post cannot be posted before the original post + same_language_as_original: Translated post cannot be same language as original post + translation_already_exists: Admin post already has a translation in this language. block: attributes: blocked: diff --git a/features/admins/admin_post_news.feature b/features/admins/admin_post_news.feature index 5e5d4c94f07..92da4f5dff9 100755 --- a/features/admins/admin_post_news.feature +++ b/features/admins/admin_post_news.feature @@ -66,6 +66,15 @@ Feature: Admin Actions to Post News And I am logged in as "ordinaryuser" Then I should see a translated admin post + Scenario: Make a second translation of an admin post in the same language + Given I have posted an admin post + And basic languages + And the admin post "Erste Ankuendigung" translating "Default Admin Post" to "Deutsch" + And I am logged in as a "translation" admin + When I make a translation of an admin post + Then I should see "Sorry! We couldn't save this admin post because:" + And I should see "Admin post already has a translation in this language." + Scenario: Make a translation of an admin post that doesn't exist Given basic languages And I am logged in as a "translation" admin diff --git a/features/step_definitions/admin_steps.rb b/features/step_definitions/admin_steps.rb index c5b90c408ba..df1b5e9f6f7 100644 --- a/features/step_definitions/admin_steps.rb +++ b/features/step_definitions/admin_steps.rb @@ -160,6 +160,16 @@ FactoryBot.create(:admin_post, :draft, title: title, comment_permissions: :enable_all, tag_list: tags) end +Given "the admin post {string} translating {string} to {string}" do |title, translated_title, lang| + admin_post = AdminPost.find_by!(title: translated_title) + language = Language.find_by!(name: lang) + FactoryBot.create(:admin_post, + title: title, + comment_permissions: :enable_all, + translated_post_id: admin_post.id, + language: language) +end + Given "the draft admin post {string} translating {string} to {string}" do |title, translated_title, lang| admin_post = AdminPost.find_by!(title: translated_title) language = Language.find_by!(name: lang) diff --git a/spec/models/admin_post_spec.rb b/spec/models/admin_post_spec.rb index a9f360320f0..d1440eba831 100644 --- a/spec/models/admin_post_spec.rb +++ b/spec/models/admin_post_spec.rb @@ -59,7 +59,7 @@ drafted_post = travel_to(ArchiveConfig.ADMIN_POST_COMMENTING_EXPIRATION_DAYS.days.ago) do create(:admin_post, :draft) end - drafted_post.update(posted: true) + drafted_post.update!(posted: true) AdminPost.disable_old_post_comments expect(drafted_post.reload.disable_all_comments?).to be(false) @@ -78,6 +78,61 @@ end end + describe "#translated_post_id" do + let(:admin_post) { create(:admin_post) } + let(:language) { create(:language) } + let(:translation) do + build(:admin_post, translated_post: admin_post, language: language) + end + let(:message) { "Admin post already has a translation in this language." } + + context "when the original post has a posted translation in the language" do + before do + create(:admin_post, translated_post: admin_post, language: language) + end + + it "adds an error to the translated post" do + expect(translation).to be_invalid + expect(translation.errors[:translated_post_id]).to include(message) + end + end + + context "when the original post has a draft translation in the language" do + before do + create(:admin_post, :draft, + translated_post: admin_post, language: language) + end + + it "adds an error to the translated post" do + expect(translation).to be_invalid + expect(translation.errors[:translated_post_id]).to include(message) + end + end + + context "when another post has a translation in that language" do + before do + other_post = create(:admin_post) + create(:admin_post, translated_post: other_post, language: language) + end + + it "does not add an error" do + expect(translation).to be_valid + end + end + + context "when updating the existing translation" do + let!(:existing) do + create(:admin_post, translated_post: admin_post, language: language) + end + + it "does not add an error" do + existing.title = "Updated translation title" + + expect(existing).to be_valid + end + end + end + describe "#set_published_at" do before { freeze_time }