decidim-forms 0.21.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/admin/decidim_forms_manifest.js +1 -0
  3. data/app/assets/images/decidim/surveys/icon.svg +1 -19
  4. data/app/assets/javascripts/decidim/forms/admin/collapsible_questions.js.es6 +13 -0
  5. data/app/assets/javascripts/decidim/forms/admin/forms.js.es6 +95 -7
  6. data/app/assets/javascripts/decidim/forms/admin/live_text_update.component.js.es6 +52 -0
  7. data/app/assets/javascripts/decidim/forms/forms.js.es6 +42 -1
  8. data/app/assets/javascripts/decidim/forms/max_choices_alert.component.js.es6 +44 -0
  9. data/app/assets/stylesheets/decidim/forms/forms.scss +39 -0
  10. data/app/cells/decidim/forms/matrix_readonly/show.erb +5 -0
  11. data/app/cells/decidim/forms/matrix_readonly_cell.rb +12 -0
  12. data/app/cells/decidim/forms/question_readonly/show.erb +5 -1
  13. data/app/cells/decidim/forms/question_readonly_cell.rb +5 -0
  14. data/app/cells/decidim/forms/step_navigation/show.erb +35 -0
  15. data/app/cells/decidim/forms/step_navigation_cell.rb +46 -0
  16. data/app/commands/decidim/forms/admin/update_questionnaire.rb +8 -0
  17. data/app/commands/decidim/forms/answer_questionnaire.rb +2 -1
  18. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +6 -2
  19. data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +11 -2
  20. data/app/forms/decidim/forms/admin/question_form.rb +20 -1
  21. data/app/forms/decidim/forms/admin/question_matrix_row_form.rb +26 -0
  22. data/app/forms/decidim/forms/answer_choice_form.rb +1 -0
  23. data/app/forms/decidim/forms/answer_form.rb +16 -2
  24. data/app/forms/decidim/forms/questionnaire_form.rb +25 -3
  25. data/app/helpers/decidim/forms/admin/application_helper.rb +16 -0
  26. data/app/models/decidim/forms/answer_choice.rb +7 -0
  27. data/app/models/decidim/forms/question.rb +18 -2
  28. data/app/models/decidim/forms/question_matrix_row.rb +12 -0
  29. data/app/views/decidim/forms/admin/questionnaires/_answer_option_template.html.erb +1 -1
  30. data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +37 -4
  31. data/app/views/decidim/forms/admin/questionnaires/_matrix_row.html.erb +34 -0
  32. data/app/views/decidim/forms/admin/questionnaires/_matrix_row_template.html.erb +7 -0
  33. data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +29 -6
  34. data/app/views/decidim/forms/admin/questionnaires/_separator.html.erb +41 -0
  35. data/app/views/decidim/forms/questionnaires/_answer.html.erb +21 -92
  36. data/app/views/decidim/forms/questionnaires/answers/_long_answer.html.erb +1 -0
  37. data/app/views/decidim/forms/questionnaires/answers/_matrix_multiple.html.erb +43 -0
  38. data/app/views/decidim/forms/questionnaires/answers/_matrix_single.html.erb +43 -0
  39. data/app/views/decidim/forms/questionnaires/answers/_multiple_option.html.erb +23 -0
  40. data/app/views/decidim/forms/questionnaires/answers/_separator.html.erb +1 -0
  41. data/app/views/decidim/forms/questionnaires/answers/_short_answer.html.erb +1 -0
  42. data/app/views/decidim/forms/questionnaires/answers/_single_option.html.erb +30 -0
  43. data/app/views/decidim/forms/questionnaires/answers/_sorting.html.erb +23 -0
  44. data/app/views/decidim/forms/questionnaires/show.html.erb +57 -25
  45. data/config/locales/ar.yml +7 -3
  46. data/config/locales/bg-BG.yml +16 -0
  47. data/config/locales/ca.yml +35 -3
  48. data/config/locales/cs.yml +35 -3
  49. data/config/locales/da-DK.yml +1 -0
  50. data/config/locales/de.yml +41 -3
  51. data/config/locales/el.yml +119 -0
  52. data/config/locales/en.yml +35 -3
  53. data/config/locales/es-MX.yml +35 -3
  54. data/config/locales/es-PY.yml +35 -3
  55. data/config/locales/es.yml +35 -3
  56. data/config/locales/et-EE.yml +1 -0
  57. data/config/locales/eu.yml +7 -3
  58. data/config/locales/fi-plain.yml +35 -3
  59. data/config/locales/fi.yml +36 -4
  60. data/config/locales/fr-CA.yml +120 -0
  61. data/config/locales/fr.yml +36 -4
  62. data/config/locales/ga-IE.yml +1 -0
  63. data/config/locales/gl.yml +7 -3
  64. data/config/locales/hr-HR.yml +1 -0
  65. data/config/locales/hu.yml +11 -3
  66. data/config/locales/id-ID.yml +7 -3
  67. data/config/locales/it.yml +36 -4
  68. data/config/locales/ja-JP.yml +120 -0
  69. data/config/locales/lt-LT.yml +1 -0
  70. data/config/locales/lv-LV.yml +119 -0
  71. data/config/locales/mt-MT.yml +1 -0
  72. data/config/locales/nl.yml +35 -3
  73. data/config/locales/no.yml +7 -3
  74. data/config/locales/pl.yml +63 -25
  75. data/config/locales/pt-BR.yml +8 -4
  76. data/config/locales/pt.yml +62 -24
  77. data/config/locales/ro-RO.yml +118 -0
  78. data/config/locales/ru.yml +4 -1
  79. data/config/locales/sk-SK.yml +88 -0
  80. data/config/locales/sk.yml +92 -0
  81. data/config/locales/sl.yml +5 -0
  82. data/config/locales/sr-CS.yml +1 -0
  83. data/config/locales/sv.yml +38 -6
  84. data/config/locales/tr-TR.yml +7 -3
  85. data/db/migrate/20200225123810_create_decidim_forms_question_matrix_rows.rb +11 -0
  86. data/db/migrate/20200304152939_add_matrix_row_id_to_decidim_forms_answer_choices.rb +11 -0
  87. data/lib/decidim/forms/test/factories.rb +20 -0
  88. data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +313 -36
  89. data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +346 -15
  90. data/lib/decidim/forms/user_answers_serializer.rb +21 -4
  91. data/lib/decidim/forms/version.rb +1 -1
  92. metadata +45 -8
