Files
grecia/spec/models/budget_spec.rb
Javi Martín 28a7aea1c0 Don't show investment filters before valuation
Before the "valuating" phase, all investments have undecided feasibility
and none have been selected, so the filters would return no results
(except the "not_unfeasible" one, which would return everything).
2021-10-29 15:01:37 +02:00

524 lines
16 KiB
Ruby

require "rails_helper"
describe Budget do
let(:budget) { create(:budget) }
it_behaves_like "sluggable", updatable_slug_trait: :drafting
it_behaves_like "reportable"
it_behaves_like "globalizable", :budget
describe "scopes" do
describe ".open" do
it "returns all budgets that are not in the finished phase" do
(Budget::Phase::PHASE_KINDS - ["finished"]).each do |phase|
budget = create(:budget, phase: phase)
expect(Budget.open).to include(budget)
end
end
end
describe ".valuating_or_later" do
it "returns budgets valuating or later" do
valuating = create(:budget, :valuating)
finished = create(:budget, :finished)
expect(Budget.valuating_or_later).to match_array([valuating, finished])
end
it "does not return budgets which haven't reached valuation" do
create(:budget, :drafting)
create(:budget, :selecting)
expect(Budget.valuating_or_later).to be_empty
end
end
describe ".drafting" do
it "returns unpublished budgets" do
undefined = create(:budget, published: nil)
drafting = create(:budget, published: false)
expect(Budget.drafting).to match_array([undefined, drafting])
end
it "does not return published budgets" do
create(:budget, published: true)
expect(Budget.drafting).to be_empty
end
end
describe ".published" do
it "does not return unpublished budgets" do
create(:budget, published: nil)
create(:budget, published: false)
expect(Budget.published).to be_empty
end
it "returns published budgets" do
published = create(:budget, published: true)
expect(Budget.published).to eq [published]
end
end
end
describe "name" do
before do
budget.update(name_en: "object name")
end
it "must not be repeated for a different budget and same locale" do
expect(build(:budget, name_en: "object name")).not_to be_valid
end
it "must not be repeated for a different budget and a different locale" do
expect(build(:budget, name_fr: "object name")).not_to be_valid
end
it "may be repeated for the same budget and a different locale" do
budget.update!(name_fr: "object name")
expect(budget.translations.last).to be_valid
end
end
describe "description" do
describe "Without Budget::Phase associated" do
before do
budget.phases.destroy_all
end
it "changes depending on the phase, falling back to budget description attributes" do
Budget::Phase::PHASE_KINDS.each do |phase_kind|
budget.phase = phase_kind
expect(budget.description).to eq(budget.send("description_#{phase_kind}"))
end
end
end
describe "With associated Budget::Phases" do
before do
budget.phases.each do |phase|
phase.description = phase.kind.humanize
phase.save!
end
end
it "changes depending on the phase" do
Budget::Phase::PHASE_KINDS.each do |phase_kind|
budget.phase = phase_kind
expect(budget.description).to eq(phase_kind.humanize)
end
end
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
valid_budget = build(:budget, main_link_text: "Text link", main_link_url: "https://consulproject.org")
expect(valid_budget).to be_valid
end
end
describe "phase" do
it "is validated" do
Budget::Phase::PHASE_KINDS.each do |phase|
budget.phase = phase
expect(budget).to be_valid
end
budget.phase = "inexisting"
expect(budget).not_to be_valid
end
it "produces auxiliary methods" do
budget.phase = "accepting"
expect(budget).to be_accepting
budget.phase = "reviewing"
expect(budget).to be_reviewing
budget.phase = "selecting"
expect(budget).to be_selecting
budget.phase = "valuating"
expect(budget).to be_valuating
budget.phase = "publishing_prices"
expect(budget).to be_publishing_prices
budget.phase = "balloting"
expect(budget).to be_balloting
budget.phase = "reviewing_ballots"
expect(budget).to be_reviewing_ballots
budget.phase = "finished"
expect(budget).to be_finished
end
describe "#valuating_or_later?" do
it "returns false before valuating" do
budget.phase = "selecting"
expect(budget).not_to be_valuating_or_later
end
it "returns true while valuating" do
budget.phase = "valuating"
expect(budget).to be_valuating_or_later
end
it "returns true after valuating" do
budget.phase = "publishing_prices"
expect(budget).to be_valuating_or_later
end
end
describe "#publishing_prices_or_later?" do
it "returns false before publishing prices" do
budget.phase = "valuating"
expect(budget).not_to be_publishing_prices_or_later
end
it "returns true while publishing prices" do
budget.phase = "publishing_prices"
expect(budget).to be_publishing_prices_or_later
end
it "returns true after publishing prices" do
budget.phase = "balloting"
expect(budget).to be_publishing_prices_or_later
end
end
describe "#balloting_or_later?" do
it "returns false before balloting" do
budget.phase = "publishing_prices"
expect(budget).not_to be_balloting_or_later
end
it "returns true while balloting" do
budget.phase = "balloting"
expect(budget).to be_balloting_or_later
end
it "returns true after balloting" do
budget.phase = "finished"
expect(budget).to be_balloting_or_later
end
end
end
describe "#current" do
it "returns nil if there is only one budget and it is still in drafting phase" do
create(:budget, :drafting)
expect(Budget.current).to eq(nil)
end
it "returns the budget if there is only one and not in drafting phase" do
budget = create(:budget, :accepting)
expect(Budget.current).to eq(budget)
end
it "returns the last budget created that is not in drafting phase" do
create(:budget, :finished, created_at: 2.years.ago, name: "Old")
create(:budget, :accepting, created_at: 1.year.ago, name: "Previous")
create(:budget, :accepting, created_at: 1.month.ago, name: "Current")
create(:budget, :drafting, created_at: 1.week.ago, name: "Next")
expect(Budget.current.name).to eq "Current"
end
end
describe "heading_price" do
it "returns the heading price if the heading provided is part of the budget" do
heading = create(:budget_heading, price: 100, budget: budget)
expect(budget.heading_price(heading)).to eq(100)
end
it "returns -1 if the heading provided is not part of the budget" do
expect(budget.heading_price(create(:budget_heading))).to eq(-1)
end
end
describe "investments_orders" do
it "is random when accepting and reviewing" do
budget.phase = "accepting"
expect(budget.investments_orders).to eq(["random"])
budget.phase = "reviewing"
expect(budget.investments_orders).to eq(["random"])
end
it "is random and price when ballotting and reviewing ballots" do
budget.phase = "publishing_prices"
expect(budget.investments_orders).to eq(["random", "price"])
budget.phase = "balloting"
expect(budget.investments_orders).to eq(["random", "price"])
budget.phase = "reviewing_ballots"
expect(budget.investments_orders).to eq(["random", "price"])
end
it "is random and confidence_score in all other cases" do
budget.phase = "selecting"
expect(budget.investments_orders).to eq(["random", "confidence_score"])
budget.phase = "valuating"
expect(budget.investments_orders).to eq(["random", "confidence_score"])
end
end
describe "#investments_filters" do
it "returns no filters before valuating" do
%w[informing accepting reviewing selecting].each do |phase|
budget.phase = phase
expect(budget.investments_filters).to be_empty
end
end
it "returns feasibility filters during valuation" do
budget.phase = "valuating"
expect(budget.investments_filters).to eq(%w[not_unfeasible feasible unfeasible])
end
it "returns feasibility and selection filters during the final voting phases" do
%w[publishing_prices balloting reviewing_ballots].each do |phase|
budget.phase = phase
expect(budget.investments_filters).to eq(%w[not_unfeasible feasible unfeasible selected unselected])
end
end
it "returns all filters after the budget has finished" do
budget.phase = "finished"
expect(budget.investments_filters).to eq(%w[not_unfeasible feasible unfeasible selected unselected winners])
end
end
describe "#has_winning_investments?" do
it "returns true if there is a winner investment" do
budget.investments << build(:budget_investment, :winner, price: 3, ballot_lines_count: 2)
expect(budget.has_winning_investments?).to eq true
end
it "hould return false if there is not a winner investment" do
expect(budget.has_winning_investments?).to eq false
end
end
describe "#generate_phases" do
let(:informing_phase) { budget.phases.informing }
let(:accepting_phase) { budget.phases.accepting }
let(:reviewing_phase) { budget.phases.reviewing }
let(:selecting_phase) { budget.phases.selecting }
let(:valuating_phase) { budget.phases.valuating }
let(:publishing_prices_phase) { budget.phases.publishing_prices }
let(:balloting_phase) { budget.phases.balloting }
let(:reviewing_ballots_phase) { budget.phases.reviewing_ballots }
let(:finished_phase) { budget.phases.finished }
it "generates all phases linked in correct order" do
expect(budget.phases.count).to eq(Budget::Phase::PHASE_KINDS.count)
expect(informing_phase.next_phase).to eq(accepting_phase)
expect(accepting_phase.next_phase).to eq(reviewing_phase)
expect(reviewing_phase.next_phase).to eq(selecting_phase)
expect(selecting_phase.next_phase).to eq(valuating_phase)
expect(valuating_phase.next_phase).to eq(publishing_prices_phase)
expect(publishing_prices_phase.next_phase).to eq(balloting_phase)
expect(balloting_phase.next_phase).to eq(reviewing_ballots_phase)
expect(reviewing_ballots_phase.next_phase).to eq(finished_phase)
expect(finished_phase.next_phase).to eq(nil)
expect(informing_phase.prev_phase).to eq(nil)
expect(accepting_phase.prev_phase).to eq(informing_phase)
expect(reviewing_phase.prev_phase).to eq(accepting_phase)
expect(selecting_phase.prev_phase).to eq(reviewing_phase)
expect(valuating_phase.prev_phase).to eq(selecting_phase)
expect(publishing_prices_phase.prev_phase).to eq(valuating_phase)
expect(balloting_phase.prev_phase).to eq(publishing_prices_phase)
expect(reviewing_ballots_phase.prev_phase).to eq(balloting_phase)
expect(finished_phase.prev_phase).to eq(reviewing_ballots_phase)
end
end
describe "#formatted_amount" do
it "correctly formats Euros with Spanish" do
budget.update!(currency_symbol: "")
I18n.with_locale(:es) do
expect(budget.formatted_amount(1000.00)).to eq "1.000 €"
end
end
it "correctly formats Dollars with Spanish" do
budget.update!(currency_symbol: "$")
I18n.with_locale(:es) do
expect(budget.formatted_amount(1000.00)).to eq "1.000 $"
end
end
it "correctly formats Dollars with English" do
budget.update!(currency_symbol: "$")
I18n.with_locale(:en) do
expect(budget.formatted_amount(1000.00)).to eq "$1,000"
end
end
it "correctly formats Euros with English" do
budget.update!(currency_symbol: "")
I18n.with_locale(:en) do
expect(budget.formatted_amount(1000.00)).to eq "€1,000"
end
end
end
describe "#investments_milestone_tags" do
let(:investment1) { build(:budget_investment, :winner) }
let(:investment2) { build(:budget_investment, :winner) }
let(:investment3) { build(:budget_investment) }
it "returns an empty array if not investments milestone_tags" do
budget.investments << investment1
expect(budget.investments_milestone_tags).to eq([])
end
it "returns array of investments milestone_tags" do
investment1.milestone_tag_list = "tag1"
investment1.save!
budget.investments << investment1
expect(budget.investments_milestone_tags).to eq(["tag1"])
end
it "returns uniq list of investments milestone_tags" do
investment1.milestone_tag_list = "tag1"
investment1.save!
investment2.milestone_tag_list = "tag1"
investment2.save!
budget.investments << investment1
budget.investments << investment2
expect(budget.investments_milestone_tags).to eq(["tag1"])
end
it "returns tags only for winner investments" do
investment1.milestone_tag_list = "tag1"
investment1.save!
investment3.milestone_tag_list = "tag2"
investment3.save!
budget.investments << investment1
budget.investments << investment3
expect(budget.investments_milestone_tags).to eq(["tag1"])
end
end
describe "#voting_style" do
context "Validations" do
it { expect(build(:budget, :approval)).to be_valid }
it { expect(build(:budget, :knapsack)).to be_valid }
it { expect(build(:budget, voting_style: "Oups!")).not_to be_valid }
end
context "Related supportive methods" do
describe "#approval_voting?" do
it { expect(build(:budget, :approval).approval_voting?).to be true }
it { expect(build(:budget, :knapsack).approval_voting?).to be false }
end
end
context "Defaults" do
it "defaults to knapsack voting style" do
expect(build(:budget).voting_style).to eq "knapsack"
end
end
end
describe "#budget_administrators" do
it "destroys relation with administrators when destroying the budget" do
budget = create(:budget, administrators: [create(:administrator)])
budget.destroy!
expect(BudgetAdministrator.count).to be 0
expect(Administrator.count).to be 1
end
end
describe "#budget_valuators" do
it "destroys relation with valuators when destroying the budget" do
budget = create(:budget, valuators: [create(:valuator)])
budget.destroy!
expect(BudgetValuator.count).to be 0
expect(Valuator.count).to be 1
end
end
describe "#single_heading?" do
it "returns false for budgets with no groups nor headings" do
expect(create(:budget).single_heading?).to be false
end
it "returns false for budgets with one group and no headings" do
create(:budget_group, budget: budget)
expect(budget.single_heading?).to be false
end
it "returns false for budgets with multiple groups and one heading" do
2.times { create(:budget_group, budget: budget) }
create(:budget_heading, group: budget.groups.last)
expect(budget.single_heading?).to be false
end
it "returns false for budgets with one group and multiple headings" do
group = create(:budget_group, budget: budget)
2.times { create(:budget_heading, group: group) }
expect(budget.single_heading?).to be false
end
it "returns false for budgets with one group and multiple headings" do
2.times { create(:budget_group, budget: budget) }
2.times { create(:budget_heading, group: budget.groups.sample) }
expect(budget.single_heading?).to be false
end
it "returns true for budgets with one group and one heading" do
create(:budget_heading, group: create(:budget_group, budget: budget))
expect(budget.single_heading?).to be true
end
end
end