Having exceptions is better than having silent bugs.
There are a few methods I've kept the same way they were.
The `RelatedContentScore#score_with_opposite` method is a bit peculiar:
it creates scores for both itself and the opposite related content,
which means the opposite related content will try to create the same
scores as well.
We've already got a test to check `Budget::Ballot#add_investment` when
creating a line fails ("Edge case voting a non-elegible investment").
Finally, the method `User#send_oauth_confirmation_instructions` doesn't
update the record when the email address isn't already present, leading
to the test "Try to register with the email of an already existing user,
when an unconfirmed email was provided by oauth" fo fail if we raise an
exception for an invalid user. That's because updating a user's email
doesn't update the database automatically, but instead a confirmation
email is sent.
There are also a few false positives for classes which don't have bang
methods (like the GraphQL classes) or destroying attachments.
For these reasons, I'm adding the rule with a "Refactor" severity,
meaning it's a rule we can break if necessary.
351 lines
13 KiB
Ruby
351 lines
13 KiB
Ruby
require "rails_helper"
|
|
|
|
describe Dashboard::Action do
|
|
subject do
|
|
build :dashboard_action,
|
|
title: title,
|
|
description: description,
|
|
day_offset: day_offset,
|
|
required_supports: required_supports,
|
|
request_to_administrators: request_to_administrators,
|
|
action_type: action_type
|
|
end
|
|
|
|
let(:title) { Faker::Lorem.sentence }
|
|
let(:description) { Faker::Lorem.sentence }
|
|
let(:day_offset) { 0 }
|
|
let(:required_supports) { 0 }
|
|
let(:request_to_administrators) { true }
|
|
let(:action_type) { "resource" }
|
|
|
|
it "is invalid when title is blank" do
|
|
action = build(:dashboard_action, title: "")
|
|
expect(action).not_to be_valid
|
|
end
|
|
|
|
it "is invalid when title is too short" do
|
|
action = build(:dashboard_action, title: "abc")
|
|
expect(action).not_to be_valid
|
|
end
|
|
|
|
it "is invalid when title is too long" do
|
|
action = build(:dashboard_action, title: "a" * 81)
|
|
expect(action).not_to be_valid
|
|
end
|
|
|
|
it "is invalid when day_offset is not defined" do
|
|
action = build(:dashboard_action, day_offset: nil)
|
|
expect(action).not_to be_valid
|
|
end
|
|
|
|
it "is invalid when day_offset is negative" do
|
|
action = build(:dashboard_action, day_offset: -1)
|
|
expect(action).not_to be_valid
|
|
end
|
|
|
|
it "is invalid when day_offset not an integer" do
|
|
action = build(:dashboard_action, day_offset: 1.23)
|
|
expect(action).not_to be_valid
|
|
end
|
|
|
|
it "is invalid when required_supports is nil" do
|
|
action = build(:dashboard_action, required_supports: nil)
|
|
expect(action).not_to be_valid
|
|
end
|
|
|
|
it "is invalid when required_supports is negative" do
|
|
action = build(:dashboard_action, required_supports: -1)
|
|
expect(action).not_to be_valid
|
|
end
|
|
|
|
it "is invalid when required_supports is not an integer" do
|
|
action = build(:dashboard_action, required_supports: 1.23)
|
|
expect(action).not_to be_valid
|
|
end
|
|
|
|
it "is invalid when action_type is nil" do
|
|
action = build(:dashboard_action, action_type: nil)
|
|
expect(action).not_to be_valid
|
|
end
|
|
|
|
context "#active_for?" do
|
|
it "is active when required supports is 0 and day_offset is 0" do
|
|
action = build(:dashboard_action, required_supports: 0, day_offset: 0)
|
|
proposal = build(:proposal)
|
|
|
|
expect(action).to be_active_for(proposal)
|
|
end
|
|
|
|
it "is active when published after day_offset" do
|
|
action = build(:dashboard_action, required_supports: 0, day_offset: 10)
|
|
proposal = build(:proposal, published_at: Time.current - 10.days)
|
|
|
|
expect(action).to be_active_for(proposal)
|
|
end
|
|
|
|
it "is active when have enough supports" do
|
|
action = build(:dashboard_action, required_supports: 10, day_offset: 0)
|
|
proposal = build(:proposal, cached_votes_up: 10)
|
|
|
|
expect(action).to be_active_for(proposal)
|
|
end
|
|
|
|
it "is not active when not enough time published" do
|
|
action = build(:dashboard_action, required_supports: 0, day_offset: 10)
|
|
proposal = build(:proposal, published_at: Time.current - 9.days)
|
|
|
|
expect(action).not_to be_active_for(proposal)
|
|
end
|
|
|
|
it "is not active when not enough supports" do
|
|
action = build(:dashboard_action, required_supports: 10, day_offset: 0)
|
|
proposal = build(:proposal, cached_votes_up: 9)
|
|
|
|
expect(action).not_to be_active_for(proposal)
|
|
end
|
|
end
|
|
|
|
context "#requested_for?" do
|
|
it "is not requested when no administrator task" do
|
|
proposal = create(:proposal)
|
|
action = create(:dashboard_action, :active, :admin_request, :resource)
|
|
|
|
expect(action).not_to be_requested_for(proposal)
|
|
end
|
|
|
|
it "is requested when administrator task" do
|
|
proposal = create(:proposal)
|
|
action = create(:dashboard_action, :active, :admin_request, :resource)
|
|
executed_action = create(:dashboard_executed_action, proposal: proposal, action: action)
|
|
_task = create(:dashboard_administrator_task, :pending, source: executed_action)
|
|
|
|
expect(action).to be_requested_for(proposal)
|
|
end
|
|
end
|
|
|
|
context "#executed_for?" do
|
|
it "is not executed when no administrator task" do
|
|
proposal = create(:proposal)
|
|
action = create(:dashboard_action, :active, :admin_request, :resource)
|
|
|
|
expect(action).not_to be_executed_for(proposal)
|
|
end
|
|
|
|
it "is not executed when pending administrator task" do
|
|
proposal = create(:proposal)
|
|
action = create(:dashboard_action, :active, :admin_request, :resource)
|
|
executed_action = create(:dashboard_executed_action, proposal: proposal, action: action)
|
|
_task = create(:dashboard_administrator_task, :pending, source: executed_action)
|
|
|
|
expect(action).not_to be_executed_for(proposal)
|
|
end
|
|
|
|
it "is executed when done administrator task" do
|
|
proposal = create(:proposal)
|
|
action = create(:dashboard_action, :active, :admin_request, :resource)
|
|
executed_action = create(:dashboard_executed_action, proposal: proposal, action: action)
|
|
_task = create(:dashboard_administrator_task, :done, source: executed_action)
|
|
|
|
expect(action).to be_executed_for(proposal)
|
|
end
|
|
end
|
|
|
|
context "#active_for" do
|
|
let!(:active_action) { create :dashboard_action, :active, day_offset: 0, required_supports: 0 }
|
|
let!(:inactive_action) { create :dashboard_action, :inactive }
|
|
let!(:not_enough_supports_action) do
|
|
create :dashboard_action, :active, day_offset: 0, required_supports: 10_000
|
|
end
|
|
|
|
let!(:future_action) do
|
|
create :dashboard_action, :active, day_offset: 300, required_supports: 0
|
|
end
|
|
|
|
let!(:action_published_proposal) do
|
|
create :dashboard_action,
|
|
:active,
|
|
day_offset: 0,
|
|
required_supports: 0,
|
|
published_proposal: true
|
|
end
|
|
|
|
let!(:action_for_draft_proposal) do
|
|
create :dashboard_action,
|
|
:active,
|
|
day_offset: 0,
|
|
required_supports: 0,
|
|
published_proposal: false
|
|
end
|
|
|
|
let(:proposal) { create :proposal }
|
|
let(:draft_proposal) { create :proposal, :draft }
|
|
|
|
it "actions with enough supports or days are active" do
|
|
expect(Dashboard::Action.active_for(proposal)).to include(active_action)
|
|
end
|
|
|
|
it "inactive actions are not included" do
|
|
expect(Dashboard::Action.active_for(proposal)).not_to include(inactive_action)
|
|
end
|
|
|
|
it "actions without enough supports are not active" do
|
|
expect(Dashboard::Action.active_for(proposal)).not_to include(not_enough_supports_action)
|
|
end
|
|
|
|
it "actions planned to be active in the future are not active" do
|
|
expect(Dashboard::Action.active_for(proposal)).not_to include(future_action)
|
|
end
|
|
|
|
it "actions with published_proposal: true, are not included on draft proposal" do
|
|
expect(Dashboard::Action.active_for(draft_proposal)).not_to include(action_published_proposal)
|
|
end
|
|
|
|
it "actions with published_proposal: true, are included on published proposal" do
|
|
expect(Dashboard::Action.active_for(proposal)).to include(action_published_proposal)
|
|
end
|
|
|
|
it "actions with published_proposal: false, are included on draft proposal" do
|
|
expect(Dashboard::Action.active_for(draft_proposal)).to include(action_for_draft_proposal)
|
|
end
|
|
|
|
it "actions with published_proposal: false, are included on published proposal" do
|
|
expect(Dashboard::Action.active_for(proposal)).to include(action_for_draft_proposal)
|
|
end
|
|
end
|
|
|
|
context "#course_for" do
|
|
let!(:proposed_action) { create :dashboard_action, :active, required_supports: 0 }
|
|
let!(:inactive_resource) do
|
|
create :dashboard_action, :inactive, :resource, required_supports: 0
|
|
end
|
|
let!(:resource) { create :dashboard_action, :active, :resource, required_supports: 10_000 }
|
|
let!(:achieved_resource) { create :dashboard_action, :active, :resource, required_supports: 0 }
|
|
let(:proposal) { create :proposal }
|
|
|
|
it "proposed actions are not part of proposal's course" do
|
|
expect(Dashboard::Action.course_for(proposal)).not_to include(proposed_action)
|
|
end
|
|
|
|
it "inactive resources are not part of proposal's course" do
|
|
expect(Dashboard::Action.course_for(proposal)).not_to include(inactive_resource)
|
|
end
|
|
|
|
it "achievements are not part of the proposal's course" do
|
|
expect(Dashboard::Action.course_for(proposal)).not_to include(achieved_resource)
|
|
end
|
|
|
|
it "active resources are part of proposal's course" do
|
|
expect(Dashboard::Action.course_for(proposal)).to include(resource)
|
|
end
|
|
end
|
|
|
|
context "#detect_new_actions_since" do
|
|
|
|
describe "No detect new actions" do
|
|
|
|
let!(:action) { create(:dashboard_action, :proposed_action, :active, day_offset: 1) }
|
|
let!(:resource) { create(:dashboard_action, :resource, :active, day_offset: 1) }
|
|
|
|
it "when there are not news actions actived for published proposals" do
|
|
proposal = create(:proposal)
|
|
action.update!(published_proposal: true)
|
|
resource.update!(published_proposal: true)
|
|
|
|
expect(Dashboard::Action.detect_new_actions_since(Date.yesterday, proposal)).to eq []
|
|
end
|
|
|
|
it "when there are news actions actived for draft_proposal but proposal is published" do
|
|
proposal = create(:proposal)
|
|
action.update!(published_proposal: false, day_offset: 0)
|
|
resource.update!(published_proposal: false, day_offset: 0)
|
|
|
|
expect(Dashboard::Action.detect_new_actions_since(Date.yesterday, proposal)).to eq []
|
|
end
|
|
|
|
it "when there are not news actions actived for draft proposals" do
|
|
proposal = create(:proposal, :draft)
|
|
action.update!(published_proposal: false)
|
|
resource.update!(published_proposal: false)
|
|
|
|
expect(Dashboard::Action.detect_new_actions_since(Date.yesterday, proposal)).to eq []
|
|
end
|
|
|
|
it "when there are news actions actived for published_proposal but proposal is draft" do
|
|
proposal = create(:proposal, :draft)
|
|
action.update!(published_proposal: true, day_offset: 0)
|
|
resource.update!(published_proposal: true, day_offset: 0)
|
|
|
|
expect(Dashboard::Action.detect_new_actions_since(Date.yesterday, proposal)).to eq []
|
|
end
|
|
|
|
end
|
|
|
|
describe "Detect new actions when there are news actions actived" do
|
|
|
|
context "for published proposals" do
|
|
let!(:proposal) { create(:proposal) }
|
|
|
|
let!(:action) do
|
|
create(:dashboard_action, :proposed_action, :active, day_offset: 0, published_proposal: true)
|
|
end
|
|
|
|
let!(:resource) do
|
|
create(:dashboard_action, :resource, :active, day_offset: 0, published_proposal: true)
|
|
end
|
|
|
|
it "when proposal has been created today and day_offset is valid only for today" do
|
|
expect(Dashboard::Action.detect_new_actions_since(Date.yesterday,
|
|
proposal)).to include(resource.id)
|
|
expect(Dashboard::Action.detect_new_actions_since(Date.yesterday,
|
|
proposal)).to include(action.id)
|
|
end
|
|
|
|
it "when proposal has received a new vote today" do
|
|
proposal.update!(created_at: Date.yesterday, published_at: Date.yesterday)
|
|
action.update!(required_supports: 1)
|
|
resource.update!(required_supports: 0)
|
|
create(:vote, voter: proposal.author, votable: proposal)
|
|
|
|
expect(Dashboard::Action.detect_new_actions_since(Date.yesterday,
|
|
proposal)).to include(action.id)
|
|
expect(Dashboard::Action.detect_new_actions_since(Date.yesterday,
|
|
proposal)).not_to include(resource.id)
|
|
end
|
|
|
|
end
|
|
|
|
context "for draft proposals" do
|
|
let!(:proposal) { create(:proposal, :draft) }
|
|
|
|
let!(:action) do
|
|
create(:dashboard_action, :proposed_action, :active, day_offset: 0, published_proposal: false)
|
|
end
|
|
|
|
let!(:resource) do
|
|
create(:dashboard_action, :resource, :active, day_offset: 0, published_proposal: false)
|
|
end
|
|
|
|
it "when day_offset field is valid for today and invalid for yesterday" do
|
|
expect(Dashboard::Action.detect_new_actions_since(Date.yesterday,
|
|
proposal)).to include(resource.id)
|
|
expect(Dashboard::Action.detect_new_actions_since(Date.yesterday,
|
|
proposal)).to include(action.id)
|
|
end
|
|
|
|
it "when proposal has received a new vote today" do
|
|
proposal.update!(created_at: Date.yesterday)
|
|
action.update!(required_supports: 1)
|
|
resource.update!(required_supports: 2)
|
|
create(:vote, voter: proposal.author, votable: proposal)
|
|
|
|
expect(Dashboard::Action.detect_new_actions_since(Date.yesterday,
|
|
proposal)).to include(action.id)
|
|
expect(Dashboard::Action.detect_new_actions_since(Date.yesterday,
|
|
proposal)).not_to include(resource.id)
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|
|
end
|