@@ -13,9 +13,10 @@ ru:
13
13
  remove: Удалить
14
14
  edit:
15
15
  save: Сохранить
16
- title: Заголовок
17
16
  form:
18
17
  add_question: Добавить вопрос
18
+ matrix_row:
19
+ remove: Удалить
19
20
  question:
20
21
  add_answer_option: Добавить вариант ответа
21
22
  any: Любые
@@ -42,4 +43,6 @@ ru:
42
43
  questionnaire_for_private_users:
43
44
  body: Форма доступна только для частных пользователей
44
45
  title: Форма закрыта
46
+ step_navigation:
47
+ show:
45
48
  submit: Отправить
@@ -0,0 +1,88 @@
1
+ sk:
2
+ activemodel:
3
+ attributes:
4
+ answer:
5
+ body: Odpoveď
6
+ question:
7
+ max_choices: Maximálny počet možností
8
+ question_type: Typ
9
+ questionnaire_question:
10
+ mandatory: Povinné
11
+ errors:
12
+ models:
13
+ answer:
14
+ attributes:
15
+ choices:
16
+ missing: nie je kompletné
17
+ too_many: je príliš veľa
18
+ questionnaire:
19
+ request_invalid: Počas požiadavku sa vyskytla chyba, skúste to znova.
20
+ decidim:
21
+ forms:
22
+ admin:
23
+ models:
24
+ components:
25
+ description: Popis
26
+ tos: Podmienky použitia
27
+ questionnaires:
28
+ answer_option:
29
+ answer_option: Možnosť odpovede
30
+ free_text: Voľný text
31
+ remove: Odstrániť
32
+ statement: Prehlásenie
33
+ edit:
34
+ save: Uložiť
35
+ title: Názov
36
+ form:
37
+ add_question: Pridať otázku
38
+ already_answered_warning: Na formulár už niekto odpovedal, takže nemôžete meniť jeho otázky.
39
+ question:
40
+ add_answer_option: Pridať možnosť odpovede
41
+ any: Akékoľvek
42
+ description: Popis
43
+ down: Nadol
44
+ question: Otázka
45
+ remove: Odstrániť
46
+ statement: Prehlásenie
47
+ up: Hore
48
+ update:
49
+ invalid: Vyskytol sa problém s ukladaním formulára.
50
+ success: Formulár úspešne uložený.
51
+ errors:
52
+ answer:
53
+ body: Telo nemôže byť prázdne
54
+ question_types:
55
+ long_answer: Dlhá odpoveď
56
+ multiple_option: Viacero možností
57
+ short_answer: Krátka odpoveď
58
+ single_option: Jedna možnosť
59
+ sorting: Zoradenie
60
+ questionnaires:
61
+ answer:
62
+ invalid: Vyskytol sa problém s odpovedaním na formulár.
63
+ success: Formulár úspešne zodpovedaný.
64
+ question:
65
+ max_choices: 'Maximum možností: %{n}'
66
+ show:
67
+ answer_questionnaire:
68
+ anonymous_user_message: <a href="%{sign_in_link}">Prihláste sa so svojím účtom</a> alebo <a href="%{sign_up_link}"> sa zaregistrujte</a>, aby ste mohli odpovedať.
69
+ title: Odpovedať na formulár
70
+ are_you_sure: Táto akcia sa nedá vrátiť späť, a nebudete môcť upraviť svoje odpovede. Ste si istí?
71
+ questionnaire_answered:
72
+ body: Na tento formulár už ste dopovedali.
73
+ title: Už ste odpovedali
74
+ questionnaire_closed:
75
+ body: Tento formulár je už uzavretý a nedá sa naň odpovedať.
76
+ title: Formulár je uzavretý.
77
+ questionnaire_for_private_users:
78
+ body: Formulár je otvorený len pre súkromných používateľov
79
+ title: Formulár je uzavretý
80
+ submit: Poslať
81
+ tos_agreement: Účasťou súhlasíte s našimi Podmienkami použitia
82
+ user_answers_serializer:
83
+ created_at: Odpovedané na
84
+ id: ID odpovede
85
+ ip_hash: IP Hash
86
+ registered: Registrovaný
87
+ unregistered: Neregistrovaný
88
+ user_status: Status Užívateľa
@@ -0,0 +1,92 @@
1
+ sk:
2
+ activemodel:
3
+ attributes:
4
+ answer:
5
+ body: Odpoveď
6
+ question:
7
+ max_choices: Maximálny počet možností
8
+ question_type: Typ
9
+ questionnaire_question:
10
+ mandatory: Povinné
11
+ errors:
12
+ models:
13
+ answer:
14
+ attributes:
15
+ choices:
16
+ missing: nie je kompletné
17
+ too_many: je príliš veľa
18
+ questionnaire:
19
+ request_invalid: Počas požiadavku sa vyskytla chyba, skúste to znova.
20
+ decidim:
21
+ forms:
22
+ admin:
23
+ models:
24
+ components:
25
+ description: Popis
26
+ tos: Podmienky použitia
27
+ questionnaires:
28
+ answer_option:
29
+ answer_option: Možnosť odpovede
30
+ free_text: Voľný text
31
+ remove: Odstrániť
32
+ statement: Prehlásenie
33
+ edit:
34
+ save: Uložiť
35
+ form:
36
+ add_question: Pridať otázku
37
+ already_answered_warning: Na formulár už niekto odpovedal, takže nemôžete meniť jeho otázky.
38
+ matrix_row:
39
+ remove: Odstrániť
40
+ statement: Prehlásenie
41
+ question:
42
+ add_answer_option: Pridať možnosť odpovede
43
+ any: Akékoľvek
44
+ description: Popis
45
+ down: Nadol
46
+ question: Otázka
47
+ remove: Odstrániť
48
+ statement: Prehlásenie
49
+ up: Hore
50
+ update:
51
+ invalid: Vyskytol sa problém s ukladaním formulára.
52
+ success: Formulár úspešne uložený.
53
+ errors:
54
+ answer:
55
+ body: Telo nemôže byť prázdne
56
+ question_types:
57
+ long_answer: Dlhá odpoveď
58
+ multiple_option: Viacero možností
59
+ short_answer: Krátka odpoveď
60
+ single_option: Jedna možnosť
61
+ sorting: Zoradenie
62
+ questionnaires:
63
+ answer:
64
+ invalid: Vyskytol sa problém s odpovedaním na formulár.
65
+ success: Formulár úspešne zodpovedaný.
66
+ question:
67
+ max_choices: 'Maximum možností: %{n}'
68
+ show:
69
+ answer_questionnaire:
70
+ anonymous_user_message: <a href="%{sign_in_link}">Prihláste sa so svojím účtom</a> alebo <a href="%{sign_up_link}"> sa zaregistrujte</a>, aby ste mohli odpovedať.
71
+ title: Odpovedať na formulár
72
+ questionnaire_answered:
73
+ body: Na tento formulár už ste dopovedali.
74
+ title: Už ste odpovedali
75
+ questionnaire_closed:
76
+ body: Tento formulár je už uzavretý a nedá sa naň odpovedať.
77
+ title: Formulár je uzavretý.
78
+ questionnaire_for_private_users:
79
+ body: Formulár je otvorený len pre súkromných používateľov
80
+ title: Formulár je uzavretý
81
+ tos_agreement: Účasťou súhlasíte s našimi Podmienkami použitia
82
+ step_navigation:
83
+ show:
84
+ are_you_sure: Táto akcia sa nedá vrátiť späť, a nebudete môcť upraviť svoje odpovede. Ste si istí?
85
+ submit: Poslať
86
+ user_answers_serializer:
87
+ created_at: Odpovedané na
88
+ id: ID odpovede
89
+ ip_hash: IP Hash
90
+ registered: Registrovaný
91
+ unregistered: Neregistrovaný
92
+ user_status: Status Užívateľa
@@ -0,0 +1,5 @@
1
+ sl:
2
+ activemodel:
3
+ attributes:
4
+ answer:
5
+ body: Odgovor
@@ -0,0 +1 @@
1
+ sr:
@@ -16,7 +16,7 @@ sv:
16
16
  missing: är inte fullständiga
