decidim-forms 0.21.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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