diff --git a/app/components/admin/votation_types/fields_component.rb b/app/components/admin/votation_types/fields_component.rb index a51a795a5..dc2fc09a0 100644 --- a/app/components/admin/votation_types/fields_component.rb +++ b/app/components/admin/votation_types/fields_component.rb @@ -10,7 +10,8 @@ class Admin::VotationTypes::FieldsComponent < ApplicationComponent def descriptions { unique: t("admin.polls.votation_type.unique_description"), - multiple: t("admin.polls.votation_type.multiple_description") + multiple: t("admin.polls.votation_type.multiple_description"), + open: t("admin.polls.votation_type.open_description") } end diff --git a/app/models/poll/question.rb b/app/models/poll/question.rb index 97d1d2c60..d7a8d07e5 100644 --- a/app/models/poll/question.rb +++ b/app/models/poll/question.rb @@ -27,7 +27,7 @@ class Poll::Question < ApplicationRecord accepts_nested_attributes_for :question_options, reject_if: :all_blank, allow_destroy: true accepts_nested_attributes_for :votation_type - delegate :multiple?, :vote_type, to: :votation_type, allow_nil: true + delegate :multiple?, :open?, :vote_type, to: :votation_type, allow_nil: true scope :sort_for_list, -> { order(Arel.sql("poll_questions.proposal_id IS NULL"), :created_at) } scope :for_render, -> { includes(:author, :proposal) } diff --git a/app/models/votation_type.rb b/app/models/votation_type.rb index 71d61c62d..24326204b 100644 --- a/app/models/votation_type.rb +++ b/app/models/votation_type.rb @@ -3,7 +3,7 @@ class VotationType < ApplicationRecord QUESTIONABLE_TYPES = %w[Poll::Question].freeze - enum :vote_type, { unique: 0, multiple: 1 } + enum :vote_type, { unique: 0, multiple: 1, open: 2 } validates :questionable, presence: true validates :questionable_type, inclusion: { in: ->(*) { QUESTIONABLE_TYPES }} diff --git a/config/locales/en/activerecord.yml b/config/locales/en/activerecord.yml index 951fa9168..852155ee5 100644 --- a/config/locales/en/activerecord.yml +++ b/config/locales/en/activerecord.yml @@ -534,6 +534,7 @@ en: max_votes: Maximum number of votes vote_type: Votation type votation_type/vote_type: + open: Open-ended unique: Unique answer multiple: Multiple answers cookies/vendor: diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml index 80289656d..d6917a5e5 100644 --- a/config/locales/en/admin.yml +++ b/config/locales/en/admin.yml @@ -1131,6 +1131,7 @@ en: title: "Votation type" unique_description: "It's only possible to answer one time to the question." multiple_description: "Allows to choose multiple answers. It's possible to set the maximum number of answers." + open_description: "Open-ended question that allows users to provide a single answer in their own words." questions: index: create: "Create question" diff --git a/config/locales/es/activerecord.yml b/config/locales/es/activerecord.yml index 8148cefbd..61e389ee3 100644 --- a/config/locales/es/activerecord.yml +++ b/config/locales/es/activerecord.yml @@ -534,6 +534,7 @@ es: max_votes: Número máximo de votos vote_type: Tipo de votación votation_type/vote_type: + open: Respuesta abierta unique: Respuesta única multiple: Respuesta múltiple cookies/vendor: diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml index 3f7bac10d..8db768fed 100644 --- a/config/locales/es/admin.yml +++ b/config/locales/es/admin.yml @@ -1131,6 +1131,7 @@ es: title: "Tipo de votación" unique_description: "Solo se puede responder a la pregunta con una única respuesta." multiple_description: "Permite elegir más de una respuesta. Se puede elegir el número máximo de respuestas." + open_description: "Pregunta abierta que permite al usuario dar una única respuesta con sus propias palabras." questions: index: create: "Crear pregunta ciudadana" diff --git a/spec/factories/polls.rb b/spec/factories/polls.rb index 358af5e80..155066fd6 100644 --- a/spec/factories/polls.rb +++ b/spec/factories/polls.rb @@ -94,6 +94,12 @@ FactoryBot.define do create(:votation_type_multiple, questionable: question, max_votes: evaluator.max_votes) end end + + factory :poll_question_open do + after(:create) do |question| + create(:votation_type_open, questionable: question) + end + end end factory :poll_question_option, class: "Poll::Question::Option" do diff --git a/spec/factories/votation_type.rb b/spec/factories/votation_type.rb index 5a9e77e7d..ef91b836a 100644 --- a/spec/factories/votation_type.rb +++ b/spec/factories/votation_type.rb @@ -9,6 +9,10 @@ FactoryBot.define do max_votes { 3 } end + factory :votation_type_open do + vote_type { "open" } + end + questionable factory: :poll_question end end diff --git a/spec/models/poll/answer_spec.rb b/spec/models/poll/answer_spec.rb index a70ed3a4d..bc5c50402 100644 --- a/spec/models/poll/answer_spec.rb +++ b/spec/models/poll/answer_spec.rb @@ -30,6 +30,13 @@ describe Poll::Answer do expect(answer).not_to be_valid end + it "is not valid without an answer when question is open-ended" do + answer.question = create(:poll_question_open) + answer.answer = nil + + expect(answer).not_to be_valid + end + it "is not valid if there's already an answer to that question" do author = create(:user) question = create(:poll_question, :yes_no) diff --git a/spec/models/votation_type_spec.rb b/spec/models/votation_type_spec.rb index 4c947ddd6..dac4799cd 100644 --- a/spec/models/votation_type_spec.rb +++ b/spec/models/votation_type_spec.rb @@ -1,7 +1,7 @@ require "rails_helper" describe VotationType do - let(:vote_types) { %i[votation_type_unique votation_type_multiple] } + let(:vote_types) { %i[votation_type_unique votation_type_multiple votation_type_open] } let(:votation_type) { build(vote_types.sample) } it "is valid" do @@ -27,6 +27,10 @@ describe VotationType do expect(votation_type).to be_valid + votation_type.vote_type = "open" + + expect(votation_type).to be_valid + votation_type.vote_type = "multiple" expect(votation_type).not_to be_valid diff --git a/spec/system/admin/poll/questions_spec.rb b/spec/system/admin/poll/questions_spec.rb index 2a504de98..3997c3af7 100644 --- a/spec/system/admin/poll/questions_spec.rb +++ b/spec/system/admin/poll/questions_spec.rb @@ -81,6 +81,8 @@ describe "Admin poll questions", :admin do expect(page).to have_content "It's only possible to answer one time to the question." expect(page).not_to have_content "Allows to choose multiple answers." expect(page).not_to have_field "Maximum number of votes" + expect(page).not_to have_content "Open-ended question that allows users to provide " \ + "a single answer in their own words." click_button "Save" @@ -94,6 +96,8 @@ describe "Admin poll questions", :admin do expect(page).not_to have_content "It's only possible to answer one time to the question." expect(page).to have_content "Allows to choose multiple answers." + expect(page).not_to have_content "Open-ended question that allows users to provide " \ + "a single answer in their own words." fill_in "Maximum number of votes", with: 6 click_button "Save" @@ -101,6 +105,21 @@ describe "Admin poll questions", :admin do expect(page).to have_content "Question with multiple answers" expect(page).to have_content "Multiple answers" end + + scenario "Open-ended" do + fill_in "Question", with: "What do you want?" + select "Open-ended", from: "Votation type" + + expect(page).not_to have_content "Allows to choose multiple answers." + expect(page).not_to have_field "Maximum number of votes" + expect(page).to have_content "Open-ended question that allows users to provide " \ + "a single answer in their own words." + + click_button "Save" + + expect(page).to have_content "What do you want?" + expect(page).to have_content "Open-ended" + end end end @@ -143,7 +162,7 @@ describe "Admin poll questions", :admin do scenario "Update" do poll = create(:poll, :future) - question = create(:poll_question, poll: poll) + question = create(:poll_question_open, poll: poll) old_title = question.title new_title = "Vegetables are great and everyone should have one" @@ -154,6 +173,12 @@ describe "Admin poll questions", :admin do end expect(page).to have_link "Go back", href: admin_poll_path(poll) + expect(page).to have_select "Votation type", selected: "Open-ended" + expect(page).not_to have_content "Allows to choose multiple answers." + expect(page).not_to have_field "Maximum number of votes" + expect(page).to have_content "Open-ended question that allows users to provide " \ + "a single answer in their own words." + fill_in "Question", with: new_title click_button "Save"