17
17
  too_many: är för många
18
18
  questionnaire:
19
- request_invalid: Ett fel uppstod när begäran skulle hanteras. Vänligen försök igen
19
+ request_invalid: Ett fel uppstod när begäran skulle hanteras. Försök igen
20
20
  decidim:
21
21
  forms:
22
22
  admin:
@@ -32,27 +32,52 @@ sv:
32
32
  statement: Påstående
33
33
  edit:
34
34
  save: Spara
35
- title: Titel
35
+ title: Redigera frågeformulär
36
36
  form:
37
37
  add_question: Lägg till fråga
38
+ add_separator: Lägg till separator
38
39
  already_answered_warning: Frågeformuläret har redan besvarats av vissa användare så du inte kan ändra dess frågor.
40
+ collapse: Komprimera alla frågor
41
+ expand: Expandera alla frågor
42
+ matrix_row:
43
+ matrix_row: Rad
44
+ remove: Ta bort
45
+ statement: Påstående
39
46
  question:
40
47
  add_answer_option: Lägg till svarsalternativ
48
+ add_matrix_row: Lägg till rad
41
49
  any: Någon
50
+ collapse: Komprimera
42
51
  description: Beskrivning
43
52
  down: Ned
53
+ expand: Expandera
44
54
  question: Fråga
