diff --git a/.rubocop_ruby.yml b/.rubocop_ruby.yml index 6e3c4bc..892ef63 100644 --- a/.rubocop_ruby.yml +++ b/.rubocop_ruby.yml @@ -69,7 +69,7 @@ AllCops: # If a value is specified for TargetRubyVersion then it is used. # Else if .ruby-version exists and it contains an MRI version it is used. # Otherwise we fallback to the oldest officially supported Ruby version (2.0). - TargetRubyVersion: 2.7 + TargetRubyVersion: 3.0 RSpec: Patterns: diff --git a/.simplecov b/.simplecov index 03f7423..f0bcafe 100644 --- a/.simplecov +++ b/.simplecov @@ -1,12 +1,12 @@ # frozen_string_literal: true SimpleCov.start do - root ENV["ENGINE_ROOT"] + root ENV.fetch("ENGINE_ROOT", nil) add_filter "lib/decidim/survey_multiple_answers/version.rb" add_filter "/spec" end -SimpleCov.command_name ENV["COMMAND_NAME"] || File.basename(Dir.pwd) +SimpleCov.command_name ENV.fetch("COMMAND_NAME", nil) || File.basename(Dir.pwd) SimpleCov.merge_timeout 1800 diff --git a/Gemfile b/Gemfile index c43479c..6380719 100644 --- a/Gemfile +++ b/Gemfile @@ -8,8 +8,8 @@ gem "decidim", "~> 0.27" gem "decidim-custom_proposal_states", path: "." gem "decidim-elections", "~> 0.27" -gem "puma", ">= 4.3" gem "bootsnap", "~> 1.4" +gem "puma", ">= 4.3" group :development, :test do gem "byebug", "~> 11.0", platform: :mri diff --git a/app/commands/decidim/custom_proposal_states/admin/create_proposal_state.rb b/app/commands/decidim/custom_proposal_states/admin/create_proposal_state.rb index d3c7325..d4e0a32 100644 --- a/app/commands/decidim/custom_proposal_states/admin/create_proposal_state.rb +++ b/app/commands/decidim/custom_proposal_states/admin/create_proposal_state.rb @@ -3,7 +3,7 @@ module Decidim module CustomProposalStates module Admin - class CreateProposalState < Rectify::Command + class CreateProposalState < Decidim::Command def initialize(form, component) @form = form @component = component diff --git a/app/commands/decidim/custom_proposal_states/admin/destroy_proposal_state.rb b/app/commands/decidim/custom_proposal_states/admin/destroy_proposal_state.rb index b2cd0d4..b83c4a6 100644 --- a/app/commands/decidim/custom_proposal_states/admin/destroy_proposal_state.rb +++ b/app/commands/decidim/custom_proposal_states/admin/destroy_proposal_state.rb @@ -3,7 +3,7 @@ module Decidim module CustomProposalStates module Admin - class DestroyProposalState < Rectify::Command + class DestroyProposalState < Decidim::Command # Initializes an UpdateResult Command. # # result - The current instance of the result to be destroyed. diff --git a/app/commands/decidim/custom_proposal_states/admin/update_proposal_state.rb b/app/commands/decidim/custom_proposal_states/admin/update_proposal_state.rb index 4b68484..0dccc30 100644 --- a/app/commands/decidim/custom_proposal_states/admin/update_proposal_state.rb +++ b/app/commands/decidim/custom_proposal_states/admin/update_proposal_state.rb @@ -3,7 +3,7 @@ module Decidim module CustomProposalStates module Admin - class UpdateProposalState < Rectify::Command + class UpdateProposalState < Decidim::Command include TranslatableAttributes def initialize(form, state) diff --git a/db/migrate/20231102173159_create_decidim_proposals_proposal_state.rb b/db/migrate/20231102173159_create_decidim_proposals_proposal_state.rb index e2af74a..f0ad4d1 100644 --- a/db/migrate/20231102173159_create_decidim_proposals_proposal_state.rb +++ b/db/migrate/20231102173159_create_decidim_proposals_proposal_state.rb @@ -18,4 +18,4 @@ def change t.string :css_class end end -end \ No newline at end of file +end diff --git a/db/migrate/20231102173214_add_state_id_to_decidim_proposals_proposals.rb b/db/migrate/20231102173214_add_state_id_to_decidim_proposals_proposals.rb index 5d9780b..44c3a6e 100644 --- a/db/migrate/20231102173214_add_state_id_to_decidim_proposals_proposals.rb +++ b/db/migrate/20231102173214_add_state_id_to_decidim_proposals_proposals.rb @@ -11,4 +11,4 @@ def down remove_foreign_key :decidim_proposals_proposals, column: :decidim_proposals_proposal_state_id remove_column :decidim_proposals_proposals, :decidim_proposals_proposal_state_id end -end \ No newline at end of file +end diff --git a/db/migrate/20231102234909_create_default_proposal_states.rb b/db/migrate/20231102234909_create_default_proposal_states.rb index 5402615..e435d75 100644 --- a/db/migrate/20231102234909_create_default_proposal_states.rb +++ b/db/migrate/20231102234909_create_default_proposal_states.rb @@ -15,7 +15,7 @@ def up return unless Decidim.version.to_s.include?("0.26") states = { - "0" => :not_answered, + "0" => :not_answered, "10" => :evaluating, "20" => :accepted, "-10" => :rejected, @@ -37,4 +37,4 @@ def up end def down; end -end \ No newline at end of file +end diff --git a/decidim-custom_proposal_states.gemspec b/decidim-custom_proposal_states.gemspec index b207c63..76f0001 100644 --- a/decidim-custom_proposal_states.gemspec +++ b/decidim-custom_proposal_states.gemspec @@ -26,4 +26,5 @@ Gem::Specification.new do |s| s.add_development_dependency "decidim-dev", "~> 0.27" s.add_development_dependency "decidim-elections", "~> 0.27" s.add_development_dependency "decidim-sortitions", "~> 0.27" + s.metadata["rubygems_mfa_required"] = "true" end diff --git a/lib/decidim/custom_proposal_states/overrides/proposal_cells_helper.rb b/lib/decidim/custom_proposal_states/overrides/proposal_cells_helper.rb index 65decf8..113849e 100644 --- a/lib/decidim/custom_proposal_states/overrides/proposal_cells_helper.rb +++ b/lib/decidim/custom_proposal_states/overrides/proposal_cells_helper.rb @@ -20,12 +20,10 @@ def state_classes case state when "accepted" ["success"] - when "rejected" + when "rejected", "withdrawn" ["alert"] when "evaluating" ["warning"] - when "withdrawn" - ["alert"] else ["muted"] end diff --git a/lib/decidim/custom_proposal_states/overrides/proposals_controller.rb b/lib/decidim/custom_proposal_states/overrides/proposals_controller.rb index 144f9e0..16e37fd 100644 --- a/lib/decidim/custom_proposal_states/overrides/proposals_controller.rb +++ b/lib/decidim/custom_proposal_states/overrides/proposals_controller.rb @@ -8,12 +8,12 @@ def self.prepended(base) base.class_eval do def default_filter_params { - search_text: "", - state: default_states, - origin: default_filter_origin_params, + search_text_cont: "", + with_any_state: default_states, + with_any_origin: default_filter_origin_params, activity: "all", - category_id: default_filter_category_params, - scope_id: default_filter_scope_params, + with_any_category: default_filter_category_params, + with_any_scope: default_filter_scope_params, related_to: "", type: "all" } diff --git a/spec/i18n_spec.rb b/spec/i18n_spec.rb index 1670ba8..c74b8ce 100644 --- a/spec/i18n_spec.rb +++ b/spec/i18n_spec.rb @@ -7,7 +7,7 @@ ENV["ENFORCED_LOCALES"].presence || "en" end - let(:i18n) { I18n::Tasks::BaseTask.new({ locales: locales.split(",") }) } + let(:i18n) { I18n::Tasks::BaseTask.new(locales: locales.split(",")) } let(:missing_keys) { i18n.missing_keys } let(:unused_keys) { i18n.unused_keys } let(:non_normalized_paths) { i18n.non_normalized_paths } @@ -23,8 +23,8 @@ unless ENV["SKIP_NORMALIZATION"] it "is normalized" do error_message = "The following files need to be normalized:\n" \ - "#{non_normalized_paths.map { |path| " #{path}" }.join("\n")}\n" \ - "Please run `bundle exec i18n-tasks normalize --locales #{locales}` to fix them" + "#{non_normalized_paths.map { |path| " #{path}" }.join("\n")}\n" \ + "Please run `bundle exec i18n-tasks normalize --locales #{locales}` to fix them" expect(non_normalized_paths).to be_empty, error_message end diff --git a/spec/proposals/cells/decidim/proposals/proposal_m_cell_spec.rb b/spec/proposals/cells/decidim/proposals/proposal_m_cell_spec.rb index 1ee7747..204d718 100644 --- a/spec/proposals/cells/decidim/proposals/proposal_m_cell_spec.rb +++ b/spec/proposals/cells/decidim/proposals/proposal_m_cell_spec.rb @@ -10,7 +10,7 @@ module Decidim::Proposals let(:my_cell) { cell("decidim/proposals/proposal_m", proposal, context: { show_space: show_space }) } let(:cell_html) { my_cell.call } - let(:created_at) { Time.current - 1.month } + let(:created_at) { 1.month.ago } let(:published_at) { Time.current } let(:component) { create(:extended_proposal_component, :with_attachments_allowed) } let!(:proposal) { create(:extended_proposal, component: component, created_at: created_at, published_at: published_at) } @@ -80,6 +80,7 @@ module Decidim::Proposals let!(:attachment_3_pdf) { create(:attachment, :with_pdf, attached_to: proposal) } it "renders the first image in the card whatever the order between attachments" do + attachment_2_img.reload expect(subject).to have_css(".card__image") expect(subject.find(".card__image")[:src]).to eq(attachment_2_img.thumbnail_url) end @@ -230,19 +231,19 @@ module Decidim::Proposals end context "when the active participatory space step change" do - let(:step_1) { create(:participatory_process_step, participatory_process: participatory_process, active: step_1_active) } + let(:step1) { create(:participatory_process_step, participatory_process: participatory_process, active: step_1_active) } let(:step_1_active) { true } - let(:step_2) { create(:participatory_process_step, participatory_process: participatory_process, active: step_2_active) } + let(:step2) { create(:participatory_process_step, participatory_process: participatory_process, active: step_2_active) } let(:step_2_active) { false } - let(:step_3) { create(:participatory_process_step, participatory_process: participatory_process, active: step_3_active) } + let(:step3) { create(:participatory_process_step, participatory_process: participatory_process, active: step_3_active) } let(:step_3_active) { false } let(:component) do create(:extended_proposal_component, participatory_space: participatory_process, step_settings: { - step_1.id => { votes_enabled: false }, - step_2.id => { votes_enabled: true }, - step_3.id => { votes_enabled: false } + step1.id => { votes_enabled: false }, + step2.id => { votes_enabled: true }, + step3.id => { votes_enabled: false } }) end let(:participatory_process) { create(:participatory_process) } @@ -251,8 +252,8 @@ module Decidim::Proposals it "generates a different hash" do old_hash = my_cell.send(:cache_hash) - step_1.update!(active: false) - step_2.update!(active: true) + step1.update!(active: false) + step2.update!(active: true) proposal.reload expect(my_cell.send(:cache_hash)).not_to eq(old_hash) @@ -266,8 +267,8 @@ module Decidim::Proposals it "generates a different hash" do old_hash = my_cell.send(:cache_hash) - step_2.update!(active: false) - step_3.update!(active: true) + step2.update!(active: false) + step3.update!(active: true) proposal.reload expect(my_cell.send(:cache_hash)).not_to eq(old_hash) diff --git a/spec/proposals/commands/decidim/proposals/admin/answer_proposal_spec.rb b/spec/proposals/commands/decidim/proposals/admin/answer_proposal_spec.rb index 6e4d8f9..3872dab 100644 --- a/spec/proposals/commands/decidim/proposals/admin/answer_proposal_spec.rb +++ b/spec/proposals/commands/decidim/proposals/admin/answer_proposal_spec.rb @@ -64,7 +64,7 @@ module Admin context "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do diff --git a/spec/proposals/commands/decidim/proposals/admin/create_proposal_spec.rb b/spec/proposals/commands/decidim/proposals/admin/create_proposal_spec.rb index 90058a0..e59878a 100644 --- a/spec/proposals/commands/decidim/proposals/admin/create_proposal_spec.rb +++ b/spec/proposals/commands/decidim/proposals/admin/create_proposal_spec.rb @@ -54,7 +54,7 @@ module Admin describe "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do @@ -197,10 +197,17 @@ module Admin context "when attachments are allowed" do let(:component) { create(:extended_proposal_component, :with_attachments_allowed) } + let(:blob) do + ActiveStorage::Blob.create_and_upload!( + io: File.open(Decidim::Dev.test_file("city.jpeg", "image/jpeg"), "rb"), + filename: "city.jpeg", + content_type: "image/jpeg" # Or figure it out from `name` if you have non-JPEGs + ) + end let(:attachment_params) do { title: "My attachment", - file: Decidim::Dev.test_file("city.jpeg", "image/jpeg") + file: blob.signed_id } end diff --git a/spec/proposals/commands/decidim/proposals/admin/import_participatory_text_spec.rb b/spec/proposals/commands/decidim/proposals/admin/import_participatory_text_spec.rb index 5e6446a..aec3c9b 100644 --- a/spec/proposals/commands/decidim/proposals/admin/import_participatory_text_spec.rb +++ b/spec/proposals/commands/decidim/proposals/admin/import_participatory_text_spec.rb @@ -7,7 +7,7 @@ module Proposals module Admin describe ImportParticipatoryText do describe "call" do - let!(:document_file) { IO.read(Decidim::Dev.asset(document_name)) } + let!(:document_file) { File.read(Decidim::Dev.asset(document_name)) } let(:current_component) do create( :extended_proposal_component, @@ -70,7 +70,7 @@ module Admin it "doesn't create any proposal" do expect do command.call - end.to change(Proposal, :count).by(0) + end.not_to change(Proposal, :count) end end diff --git a/spec/proposals/commands/decidim/proposals/admin/import_proposals_spec.rb b/spec/proposals/commands/decidim/proposals/admin/import_proposals_spec.rb index bea6186..065d1ad 100644 --- a/spec/proposals/commands/decidim/proposals/admin/import_proposals_spec.rb +++ b/spec/proposals/commands/decidim/proposals/admin/import_proposals_spec.rb @@ -55,7 +55,7 @@ module Admin it "doesn't create the proposal" do expect do command.call - end.to change(Proposal, :count).by(0) + end.not_to change(Proposal, :count) end end diff --git a/spec/proposals/commands/decidim/proposals/admin/update_proposal_spec.rb b/spec/proposals/commands/decidim/proposals/admin/update_proposal_spec.rb index 1aaee91..d9c4d34 100644 --- a/spec/proposals/commands/decidim/proposals/admin/update_proposal_spec.rb +++ b/spec/proposals/commands/decidim/proposals/admin/update_proposal_spec.rb @@ -48,7 +48,7 @@ describe "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do @@ -112,10 +112,18 @@ context "when attachments are allowed" do let(:component) { create(:extended_proposal_component, :with_attachments_allowed) } + let(:blob) do + ActiveStorage::Blob.create_and_upload!( + io: File.open(Decidim::Dev.test_file("city.jpeg", "image/jpeg"), "rb"), + filename: "city.jpeg", + content_type: "image/jpeg" # Or figure it out from `name` if you have non-JPEGs + ) + end + let(:attachment_params) do { title: "My attachment", - file: Decidim::Dev.test_file("city.jpeg", "image/jpeg") + file: blob.signed_id } end diff --git a/spec/proposals/commands/decidim/proposals/create_proposal_spec.rb b/spec/proposals/commands/decidim/proposals/create_proposal_spec.rb index 9ca0eb2..9beecc6 100644 --- a/spec/proposals/commands/decidim/proposals/create_proposal_spec.rb +++ b/spec/proposals/commands/decidim/proposals/create_proposal_spec.rb @@ -41,7 +41,7 @@ module Proposals describe "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do @@ -104,7 +104,7 @@ module Proposals creator = proposal.creator expect(creator.author).to eq(author) - expect(creator.user_group).to eq(nil) + expect(creator.user_group).to be_nil end it "adds the author as a follower" do diff --git a/spec/proposals/commands/decidim/proposals/publish_collaborative_draft_spec.rb b/spec/proposals/commands/decidim/proposals/publish_collaborative_draft_spec.rb index d3a00b5..d001492 100644 --- a/spec/proposals/commands/decidim/proposals/publish_collaborative_draft_spec.rb +++ b/spec/proposals/commands/decidim/proposals/publish_collaborative_draft_spec.rb @@ -24,7 +24,7 @@ module Proposals let(:current_user) { create(:user, organization: component.organization) } it "broadcasts invalid" do - expect(collaborative_draft.authored_by?(current_user)).to eq(false) + expect(collaborative_draft.authored_by?(current_user)).to be(false) expect { command.call }.to broadcast(:invalid) end end diff --git a/spec/proposals/commands/decidim/proposals/update_proposal_spec.rb b/spec/proposals/commands/decidim/proposals/update_proposal_spec.rb index b6d8053..59f85d8 100644 --- a/spec/proposals/commands/decidim/proposals/update_proposal_spec.rb +++ b/spec/proposals/commands/decidim/proposals/update_proposal_spec.rb @@ -64,7 +64,7 @@ module Proposals describe "when the form is not valid" do before do - expect(form).to receive(:invalid?).and_return(true) + allow(form).to receive(:invalid?).and_return(true) end it "broadcasts invalid" do @@ -80,7 +80,7 @@ module Proposals describe "when the proposal is not editable by the user" do before do - expect(proposal).to receive(:editable_by?).and_return(false) + allow(proposal).to receive(:editable_by?).and_return(false) end it "broadcasts invalid" do @@ -178,12 +178,14 @@ module Proposals let(:component) { create(:extended_proposal_component, :with_attachments_allowed) } let(:uploaded_files) do [ - Decidim::Dev.test_file("Exampledocument.pdf", "application/pdf") + file: upload_test_file(Decidim::Dev.asset("Exampledocument.pdf"), content_type: "application/pdf") ] end let(:uploaded_photos) do [ - Decidim::Dev.test_file("city.jpeg", "image/jpeg") + { + file: upload_test_file(Decidim::Dev.asset("city.jpeg"), content_type: "image/jpeg") + } ] end @@ -209,13 +211,13 @@ module Proposals let(:component) { create(:extended_proposal_component, :with_attachments_allowed) } let(:uploaded_files) do [ - Decidim::Dev.test_file("city.jpeg", "image/jpeg"), - Decidim::Dev.test_file("verify_user_groups.csv", "text/csv") + { file: upload_test_file(Decidim::Dev.asset("Exampledocument.pdf"), content_type: "application/pdf") }, + { file: upload_test_file(Decidim::Dev.asset("verify_user_groups.csv"), content_type: "text/csv") } ] end it "does not create atachments for the proposal" do - expect { command.call }.to change(Decidim::Attachment, :count).by(0) + expect { command.call }.not_to change(Decidim::Attachment, :count) end it "broadcasts invalid" do @@ -225,12 +227,8 @@ module Proposals context "when documents and gallery are allowed" do let(:component) { create(:extended_proposal_component, :with_attachments_allowed) } - let(:uploaded_photos) { [Decidim::Dev.test_file("city.jpeg", "image/jpeg")] } - let(:uploaded_files) do - [ - Decidim::Dev.test_file("Exampledocument.pdf", "application/pdf") - ] - end + let(:uploaded_photos) { [{ file: upload_test_file(Decidim::Dev.asset("city.jpeg"), content_type: "image/jpeg") }] } + let(:uploaded_files) { [{ file: upload_test_file(Decidim::Dev.asset("Exampledocument.pdf"), content_type: "application/pdf") }] } it "Create gallery and documents for the proposal" do expect { command.call }.to change(Decidim::Attachment, :count).by(2) @@ -239,7 +237,7 @@ module Proposals context "when gallery are allowed" do let(:component) { create(:extended_proposal_component, :with_attachments_allowed) } - let(:uploaded_photos) { [Decidim::Dev.test_file("city.jpeg", "image/jpeg")] } + let(:uploaded_photos) { [{ file: upload_test_file(Decidim::Dev.asset("city.jpeg"), content_type: "image/jpeg") }] } it "creates an image attachment for the proposal" do expect { command.call }.to change(Decidim::Attachment, :count).by(1) diff --git a/spec/proposals/commands/decidim/proposals/withdraw_proposal_spec.rb b/spec/proposals/commands/decidim/proposals/withdraw_proposal_spec.rb index 5c5067d..9d89d7a 100644 --- a/spec/proposals/commands/decidim/proposals/withdraw_proposal_spec.rb +++ b/spec/proposals/commands/decidim/proposals/withdraw_proposal_spec.rb @@ -19,7 +19,7 @@ module Proposals it "withdraws the proposal" do expect do expect { command.call }.to broadcast(:ok) - end.to change { Decidim::Proposals::Proposal.count }.by(0) + end.not_to change(Decidim::Proposals::Proposal, :count) expect(proposal.state).to eq("withdrawn") end end @@ -32,7 +32,7 @@ module Proposals it "is not able to withdraw the proposal" do expect do expect { command.call }.to broadcast(:has_supports) - end.to change { Decidim::Proposals::Proposal.count }.by(0) + end.not_to change(Decidim::Proposals::Proposal, :count) expect(proposal.state).not_to eq("withdrawn") end end diff --git a/spec/proposals/controllers/decidim/proposals/admin/participatory_texts_controller_spec.rb b/spec/proposals/controllers/decidim/proposals/admin/participatory_texts_controller_spec.rb index 7815e6d..e3031f4 100644 --- a/spec/proposals/controllers/decidim/proposals/admin/participatory_texts_controller_spec.rb +++ b/spec/proposals/controllers/decidim/proposals/admin/participatory_texts_controller_spec.rb @@ -10,7 +10,7 @@ module Admin let(:user) { create(:user, :confirmed, :admin, organization: component.organization) } let(:component) { create :extended_proposal_component, :with_participatory_texts_enabled } - let(:document_file) { fixture_file_upload(Decidim::Dev.asset("participatory_text.md"), "text/markdown") } + let(:document_file) { upload_test_file(Decidim::Dev.asset("participatory_text.md"), content_type: "text/markdown") } let(:title) { { en: ::Faker::Book.title } } let(:params) do { diff --git a/spec/proposals/forms/decidim/proposals/admin/import_participatory_text_form_spec.rb b/spec/proposals/forms/decidim/proposals/admin/import_participatory_text_form_spec.rb index 2f3878b..7cf9541 100644 --- a/spec/proposals/forms/decidim/proposals/admin/import_participatory_text_form_spec.rb +++ b/spec/proposals/forms/decidim/proposals/admin/import_participatory_text_form_spec.rb @@ -16,7 +16,7 @@ module Admin es: "Ya para ser feliz quiero un camión" } end - let(:description) {} + let(:description) { nil } let(:document) { Decidim::Dev.test_file("participatory_text.md", "text/markdown") } let(:params) do diff --git a/spec/proposals/forms/decidim/proposals/proposal_wizard_create_step_form_spec.rb b/spec/proposals/forms/decidim/proposals/proposal_wizard_create_step_form_spec.rb index df85735..d080180 100644 --- a/spec/proposals/forms/decidim/proposals/proposal_wizard_create_step_form_spec.rb +++ b/spec/proposals/forms/decidim/proposals/proposal_wizard_create_step_form_spec.rb @@ -44,7 +44,7 @@ module Proposals it "only adds errors to this field" do subject.valid? - expect(subject.errors.keys).to eq [:title] + expect(subject.errors.attribute_names).to eq [:title] end end diff --git a/spec/proposals/helpers/application_helper_spec.rb b/spec/proposals/helpers/application_helper_spec.rb index 40a1f5a..2824a02 100644 --- a/spec/proposals/helpers/application_helper_spec.rb +++ b/spec/proposals/helpers/application_helper_spec.rb @@ -43,7 +43,7 @@ module Proposals end let(:body) { "" } - let(:proposal_trait) { :citizen_author } + let(:proposal_trait) { :participant_author } let(:proposal) { create(:extended_proposal, proposal_trait, body: { "en" => body }) } it "renders a sanitized body" do @@ -85,7 +85,16 @@ module Proposals end it "renders the image and iframe embed" do - expect(subject).to eq(%(
#{body}
)) + expect(subject).to eq( + <<~HTML.strip +

Image

+
+
+
+
+
+ HTML + ) end end end diff --git a/spec/proposals/lib/decidim/admin/import/importer_spec.rb b/spec/proposals/lib/decidim/admin/import/importer_spec.rb index 2881725..d1b27ba 100644 --- a/spec/proposals/lib/decidim/admin/import/importer_spec.rb +++ b/spec/proposals/lib/decidim/admin/import/importer_spec.rb @@ -3,7 +3,7 @@ require "spec_helper" describe Decidim::Admin::Import::Importer do - subject { described_class.new(file: file, reader: reader, creator: creator, context: context) } + subject { described_class.new(file: blob, reader: reader, creator: creator, context: context) } let(:creator) { Decidim::Proposals::Import::ProposalCreator } @@ -21,7 +21,7 @@ let(:current_component) { create :extended_proposal_component, participatory_space: participatory_process } context "with CSV" do - let(:file) { File.new Decidim::Dev.asset("import_proposals.csv") } + let(:blob) { upload_test_file(Decidim::Dev.asset("import_proposals.csv"), return_blob: true) } let(:reader) { Decidim::Admin::Import::Readers::CSV } it_behaves_like "proposal importer" @@ -51,14 +51,14 @@ end context "with JSON" do - let(:file) { File.new Decidim::Dev.asset("import_proposals.json") } + let(:blob) { upload_test_file(Decidim::Dev.asset("import_proposals.json"), return_blob: true) } let(:reader) { Decidim::Admin::Import::Readers::JSON } it_behaves_like "proposal importer" end context "with XLSX" do - let(:file) { File.new Decidim::Dev.asset("import_proposals.xlsx") } + let(:blob) { upload_test_file(Decidim::Dev.asset("import_proposals.xlsx"), return_blob: true) } let(:reader) { Decidim::Admin::Import::Readers::XLSX } it_behaves_like "proposal importer" diff --git a/spec/proposals/lib/decidim/content_parsers/proposal_parser_spec.rb b/spec/proposals/lib/decidim/content_parsers/proposal_parser_spec.rb index 4de5b6e..d5ade19 100644 --- a/spec/proposals/lib/decidim/content_parsers/proposal_parser_spec.rb +++ b/spec/proposals/lib/decidim/content_parsers/proposal_parser_spec.rb @@ -14,7 +14,7 @@ module ContentParsers let(:content) { "" } it "must call ProposalParser.parse" do - expect(described_class).to receive(:new).with(content, context).and_return(parser) + allow(described_class).to receive(:new).with(content, context).and_return(parser) result = Decidim::ContentProcessor.parse(content, context) diff --git a/spec/proposals/lib/decidim/content_renderers/proposal_renderer_spec.rb b/spec/proposals/lib/decidim/content_renderers/proposal_renderer_spec.rb index 51da910..8e974ab 100644 --- a/spec/proposals/lib/decidim/content_renderers/proposal_renderer_spec.rb +++ b/spec/proposals/lib/decidim/content_renderers/proposal_renderer_spec.rb @@ -38,17 +38,17 @@ module ContentRenderers end context "when content has many links" do - let(:proposal_1) { create(:extended_proposal) } - let(:proposal_2) { create(:extended_proposal) } - let(:proposal_3) { create(:extended_proposal) } + let(:proposal1) { create(:extended_proposal) } + let(:proposal2) { create(:extended_proposal) } + let(:proposal3) { create(:extended_proposal) } let(:content) do - gid1 = proposal_1.to_global_id - gid2 = proposal_2.to_global_id - gid3 = proposal_3.to_global_id + gid1 = proposal1.to_global_id + gid2 = proposal2.to_global_id + gid3 = proposal3.to_global_id "This content references the following proposals: #{gid1}, #{gid2} and #{gid3}. Great?I like them!" end - it { is_expected.to eq("This content references the following proposals: #{resource_as_html_link(proposal_1)}, #{resource_as_html_link(proposal_2)} and #{resource_as_html_link(proposal_3)}. Great?I like them!") } + it { is_expected.to eq("This content references the following proposals: #{resource_as_html_link(proposal1)}, #{resource_as_html_link(proposal2)} and #{resource_as_html_link(proposal3)}. Great?I like them!") } end end diff --git a/spec/proposals/lib/decidim/proposals/component_spec.rb b/spec/proposals/lib/decidim/proposals/component_spec.rb index 2371a8e..2836f53 100644 --- a/spec/proposals/lib/decidim/proposals/component_spec.rb +++ b/spec/proposals/lib/decidim/proposals/component_spec.rb @@ -12,7 +12,7 @@ it "destroys the component" do expect do Decidim::Admin::DestroyComponent.call(component, current_user) - end.to change { Decidim::Component.count }.by(-1) + end.to change(Decidim::Component, :count).by(-1) expect(component).to be_destroyed end diff --git a/spec/proposals/lib/decidim/proposals/import/proposal_answer_creator_spec.rb b/spec/proposals/lib/decidim/proposals/import/proposal_answer_creator_spec.rb index 8266c26..55da98f 100644 --- a/spec/proposals/lib/decidim/proposals/import/proposal_answer_creator_spec.rb +++ b/spec/proposals/lib/decidim/proposals/import/proposal_answer_creator_spec.rb @@ -62,7 +62,7 @@ it "does not produce a record" do record = subject.produce - expect(record).to be(nil) + expect(record).to be_nil end end end diff --git a/spec/proposals/permissions/decidim/proposals/admin/permissions_spec.rb b/spec/proposals/permissions/decidim/proposals/admin/permissions_spec.rb index 6cf6bfa..1cba9a7 100644 --- a/spec/proposals/permissions/decidim/proposals/admin/permissions_spec.rb +++ b/spec/proposals/permissions/decidim/proposals/admin/permissions_spec.rb @@ -37,7 +37,7 @@ let(:component_settings_participatory_texts_enabled?) { false } let(:current_settings_proposal_answering_enabled?) { true } let(:current_settings_publish_answers_immediately?) { true } - let(:permission_action) { Decidim::PermissionAction.new(action) } + let(:permission_action) { Decidim::PermissionAction.new(**action) } shared_examples "can create proposal notes" do describe "proposal note creation" do @@ -46,7 +46,7 @@ end context "when the space allows it" do - it { is_expected.to eq true } + it { is_expected.to be true } end end end @@ -58,19 +58,19 @@ end context "when everything is OK" do - it { is_expected.to eq true } + it { is_expected.to be true } end context "when answering is disabled in the step level" do let(:current_settings_proposal_answering_enabled?) { false } - it { is_expected.to eq false } + it { is_expected.to be false } end context "when answering is disabled in the component level" do let(:component_settings_proposal_answering_enabled?) { false } - it { is_expected.to eq false } + it { is_expected.to be false } end end end @@ -82,7 +82,7 @@ end context "when everything is OK" do - it { is_expected.to eq true } + it { is_expected.to be true } end end end @@ -109,7 +109,7 @@ end let(:extra_context) { { valuator: user } } - it { is_expected.to eq true } + it { is_expected.to be true } end end end @@ -124,19 +124,19 @@ end context "when everything is OK" do - it { is_expected.to eq true } + it { is_expected.to be true } end context "when creation is disabled" do let(:creation_enabled?) { false } - it { is_expected.to eq false } + it { is_expected.to be false } end context "when official proposals are disabled" do let(:official_proposals_enabled?) { false } - it { is_expected.to eq false } + it { is_expected.to be false } end context "when participatory texts is enabled" do @@ -161,7 +161,7 @@ let(:proposal) { create :proposal, :official, component: current_component } context "when everything is OK" do - it { is_expected.to eq true } + it { is_expected.to be true } end context "when it has some votes" do @@ -179,7 +179,7 @@ { scope: :admin, action: :update, subject: :proposal_category } end - it { is_expected.to eq true } + it { is_expected.to be true } end describe "import proposals from another component" do @@ -187,7 +187,7 @@ { scope: :admin, action: :import, subject: :proposals } end - it { is_expected.to eq true } + it { is_expected.to be true } end describe "split proposals" do @@ -195,7 +195,7 @@ { scope: :admin, action: :split, subject: :proposals } end - it { is_expected.to eq true } + it { is_expected.to be true } end describe "merge proposals" do @@ -203,7 +203,7 @@ { scope: :admin, action: :merge, subject: :proposals } end - it { is_expected.to eq true } + it { is_expected.to be true } end describe "proposal answers publishing" do @@ -212,12 +212,12 @@ { scope: :admin, action: :publish_answers, subject: :proposals } end - it { is_expected.to eq false } + it { is_expected.to be false } context "when user is an admin" do let(:user) { create(:user, :admin) } - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -226,7 +226,7 @@ { scope: :admin, action: :assign_to_valuator, subject: :proposals } end - it { is_expected.to eq true } + it { is_expected.to be true } end describe "unassign proposals from a valuator" do @@ -234,7 +234,7 @@ { scope: :admin, action: :unassign_from_valuator, subject: :proposals } end - it { is_expected.to eq true } + it { is_expected.to be true } end describe "manage participatory texts" do @@ -243,6 +243,6 @@ { scope: :admin, action: :manage, subject: :participatory_texts } end - it { is_expected.to eq true } + it { is_expected.to be true } end end diff --git a/spec/proposals/permissions/decidim/proposals/permissions_spec.rb b/spec/proposals/permissions/decidim/proposals/permissions_spec.rb index 8749e13..dd64033 100644 --- a/spec/proposals/permissions/decidim/proposals/permissions_spec.rb +++ b/spec/proposals/permissions/decidim/proposals/permissions_spec.rb @@ -28,7 +28,7 @@ } end let(:extra_settings) { {} } - let(:permission_action) { Decidim::PermissionAction.new(action) } + let(:permission_action) { Decidim::PermissionAction.new(**action) } context "when scope is admin" do let(:action) do @@ -62,13 +62,13 @@ context "when creation is disabled" do let(:extra_settings) { { creation_enabled?: false } } - it { is_expected.to eq false } + it { is_expected.to be false } end context "when user is authorized" do let(:extra_settings) { { creation_enabled?: true } } - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -84,13 +84,13 @@ context "when proposal is editable" do let(:editable) { true } - it { is_expected.to eq true } + it { is_expected.to be true } end context "when proposal is not editable" do let(:editable) { false } - it { is_expected.to eq false } + it { is_expected.to be false } end end @@ -100,13 +100,13 @@ end context "when proposal author is the user trying to withdraw" do - it { is_expected.to eq true } + it { is_expected.to be true } end context "when trying by another user" do let(:user) { build :user } - it { is_expected.to eq false } + it { is_expected.to be false } end end @@ -123,7 +123,7 @@ } end - it { is_expected.to eq false } + it { is_expected.to be false } end context "when votes are blocked" do @@ -134,7 +134,7 @@ } end - it { is_expected.to eq false } + it { is_expected.to be false } end context "when the user has no more remaining votes" do @@ -151,7 +151,7 @@ create :proposal_vote, author: user, proposal: proposals[1] end - it { is_expected.to eq false } + it { is_expected.to be false } end context "when the user is authorized" do @@ -162,7 +162,7 @@ } end - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -179,7 +179,7 @@ } end - it { is_expected.to eq false } + it { is_expected.to be false } end context "when votes are blocked" do @@ -190,7 +190,7 @@ } end - it { is_expected.to eq false } + it { is_expected.to be false } end context "when the user is authorized" do @@ -201,7 +201,7 @@ } end - it { is_expected.to eq true } + it { is_expected.to be true } end end @@ -217,7 +217,7 @@ } end - it { is_expected.to eq false } + it { is_expected.to be false } end context "when the user is authorized" do @@ -227,7 +227,7 @@ } end - it { is_expected.to eq true } + it { is_expected.to be true } end end end diff --git a/spec/proposals/services/decidim/proposals/proposal_search_spec.rb b/spec/proposals/services/decidim/proposals/proposal_search_spec.rb index 8af0aee..178615e 100644 --- a/spec/proposals/services/decidim/proposals/proposal_search_spec.rb +++ b/spec/proposals/services/decidim/proposals/proposal_search_spec.rb @@ -3,166 +3,178 @@ require "spec_helper" module Decidim - module Proposals - describe ProposalSearch do - subject { described_class.new(params).results } - - let(:component) { create(:extended_proposal_component) } - let(:default_params) { { component: component, user: user } } - let(:params) { default_params } - let(:participatory_process) { component.participatory_space } - let(:user) { create(:user, organization: component.organization) } - - it_behaves_like "a resource search", :extended_proposal - it_behaves_like "a resource search with scopes", :extended_proposal - it_behaves_like "a resource search with categories", :extended_proposal - it_behaves_like "a resource search with origin", :extended_proposal - - describe "results" do - let!(:proposal) { create(:extended_proposal, component: component) } - - describe "search_text filter" do - let(:params) { default_params.merge(search_text: search_text) } - let(:search_text) { "dog" } - - it "returns the proposals containing the search in the title or the body" do - create_list(:extended_proposal, 3, component: component) - create(:extended_proposal, title: "A dog", component: component) - create(:extended_proposal, body: "There is a dog in the office", component: component) - - expect(subject.size).to eq(2) - end - end - - describe "activity filter" do - let(:params) { default_params.merge(activity: activity) } - - context "when filtering by supported" do - let(:activity) { "voted" } + describe Search do + subject { described_class.new(params) } + + include_context "when a resource is ready for global search" + + let(:participatory_space) { create(:participatory_process, :published, :with_steps, organization: organization) } + let(:current_component) { create :extended_proposal_component, organization: organization, participatory_space: participatory_space } + let!(:proposal) do + create( + :proposal, + :draft, + skip_injection: true, + component: current_component, + scope: scope1, + body: description1, + users: [author] + ) + end - it "returns the proposals voted by the user" do - create_list(:extended_proposal, 3, component: component) - create(:proposal_vote, proposal: Proposal.first, author: user) + describe "Indexing of proposals" do + context "when implementing Searchable" do + context "when on create" do + context "when proposals are NOT official" do + let(:proposal2) do + create(:proposal, skip_injection: true, component: current_component) + end - expect(subject.size).to eq(1) + it "does not index a SearchableResource after Proposal creation when it is not official" do + searchables = SearchableResource.where(resource_type: proposal.class.name, resource_id: [proposal.id, proposal2.id]) + expect(searchables).to be_empty end end - context "when filtering by my proposals" do - let(:activity) { "my_proposals" } + context "when proposals ARE official" do + let(:author) { organization } - it "returns the proposals created by the user" do - create_list(:extended_proposal, 3, component: component) - create(:extended_proposal, component: component, users: [user]) + before do + proposal.update(published_at: Time.current) + end - expect(subject.size).to eq(1) + it "does indexes a SearchableResource after Proposal creation when it is official" do + organization.available_locales.each do |locale| + searchable = SearchableResource.find_by(resource_type: proposal.class.name, resource_id: proposal.id, locale: locale) + expect_searchable_resource_to_correspond_to_proposal(searchable, proposal, locale) + end end end end - describe "state filter" do - let(:params) { default_params.merge(state: states) } - - context "when filtering for default states" do - let(:states) { [] } - - it "returns all except withdrawn proposals" do - create_list(:extended_proposal, 3, :withdrawn, component: component) - other_proposals = create_list(:extended_proposal, 3, component: component) - other_proposals << proposal - - expect(subject.size).to eq(4) - expect(subject).to match_array(other_proposals) + context "when on update" do + context "when it is NOT published" do + it "does not index a SearchableResource when Proposal changes but is not published" do + searchables = SearchableResource.where(resource_type: proposal.class.name, resource_id: proposal.id) + expect(searchables).to be_empty end end - context "when filtering :except_rejected proposals" do - let(:states) { %w(accepted evaluating state_not_published) } - - it "hides withdrawn and rejected proposals" do - create(:extended_proposal, :withdrawn, component: component) - create(:extended_proposal, :rejected, component: component) - accepted_proposal = create(:extended_proposal, :accepted, component: component) + context "when it IS published" do + before do + proposal.update published_at: Time.current + end - expect(subject.size).to eq(2) - expect(subject).to match_array([accepted_proposal, proposal]) + it "inserts a SearchableResource after Proposal is published" do + organization.available_locales.each do |locale| + searchable = SearchableResource.find_by(resource_type: proposal.class.name, resource_id: proposal.id, locale: locale) + expect_searchable_resource_to_correspond_to_proposal(searchable, proposal, locale) + end end - end - context "when filtering accepted proposals" do - let(:states) { %w(accepted) } + it "updates the associated SearchableResource after published Proposal update" do + searchable = SearchableResource.find_by(resource_type: proposal.class.name, resource_id: proposal.id) + created_at = searchable.created_at + updated_title = { "en" => "Brand new title", "machine_translations" => {} } + proposal.update(title: updated_title) - it "returns only accepted proposals" do - accepted_proposals = create_list(:extended_proposal, 3, :accepted, component: component) - create_list(:extended_proposal, 3, component: component) + proposal.save! + searchable.reload - expect(subject.size).to eq(3) - expect(subject).to match_array(accepted_proposals) + organization.available_locales.each do |locale| + searchable = SearchableResource.find_by(resource_type: proposal.class.name, resource_id: proposal.id, locale: locale) + expect(searchable.content_a).to eq updated_title[locale.to_s].to_s + expect(searchable.updated_at).to be > created_at + end end - end - - context "when filtering rejected proposals" do - let(:states) { %w(rejected) } - it "returns only rejected proposals" do - create_list(:extended_proposal, 3, component: component) - rejected_proposals = create_list(:extended_proposal, 3, :rejected, component: component) + it "removes the associated SearchableResource after unpublishing a published Proposal on update" do + proposal.update(published_at: nil) - expect(subject.size).to eq(3) - expect(subject).to match_array(rejected_proposals) + searchables = SearchableResource.where(resource_type: proposal.class.name, resource_id: proposal.id) + expect(searchables).to be_empty end end + end - context "when filtering withdrawn proposals" do - let(:params) { default_params.merge(state_withdraw: state_withdraw) } - let(:state_withdraw) { "withdrawn" } + context "when on destroy" do + it "destroys the associated SearchableResource after Proposal destroy" do + proposal.destroy - it "returns only withdrawn proposals" do - create_list(:extended_proposal, 3, component: component) - withdrawn_proposals = create_list(:extended_proposal, 3, :withdrawn, component: component) + searchables = SearchableResource.where(resource_type: proposal.class.name, resource_id: proposal.id) - expect(subject.size).to eq(3) - expect(subject).to match_array(withdrawn_proposals) - end + expect(searchables.any?).to be false end end + end + end - describe "related_to filter" do - let(:params) { default_params.merge(related_to: related_to) } - - context "when filtering by related to meetings" do - let(:related_to) { "Decidim::Meetings::Meeting".underscore } - let(:meetings_component) { create(:component, manifest_name: "meetings", participatory_space: participatory_process) } - let(:meeting) { create :meeting, component: meetings_component } + describe "Search" do + context "when searching by Proposal resource_type" do + let!(:proposal2) do + create( + :proposal, + component: current_component, + scope: scope1, + title: Decidim::Faker.name, + body: "Chewie, I'll be waiting for your signal. Take care, you two. May the Force be with you. Ow!" + ) + end - it "returns only proposals related to meetings" do - related_proposal = create(:extended_proposal, :accepted, component: component) - related_proposal2 = create(:extended_proposal, :accepted, component: component) - create_list(:extended_proposal, 3, component: component) - meeting.link_resources([related_proposal], "proposals_from_meeting") - related_proposal2.link_resources([meeting], "proposals_from_meeting") + before do + proposal.update(published_at: Time.current) + proposal2.update(published_at: Time.current) + end - expect(subject).to match_array([related_proposal, related_proposal2]) + it "returns Proposal results" do + Decidim::Search.call("Ow", organization, resource_type: proposal.class.name) do + on(:ok) do |results_by_type| + results = results_by_type[proposal.class.name] + expect(results[:count]).to eq 2 + expect(results[:results]).to match_array [proposal, proposal2] end + on(:invalid) { raise("Should not happen") } end + end - context "when filtering by related to resources" do - let(:related_to) { "Decidim::DummyResources::DummyResource".underscore } - let(:dummy_component) { create(:component, manifest_name: "dummy", participatory_space: participatory_process) } - let(:dummy_resource) { create :dummy_resource, component: dummy_component } - - it "returns only proposals related to results" do - related_proposal = create(:extended_proposal, :accepted, component: component) - related_proposal2 = create(:extended_proposal, :accepted, component: component) - create_list(:extended_proposal, 3, component: component) - dummy_resource.link_resources([related_proposal], "included_proposals") - related_proposal2.link_resources([dummy_resource], "included_proposals") - - expect(subject).to match_array([related_proposal, related_proposal2]) + it "allows searching by prefix characters" do + Decidim::Search.call("wait", organization, resource_type: proposal.class.name) do + on(:ok) do |results_by_type| + results = results_by_type[proposal.class.name] + expect(results[:count]).to eq 1 + expect(results[:results]).to eq [proposal2] end + on(:invalid) { raise("Should not happen") } end end end end + + private + + def expect_searchable_resource_to_correspond_to_proposal(searchable, proposal, locale) + attrs = searchable.attributes.clone + attrs.delete("id") + attrs.delete("created_at") + attrs.delete("updated_at") + expect(attrs.delete("datetime").to_s(:short)).to eq(proposal.published_at.to_s(:short)) + expect(attrs).to eq(expected_searchable_resource_attrs(proposal, locale)) + end + + def expected_searchable_resource_attrs(proposal, locale) + { + "content_a" => I18n.transliterate(translated(proposal.title, locale: locale)), + "content_b" => "", + "content_c" => "", + "content_d" => I18n.transliterate(translated(proposal.body, locale: locale)), + "locale" => locale, + "decidim_organization_id" => proposal.component.organization.id, + "decidim_participatory_space_id" => current_component.participatory_space_id, + "decidim_participatory_space_type" => current_component.participatory_space_type, + "decidim_scope_id" => proposal.decidim_scope_id, + "resource_id" => proposal.id, + "resource_type" => "Decidim::Proposals::Proposal" + } + end end end diff --git a/spec/proposals/shared/admin_manages_proposal_answer_imports_examples.rb b/spec/proposals/shared/admin_manages_proposal_answer_imports_examples.rb index 93941c1..25e42c5 100644 --- a/spec/proposals/shared/admin_manages_proposal_answer_imports_examples.rb +++ b/spec/proposals/shared/admin_manages_proposal_answer_imports_examples.rb @@ -13,12 +13,12 @@ it "returns error without a file" do click_button "Import" - expect(page).to have_content("There was a problem during the import") + expect(page).to have_content("There's an error in this field") end it "adds proposal answers after succesfully import" do File.write(json_file, JSON.pretty_generate(answers)) - attach_file(:import_file, json_file) + dynamically_attach_file(:import_file, json_file) expect(Decidim::Proposals::Admin::NotifyProposalAnswer).to receive(:call).exactly(amount).times @@ -35,7 +35,7 @@ it "doesnt accept file without required headers" do File.write(json_file, JSON.pretty_generate(missing_answers)) - attach_file(:import_file, json_file) + dynamically_attach_file(:import_file, json_file) click_button "Import" expect(page).to have_content("Missing column answer/en. Please check that the file contains required columns.") end @@ -57,7 +57,7 @@ it "adds proposal answers after succesfully import" do File.write(json_file, JSON.pretty_generate(answers)) - attach_file(:import_file, json_file) + dynamically_attach_file(:import_file, json_file) expect(Decidim::Proposals::Admin::NotifyProposalAnswer).to receive(:call).exactly(amount).times diff --git a/spec/proposals/shared/import_proposals_examples.rb b/spec/proposals/shared/import_proposals_examples.rb index 6942e4e..ab13d0c 100644 --- a/spec/proposals/shared/import_proposals_examples.rb +++ b/spec/proposals/shared/import_proposals_examples.rb @@ -37,7 +37,7 @@ end it "imports from a csv file" do - attach_file("proposals_file_import_file", Decidim::Dev.asset("import_proposals.csv")) + dynamically_attach_file(:proposals_file_import_file, Decidim::Dev.asset("import_proposals.csv")) click_button "Import" confirm_flash_message @@ -45,7 +45,7 @@ end it "imports from a json file" do - attach_file("proposals_file_import_file", Decidim::Dev.asset("import_proposals.json")) + dynamically_attach_file(:proposals_file_import_file, Decidim::Dev.asset("import_proposals.json")) click_button "Import" @@ -54,7 +54,7 @@ end it "imports from a excel file" do - attach_file("proposals_file_import_file", Decidim::Dev.asset("import_proposals.xlsx")) + dynamically_attach_file(:proposals_file_import_file, Decidim::Dev.asset("import_proposals.xlsx")) click_button "Import" diff --git a/spec/proposals/shared/manage_proposals_examples.rb b/spec/proposals/shared/manage_proposals_examples.rb index d43e4d8..ec95224 100644 --- a/spec/proposals/shared/manage_proposals_examples.rb +++ b/spec/proposals/shared/manage_proposals_examples.rb @@ -231,7 +231,11 @@ fill_in_i18n :proposal_title, "#proposal-title-tabs", en: "Proposal with attachments" fill_in_i18n_editor :proposal_body, "#proposal-body-tabs", en: "This is my proposal and I want to upload attachments." fill_in :proposal_attachment_title, with: "My attachment" - attach_file :proposal_attachment_file, Decidim::Dev.asset("city.jpeg") + end + + dynamically_attach_file(:proposal_photos, Decidim::Dev.asset("city.jpeg")) + + within ".new_proposal" do find("*[type=submit]").click end @@ -415,8 +419,8 @@ end proposal.reload - expect(proposal.answered_at).to eq(nil) - expect(proposal.state_published_at).to eq(nil) + expect(proposal.answered_at).to be_nil + expect(proposal.state_published_at).to be_nil end it "can edit a proposal answer" do diff --git a/spec/proposals/shared/proposal_form_examples.rb b/spec/proposals/shared/proposal_form_examples.rb index 605275e..8ae0145 100644 --- a/spec/proposals/shared/proposal_form_examples.rb +++ b/spec/proposals/shared/proposal_form_examples.rb @@ -76,9 +76,9 @@ it "only adds errors to this field" do subject.valid? if options[:i18n] - expect(subject.errors.keys).to eq [:title_en] + expect(subject.errors.attribute_names).to eq [:title_en] else - expect(subject.errors.keys).to eq [:title] + expect(subject.errors.attribute_names).to eq [:title] end end end @@ -154,9 +154,9 @@ context "when the address is not present" do it "does not store the coordinates" do expect(subject).to be_valid - expect(subject.address).to be(nil) - expect(subject.latitude).to be(nil) - expect(subject.longitude).to be(nil) + expect(subject.address).to be_nil + expect(subject.latitude).to be_nil + expect(subject.longitude).to be_nil end end @@ -181,8 +181,8 @@ it "is valid" do expect(subject).to be_valid - expect(subject.latitude).to eq(nil) - expect(subject.longitude).to eq(nil) + expect(subject.latitude).to be_nil + expect(subject.longitude).to be_nil end end @@ -240,13 +240,13 @@ context "when the category does not exist" do let(:category_id) { 7654 } - it { is_expected.to eq(nil) } + it { is_expected.to be_nil } end context "when the category is from another process" do let(:category_id) { create(:category).id } - it { is_expected.to eq(nil) } + it { is_expected.to be_nil } end end @@ -290,10 +290,10 @@ if options[:i18n] expect(subject.errors.full_messages).to match_array(["Title en can't be blank", "Add photos Needs to be reattached"]) - expect(subject.errors.keys).to match_array([:title_en, :add_photos]) + expect(subject.errors.attribute_names).to match_array([:title_en, :add_photos]) else expect(subject.errors.full_messages).to match_array(["Title can't be blank", "Title is too short (under 15 characters)", "Add photos Needs to be reattached"]) - expect(subject.errors.keys).to match_array([:title, :add_photos]) + expect(subject.errors.attribute_names).to match_array([:title, :add_photos]) end end end diff --git a/spec/proposals/shared/proposals_wizards_examples.rb b/spec/proposals/shared/proposals_wizards_examples.rb index 5782c87..adaa8a3 100644 --- a/spec/proposals/shared/proposals_wizards_examples.rb +++ b/spec/proposals/shared/proposals_wizards_examples.rb @@ -338,7 +338,6 @@ end end - # rubocop:disable RSpec/EmptyExampleGroup context "when creating a new proposal" do before do login_as user, scope: :user @@ -349,5 +348,4 @@ it_behaves_like "with address" if options[:with_address] it_behaves_like "without address" unless options[:with_address] end - # rubocop:enable RSpec/EmptyExampleGroup end diff --git a/spec/proposals/system/admin/admin_manages_participatory_texts_spec.rb b/spec/proposals/system/admin/admin_manages_participatory_texts_spec.rb index ef86128..265ee11 100644 --- a/spec/proposals/system/admin/admin_manages_participatory_texts_spec.rb +++ b/spec/proposals/system/admin/admin_manages_participatory_texts_spec.rb @@ -42,7 +42,7 @@ def import_document en: "The description of some participatory text", es: "La descripción de algún texto participativo" ) - attach_file :import_participatory_text_document, Decidim::Dev.asset("participatory_text.md") + dynamically_attach_file(:import_participatory_text_document, Decidim::Dev.asset("participatory_text.md")) click_button "Upload document" expect(page).to have_content "The following sections have been converted to proposals. Now you can review and adjust them before publishing." expect(page).to have_content "Preview participatory text" diff --git a/spec/proposals/system/admin/import_proposal_answers_spec.rb b/spec/proposals/system/admin/import_proposal_answers_spec.rb index bab992f..1a7466b 100644 --- a/spec/proposals/system/admin/import_proposal_answers_spec.rb +++ b/spec/proposals/system/admin/import_proposal_answers_spec.rb @@ -29,7 +29,7 @@ id: proposal.id, state: %w(accepted rejected evaluating).sample, "answer/fi": Faker::Lorem.sentence, - "hello": "world" + hello: "world" } end end diff --git a/spec/proposals/system/admin/import_proposals_spec.rb b/spec/proposals/system/admin/import_proposals_spec.rb index c2c9d1a..dc1d35d 100644 --- a/spec/proposals/system/admin/import_proposals_spec.rb +++ b/spec/proposals/system/admin/import_proposals_spec.rb @@ -26,18 +26,18 @@ it "returns error without a file" do click_button "Import" - expect(page).to have_content("There was a problem during the import") + expect(page).to have_content("There's an error in this field") end it "doesnt change proposal amount if one imported row fails" do - attach_file :proposals_file_import_file, Decidim::Dev.asset("import_proposals_broken.csv") + dynamically_attach_file(:proposals_file_import_file, Decidim::Dev.asset("import_proposals_broken.csv")) click_button "Import" expect(page).to have_content("Found an error in the import file on line 4") expect(Decidim::Proposals::Proposal.count).to eq(0) end it "creates proposals after succesfully import" do - attach_file :proposals_file_import_file, Decidim::Dev.asset("import_proposals.csv") + dynamically_attach_file(:proposals_file_import_file, Decidim::Dev.asset("import_proposals.csv")) click_button "Import" expect(page).to have_content("3 proposals successfully imported") expect(Decidim::Proposals::Proposal.count).to eq(3) @@ -60,7 +60,7 @@ it "links proposal to user group during the import" do page.find("#proposals_file_import_user_group_id").click select user_group.name, from: "proposals_file_import_user_group_id" - attach_file :proposals_file_import_file, Decidim::Dev.asset("import_proposals.csv") + dynamically_attach_file(:proposals_file_import_file, Decidim::Dev.asset("import_proposals.csv")) click_button "Import" expect(page).to have_content("3 proposals successfully imported") expect(Decidim::Proposals::Proposal.last.user_groups.count).to eq(1) diff --git a/spec/proposals/system/admin/index_proposal_notes_spec.rb b/spec/proposals/system/admin/index_proposal_notes_spec.rb index b033213..9aa86ef 100644 --- a/spec/proposals/system/admin/index_proposal_notes_spec.rb +++ b/spec/proposals/system/admin/index_proposal_notes_spec.rb @@ -40,7 +40,7 @@ end context "when the form has a text inside body" do - it "creates a proposal note ", :slow do + it "creates a proposal note", :slow do within ".new_proposal_note" do fill_in :proposal_note_body, with: body diff --git a/spec/proposals/system/admin/view_proposal_details_from_admin_spec.rb b/spec/proposals/system/admin/view_proposal_details_from_admin_spec.rb index e19b7fa..f53b4ca 100644 --- a/spec/proposals/system/admin/view_proposal_details_from_admin_spec.rb +++ b/spec/proposals/system/admin/view_proposal_details_from_admin_spec.rb @@ -209,9 +209,7 @@ go_to_admin_proposal_page(proposal) - within "#related-meetings" do - expect(page).not_to have_selector("a", text: translated(moderated_meeting.title)) - end + expect(page).not_to have_content "Related meetings" end end @@ -230,6 +228,7 @@ context "with attached photos" do it "lists the documents" do image = create :attachment, :with_image, attached_to: proposal + image.reload go_to_admin_proposal_page(proposal) within "#photos" do diff --git a/spec/proposals/system/collaborative_drafts_fields_spec.rb b/spec/proposals/system/collaborative_drafts_fields_spec.rb index 0fef335..96237bb 100644 --- a/spec/proposals/system/collaborative_drafts_fields_spec.rb +++ b/spec/proposals/system/collaborative_drafts_fields_spec.rb @@ -325,8 +325,11 @@ within ".new_collaborative_draft" do fill_in :collaborative_draft_title, with: "Collaborative draft with attachments" fill_in :collaborative_draft_body, with: "This is my collaborative draft and I want to upload attachments." - fill_in :collaborative_draft_attachment_title, with: "My attachment" - attach_file :collaborative_draft_attachment_file, Decidim::Dev.asset("city.jpeg") + end + + dynamically_attach_file(:collaborative_draft_documents, Decidim::Dev.asset("city.jpeg"), { title: "My attachment" }) + + within ".new_collaborative_draft" do find("*[type=submit]").click end diff --git a/spec/proposals/system/collaborative_drafts_spec.rb b/spec/proposals/system/collaborative_drafts_spec.rb index dd93699..4634ac8 100644 --- a/spec/proposals/system/collaborative_drafts_spec.rb +++ b/spec/proposals/system/collaborative_drafts_spec.rb @@ -53,7 +53,7 @@ expect(page).to have_css(".success.card__text--status", text: "OPEN") end within ".filters" do - expect(find(:css, "input[name='filter[state][]'][value='open']")).to be_checked + expect(find(:css, "input[name='filter[with_any_state][]'][value='open']")).to be_checked end end @@ -67,7 +67,7 @@ end it "shows state filters" do - within ".filters .state_check_boxes_tree_filter" do + within ".filters .with_any_state_check_boxes_tree_filter" do expect(page).to have_field("All") expect(page).to have_field("Open") expect(page).to have_field("Withdrawn") @@ -76,7 +76,7 @@ end it "shows category filters" do - within ".filters .category_id_check_boxes_tree_filter" do + within ".filters .with_any_category_check_boxes_tree_filter" do expect(page).to have_field("All") [category, category2, category3].each do |cat| expect(page).to have_field(cat.name[I18n.locale.to_s]) diff --git a/spec/proposals/system/edit_collaborative_draft_spec.rb b/spec/proposals/system/edit_collaborative_draft_spec.rb index 00674dd..8341bf3 100644 --- a/spec/proposals/system/edit_collaborative_draft_spec.rb +++ b/spec/proposals/system/edit_collaborative_draft_spec.rb @@ -60,11 +60,9 @@ click_link collaborative_draft.title click_link "Edit collaborative draft" - expect(page).to have_css "#collaborative_draft_attachment_file" + dynamically_attach_file(:collaborative_draft_documents, Decidim::Dev.asset("city.jpeg"), { title: "My attachment" }) within "form.edit_collaborative_draft" do - fill_in :collaborative_draft_attachment_title, with: "My attachment" - attach_file :collaborative_draft_attachment_file, Decidim::Dev.asset("city.jpeg") find("*[type=submit]").click end @@ -99,7 +97,7 @@ click_button "Send" end - expect(page).to have_content("At least 15 characters", count: 2) + expect(page).to have_content("At least 15 characters", count: 4) within "form.edit_collaborative_draft" do fill_in :collaborative_draft_body, with: "WE DO NOT WANT TO SHOUT IN THE PROPOSAL BODY TEXT!" diff --git a/spec/proposals/system/edit_proposal_spec.rb b/spec/proposals/system/edit_proposal_spec.rb index 6d8f9ee..c3c345f 100644 --- a/spec/proposals/system/edit_proposal_spec.rb +++ b/spec/proposals/system/edit_proposal_spec.rb @@ -50,8 +50,8 @@ def visit_proposal context "with attachments allowed" do let(:component) { create(:extended_proposal_component, :with_attachments_allowed, participatory_space: participatory_process) } - let!(:file) { create(:attachment, :with_pdf, attached_to: proposal) } - let!(:photo) { create(:attachment, :with_image, attached_to: proposal) } + let!(:file) { create(:attachment, :with_pdf, weight: 1, attached_to: proposal) } + let!(:photo) { create(:attachment, :with_image, weight: 0, attached_to: proposal) } it "can delete attachments" do visit_component @@ -60,12 +60,16 @@ def visit_proposal expect(page).to have_content("RELATED IMAGES") click_link "Edit proposal" - within "#attachment_#{file.id}" do - click_button "Delete Document" + click_button "Edit documents" + within ".upload-modal" do + find("button.remove-upload-item").click + click_button "Save" end - within "#attachment_#{photo.id}" do - click_button "Delete Image" + click_button "Edit image" + within ".upload-modal" do + find("button.remove-upload-item").click + click_button "Save" end click_button "Send" @@ -156,7 +160,7 @@ def visit_proposal click_button "Send" end - expect(page).to have_content("At least 15 characters", count: 2) + expect(page).to have_content("At least 15 characters", count: 4) within "form.edit_proposal" do fill_in :proposal_body, with: "WE DO NOT WANT TO SHOUT IN THE PROPOSAL BODY TEXT!" diff --git a/spec/proposals/system/filter_proposals_spec.rb b/spec/proposals/system/filter_proposals_spec.rb index 5b5a260..6c63623 100644 --- a/spec/proposals/system/filter_proposals_spec.rb +++ b/spec/proposals/system/filter_proposals_spec.rb @@ -51,7 +51,7 @@ component: component, scope: scope) visit_component - within ".filters .state_check_boxes_tree_filter" do + within ".filters .with_any_state_check_boxes_tree_filter" do check "All" uncheck "All" check "Custom state" @@ -69,7 +69,7 @@ create(:extended_proposal, :accepted, component: component, scope: scope) visit_component - within ".filters .state_check_boxes_tree_filter" do + within ".filters .with_any_state_check_boxes_tree_filter" do check "All" uncheck "All" check "Accepted" @@ -87,7 +87,7 @@ create(:extended_proposal, :rejected, component: component, scope: scope) visit_component - within ".filters .state_check_boxes_tree_filter" do + within ".filters .with_any_state_check_boxes_tree_filter" do check "All" uncheck "All" check "Rejected" @@ -111,7 +111,7 @@ end it "shows only accepted proposals with published answers" do - within ".filters .state_check_boxes_tree_filter" do + within ".filters .with_any_state_check_boxes_tree_filter" do check "All" uncheck "All" check "Accepted" @@ -126,7 +126,7 @@ end it "shows accepted proposals with not published answers as not answered" do - within ".filters .state_check_boxes_tree_filter" do + within ".filters .with_any_state_check_boxes_tree_filter" do check "All" uncheck "All" check "Not answered" diff --git a/spec/proposals/system/participatory_texts_spec.rb b/spec/proposals/system/participatory_texts_spec.rb index 4af9aa1..f842e4d 100644 --- a/spec/proposals/system/participatory_texts_spec.rb +++ b/spec/proposals/system/participatory_texts_spec.rb @@ -145,11 +145,11 @@ def should_have_proposal(selector, proposal) end context "with existing amendments" do - let!(:emendation_1) { create(:extended_proposal, :published, component: component) } - let!(:amendment_1) { create :amendment, amendable: proposals.first, emendation: emendation_1 } - let!(:emendation_2) { create(:extended_proposal, component: component) } - let!(:amendment_2) { create(:amendment, amendable: proposals.first, emendation: emendation_2) } - let(:user) { amendment_1.amender } + let!(:emendation1) { create(:extended_proposal, :published, component: component) } + let!(:amendment1) { create :amendment, amendable: proposals.first, emendation: emendation1 } + let!(:emendation2) { create(:extended_proposal, component: component) } + let!(:amendment2) { create(:amendment, amendable: proposals.first, emendation: emendation2) } + let(:user) { amendment1.amender } context "when amendment CREATION is enabled" do before { update_step_settings(amendment_creation_enabled: true) } @@ -202,7 +202,7 @@ def should_have_proposal(selector, proposal) before { update_step_settings(amendments_visibility: "all") } context "when the user is logged in" do - let(:user) { amendment_1.amender } + let(:user) { amendment1.amender } before { login_as user, scope: :user } @@ -224,7 +224,7 @@ def should_have_proposal(selector, proposal) before { update_step_settings(amendments_visibility: "participants") } context "when the user is logged in" do - let(:user) { amendment_1.amender } + let(:user) { amendment1.amender } before { login_as user, scope: :user } diff --git a/spec/proposals/system/proposals_fields_spec.rb b/spec/proposals/system/proposals_fields_spec.rb index 00a67ae..5548186 100644 --- a/spec/proposals/system/proposals_fields_spec.rb +++ b/spec/proposals/system/proposals_fields_spec.rb @@ -310,7 +310,11 @@ within ".edit_proposal" do fill_in :proposal_title, with: "Proposal with attachments" fill_in :proposal_body, with: "This is my proposal and I want to upload attachments." - attach_file :proposal_add_photos, Decidim::Dev.asset("city.jpeg") + end + + dynamically_attach_file(:proposal_photos, Decidim::Dev.asset("city.jpeg")) + + within ".edit_proposal" do find("*[type=submit]").click end diff --git a/spec/proposals/system/proposals_spec.rb b/spec/proposals/system/proposals_spec.rb index d8c826a..e17f663 100644 --- a/spec/proposals/system/proposals_spec.rb +++ b/spec/proposals/system/proposals_spec.rb @@ -641,7 +641,7 @@ it "finds the correct proposal" do within "form.new_filter" do - find("input[name='filter[search_text]']", match: :first).set("lorem") + find("input[name='filter[search_text_cont]']", match: :first).set("lorem") find("*[type=submit]").click end diff --git a/spec/proposals/system/search_proposals_spec.rb b/spec/proposals/system/search_proposals_spec.rb index aa18d36..6143cc7 100644 --- a/spec/proposals/system/search_proposals_spec.rb +++ b/spec/proposals/system/search_proposals_spec.rb @@ -11,7 +11,7 @@ end let(:manifest_name) { "proposals" } let!(:searchables) { create_list(:extended_proposal, 3, component: component) } - let!(:term) { translated(searchables.first.title).split(" ").last } + let!(:term) { translated(searchables.first.title).split.last } let(:component) { create(:extended_proposal_component, participatory_space: participatory_process) } let(:hashtag) { "#decidim" } diff --git a/spec/proposals/system/vote_proposal_spec.rb b/spec/proposals/system/vote_proposal_spec.rb index b6e1c56..ab9c1fd 100644 --- a/spec/proposals/system/vote_proposal_spec.rb +++ b/spec/proposals/system/vote_proposal_spec.rb @@ -287,7 +287,7 @@ def expect_page_not_to_include_votes it "cannot be voted" do visit_component - within ".filters .state_check_boxes_tree_filter" do + within ".filters .with_any_state_check_boxes_tree_filter" do check "All" uncheck "All" check "Rejected" diff --git a/spec/proposals/types/integration_schema_spec.rb b/spec/proposals/types/integration_schema_spec.rb index 2aa556d..29a304a 100644 --- a/spec/proposals/types/integration_schema_spec.rb +++ b/spec/proposals/types/integration_schema_spec.rb @@ -8,7 +8,7 @@ include_context "with a graphql decidim component" let(:component_type) { "Proposals" } let!(:current_component) { create :extended_proposal_component, participatory_space: participatory_process } - let!(:proposal) { create(:extended_proposal, :with_votes, :with_endorsements, :citizen_author, component: current_component, category: category) } + let!(:proposal) { create(:extended_proposal, :with_votes, :with_endorsements, :participant_author, component: current_component, category: category) } let!(:amendments) { create_list(:proposal_amendment, 5, amendable: proposal, emendation: proposal) } let(:proposal_single_result) do diff --git a/spec/proposals/types/proposal_type_spec.rb b/spec/proposals/types/proposal_type_spec.rb index bd7b217..880d195 100644 --- a/spec/proposals/types/proposal_type_spec.rb +++ b/spec/proposals/types/proposal_type_spec.rb @@ -53,7 +53,7 @@ module Proposals let(:component) { create(:extended_proposal_component, :with_votes_hidden) } it "returns nil" do - expect(response["voteCount"]).to eq(nil) + expect(response["voteCount"]).to be_nil end end end diff --git a/spec/sortitions/create_sortition_spec.rb b/spec/sortitions/create_sortition_spec.rb index cb8b323..da80fae 100644 --- a/spec/sortitions/create_sortition_spec.rb +++ b/spec/sortitions/create_sortition_spec.rb @@ -65,7 +65,7 @@ module Admin end before do - expect(form).to receive(:invalid?).and_return(false) + allow(form).to receive(:invalid?).and_return(false) end it "broadcasts ok" do @@ -104,7 +104,7 @@ module Admin it "has no category" do command.call sortition = Sortition.where(component: sortition_component).last - expect(sortition.category).to eq(nil) + expect(sortition.category).to be_nil end context "when restricted to a category without proposals" do diff --git a/spec/sortitions/draw_spec.rb b/spec/sortitions/draw_spec.rb index 1c8b530..09d9a41 100644 --- a/spec/sortitions/draw_spec.rb +++ b/spec/sortitions/draw_spec.rb @@ -25,9 +25,10 @@ module Admin decidim_proposals_component: proposal_component ) end + let(:initial_draw) { Draw.for(sortition) } it "Draw can be reproduced several times" do - expect(Draw.for(sortition)).to eq(Draw.for(sortition)) + expect(Draw.for(sortition)).to eq(initial_draw) end end end diff --git a/spec/sortitions/show_spec.rb b/spec/sortitions/show_spec.rb index 9773515..fef6e0f 100644 --- a/spec/sortitions/show_spec.rb +++ b/spec/sortitions/show_spec.rb @@ -62,7 +62,7 @@ let!(:sortition) { create(:sortition, :cancelled, decidim_proposals_component: proposals_component, component: component, witnesses: witnesses, additional_info: additional_info, cancel_reason: cancel_reason) } before do - page.visit "#{main_component_path(component)}?filter[state]=cancelled" + page.visit "#{main_component_path(component)}?filter[with_any_state]=cancelled" click_link "View" end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index eb724a5..cfc1a79 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -11,7 +11,7 @@ require "decidim/comments/test" engine_spec_dir = File.join(Dir.pwd, "spec") -Dir["#{engine_spec_dir}/proposals/shared/**/*.rb"].sort.each { |f| require f } +Dir["#{engine_spec_dir}/proposals/shared/**/*.rb"].each { |f| require f } RSpec.configure do |config| config.backtrace_exclusion_patterns = [