diff --git a/app/views/sdg_management/relations/edit.html.erb b/app/views/sdg_management/relations/edit.html.erb
new file mode 100644
index 000000000000..4092359d7eb7
--- /dev/null
+++ b/app/views/sdg_management/relations/edit.html.erb
@@ -0,0 +1 @@
+<%= render SDGManagement::Relations::EditComponent.new(@record) %>
diff --git a/app/views/sdg_management/relations/index.html.erb b/app/views/sdg_management/relations/index.html.erb
new file mode 100644
index 000000000000..55878cd907ff
--- /dev/null
+++ b/app/views/sdg_management/relations/index.html.erb
@@ -0,0 +1 @@
+<%= render SDGManagement::Relations::IndexComponent.new(@records) %>
diff --git a/config/locales/en/activerecord.yml b/config/locales/en/activerecord.yml
index bc561d09360f..84264fbceedc 100644
--- a/config/locales/en/activerecord.yml
+++ b/config/locales/en/activerecord.yml
@@ -2,6 +2,7 @@ en:
attributes:
geozone_id: "Scope of operation"
results_enabled: "Show results"
+ sdg_target_list: "Targets"
stats_enabled: "Show stats"
advanced_stats_enabled: "Show advanced stats"
name: Name
@@ -287,6 +288,7 @@ en:
responsible_name: "Person responsible for the group"
poll:
name: "Name"
+ title: "Name"
starts_at: "Start Date"
ends_at: "Closing Date"
geozone_restricted: "Restricted by geozone"
diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml
index df6d749902af..18d9ceb534a2 100644
--- a/config/locales/en/admin.yml
+++ b/config/locales/en/admin.yml
@@ -1254,19 +1254,24 @@ en:
true_value: "Yes"
false_value: "No"
search:
+ advanced_filters:
+ sdg_goals:
+ all: "All goals"
+ label: "By goal"
+ sdg_targets:
+ all: "All targets"
+ label: "By target"
+ label:
+ booths: "Search booth by name or location"
+ budget_investments: "Search investments by title, description or heading"
+ debates: "Search debates by title or description"
+ legislation_processes: "Search processes by title or description"
+ poll_officers: "Search poll officers"
+ poll_questions: "Search poll questions"
+ polls: "Search polls by name or description"
+ proposals: "Search proposals by title, code, description or question"
+ users: "Search user by name or email"
search: "Search"
- booths_search:
- placeholder: Search booth by name or location
- poll_officers_search:
- placeholder: Search poll officers
- poll_questions_search:
- placeholder: Search poll questions
- proposal_search:
- placeholder: Search proposals by title, code, description or question
- debate_search:
- placeholder: Search debates by title or description
- user_search:
- placeholder: Search user by name or email
search_results: "Search results"
no_search_results: "No results found."
actions: Actions
diff --git a/config/locales/en/sdg_management.yml b/config/locales/en/sdg_management.yml
index 1e075fd76870..bacc84bbb5f5 100644
--- a/config/locales/en/sdg_management.yml
+++ b/config/locales/en/sdg_management.yml
@@ -1,8 +1,15 @@
en:
sdg_management:
+ actions:
+ edit: "Manage goals and targets"
header:
title: "SDG content"
menu:
+ budget_investments: "Participatory budgets"
+ debates: "Debates"
+ legislation_processes: "Collaborative legislation"
+ polls: "Polls"
+ proposals: "Proposals"
sdg_content: "Goals and Targets"
local_targets:
create:
diff --git a/config/locales/es/activerecord.yml b/config/locales/es/activerecord.yml
index 1f505a6bca45..d59c643c4070 100644
--- a/config/locales/es/activerecord.yml
+++ b/config/locales/es/activerecord.yml
@@ -2,6 +2,7 @@ es:
attributes:
geozone_id: "Ámbito de actuación"
results_enabled: "Mostrar resultados"
+ sdg_target_list: "Metas"
stats_enabled: "Mostrar estadísticas"
advanced_stats_enabled: "Mostrar estadísticas avanzadas"
name: Nombre
@@ -287,6 +288,7 @@ es:
responsible_name: "Persona responsable del colectivo"
poll:
name: "Nombre"
+ title: "Nombre"
starts_at: "Fecha de apertura"
ends_at: "Fecha de cierre"
geozone_restricted: "Restringida por zonas"
diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml
index 81ecc1259d5c..c03515bf223b 100644
--- a/config/locales/es/admin.yml
+++ b/config/locales/es/admin.yml
@@ -1253,19 +1253,24 @@ es:
true_value: "Sí"
false_value: "No"
search:
+ advanced_filters:
+ sdg_goals:
+ all: "Todos los objetivos"
+ label: "Por objetivo"
+ sdg_targets:
+ all: "Todas las metas"
+ label: "Por meta"
+ label:
+ booths: "Buscar urna por nombre"
+ budget_investments: "Buscar proyectos por título, descripción o partida"
+ debates: "Buscar debates por título o descripción"
+ legislation_processes: "Buscar procesos por título o descripción"
+ poll_officers: "Buscar presidentes de mesa"
+ poll_questions: "Buscar preguntas"
+ polls: "Buscar votaciones por nombre o descripción"
+ proposals: "Buscar propuestas por título, código, descripción o pregunta"
+ users: "Buscar usuario por nombre o email"
search: "Buscar"
- booths_search:
- placeholder: Buscar urna por nombre
- poll_officers_search:
- placeholder: Buscar presidentes de mesa
- poll_questions_search:
- placeholder: Buscar preguntas
- proposal_search:
- placeholder: Buscar propuestas por título, código, descripción o pregunta
- debate_search:
- placeholder: Buscar debates por título o descripción
- user_search:
- placeholder: Buscar usuario por nombre o email
search_results: "Resultados de la búsqueda"
no_search_results: "No se han encontrado resultados."
actions: Acciones
diff --git a/config/locales/es/sdg_management.yml b/config/locales/es/sdg_management.yml
index 4ee4d8893c61..23c10bd4a73d 100644
--- a/config/locales/es/sdg_management.yml
+++ b/config/locales/es/sdg_management.yml
@@ -1,8 +1,15 @@
es:
sdg_management:
+ actions:
+ edit: "Asignar objetivos y metas"
header:
title: "Contenido ODS"
menu:
+ budget_investments: "Presupuestos participativos"
+ debates: "Debates"
+ legislation_processes: "Legislación colaborativa"
+ polls: "Votaciones"
+ proposals: "Propuestas"
sdg_content: "Objetivos y Metas"
local_targets:
create:
diff --git a/config/routes/sdg_management.rb b/config/routes/sdg_management.rb
index cad7cbe66de9..6f303b45c4cd 100644
--- a/config/routes/sdg_management.rb
+++ b/config/routes/sdg_management.rb
@@ -4,4 +4,16 @@
resources :goals, only: [:index]
resources :targets, only: [:index]
resources :local_targets, except: [:show]
+
+ types = SDG::Related::RELATABLE_TYPES.map(&:tableize)
+ types_constraint = /#{types.join("|")}/
+
+ get "*relatable_type", to: "relations#index", as: "relations", relatable_type: types_constraint
+ get "*relatable_type/:id/edit", to: "relations#edit", as: "edit_relation", relatable_type: types_constraint
+ patch "*relatable_type/:id", to: "relations#update", as: "relation", relatable_type: types_constraint
+
+ types.each do |type|
+ get type, to: "relations#index", as: type
+ get "#{type}/:id/edit", to: "relations#edit", as: "edit_#{type.singularize}"
+ end
end
diff --git a/db/migrate/20201216132234_add_tsv_to_polls.rb b/db/migrate/20201216132234_add_tsv_to_polls.rb
new file mode 100644
index 000000000000..a629bf975046
--- /dev/null
+++ b/db/migrate/20201216132234_add_tsv_to_polls.rb
@@ -0,0 +1,5 @@
+class AddTsvToPolls < ActiveRecord::Migration[5.2]
+ def change
+ add_column :polls, :tsv, :tsvector
+ end
+end
diff --git a/db/migrate/20201216132642_add_tsv_to_legislation_processes.rb b/db/migrate/20201216132642_add_tsv_to_legislation_processes.rb
new file mode 100644
index 000000000000..fdeb8fdd5a1c
--- /dev/null
+++ b/db/migrate/20201216132642_add_tsv_to_legislation_processes.rb
@@ -0,0 +1,5 @@
+class AddTsvToLegislationProcesses < ActiveRecord::Migration[5.2]
+ def change
+ add_column :legislation_processes, :tsv, :tsvector
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 5f69e9ac43f1..6a67f083fb4a 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2020_11_24_145559) do
+ActiveRecord::Schema.define(version: 2020_12_16_132642) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm"
@@ -747,6 +747,7 @@
t.boolean "homepage_enabled", default: false
t.text "background_color"
t.text "font_color"
+ t.tsvector "tsv"
t.index ["allegations_end_date"], name: "index_legislation_processes_on_allegations_end_date"
t.index ["allegations_start_date"], name: "index_legislation_processes_on_allegations_start_date"
t.index ["debate_end_date"], name: "index_legislation_processes_on_debate_end_date"
@@ -1166,6 +1167,7 @@
t.integer "budget_id"
t.string "related_type"
t.integer "related_id"
+ t.tsvector "tsv"
t.index ["budget_id"], name: "index_polls_on_budget_id", unique: true
t.index ["related_type", "related_id"], name: "index_polls_on_related_type_and_related_id"
t.index ["starts_at", "ends_at"], name: "index_polls_on_starts_at_and_ends_at"
diff --git a/lib/tasks/consul.rake b/lib/tasks/consul.rake
index 911460c68607..4f169c387a50 100644
--- a/lib/tasks/consul.rake
+++ b/lib/tasks/consul.rake
@@ -6,6 +6,7 @@ namespace :consul do
desc "Runs tasks needed to upgrade from 1.2.0 to 1.3.0"
task "execute_release_1.3.0_tasks": [
- "db:load_sdg"
+ "db:load_sdg",
+ "db:calculate_tsv"
]
end
diff --git a/lib/tasks/db.rake b/lib/tasks/db.rake
index a64643adc518..622f9e9c541d 100644
--- a/lib/tasks/db.rake
+++ b/lib/tasks/db.rake
@@ -10,4 +10,10 @@ namespace :db do
ApplicationLogger.new.info "Adding Sustainable Development Goals content"
load(Rails.root.join("db", "sdg.rb"))
end
+
+ desc "Calculates the TSV column for all polls and legislation processes"
+ task calculate_tsv: :environment do
+ Poll.find_each(&:calculate_tsvector)
+ Legislation::Process.find_each(&:calculate_tsvector)
+ end
end
diff --git a/spec/components/sdg_management/menu_component_spec.rb b/spec/components/sdg_management/menu_component_spec.rb
new file mode 100644
index 000000000000..10547e4dd320
--- /dev/null
+++ b/spec/components/sdg_management/menu_component_spec.rb
@@ -0,0 +1,92 @@
+require "rails_helper"
+
+describe SDGManagement::MenuComponent, type: :component do
+ let(:component) { SDGManagement::MenuComponent.new }
+
+ before do
+ Setting["sdg.process.budgets"] = true
+ Setting["sdg.process.debates"] = true
+ Setting["sdg.process.legislation"] = true
+ Setting["sdg.process.polls"] = true
+ Setting["sdg.process.proposals"] = true
+ end
+
+ context "processes enabled" do
+ it "generates links to all processes" do
+ render_inline component
+
+ expect(page).to have_link "Goals and Targets"
+ expect(page).to have_link "Participatory budgets"
+ expect(page).to have_link "Debates"
+ expect(page).to have_link "Collaborative legislation"
+ expect(page).to have_link "Polls"
+ expect(page).to have_link "Proposals"
+ end
+ end
+
+ context "processes disabled" do
+ before do
+ Setting["process.budgets"] = false
+ Setting["process.debates"] = false
+ Setting["process.legislation"] = false
+ Setting["process.polls"] = false
+ Setting["process.proposals"] = false
+ end
+
+ it "does not generate links to any processes" do
+ render_inline component
+
+ expect(page).to have_css "a", count: 1
+ expect(page).to have_link "Goals and Targets"
+ end
+ end
+
+ context "SDG processes disabled" do
+ before do
+ Setting["sdg.process.budgets"] = false
+ Setting["sdg.process.debates"] = false
+ Setting["sdg.process.legislation"] = false
+ Setting["sdg.process.polls"] = false
+ Setting["sdg.process.proposals"] = false
+ end
+
+ it "does not generate links to any processes" do
+ render_inline component
+
+ expect(page).to have_css "a", count: 1
+ expect(page).to have_link "Goals and Targets"
+ end
+ end
+
+ context "one process disabled" do
+ before { Setting["process.debates"] = false }
+
+ it "generates links to the enabled processes" do
+ render_inline component
+
+ expect(page).to have_link "Goals and Targets"
+ expect(page).to have_link "Participatory budgets"
+ expect(page).to have_link "Collaborative legislation"
+ expect(page).to have_link "Polls"
+ expect(page).to have_link "Proposals"
+
+ expect(page).not_to have_link "Debates"
+ end
+ end
+
+ context "one SDG process disabled" do
+ before { Setting["sdg.process.legislation"] = false }
+
+ it "generates links to the enabled processes" do
+ render_inline component
+
+ expect(page).to have_link "Goals and Targets"
+ expect(page).to have_link "Debates"
+ expect(page).to have_link "Participatory budgets"
+ expect(page).to have_link "Polls"
+ expect(page).to have_link "Proposals"
+
+ expect(page).not_to have_link "Collaborative legislation"
+ end
+ end
+end
diff --git a/spec/controllers/sdg_management/relations_spec.rb b/spec/controllers/sdg_management/relations_spec.rb
new file mode 100644
index 000000000000..fc5e8ecb7d03
--- /dev/null
+++ b/spec/controllers/sdg_management/relations_spec.rb
@@ -0,0 +1,98 @@
+require "rails_helper"
+
+describe SDGManagement::RelationsController do
+ before do
+ sign_in create(:administrator).user
+
+ Setting["feature.sdg"] = true
+ Setting["sdg.process.budgets"] = true
+ Setting["sdg.process.debates"] = true
+ Setting["sdg.process.legislation"] = true
+ Setting["sdg.process.polls"] = true
+ Setting["sdg.process.proposals"] = true
+ end
+
+ context "processes disabled" do
+ it "raises feature disabled for budgets" do
+ Setting["process.budgets"] = false
+
+ expect do
+ get :index, params: { relatable_type: "budget/investments" }
+ end.to raise_exception(FeatureFlags::FeatureDisabled)
+ end
+
+ it "raises feature disabled for debates" do
+ Setting["process.debates"] = false
+
+ expect do
+ get :index, params: { relatable_type: "debates" }
+ end.to raise_exception(FeatureFlags::FeatureDisabled)
+ end
+
+ it "raises feature disabled for legislation processes" do
+ Setting["process.legislation"] = false
+
+ expect do
+ get :index, params: { relatable_type: "legislation/processes" }
+ end.to raise_exception(FeatureFlags::FeatureDisabled)
+ end
+
+ it "raises feature disabled for polls" do
+ Setting["process.polls"] = false
+
+ expect do
+ get :index, params: { relatable_type: "polls" }
+ end.to raise_exception(FeatureFlags::FeatureDisabled)
+ end
+
+ it "raises feature disabled for proposals" do
+ Setting["process.proposals"] = false
+
+ expect do
+ get :index, params: { relatable_type: "proposals" }
+ end.to raise_exception(FeatureFlags::FeatureDisabled)
+ end
+ end
+
+ context "SDG processes disabled" do
+ it "raises feature disabled for budgets" do
+ Setting["sdg.process.budgets"] = false
+
+ expect do
+ get :index, params: { relatable_type: "budget/investments" }
+ end.to raise_exception(FeatureFlags::FeatureDisabled)
+ end
+
+ it "raises feature disabled for debates" do
+ Setting["sdg.process.debates"] = false
+
+ expect do
+ get :index, params: { relatable_type: "debates" }
+ end.to raise_exception(FeatureFlags::FeatureDisabled)
+ end
+
+ it "raises feature disabled for legislation processes" do
+ Setting["sdg.process.legislation"] = false
+
+ expect do
+ get :index, params: { relatable_type: "legislation/processes" }
+ end.to raise_exception(FeatureFlags::FeatureDisabled)
+ end
+
+ it "raises feature disabled for polls" do
+ Setting["sdg.process.polls"] = false
+
+ expect do
+ get :index, params: { relatable_type: "polls" }
+ end.to raise_exception(FeatureFlags::FeatureDisabled)
+ end
+
+ it "raises feature disabled for proposals" do
+ Setting["sdg.process.proposals"] = false
+
+ expect do
+ get :index, params: { relatable_type: "proposals" }
+ end.to raise_exception(FeatureFlags::FeatureDisabled)
+ end
+ end
+end
diff --git a/spec/lib/tasks/load_sdg_spec.rb b/spec/lib/tasks/db_spec.rb
similarity index 56%
rename from spec/lib/tasks/load_sdg_spec.rb
rename to spec/lib/tasks/db_spec.rb
index 6581ba7a5bfe..b556b41b4db7 100644
--- a/spec/lib/tasks/load_sdg_spec.rb
+++ b/spec/lib/tasks/db_spec.rb
@@ -32,3 +32,33 @@
expect(SDG::Target.last.id).to eq target_id
end
end
+
+describe "rake db:calculate_tsv" do
+ before { Rake::Task["db:calculate_tsv"].reenable }
+
+ let :run_rake_task do
+ Rake.application.invoke_task("db:calculate_tsv")
+ end
+
+ it "calculates the tsvector for polls" do
+ poll = create(:poll)
+ poll.update_column(:tsv, nil)
+
+ expect(poll.reload.tsv).to be nil
+
+ run_rake_task
+
+ expect(poll.reload.tsv).not_to be nil
+ end
+
+ it "calculates the tsvector for legislation processes" do
+ process = create(:legislation_process)
+ process.update_column(:tsv, nil)
+
+ expect(process.reload.tsv).to be nil
+
+ run_rake_task
+
+ expect(process.reload.tsv).not_to be nil
+ end
+end
diff --git a/spec/models/legislation/process_spec.rb b/spec/models/legislation/process_spec.rb
index 0ea89c71577d..5302497a07d5 100644
--- a/spec/models/legislation/process_spec.rb
+++ b/spec/models/legislation/process_spec.rb
@@ -229,4 +229,35 @@
end
end
end
+
+ describe ".search" do
+ let!(:traffic) do
+ create(:legislation_process,
+ title: "Traffic regulation",
+ summary: "Lane structure",
+ description: "From top to bottom")
+ end
+
+ let!(:animal_farm) do
+ create(:legislation_process,
+ title: "Hierarchy structure",
+ summary: "Pigs at the top",
+ description: "Napoleon in charge of the traffic")
+ end
+
+ it "returns only matching polls" do
+ expect(Legislation::Process.search("lane")).to eq [traffic]
+ expect(Legislation::Process.search("pigs")).to eq [animal_farm]
+ expect(Legislation::Process.search("nothing here")).to be_empty
+ end
+
+ it "gives more weight to name" do
+ expect(Legislation::Process.search("traffic")).to eq [traffic, animal_farm]
+ expect(Legislation::Process.search("structure")).to eq [animal_farm, traffic]
+ end
+
+ it "gives more weight to summary than description" do
+ expect(Legislation::Process.search("top")).to eq [animal_farm, traffic]
+ end
+ end
end
diff --git a/spec/models/poll/poll_spec.rb b/spec/models/poll/poll_spec.rb
index 0a1fc94bdcc3..1223e53d62fe 100644
--- a/spec/models/poll/poll_spec.rb
+++ b/spec/models/poll/poll_spec.rb
@@ -433,4 +433,29 @@
expect(poll.recounts_confirmed?).to be true
end
end
+
+ describe ".search" do
+ let!(:square) do
+ create(:poll, name: "Square reform", summary: "Next to the park", description: "Give it more space")
+ end
+
+ let!(:park) do
+ create(:poll, name: "New park", summary: "Green spaces", description: "Next to the square")
+ end
+
+ it "returns only matching polls" do
+ expect(Poll.search("reform")).to eq [square]
+ expect(Poll.search("green")).to eq [park]
+ expect(Poll.search("nothing here")).to be_empty
+ end
+
+ it "gives more weight to name" do
+ expect(Poll.search("square")).to eq [square, park]
+ expect(Poll.search("park")).to eq [park, square]
+ end
+
+ it "gives more weight to summary than description" do
+ expect(Poll.search("space")).to eq [park, square]
+ end
+ end
end
diff --git a/spec/models/sdg/relatable_spec.rb b/spec/models/sdg/relatable_spec.rb
index e6fd1b8d0c00..036b5af96c8b 100644
--- a/spec/models/sdg/relatable_spec.rb
+++ b/spec/models/sdg/relatable_spec.rb
@@ -28,6 +28,14 @@
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_targets" do
it "can assign targets to a model" do
relatable.sdg_targets = [target, another_target]
@@ -46,6 +54,14 @@
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
+ end
+
describe "#sdg_local_targets" do
it "can assign local targets to a model" do
relatable.sdg_local_targets = [local_target, another_local_target]
@@ -74,4 +90,72 @@
expect(relatable.reload.related_sdgs).to match_array related_sdgs
end
end
+
+ describe "#sdg_target_list=" do
+ it "assigns a single target" do
+ relatable.sdg_target_list = "1.1"
+
+ expect(relatable.reload.sdg_targets).to match_array [SDG::Target["1.1"]]
+ end
+
+ it "assigns multiple targets" do
+ relatable.sdg_target_list = "1.1,2.3"
+
+ expect(relatable.reload.sdg_targets).to match_array [SDG::Target["1.1"], SDG::Target["2.3"]]
+ end
+
+ it "ignores trailing spaces and spaces between commas" do
+ relatable.sdg_target_list = " 1.1, 2.3 "
+
+ expect(relatable.reload.sdg_targets).to match_array [SDG::Target["1.1"], SDG::Target["2.3"]]
+ end
+
+ it "assigns goals" do
+ relatable.sdg_target_list = "1.1,1.2,2.3"
+
+ expect(relatable.reload.sdg_goals).to match_array [SDG::Goal[1], SDG::Goal[2]]
+ 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_targets: [another_target])
+
+ expect(relatable.class.by_target(target.code)).to be_empty
+ end
+ end
end
diff --git a/spec/routing/sdg_management_routes_spec.rb b/spec/routing/sdg_management_routes_spec.rb
new file mode 100644
index 000000000000..c04748e47fa5
--- /dev/null
+++ b/spec/routing/sdg_management_routes_spec.rb
@@ -0,0 +1,32 @@
+require "rails_helper"
+
+describe "SDG Management routes" do
+ it "maps routes for relatable classes" do
+ expect(get("/sdg_management/proposals")).to route_to(
+ controller: "sdg_management/relations",
+ action: "index",
+ relatable_type: "proposals"
+ )
+ end
+
+ it "admits named routes" do
+ expect(get(sdg_management_polls_path)).to route_to(
+ controller: "sdg_management/relations",
+ action: "index",
+ relatable_type: "polls"
+ )
+ end
+
+ it "routes relatable types containing a slash" do
+ expect(url_for(
+ controller: "sdg_management/relations",
+ action: "index",
+ relatable_type: "legislation/processes",
+ only_path: true
+ )).to eq "/sdg_management/legislation/processes"
+ end
+
+ it "does not accept non-relatable classes" do
+ expect(get("/sdg_management/tags")).not_to be_routable
+ end
+end
diff --git a/spec/system/sdg_management/relations_spec.rb b/spec/system/sdg_management/relations_spec.rb
new file mode 100644
index 000000000000..05b0a9965ce1
--- /dev/null
+++ b/spec/system/sdg_management/relations_spec.rb
@@ -0,0 +1,145 @@
+require "rails_helper"
+
+describe "SDG Relations", :js do
+ before do
+ login_as(create(:administrator).user)
+ Setting["feature.sdg"] = true
+ Setting["sdg.process.budgets"] = true
+ Setting["sdg.process.debates"] = true
+ Setting["sdg.process.legislation"] = true
+ Setting["sdg.process.polls"] = true
+ Setting["sdg.process.proposals"] = true
+ end
+
+ scenario "navigation" do
+ visit sdg_management_root_path
+
+ within("#side_menu") { click_link "Participatory budgets" }
+
+ expect(page).to have_current_path "/sdg_management/budget/investments"
+ expect(page).to have_css "h2", exact_text: "Participatory budgets"
+
+ within("#side_menu") { click_link "Debates" }
+
+ expect(page).to have_current_path "/sdg_management/debates"
+ expect(page).to have_css "h2", exact_text: "Debates"
+
+ within("#side_menu") { click_link "Collaborative legislation" }
+
+ expect(page).to have_current_path "/sdg_management/legislation/processes"
+ expect(page).to have_css "h2", exact_text: "Collaborative legislation"
+
+ within("#side_menu") { click_link "Polls" }
+
+ expect(page).to have_current_path "/sdg_management/polls"
+ expect(page).to have_css "h2", exact_text: "Polls"
+
+ within("#side_menu") { click_link "Proposals" }
+
+ expect(page).to have_current_path "/sdg_management/proposals"
+ expect(page).to have_css "h2", exact_text: "Proposals"
+ end
+
+ describe "Index" do
+ scenario "list records for the current model" do
+ create(:debate, title: "I'm a debate")
+ create(:proposal, title: "And I'm a proposal")
+
+ visit sdg_management_debates_path
+
+ expect(page).to have_text "I'm a debate"
+ expect(page).not_to have_text "I'm a proposal"
+
+ visit sdg_management_proposals_path
+
+ expect(page).to have_text "I'm a proposal"
+ expect(page).not_to have_text "I'm a debate"
+ end
+
+ scenario "list goals and target for all records" do
+ redistribute = create(:proposal, title: "Resources distribution")
+ redistribute.sdg_goals = [SDG::Goal[1]]
+ redistribute.sdg_targets = [SDG::Target["1.1"]]
+
+ treatment = create(:proposal, title: "Treatment system")
+ treatment.sdg_goals = [SDG::Goal[6]]
+ treatment.sdg_targets = [SDG::Target["6.1"], SDG::Target["6.2"]]
+
+ visit sdg_management_proposals_path
+
+ within("tr", text: "Resources distribution") do
+ expect(page).to have_content "1.1"
+ end
+
+ within("tr", text: "Treatment system") do
+ expect(page).to have_content "6.1, 6.2"
+ end
+ end
+
+ scenario "shows link to edit a record" do
+ create(:budget_investment, title: "Build a hospital")
+
+ visit sdg_management_budget_investments_path
+
+ within("tr", text: "Build a hospital") do
+ click_link "Manage goals and targets"
+ end
+
+ expect(page).to have_css "h2", exact_text: "Build a hospital"
+ end
+
+ describe "search" do
+ scenario "search by terms" do
+ create(:poll, name: "Internet speech freedom")
+ create(:poll, name: "SDG interest")
+
+ visit sdg_management_polls_path
+
+ fill_in "search", with: "speech"
+ click_button "Search"
+
+ expect(page).to have_content "Internet speech freedom"
+ expect(page).not_to have_content "SDG interest"
+ end
+
+ scenario "goal filter" do
+ create(:budget_investment, title: "School", sdg_goals: [SDG::Goal[4]])
+ create(:budget_investment, title: "Hospital", sdg_goals: [SDG::Goal[3]])
+
+ visit sdg_management_budget_investments_path
+ select "4. Quality Education", from: "goal_code"
+ click_button "Search"
+
+ expect(page).to have_content "School"
+ expect(page).not_to have_content "Hospital"
+ end
+ end
+
+ scenario "target filter" do
+ create(:budget_investment, title: "School", sdg_targets: [SDG::Target[4.1]])
+ create(:budget_investment, title: "Preschool", sdg_targets: [SDG::Target[4.2]])
+
+ visit sdg_management_budget_investments_path
+ select "4.1", from: "target_code"
+ click_button "Search"
+
+ expect(page).to have_content "School"
+ expect(page).not_to have_content "Preschool"
+ end
+ end
+
+ describe "Edit" do
+ scenario "allows changing the targets" do
+ process = create(:legislation_process, title: "SDG process")
+ process.sdg_targets = [SDG::Target["3.3"]]
+
+ visit sdg_management_edit_legislation_process_path(process)
+ fill_in "Targets", with: "1.2, 2.1"
+ click_button "Update Process"
+
+ within("tr", text: "SDG process") do
+ expect(page).to have_css "td", exact_text: "1.2, 2.1"
+ end
+ end
+ end
+end