45
55
  remove: Ta bort
46
56
  statement: Påstående
47
57
  up: Upp
58
+ separator:
59
+ down: Ner
60
+ remove: Radera
61
+ separator: Avgränsare
62
+ up: Upp
48
63
  update:
49
64
  invalid: Det gick inte att spara formuläret.
50
65
  success: Formuläret har sparats.
51
66
  errors:
52
67
  answer:
53
68
  body: Kroppen kan inte vara to
69
+ files:
70
+ extension_whitelist: 'Godkända format:'
71
+ images:
72
+ dimensions: "%{width} x %{height} px"
73
+ dimensions_info: 'Denna bild kommer att vara:'
74
+ processors:
75
+ resize_and_pad: Anpassad och vadderad till
76
+ resize_to_fit: Anpassad för att passa
54
77
  question_types:
55
78
  long_answer: Långt svar
79
+ matrix_multiple: Matris (flera alternativ)
80
+ matrix_single: Matris (Single alternativ)
56
81
  multiple_option: Flera alternativ
57
82
  short_answer: Kort svar
58
83
  single_option: Ett alternativ
@@ -60,6 +85,7 @@ sv:
60
85
  questionnaires:
61
86
  answer:
62
87
  invalid: Det gick inte att besvara formuläret.
88
+ max_choices_alert: Det finns för många val valda
63
89
  success: Formuläret har besvarats.
64
90
  question:
65
91
  max_choices: 'Högst antal val: %{n}'
@@ -67,7 +93,8 @@ sv:
67
93
  answer_questionnaire:
68
94
  anonymous_user_message: <a href="%{sign_in_link}">Logga in med ditt konto</a> eller <a href="%{sign_up_link}">registrera dig</a> om du vill svara på formuläret.
69
95
  title: Besvara formuläret
70
- are_you_sure: Den här åtgärden kan inte ångras och du kommer inte att kunna redigera dina svar. Är du säker?
96
+ current_step: Steg %{step}
97
+ of_total_steps: av %{total_steps}
71
98
  questionnaire_answered:
72
99
  body: Du har redan besvarat det här formuläret.
73
100
  title: Redan svarat
@@ -77,12 +104,17 @@ sv:
77
104
  questionnaire_for_private_users:
78
105
  body: Formuläret är endast tillgängligt för privata användare
79
106
  title: Formuläret är stängt
80
- submit: Skicka in
81
107
  tos_agreement: Genom att delta godkänner du användarvillkoren
108
+ step_navigation:
109
+ show:
110
+ are_you_sure: Den här åtgärden kan inte ångras och du kommer inte att kunna redigera dina svar. Är du säker?
111
+ back: Tillbaka
112
+ continue: Fortsätt
113
+ submit: Skicka in
82
114
  user_answers_serializer:
83
115
  created_at: Besvarad
84
116
  id: Svars-ID
85
- ip_hash: Ip Hash
117
+ ip_hash: Ip-hash
86
118
  registered: Registrerad
87
- unregistered: Oregistrerad
119
+ unregistered: Ej registrerad
88
120
  user_status: Användarstatus
@@ -30,10 +30,12 @@ tr:
30
30
  statement: Beyan
31
31
  edit:
32
32
  save: Kayıt etmek
33
- title: Başlık
34
33
  form:
35
34
  add_question: Soru ekle
36
35
  already_answered_warning: Form, bazı kullanıcılar tarafından zaten yanıtlandı, bu nedenle sorularını değiştiremezsiniz.
36
+ matrix_row:
37
+ remove: Kaldır
38
+ statement: Beyan
37
39
  question:
38
40
  add_answer_option: Cevap seçeneği ekle
39
41
  any: herhangi
@@ -65,7 +67,6 @@ tr:
65
67
  answer_questionnaire:
66
68
  anonymous_user_message: <a href="%{sign_in_link}">Formu yanıtlamak için</a> veya <a href="%{sign_up_link}">hesabınızla giriş yapın</a>.
67
69
  title: Formu cevapla
68
- are_you_sure: Bu işlem geri alınamaz ve cevaplarınızı düzenleyemezsiniz. Emin misiniz?
69
70
  questionnaire_answered:
70
71
  body: Bu formu zaten cevapladınız.
71
72
  title: Zaten cevaplandı
