For the HashAlignment rule, we're using the default `key` style (keys are aligned and values aren't) instead of the `table` style (both keys and values are aligned) because, even if we used both in the application, we used the `key` style a lot more. Furthermore, the `table` style looks strange in places where there are both very long and very short keys and sometimes we weren't even consistent with the `table` style, aligning some keys without aligning other keys. Ideally we could align hashes to "either key or table", so developers can decide whether keeping the symmetry of the code is worth it in a case-per-case basis, but Rubocop doesn't allow this option.
254 lines
9.0 KiB
Ruby
254 lines
9.0 KiB
Ruby
require "rails_helper"
|
|
|
|
describe Budget::Phase do
|
|
let(:budget) { create(:budget) }
|
|
let(:informing_phase) { budget.phases.informing }
|
|
let(:accepting_phase) { budget.phases.accepting }
|
|
let(:reviewing_phase) { budget.phases.reviewing }
|
|
let(:finished_phase) { budget.phases.finished }
|
|
|
|
it_behaves_like "globalizable", :budget_phase
|
|
|
|
describe "validates" do
|
|
it "is not valid without a budget" do
|
|
expect(build(:budget_phase, budget: nil)).not_to be_valid
|
|
end
|
|
|
|
describe "kind validations" do
|
|
it "is not valid without a kind" do
|
|
expect(build(:budget_phase, kind: nil)).not_to be_valid
|
|
end
|
|
|
|
it "is not valid with a kind not in valid budget phases" do
|
|
expect(build(:budget_phase, kind: "invalid_phase_kind")).not_to be_valid
|
|
end
|
|
|
|
it "is not valid with the same kind as another budget's phase" do
|
|
expect(build(:budget_phase, budget: budget)).not_to be_valid
|
|
end
|
|
end
|
|
|
|
describe "description validations" do
|
|
it "dynamically validates the maximum length" do
|
|
stub_const("#{Budget::Phase}::DESCRIPTION_MAX_LENGTH", 3)
|
|
|
|
informing_phase.description_en = "long"
|
|
|
|
expect(informing_phase).not_to be_valid
|
|
end
|
|
end
|
|
|
|
describe "#dates_range_valid?" do
|
|
it "is valid when start & end dates are different & consecutive" do
|
|
informing_phase.assign_attributes(starts_at: Date.current, ends_at: Date.tomorrow)
|
|
|
|
expect(informing_phase).to be_valid
|
|
end
|
|
|
|
it "is not valid when dates are equal" do
|
|
informing_phase.assign_attributes(starts_at: Date.current, ends_at: Date.current)
|
|
|
|
expect(informing_phase).not_to be_valid
|
|
end
|
|
|
|
it "is not valid when start date is later than end date" do
|
|
informing_phase.assign_attributes(starts_at: Date.tomorrow, ends_at: Date.current)
|
|
|
|
expect(informing_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 (Information)"
|
|
end
|
|
|
|
it "is invalid when start date is same as previous enabled phase start date" do
|
|
accepting_phase.assign_attributes(starts_at: accepting_phase.prev_enabled_phase.starts_at)
|
|
|
|
expect(accepting_phase).not_to be_valid
|
|
expect(accepting_phase.errors.messages[:starts_at]).to include(error)
|
|
end
|
|
|
|
it "is invalid when start date is earlier than previous enabled phase start date" do
|
|
accepting_phase.assign_attributes(starts_at: accepting_phase.prev_enabled_phase.starts_at - 1.day)
|
|
|
|
expect(accepting_phase).not_to be_valid
|
|
expect(accepting_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
|
|
accepting_phase.assign_attributes(starts_at: accepting_phase.prev_enabled_phase.starts_at + 1.day)
|
|
|
|
expect(accepting_phase).to be_valid
|
|
end
|
|
|
|
it "is valid when start date is later than previous enabled phase end date" do
|
|
accepting_phase.assign_attributes(starts_at: accepting_phase.prev_enabled_phase.ends_at + 1.day)
|
|
|
|
expect(accepting_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 (Accepting projects)"
|
|
end
|
|
|
|
it "is invalid when end date is same as next enabled phase end date" do
|
|
informing_phase.assign_attributes(ends_at: informing_phase.next_enabled_phase.ends_at)
|
|
|
|
expect(informing_phase).not_to be_valid
|
|
expect(informing_phase.errors.messages[:ends_at]).to include(error)
|
|
end
|
|
|
|
it "is invalid when end date is later than next enabled phase end date" do
|
|
informing_phase.assign_attributes(ends_at: informing_phase.next_enabled_phase.ends_at + 1.day)
|
|
|
|
expect(informing_phase).not_to be_valid
|
|
expect(informing_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
|
|
informing_phase.assign_attributes(ends_at: informing_phase.next_enabled_phase.ends_at - 1.day)
|
|
|
|
expect(informing_phase).to be_valid
|
|
end
|
|
|
|
it "is valid when end date is earlier than next enabled phase start date" do
|
|
informing_phase.assign_attributes(ends_at: informing_phase.next_enabled_phase.starts_at - 1.day)
|
|
|
|
expect(informing_phase).to be_valid
|
|
end
|
|
end
|
|
|
|
describe "main_link_url" do
|
|
it "is not required if main_link_text is not provided" do
|
|
valid_budget = build(:budget, main_link_text: nil)
|
|
|
|
expect(valid_budget).to be_valid
|
|
end
|
|
|
|
it "is required if main_link_text is provided" do
|
|
invalid_budget = build(:budget, main_link_text: "link text")
|
|
|
|
expect(invalid_budget).not_to be_valid
|
|
expect(invalid_budget.errors.count).to be 1
|
|
expect(invalid_budget.errors[:main_link_url].count).to be 1
|
|
expect(invalid_budget.errors[:main_link_url].first).to eq "can't be blank"
|
|
end
|
|
|
|
it "is valid if main_link_text and main_link_url are both provided" do
|
|
budget = build(:budget, main_link_text: "link text", main_link_url: "https://consuldemocracy.org")
|
|
|
|
expect(budget).to be_valid
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#save" do
|
|
it "touches the budget when it's updated" do
|
|
budget = create(:budget)
|
|
|
|
travel(10.seconds) do
|
|
budget.current_phase.update!(enabled: false)
|
|
|
|
expect(budget.updated_at).to eq Time.current
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#adjust_date_ranges" do
|
|
let(:prev_enabled_phase) { accepting_phase.prev_enabled_phase }
|
|
let(:next_enabled_phase) { accepting_phase.next_enabled_phase }
|
|
|
|
describe "when enabled" do
|
|
it "adjusts previous enabled phase end date to its own start date" do
|
|
expect(prev_enabled_phase.ends_at).to eq(accepting_phase.starts_at)
|
|
end
|
|
|
|
it "adjusts next enabled phase start date to its own end date" do
|
|
expect(next_enabled_phase.starts_at).to eq(accepting_phase.ends_at)
|
|
end
|
|
end
|
|
|
|
describe "when being enabled" do
|
|
before do
|
|
accepting_phase.update!(enabled: false,
|
|
starts_at: Date.current,
|
|
ends_at: Date.current + 2.days)
|
|
end
|
|
|
|
it "adjusts previous enabled phase end date to its own start date" do
|
|
expect { accepting_phase.update(enabled: true) }
|
|
.to change { prev_enabled_phase.ends_at.to_date }.to(Date.current)
|
|
end
|
|
|
|
it "adjusts next enabled phase start date to its own end date" do
|
|
expect do
|
|
accepting_phase.update(enabled: true)
|
|
end.to change { next_enabled_phase.starts_at.to_date }.to(Date.current + 2.days)
|
|
end
|
|
end
|
|
|
|
describe "when disabled" do
|
|
before do
|
|
accepting_phase.update!(enabled: false)
|
|
end
|
|
|
|
it "doesn't change previous enabled phase end date" do
|
|
expect { accepting_phase.update(starts_at: Date.current, ends_at: Date.current + 2.days) }
|
|
.not_to change { prev_enabled_phase.ends_at }
|
|
end
|
|
|
|
it "doesn't change next enabled phase start date" do
|
|
expect { accepting_phase.update(starts_at: Date.current, ends_at: Date.current + 2.days) }
|
|
.not_to change { next_enabled_phase.starts_at }
|
|
end
|
|
end
|
|
|
|
describe "when being disabled" do
|
|
it "doesn't adjust previous enabled phase end date to its own start date" do
|
|
expect do
|
|
accepting_phase.update(enabled: false,
|
|
starts_at: Date.current,
|
|
ends_at: Date.current + 2.days)
|
|
end.not_to change { prev_enabled_phase.ends_at }
|
|
end
|
|
|
|
it "adjusts next enabled phase start date to its own start date" do
|
|
expect do
|
|
accepting_phase.update(enabled: false,
|
|
starts_at: Date.current,
|
|
ends_at: Date.current + 2.days)
|
|
end.to change { next_enabled_phase.starts_at.to_date }.to(Date.current)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "next & prev enabled phases" do
|
|
before do
|
|
accepting_phase.update!(enabled: false)
|
|
%w[selecting reviewing_ballots balloting publishing_prices valuating].each do |phase|
|
|
budget.phases.send(phase).update(enabled: false)
|
|
end
|
|
end
|
|
|
|
describe "#next_enabled_phase" do
|
|
it "returns the right next enabled phase" do
|
|
expect(informing_phase.reload.next_enabled_phase).to eq(reviewing_phase)
|
|
expect(reviewing_phase.reload.next_enabled_phase).to eq(finished_phase)
|
|
expect(finished_phase.reload.next_enabled_phase).to eq(nil)
|
|
end
|
|
end
|
|
|
|
describe "#prev_enabled_phase" do
|
|
it "returns the right previous enabled phase" do
|
|
expect(informing_phase.reload.prev_enabled_phase).to eq(nil)
|
|
expect(reviewing_phase.reload.prev_enabled_phase).to eq(informing_phase)
|
|
expect(finished_phase.reload.prev_enabled_phase).to eq(reviewing_phase)
|
|
end
|
|
end
|
|
end
|
|
end
|