spec/models/sdg/relatable_spec.rb
require "rails_helper"
describe SDG::Relatable do
let(:goal) { SDG::Goal[1] }
let(:target) { SDG::Target["1.2"] }
let(:local_target) { create(:sdg_local_target, code: "1.2.1") }
let(:another_goal) { SDG::Goal[2] }
let(:another_target) { SDG::Target["2.3"] }
let(:another_local_target) { create(:sdg_local_target, code: "2.3.1") }
let(:relatable) { create(:proposal) }
describe "#sdg_goals" do
it "can assign goals to a model" do
relatable.sdg_goals = [goal, another_goal]
expect(SDG::Relation.count).to be 2
expect(SDG::Relation.first.relatable).to eq relatable
expect(SDG::Relation.last.relatable).to eq relatable
expect(SDG::Relation.first.related_sdg).to eq goal
expect(SDG::Relation.last.related_sdg).to eq another_goal
end
it "can obtain the list of goals" do
relatable.sdg_goals = [goal, another_goal]
expect(relatable.reload.sdg_goals).to match_array [goal, another_goal]
end
end
describe "#sdg_goal_list" do
it "orders goals by code" do
relatable.sdg_goals = [SDG::Goal[1], SDG::Goal[3], SDG::Goal[2]]
expect(relatable.sdg_goal_list).to eq "1, 2, 3"
end
end
describe "#sdg_global_targets" do
it "can assign targets to a model" do
relatable.sdg_global_targets = [target, another_target]
expect(SDG::Relation.count).to be 2
expect(SDG::Relation.first.relatable).to eq relatable
expect(SDG::Relation.last.relatable).to eq relatable
expect(SDG::Relation.first.related_sdg).to eq target
expect(SDG::Relation.last.related_sdg).to eq another_target
end
it "can obtain the list of targets" do
relatable.sdg_global_targets = [target, another_target]
expect(relatable.reload.sdg_global_targets).to match_array [target, another_target]
end
end
describe "#sdg_target_list" do
it "orders targets by code" do
relatable.sdg_targets = [SDG::Target[2.2], SDG::Target[1.2], SDG::Target[2.1]]
expect(relatable.sdg_target_list).to eq "1.2, 2.1, 2.2"
end
it "includes both targets and local targets in order" do
relatable.sdg_global_targets = [SDG::Target[2.2], SDG::Target[1.2], SDG::Target[2.1]]
relatable.sdg_local_targets = %w[1.1.1 2.1.3].map { |code| create(:sdg_local_target, code: code) }
expect(relatable.sdg_target_list).to eq "1.1.1, 1.2, 2.1, 2.1.3, 2.2"
end
end
describe "#sdg_targets=" do
it "assigns both targets and local targets" do
global_targets = [SDG::Target[2.2], SDG::Target[1.2]]
local_targets = %w[2.2.1 3.1.1].map { |code| create(:sdg_local_target, code: code) }
relatable.sdg_targets = global_targets + local_targets
expect(relatable.sdg_global_targets).to match_array global_targets
expect(relatable.sdg_local_targets).to match_array local_targets
end
end
describe "#sdg_local_targets" do
it "can assign local targets to a model" do
relatable.sdg_local_targets = [local_target, another_local_target]
expect(SDG::Relation.count).to be 2
expect(SDG::Relation.first.relatable).to eq relatable
expect(SDG::Relation.last.relatable).to eq relatable
expect(SDG::Relation.first.related_sdg).to eq local_target
expect(SDG::Relation.last.related_sdg).to eq another_local_target
end
it "can obtain the list of local targets" do
relatable.sdg_local_targets = [local_target, another_local_target]
expect(relatable.reload.sdg_local_targets).to match_array [local_target, another_local_target]
end
end
describe "#related_sdg_list" do
it "orders related list by code" do
relatable.sdg_goals = [SDG::Goal[1], SDG::Goal[3], SDG::Goal[2]]
local_targets = %w[2.2.2 2.2.1 3.1.1].map { |code| create(:sdg_local_target, code: code) }
relatable.sdg_targets = [SDG::Target[2.2], SDG::Target[1.2], SDG::Target[2.1]] + local_targets
expect(relatable.related_sdg_list).to eq "1, 1.2, 2, 2.1, 2.2, 2.2.1, 2.2.2, 3, 3.1.1"
end
end
describe "#related_sdgs" do
it "returns all related goals and targets" do
relatable.sdg_goals = [goal, another_goal]
relatable.sdg_targets = [target, another_target]
relatable.sdg_local_targets = [local_target, another_local_target]
related_sdgs = [goal, another_goal, target, another_target, local_target, another_local_target]
expect(relatable.reload.related_sdgs).to match_array related_sdgs
end
end
describe "#related_sdg_list=" do
it "assigns a single goal" do
relatable.related_sdg_list = "1"
expect(relatable.reload.sdg_goals).to match_array [SDG::Goal[1]]
end
it "assigns a single target" do
relatable.related_sdg_list = "1.1"
expect(relatable.reload.sdg_goals).to match_array [SDG::Goal[1]]
expect(relatable.reload.sdg_targets).to match_array [SDG::Target[1.1]]
end
it "assigns a single local target" do
relatable.related_sdg_list = local_target.code
expect(relatable.reload.sdg_goals).to match_array [local_target.goal]
expect(relatable.reload.sdg_local_targets).to match_array [local_target]
end
it "assigns multiple targets" do
relatable.related_sdg_list = "1.1,2.3"
expect(relatable.reload.sdg_goals).to match_array [SDG::Goal[1], SDG::Goal[2]]
expect(relatable.reload.sdg_targets).to match_array [SDG::Target[1.1], SDG::Target[2.3]]
end
it "assigns multiple goals" do
relatable.related_sdg_list = "3,2,1"
expect(relatable.reload.sdg_goals).to match_array [SDG::Goal[1], SDG::Goal[2], SDG::Goal[3]]
end
it "assigns multiple local targets" do
relatable.related_sdg_list = "#{local_target.code}, #{another_local_target.code}"
expect(relatable.reload.sdg_goals).to match_array [local_target.goal, another_local_target.goal]
expect(relatable.reload.sdg_local_targets).to match_array [local_target, another_local_target]
end
it "ignores trailing spaces and spaces between commas" do
relatable.related_sdg_list = " 1.1, 2.3 "
expect(relatable.reload.sdg_goals).to match_array [SDG::Goal[1], SDG::Goal[2]]
expect(relatable.reload.sdg_targets).to match_array [SDG::Target[1.1], SDG::Target[2.3]]
end
it "assigns goals, targets and local_targets" do
relatable.related_sdg_list = "1.1,3,4,4.1,#{another_local_target.code}"
expect(relatable.reload.sdg_goals).to match_array [SDG::Goal[1],
another_local_target.goal,
SDG::Goal[3],
SDG::Goal[4]]
expect(relatable.reload.sdg_global_targets).to match_array [SDG::Target[1.1], SDG::Target[4.1]]
expect(relatable.reload.sdg_local_targets).to match_array [another_local_target]
end
it "touches the associated record" do
relatable.related_sdg_list = "1.1, 2.1, 2.2"
travel(10.seconds) do
relatable.related_sdg_list = "1.1, 2.1, 2.2, 3.1"
expect(relatable.updated_at).to eq Time.current
end
end
end
describe "#sdg_review" do
it "returns nil when relatable is not reviewed" do
expect(relatable.sdg_review).to be_blank
end
it "returns the review when relatable is reviewed" do
review = create(:sdg_review, relatable: relatable)
expect(relatable.sdg_review).to eq(review)
end
end
describe ".by_goal" do
it "returns everything if no code is provided" do
expect(relatable.class.by_goal("")).to eq [relatable]
expect(relatable.class.by_goal(nil)).to eq [relatable]
end
it "returns records associated with that goal" do
same_association = create(:proposal, sdg_goals: [goal])
both_associations = create(:proposal, sdg_goals: [goal, another_goal])
expect(relatable.class.by_goal(goal.code)).to match_array [same_association, both_associations]
end
it "does not return records not associated with that goal" do
create(:proposal)
create(:proposal, sdg_goals: [another_goal])
expect(relatable.class.by_goal(goal.code)).to be_empty
end
end
describe ".by_target" do
it "returns everything if no code is provided" do
expect(relatable.class.by_target("")).to eq [relatable]
expect(relatable.class.by_target(nil)).to eq [relatable]
end
it "returns records associated with that target" do
same_association = create(:proposal, sdg_targets: [target])
both_associations = create(:proposal, sdg_targets: [target, another_target])
expect(relatable.class.by_target(target.code)).to match_array [same_association, both_associations]
end
it "does not return records not associated with that target" do
create(:proposal)
create(:proposal, sdg_global_targets: [another_target])
expect(relatable.class.by_target(target.code)).to be_empty
end
it "returns records associated to a local target" do
relatable.sdg_local_targets = [local_target]
expect(relatable.class.by_target(local_target.code)).to eq [relatable]
end
it "does not return records not associated with that local target" do
create(:proposal)
create(:proposal, sdg_local_targets: [another_local_target])
expect(relatable.class.by_target(local_target.code)).to be_empty
end
end
describe ".pending_sdg_review" do
let!(:relatable) { create(:proposal) }
it "returns records not reviewed yet" do
create(:sdg_review, relatable: create(:proposal))
expect(relatable.class.pending_sdg_review).to match_array [relatable]
end
end
describe ".sdg_reviewed" do
let!(:relatable) { create(:proposal) }
let!(:reviewed_relatable) { create(:sdg_review, relatable: create(:proposal)).relatable }
it "returns records already reviewed" do
expect(relatable.class.sdg_reviewed).to match_array [reviewed_relatable]
end
end
end