@@ -75,8 +76,11 @@ tr:
75
76
  questionnaire_for_private_users:
76
77
  body: Form yalnızca özel kullanıcılar tarafından kullanılabilir
77
78
  title: Form kapatıldı
78
- submit: Gönder
79
79
  tos_agreement: Katılarak Hizmet Şartlarını kabul etmiş olursunuz.
80
+ step_navigation:
81
+ show:
82
+ are_you_sure: Bu işlem geri alınamaz ve cevaplarınızı düzenleyemezsiniz. Emin misiniz?
83
+ submit: Gönder
80
84
  user_answers_serializer:
81
85
  created_at: Yanıtlandı
82
86
  id: Cevap kimliği
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateDecidimFormsQuestionMatrixRows < ActiveRecord::Migration[5.2]
4
+ def change
5
+ create_table :decidim_forms_question_matrix_rows do |t|
6
+ t.references :decidim_question, index: { name: "index_decidim_forms_question_matrix_questionnaire_id" }
7
+ t.integer :position, index: true
8
+ t.jsonb :body
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddMatrixRowIdToDecidimFormsAnswerChoices < ActiveRecord::Migration[5.2]
4
+ class AnswerChoice < ApplicationRecord
5
+ self.table_name = :decidim_forms_answer_choices
6
+ end
7
+
8
+ def change
9
+ add_column :decidim_forms_answer_choices, :decidim_question_matrix_row_id, :integer
10
+ end
11
+ end
@@ -28,6 +28,7 @@ FactoryBot.define do
28
28
  factory :questionnaire_question, class: "Decidim::Forms::Question" do
29
29
  transient do
30
30
  options { [] }
31
+ rows { [] }
31
32
  end
32
33
 
33
34
  body { generate_localized_title }
@@ -50,6 +51,14 @@ FactoryBot.define do
50
51
  )
51
52
  end
52
53
  end
54
+
55
+ if question.matrix_rows.empty?
56
+ evaluator.rows.each do |row|
57
+ question.matrix_rows.build(
58
+ body: row["body"]
59
+ )
60
+ end
61
+ end
53
62
  end
54
63
 
55
64
  trait :with_answer_options do
@@ -57,6 +66,10 @@ FactoryBot.define do
57
66
  Array.new(3).collect { build(:answer_option) }
58
67
  end
59
68
  end
69
+
70
+ trait :separator do
71
+ question_type { :separator }
72
+ end
60
73
  end
61
74
 
62
75
  factory :answer, class: "Decidim::Forms::Answer" do
@@ -75,5 +88,12 @@ FactoryBot.define do
75
88
  factory :answer_choice, class: "Decidim::Forms::AnswerChoice" do
76
89
  answer
77
90
  answer_option { create(:answer_option, question: answer.question) }
91
+ matrix_row { create(:question_matrix_row, question: answer.question) }
92
+ end
93
+
94
+ factory :question_matrix_row, class: "Decidim::Forms::QuestionMatrixRow" do
95
+ question { create(:questionnaire_question) }
96
+ body { generate_localized_title }
97
+ position { 0 }
78
98
  end
79
99
  end
@@ -35,7 +35,9 @@ shared_examples_for "has questionnaire" do
35
35
 
36
36
  check "questionnaire_tos_agreement"
37
37
 
38
- accept_confirm { click_button "Submit" }
38
+ accept_confirm do
39
+ click_button "Submit"
40
+ end
39
41
 
40
42
  within ".success.flash" do
41
43
  expect(page).to have_content("successfully")
@@ -47,6 +49,73 @@ shared_examples_for "has questionnaire" do
47
49
  expect(page).to have_no_i18n_content(question.body)
48
50
  end
49
51
 
52
+ context "with multiple steps" do
53
+ let!(:separator) { create(:questionnaire_question, questionnaire: questionnaire, position: 1, question_type: :separator) }
54
+ let!(:question2) { create(:questionnaire_question, questionnaire: questionnaire, position: 2) }
55
+
56
+ before do
57
+ visit questionnaire_public_path
58
+ end
59
+
60
+ it "allows answering the first questionnaire" do
61
+ expect(page).to have_content("STEP 1 OF 2")
62
+
63
+ within ".answer-questionnaire__submit" do
64
+ expect(page).to have_no_content("Back")
65
+ end
66
+
67
+ answer_first_questionnaire
68
+
69
+ expect(page).to have_no_selector(".success.flash")
70
+ end
71
+
72
+ it "allows revisiting previously-answered questionnaires with my answers" do
73
+ answer_first_questionnaire
74
+
75
+ click_link "Back"
76
+
77
+ expect(page).to have_content("STEP 1 OF 2")
78
+ expect(page).to have_field("questionnaire_answers_0", with: "My first answer")
79
+ end
80
+
81
+ it "finishes the submission when answering the last questionnaire" do
82
+ answer_first_questionnaire
83
+
84
+ check "questionnaire_tos_agreement"
85
+ accept_confirm { click_button "Submit" }
86
+
87
+ within ".success.flash" do
88
+ expect(page).to have_content("successfully")
89
+ end
90
+
91
+ visit questionnaire_public_path
92
+
93
+ expect(page).to have_content("You have already answered this form.")
94
+ end
95
+
96
+ def answer_first_questionnaire
97
+ expect(page).to have_no_selector("#questionnaire_tos_agreement")
98
+
99
+ fill_in question.body["en"], with: "My first answer"
100
+ within ".answer-questionnaire__submit" do
101
+ click_link "Continue"
102
+ end
103
+ expect(page).to have_content("STEP 2 OF 2")
104
+ end
105
+ end
106
+
107
+ it "requires confirmation when exiting mid-answering" do
108
+ visit questionnaire_public_path
109
+
110
+ fill_in question.body["en"], with: "My first answer"
111
+
112
+ dismiss_page_unload do
113
+ page.find(".logo-wrapper a").click
114
+ end
115
+
116
+ expect(page).to have_current_path questionnaire_public_path
117
+ end
118
+
50
119
  context "when the questionnaire has already been answered by someone else" do
