From 601351d1609191f1e0d2be9b1c174eb939fcd17f Mon Sep 17 00:00:00 2001 From: Bertocq Date: Mon, 15 Jan 2018 20:41:33 +0100 Subject: [PATCH] Validate next/prev phases before saving a Budget::Phase, with model specs --- app/models/budget/phase.rb | 25 ++++++++++++ config/locales/en/budgets.yml | 4 +- config/locales/es/budgets.yml | 4 +- spec/models/budget/phase_spec.rb | 65 ++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 2 deletions(-) diff --git a/app/models/budget/phase.rb b/app/models/budget/phase.rb index 7e59ff6ac..d5fc42060 100644 --- a/app/models/budget/phase.rb +++ b/app/models/budget/phase.rb @@ -13,6 +13,8 @@ class Budget validates :kind, presence: true, uniqueness: { scope: :budget }, inclusion: { in: PHASE_KINDS } validates :description, length: { maximum: DESCRIPTION_MAX_LENGTH } validate :dates_range_valid? + validate :prev_phase_dates_valid? + validate :next_phase_dates_valid? before_validation :sanitize_description @@ -42,6 +44,29 @@ class Budget end end + private + + def prev_phase_dates_valid? + if enabled? && starts_at.present? && prev_enabled_phase.present? + prev_enabled_phase.assign_attributes(ends_at: starts_at) + if prev_enabled_phase.dates_range_valid? + phase_name = I18n.t("budgets.phase.#{prev_enabled_phase.kind}") + error = I18n.t('budgets.phases.errors.prev_phase_dates_invalid', phase_name: phase_name) + errors.add(:starts_at, error) + end + end + end + + def next_phase_dates_valid? + if enabled? && ends_at.present? && next_enabled_phase.present? + next_enabled_phase.assign_attributes(starts_at: ends_at) + if next_enabled_phase.dates_range_valid? + phase_name = I18n.t("budgets.phase.#{next_enabled_phase.kind}") + error = I18n.t('budgets.phases.errors.next_phase_dates_invalid', phase_name: phase_name) + errors.add(:ends_at, error) + end + end + end def sanitize_description self.description = WYSIWYGSanitizer.new.sanitize(description) diff --git a/config/locales/en/budgets.yml b/config/locales/en/budgets.yml index 2f28b7e3b..a7dd62016 100644 --- a/config/locales/en/budgets.yml +++ b/config/locales/en/budgets.yml @@ -160,4 +160,6 @@ en: incompatibles: Incompatibles phases: errors: - dates_range_invalid: "Start date can't be equal or later than End date" \ No newline at end of file + dates_range_invalid: "Start date can't be equal or later than End date" + prev_phase_dates_invalid: "Start date must be later than the start date of the previous enabled phase (%{phase_name})" + next_phase_dates_invalid: "End date must be earlier than the end date of the next enabled phase (%{phase_name})" \ No newline at end of file diff --git a/config/locales/es/budgets.yml b/config/locales/es/budgets.yml index 40e7af533..0027b1241 100644 --- a/config/locales/es/budgets.yml +++ b/config/locales/es/budgets.yml @@ -160,4 +160,6 @@ es: incompatibles: Incompatibles phases: errors: - dates_range_invalid: "La fecha de comienzo no puede ser igual o superior a la de finalización" \ No newline at end of file + dates_range_invalid: "La fecha de comienzo no puede ser igual o superior a la de finalización" + prev_phase_dates_invalid: "La fecha de inicio debe ser posterior a la fecha de inicio de la anterior fase habilitada (%{phase_name})" + next_phase_dates_invalid: "La fecha de fin debe ser anterior a la fecha de fin de la siguiente fase habilitada (%{phase_name}) " \ No newline at end of file diff --git a/spec/models/budget/phase_spec.rb b/spec/models/budget/phase_spec.rb index d904dc8c7..fba482534 100644 --- a/spec/models/budget/phase_spec.rb +++ b/spec/models/budget/phase_spec.rb @@ -54,6 +54,71 @@ describe Budget::Phase do expect(first_phase).not_to be_valid end end + + describe "#prev_phase_dates_valid?" do + let(:error) do + "Start date must be later than the start date of the previous enabled phase"\ + " (Draft (Not visible to the public))" + end + + it "is invalid when start date is same as previous enabled phase start date" do + second_phase.assign_attributes(starts_at: second_phase.prev_enabled_phase.starts_at) + + expect(second_phase).not_to be_valid + expect(second_phase.errors.messages[:starts_at]).to include(error) + end + + it "is invalid when start date is earlier than previous enabled phase start date" do + second_phase.assign_attributes(starts_at: second_phase.prev_enabled_phase.starts_at - 1.day) + + expect(second_phase).not_to be_valid + expect(second_phase.errors.messages[:starts_at]).to include(error) + end + + it "is valid when start date is in between previous enabled phase start & end dates" do + second_phase.assign_attributes(starts_at: second_phase.prev_enabled_phase.starts_at + 1.day) + + expect(second_phase).to be_valid + end + + it "is valid when start date is later than previous enabled phase end date" do + second_phase.assign_attributes(starts_at: second_phase.prev_enabled_phase.ends_at + 1.day) + + expect(second_phase).to be_valid + end + end + + describe "#next_phase_dates_valid?" do + let(:error) do + "End date must be earlier than the end date of the next enabled phase (Reviewing projects)" + end + + it "is invalid when end date is same as next enabled phase end date" do + second_phase.assign_attributes(ends_at: second_phase.next_enabled_phase.ends_at) + + expect(second_phase).not_to be_valid + expect(second_phase.errors.messages[:ends_at]).to include(error) + end + + it "is invalid when end date is later than next enabled phase end date" do + second_phase.assign_attributes(ends_at: second_phase.next_enabled_phase.ends_at + 1.day) + + expect(second_phase).not_to be_valid + expect(second_phase.errors.messages[:ends_at]).to include(error) + end + + it "is valid when end date is in between next enabled phase start & end dates" do + second_phase.assign_attributes(ends_at: second_phase.next_enabled_phase.ends_at - 1.day) + + expect(second_phase).to be_valid + end + + it "is valid when end date is earlier than next enabled phase start date" do + second_phase.assign_attributes(ends_at: second_phase.next_enabled_phase.starts_at - 1.day) + + expect(second_phase).to be_valid + end + end end describe "next & prev enabled phases" do