51
120
  let!(:question) do
52
121
  create(
@@ -205,6 +274,7 @@ shared_examples_for "has questionnaire" do
205
274
  :questionnaire_question,
206
275
  questionnaire: questionnaire,
207
276
  question_type: question_type,
277
+ position: 1,
208
278
  options: [
209
279
  { "body" => answer_option_bodies[0] },
210
280
  { "body" => answer_option_bodies[1] },
@@ -219,6 +289,7 @@ shared_examples_for "has questionnaire" do
219
289
  questionnaire: questionnaire,
220
290
  question_type: "multiple_option",
221
291
  max_choices: 2,
292
+ position: 2,
222
293
  options: [
223
294
  { "body" => Decidim::Faker::Localized.sentence },
224
295
  { "body" => Decidim::Faker::Localized.sentence },
@@ -283,16 +354,16 @@ shared_examples_for "has questionnaire" do
283
354
  it "renders them as check boxes with attached text fields disabled by default" do
284
355
  expect(page.first(".check-box-collection")).to have_selector("input[type=checkbox]", count: 3)
285
356
 
286
- expect(page).to have_field("questionnaire_answers_0_choices_2_custom_body", disabled: true, count: 1)
357
+ expect(page).to have_field("questionnaire_responses_0_choices_2_custom_body", disabled: true, count: 1)
287
358
 
288
359
  check answer_option_bodies[2]["en"]
289
360
 
290
- expect(page).to have_field("questionnaire_answers_0_choices_2_custom_body", disabled: false, count: 1)
361
+ expect(page).to have_field("questionnaire_responses_0_choices_2_custom_body", disabled: false, count: 1)
291
362
  end
292
363
 
293
364
  it "saves the free text in a separate field if submission correct" do
294
365
  check answer_option_bodies[2]["en"]
295
- fill_in "questionnaire_answers_0_choices_2_custom_body", with: "Cacatua"
366
+ fill_in "questionnaire_responses_0_choices_2_custom_body", with: "Cacatua"
296
367
 
297
368
  check "questionnaire_tos_agreement"
298
369
  accept_confirm { click_button "Submit" }
@@ -305,12 +376,12 @@ shared_examples_for "has questionnaire" do
305
376
  end
306
377
 
307
378
  it "preserves the previous custom body if submission not correct" do
308
- check "questionnaire_answers_1_choices_0_body"
309
- check "questionnaire_answers_1_choices_1_body"
310
- check "questionnaire_answers_1_choices_2_body"
379
+ check "questionnaire_responses_1_choices_0_body"
380
+ check "questionnaire_responses_1_choices_1_body"
381
+ check "questionnaire_responses_1_choices_2_body"
311
382
 
312
383
  check answer_option_bodies[2]["en"]
313
- fill_in "questionnaire_answers_0_choices_2_custom_body", with: "Cacatua"
384
+ fill_in "questionnaire_responses_0_choices_2_custom_body", with: "Cacatua"
314
385
 
315
386
  check "questionnaire_tos_agreement"
316
387
  accept_confirm { click_button "Submit" }
@@ -319,7 +390,7 @@ shared_examples_for "has questionnaire" do
319
390
  expect(page).to have_content("There was a problem answering")
320
391
  end
321
392
 
322
- expect(page).to have_field("questionnaire_answers_0_choices_2_custom_body", with: "Cacatua")
393
+ expect(page).to have_field("questionnaire_responses_0_choices_2_custom_body", with: "Cacatua")
323
394
  end
324
395
  end
325
396
  end
@@ -409,6 +480,8 @@ shared_examples_for "has questionnaire" do
409
480
  check answer_options[1]["body"][:en]
410
481
  check answer_options[2]["body"][:en]
411
482
 
483
+ expect(page).to have_content("too many choices")
484
+
412
485
  check "questionnaire_tos_agreement"
413
486
 
414
487
  accept_confirm { click_button "Submit" }
@@ -429,33 +502,6 @@ shared_examples_for "has questionnaire" do
429
502
  end
430
503
  end
431
504
 
432
- context "when question type is multiple option" do
433
- let(:answer_options) { Array.new(2) { { "body" => Decidim::Faker::Localized.sentence } } }
434
- let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, question_type: "multiple_option", options: answer_options) }
435
-
436
- it "renders the question answers as a collection of radio buttons" do
437
- visit questionnaire_public_path
438
-
439
- expect(page).to have_selector(".check-box-collection input[type=checkbox]", count: 2)
440
-
441
- check answer_options[0]["body"][:en]
442
- check answer_options[1]["body"][:en]
443
-
444
- check "questionnaire_tos_agreement"
445
-
446
- accept_confirm { click_button "Submit" }
447
-
448
- within ".success.flash" do
449
- expect(page).to have_content("successfully")
450
- end
451
-
452
- visit questionnaire_public_path
453
-
454
- expect(page).to have_content("You have already answered this form.")
455
- expect(page).to have_no_i18n_content(question.body)
456
- end
457
- end
458
-
459
505
  context "when question type is sorting" do
460
506
  let!(:question) do
461
507
  create(
@@ -524,5 +570,236 @@ shared_examples_for "has questionnaire" do
524
570
  expect(page).to have_content("are not complete")
525
571
  end
526
572
  end
573
+
574
+ context "when question type is matrix_single" do
575
+ let(:matrix_rows) { Array.new(2) { { "body" => Decidim::Faker::Localized.sentence } } }
576
+ let(:answer_options) { Array.new(2) { { "body" => Decidim::Faker::Localized.sentence } } }
577
+ let(:mandatory) { false }
578
+
579
+ let!(:question) do
580
+ create(
581
+ :questionnaire_question,
582
+ questionnaire: questionnaire,
583
+ question_type: "matrix_single",
584
+ rows: matrix_rows,
585
+ options: answer_options,
586
+ mandatory: mandatory
587
+ )
588
+ end
589
+
590
+ it "renders the question answers as a collection of radio buttons" do
591
+ visit questionnaire_public_path
592
+
593
+ expect(page).to have_selector(".radio-button-collection input[type=radio]", count: 4)
594
+
595
+ expect(page).to have_content(matrix_rows.map { |row| row["body"]["en"] }.join("\n"))
596
+ expect(page).to have_content(answer_options.map { |option| option["body"]["en"] }.join(" "))
597
+
598
+ radio_buttons = page.all(".radio-button-collection input[type=radio]")
599
+
600
+ choose radio_buttons.first[:id]
601
+ choose radio_buttons.last[:id]
602
+
603
+ check "questionnaire_tos_agreement"
604
+
605
+ accept_confirm { click_button "Submit" }
606
+
607
+ within ".success.flash" do
608
+ expect(page).to have_content("successfully")
609
+ end
610
+
611
+ visit questionnaire_public_path
612
+
613
+ expect(page).to have_content("You have already answered this form.")
614
+ expect(page).to have_no_i18n_content(question.body)
615
+
616
+ first_choice, last_choice = Decidim::Forms::Answer.last.choices.pluck(:decidim_answer_option_id, :decidim_question_matrix_row_id)
617
+
618
+ expect(first_choice).to eq([question.answer_options.first.id, question.matrix_rows.first.id])
619
+ expect(last_choice).to eq([question.answer_options.last.id, question.matrix_rows.last.id])
620
+ end
621
+
622
+ it "preserves the chosen answers if submission not correct" do
623
+ visit questionnaire_public_path
624
+
625
+ radio_buttons = page.all(".radio-button-collection input[type=radio]")
626
+ choose radio_buttons[1][:id]
627
+
628
+ accept_confirm { click_button "Submit" }
629
+
630
+ within ".alert.flash" do
631
+ expect(page).to have_content("There was a problem answering")
632
+ end
633
+
634
+ radio_buttons = page.all(".radio-button-collection input[type=radio]")
635
+ expect(radio_buttons.map { |b| b[:checked] }).to eq([nil, "true", nil, nil])
636
+ end
637
+
638
+ context "when the question is mandatory and the answer is not complete" do
639
+ let!(:mandatory) { true }
640
+
641
+ it "shows an error if the question is mandatory and the answer is not complete" do
642
+ visit questionnaire_public_path
643
+
644
+ radio_buttons = page.all(".radio-button-collection input[type=radio]")
645
+ choose radio_buttons[0][:id]
646
+
647
+ check "questionnaire_tos_agreement"
648
+ accept_confirm { click_button "Submit" }
649
+
650
+ within ".alert.flash" do
651
+ expect(page).to have_content("There was a problem answering")
652
+ end
653
+
654
+ expect(page).to have_content("Choices are not complete")
655
+ end
656
+ end
657
+ end
658
+
659
+ context "when question type is matrix_multiple" do
660
+ let(:matrix_rows) { Array.new(2) { { "body" => Decidim::Faker::Localized.sentence } } }
661
+ let(:answer_options) { Array.new(3) { { "body" => Decidim::Faker::Localized.sentence } } }
662
+ let(:max_choices) { nil }
663
+ let(:mandatory) { false }
664
+
665
+ let!(:question) do
666
+ create(
667
+ :questionnaire_question,
668
+ questionnaire: questionnaire,
669
+ question_type: "matrix_multiple",
670
+ rows: matrix_rows,
671
+ options: answer_options,
672
+ max_choices: max_choices,
673
+ mandatory: mandatory
674
+ )
675
+ end
676
+
677
+ it "renders the question answers as a collection of check boxes" do
678
+ visit questionnaire_public_path
679
+
680
+ expect(page).to have_selector(".check-box-collection input[type=checkbox]", count: 6)
681
+
682
+ expect(page).to have_content(matrix_rows.map { |row| row["body"]["en"] }.join("\n"))
683
+ expect(page).to have_content(answer_options.map { |option| option["body"]["en"] }.join(" "))
684
+
685
+ checkboxes = page.all(".check-box-collection input[type=checkbox]")
686
+
687
+ check checkboxes[0][:id]
688
+ check checkboxes[1][:id]
689
+ check checkboxes[3][:id]
690
+
691
+ check "questionnaire_tos_agreement"
692
+
693
+ accept_confirm { click_button "Submit" }
694
+
695
+ within ".success.flash" do
696
+ expect(page).to have_content("successfully")
697
+ end
698
+
699
+ visit questionnaire_public_path
700
+
701
+ expect(page).to have_content("You have already answered this form.")
702
+ expect(page).to have_no_i18n_content(question.body)
703
+
704
+ first_choice, second_choice, third_choice = Decidim::Forms::Answer.last.choices.pluck(:decidim_answer_option_id, :decidim_question_matrix_row_id)
705
+
706
+ expect(first_choice).to eq([question.answer_options.first.id, question.matrix_rows.first.id])
707
+ expect(second_choice).to eq([question.answer_options.second.id, question.matrix_rows.first.id])
708
+ expect(third_choice).to eq([question.answer_options.first.id, question.matrix_rows.last.id])
709
+ end
710
+
711
+ context "when the question hax max_choices defined" do
712
+ let!(:max_choices) { 2 }
713
+
714
+ it "respects the max number of choices" do
715
+ visit questionnaire_public_path
716
+
717
+ expect(page).to have_content("Max choices: 2")
718
+
719
+ checkboxes = page.all(".check-box-collection input[type=checkbox]")
720
+
721
+ check checkboxes[0][:id]
722
+ check checkboxes[1][:id]
723
+ check checkboxes[2][:id]
724
+
725
+ expect(page).to have_content("too many choices")
726
+
727
+ check checkboxes[3][:id]
728
+ check checkboxes[4][:id]
729
+
730
+ expect(page).to have_content("too many choices")
731
+
732
+ check checkboxes[5][:id]
733
+
734
+ uncheck checkboxes[0][:id]
735
+
736
+ expect(page).to have_content("too many choices")
737
+
738
+ check "questionnaire_tos_agreement"
739
+
740
+ accept_confirm { click_button "Submit" }
741
+
742
+ within ".alert.flash" do
743
+ expect(page).to have_content("There was a problem answering")
744
+ end
745
+
746
+ expect(page).to have_content("are too many")
747
+
748
+ checkboxes = page.all(".check-box-collection input[type=checkbox]")
749
+
750
+ uncheck checkboxes[5][:id]
751
+
752
+ accept_confirm { click_button "Submit" }
753
+
754
+ within ".success.flash" do
755
+ expect(page).to have_content("successfully")
756
+ end
757
+ end
758
+ end
759
+
760
+ context "when the submission is not correct" do
761
+ let!(:max_choices) { 2 }
762
+
763
+ it "preserves the chosen answers" do
764
+ visit questionnaire_public_path
765
+
766
+ checkboxes = page.all(".check-box-collection input[type=checkbox]")
767
+ check checkboxes[0][:id]
768
+ check checkboxes[1][:id]
769
+ check checkboxes[2][:id]
770
+ check checkboxes[5][:id]
771
+
772
+ check "questionnaire_tos_agreement"
773
+ accept_confirm { click_button "Submit" }
774
+
775
+ within ".alert.flash" do
776
+ expect(page).to have_content("There was a problem answering")
777
+ end
778
+
779
+ checkboxes = page.all(".check-box-collection input[type=checkbox]")
780
+ expect(checkboxes.map { |c| c[:checked] }).to eq(["true", "true", "true", nil, nil, "true"])
781
+ end
782
+ end
783
+
784
+ context "when the question is mandatory and the answer is not complete" do
785
+ let!(:mandatory) { true }
786
+
787
+ it "shows an error" do
788
+ visit questionnaire_public_path
789
+
790
+ checkboxes = page.all(".check-box-collection input[type=checkbox]")
791
+ check checkboxes[0][:id]
792
+
793
+ check "questionnaire_tos_agreement"
794
+ accept_confirm { click_button "Submit" }
795
+
796
+ within ".alert.flash" do
797
+ expect(page).to have_content("There was a problem answering")
798
+ end
799
+
800
+ expect(page).to have_content("Choices are not complete")
801
+ end
802
+ end
803
+ end
527
804
  end
528
805
  end