decidim-forms 0.22.0 → 0.23.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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/admin/decidim_forms_manifest.css +3 -0
  3. data/app/assets/config/decidim_forms_manifest.css +1 -0
  4. data/app/assets/javascripts/decidim/forms/admin/auto_select_options_from_url.component.js.es6 +40 -0
  5. data/app/assets/javascripts/decidim/forms/admin/forms.js.es6 +181 -25
  6. data/app/assets/javascripts/decidim/forms/autosortable_checkboxes.component.js.es6 +54 -34
  7. data/app/assets/javascripts/decidim/forms/display_conditions.component.js.es6 +204 -0
  8. data/app/assets/javascripts/decidim/forms/forms.js.es6 +8 -1
  9. data/app/assets/stylesheets/decidim/forms/questionnaire-answers-pdf.scss +69 -0
  10. data/app/commands/decidim/forms/admin/update_questionnaire.rb +25 -1
  11. data/app/commands/decidim/forms/answer_questionnaire.rb +1 -1
  12. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +47 -1
  13. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire_answers.rb +97 -0
  14. data/app/forms/decidim/forms/admin/display_condition_form.rb +100 -0
  15. data/app/forms/decidim/forms/admin/question_form.rb +1 -0
  16. data/app/forms/decidim/forms/answer_form.rb +15 -0
  17. data/app/helpers/decidim/forms/admin/application_helper.rb +21 -0
  18. data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_pagination_helper.rb +49 -0
  19. data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_url_helper.rb +40 -0
  20. data/app/helpers/decidim/forms/admin/questionnaire_answers_helper.rb +27 -0
  21. data/app/jobs/decidim/forms/export_questionnaire_answers_job.rb +19 -0
  22. data/app/models/decidim/forms/answer.rb +0 -3
  23. data/app/models/decidim/forms/answer_option.rb +14 -0
  24. data/app/models/decidim/forms/display_condition.rb +51 -0
  25. data/app/models/decidim/forms/question.rb +34 -0
  26. data/app/models/decidim/forms/question_matrix_row.rb +3 -0
  27. data/app/models/decidim/forms/questionnaire.rb +11 -1
  28. data/app/presenters/decidim/forms/admin/questionnaire_answer_presenter.rb +43 -0
  29. data/app/presenters/decidim/forms/admin/questionnaire_participant_presenter.rb +60 -0
  30. data/app/presenters/decidim/forms/answer_option_presenter.rb +20 -0
  31. data/app/presenters/decidim/forms/question_presenter.rb +16 -0
  32. data/app/queries/decidim/forms/questionnaire_participant.rb +35 -0
  33. data/app/queries/decidim/forms/questionnaire_participants.rb +43 -0
  34. data/app/views/decidim/forms/admin/questionnaires/_display_condition.html.erb +88 -0
  35. data/app/views/decidim/forms/admin/questionnaires/_display_condition_template.html.erb +7 -0
  36. data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +30 -4
  37. data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +19 -3
  38. data/app/views/decidim/forms/admin/questionnaires/answers/export/_answer.html.erb +31 -0
  39. data/app/views/decidim/forms/admin/questionnaires/answers/export/pdf.html.erb +13 -0
  40. data/app/views/decidim/forms/admin/questionnaires/answers/index.html.erb +53 -0
  41. data/app/views/decidim/forms/admin/questionnaires/answers/show.html.erb +48 -0
  42. data/app/views/decidim/forms/admin/questionnaires/edit.html.erb +9 -5
  43. data/app/views/decidim/forms/questionnaires/_answer.html.erb +1 -1
  44. data/app/views/decidim/forms/questionnaires/show.html.erb +22 -2
  45. data/app/views/layouts/decidim/forms/admin/questionnaires/questionnaire_answers.html.erb +12 -0
  46. data/config/initializers/wicked_pdf.rb +25 -0
  47. data/config/locales/am-ET.yml +1 -0
  48. data/config/locales/ar.yml +0 -1
  49. data/config/locales/bg-BG.yml +0 -2
  50. data/config/locales/bg.yml +14 -0
  51. data/config/locales/ca.yml +56 -4
  52. data/config/locales/cs.yml +54 -2
  53. data/config/locales/da.yml +1 -0
  54. data/config/locales/de.yml +51 -1
  55. data/config/locales/el.yml +0 -2
  56. data/config/locales/en.yml +54 -2
  57. data/config/locales/eo.yml +1 -0
  58. data/config/locales/es-MX.yml +53 -1
  59. data/config/locales/es-PY.yml +53 -1
  60. data/config/locales/es.yml +54 -2
  61. data/config/locales/et.yml +1 -0
  62. data/config/locales/eu.yml +0 -1
  63. data/config/locales/fi-plain.yml +53 -1
  64. data/config/locales/fi.yml +53 -1
  65. data/config/locales/fr-CA.yml +54 -2
  66. data/config/locales/fr.yml +54 -2
  67. data/config/locales/gl.yml +0 -1
  68. data/config/locales/hr.yml +1 -0
  69. data/config/locales/hu.yml +0 -2
  70. data/config/locales/id-ID.yml +0 -1
  71. data/config/locales/is.yml +1 -0
  72. data/config/locales/it.yml +53 -1
  73. data/config/locales/ja-JP.yml +51 -1
  74. data/config/locales/ja.yml +170 -0
  75. data/config/locales/ko-KR.yml +1 -0
  76. data/config/locales/ko.yml +1 -0
  77. data/config/locales/lt.yml +1 -0
  78. data/config/locales/{lv-LV.yml → lv.yml} +0 -1
  79. data/config/locales/mt.yml +1 -0
  80. data/config/locales/nl.yml +59 -7
  81. data/config/locales/no.yml +47 -2
  82. data/config/locales/om-ET.yml +1 -0
  83. data/config/locales/pl.yml +52 -3
  84. data/config/locales/pt-BR.yml +0 -1
  85. data/config/locales/pt.yml +51 -2
  86. data/config/locales/ro-RO.yml +51 -2
  87. data/config/locales/ru.yml +0 -1
  88. data/config/locales/sk.yml +0 -2
  89. data/config/locales/sl.yml +7 -0
  90. data/config/locales/so-SO.yml +1 -0
  91. data/config/locales/sv.yml +51 -2
  92. data/config/locales/ti-ER.yml +1 -0
  93. data/config/locales/tr-TR.yml +0 -1
  94. data/config/locales/vi-VN.yml +1 -0
  95. data/config/locales/vi.yml +1 -0
  96. data/config/locales/zh-CN.yml +172 -0
  97. data/config/locales/zh-TW.yml +1 -0
  98. data/db/migrate/20200130194123_create_decidim_forms_display_conditions.rb +20 -0
  99. data/lib/decidim/exporters/form_pdf.rb +33 -0
  100. data/lib/decidim/exporters/form_pdf_controller_helper.rb +11 -0
  101. data/lib/decidim/forms.rb +5 -0
  102. data/lib/decidim/forms/admin_engine.rb +1 -1
  103. data/lib/decidim/forms/test.rb +6 -0
  104. data/lib/decidim/forms/test/factories.rb +30 -0
  105. data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +619 -38
  106. data/lib/decidim/forms/test/shared_examples/manage_questionnaire_answers.rb +108 -0
  107. data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +21 -894
  108. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_display_conditions.rb +179 -0
  109. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_questions.rb +463 -0
  110. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_display_conditions.rb +93 -0
  111. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_questions.rb +461 -0
  112. data/lib/decidim/forms/version.rb +1 -1
  113. metadata +91 -11
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ shared_examples_for "manage questionnaire answers" do
6
+ let(:first_type) { "short_answer" }
7
+ let!(:first) do
8
+ create :questionnaire_question, questionnaire: questionnaire, position: 1, question_type: first_type
9
+ end
10
+ let!(:second) do
11
+ create :questionnaire_question, questionnaire: questionnaire, position: 2, question_type: "single_option"
12
+ end
13
+ let(:questions) do
14
+ [first, second]
15
+ end
16
+
17
+ context "when there are no answers" do
18
+ it "do not answer admin link" do
19
+ visit questionnaire_edit_path
20
+ expect(page).to have_content("No answers yet")
21
+ end
22
+ end
23
+
24
+ context "when there are answers" do
25
+ let!(:answer1) { create :answer, questionnaire: questionnaire, question: first }
26
+ let!(:answer2) { create :answer, body: "second answer", questionnaire: questionnaire, question: first }
27
+ let!(:answer3) { create :answer, questionnaire: questionnaire, question: second }
28
+
29
+ it "shows the answer admin link" do
30
+ visit questionnaire_edit_path
31
+ expect(page).to have_content("Show responses")
32
+ end
33
+
34
+ context "and managing answers page" do
35
+ before do
36
+ visit questionnaire_edit_path
37
+ click_link "Show responses"
38
+ end
39
+
40
+ it "shows the anwers page" do
41
+ expect(page).to have_content(answer1.body)
42
+ expect(page).to have_content(answer1.question.body["en"])
43
+ expect(page).to have_content(answer2.body)
44
+ expect(page).to have_content(answer2.question.body["en"])
45
+ end
46
+
47
+ it "shows the percentage" do
48
+ expect(page).to have_content("50%")
49
+ end
50
+
51
+ it "has a detail link" do
52
+ expect(page).to have_link("Show answers")
53
+ end
54
+
55
+ it "has an export link" do
56
+ expect(page).to have_link(answer1.body)
57
+ expect(page).to have_link(answer2.body)
58
+ expect(page).to have_link("Export")
59
+ end
60
+
61
+ context "when no short answer exist" do
62
+ let(:first_type) { "long_answer" }
63
+
64
+ it "shows session token" do
65
+ expect(page).not_to have_content(answer1.body)
66
+ expect(page).to have_content(answer1.session_token)
67
+ expect(page).to have_content(answer2.session_token)
68
+ expect(page).to have_content(answer3.session_token)
69
+ expect(page).to have_content("User identifier")
70
+ end
71
+ end
72
+ end
73
+
74
+ context "and managing individual answer page" do
75
+ let!(:answer11) { create :answer, questionnaire: questionnaire, body: "", user: answer1.user, question: second }
76
+
77
+ before do
78
+ visit questionnaire_edit_path
79
+ click_link "Show responses"
80
+ end
81
+
82
+ it "shows all the questions and responses" do
83
+ click_link answer1.body, match: :first
84
+ expect(page).to have_content(first.body["en"])
85
+ expect(page).to have_content(second.body["en"])
86
+ expect(page).to have_content(answer1.body)
87
+ end
88
+
89
+ it "first answer has a next link" do
90
+ click_link answer1.body, match: :first
91
+ expect(page).to have_link("Next ›")
92
+ expect(page).not_to have_link("‹ Prev")
93
+ end
94
+
95
+ it "second answer has prev/next links" do
96
+ click_link answer2.body, match: :first
97
+ expect(page).to have_link("Next ›")
98
+ expect(page).to have_link("‹ Prev")
99
+ end
100
+
101
+ it "third answer has prev link" do
102
+ click_link answer3.session_token, match: :first
103
+ expect(page).not_to have_link("Next ›")
104
+ expect(page).to have_link("‹ Prev")
105
+ end
106
+ end
107
+ end
108
+ end
@@ -2,6 +2,11 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
+ require "decidim/forms/test/shared_examples/manage_questionnaires/add_questions.rb"
6
+ require "decidim/forms/test/shared_examples/manage_questionnaires/update_questions.rb"
7
+ require "decidim/forms/test/shared_examples/manage_questionnaires/add_display_conditions.rb"
8
+ require "decidim/forms/test/shared_examples/manage_questionnaires/update_display_conditions.rb"
9
+
5
10
  shared_examples_for "manage questionnaires" do
6
11
  let(:body) do
7
12
  {
@@ -37,898 +42,10 @@ shared_examples_for "manage questionnaires" do
37
42
  visit questionnaire_edit_path
38
43
  end
39
44
 
40
- it "adds a few questions and separators to the questionnaire" do
41
- questions_body = ["This is the first question", "This is the second question"]
42
-
43
- within "form.edit_questionnaire" do
44
- click_button "Add question"
45
- click_button "Add separator"
46
- click_button "Add question"
47
-
48
- expect(page).to have_selector(".questionnaire-question", count: 3)
49
-
50
- expand_all_questions
51
-
52
- page.all(".questionnaire-question .collapsible").each_with_index do |question, idx|
53
- within question do
54
- fill_in find_nested_form_field_locator("body_en"), with: questions_body[idx]
55
- end
56
- end
57
-
58
- click_button "Save"
59
- end
60
-
61
- expect(page).to have_admin_callout("successfully")
62
-
63
- visit_questionnaire_edit_path_and_expand_all
64
-
65
- expect(page).to have_selector("input[value='This is the first question']")
66
- expect(page).to have_selector("input[value='This is the second question']")
67
- expect(page).to have_content("Separator #2")
68
- end
69
-
70
- it "adds a question with a rich text description" do
71
- within "form.edit_questionnaire" do
72
- click_button "Add question"
73
- expand_all_questions
74
-
75
- within ".questionnaire-question" do
76
- fill_in find_nested_form_field_locator("body_en"), with: "Body"
77
-
78
- fill_in_editor find_nested_form_field_locator("description_en", visible: :all), with: "<b>Superkalifragilistic description</b>"
79
- end
80
-
81
- click_button "Save"
82
- end
83
-
84
- expect(page).to have_admin_callout("successfully")
85
-
86
- component.update!(
87
- step_settings: {
88
- component.participatory_space.active_step.id => {
89
- allow_answers: true
90
- }
91
- }
92
- )
93
-
94
- visit questionnaire_public_path
95
-
96
- expect(page).to have_selector("strong", text: "Superkalifragilistic description")
97
- end
98
-
99
- it "adds a question with answer options" do
100
- question_body = ["This is the first question", "This is the second question"]
101
- answer_options_body = [
102
- [
103
- "This is the Q1 first option",
104
- "This is the Q1 second option",
105
- "This is the Q1 third option"
106
- ],
107
- [
108
- "This is the Q2 first option",
109
- "This is the Q2 second option",
110
- "This is the Q2 third option"
111
- ]
112
- ]
113
-
114
- within "form.edit_questionnaire" do
115
- click_button "Add question"
116
- click_button "Add question"
117
- expand_all_questions
118
-
119
- page.all(".questionnaire-question").each_with_index do |question, idx|
120
- within question do
121
- fill_in find_nested_form_field_locator("body_en"), with: question_body[idx]
122
- end
123
- end
124
-
125
- expect(page).to have_no_content "Add answer option"
126
-
127
- page.all(".questionnaire-question").each do |question|
128
- within question do
129
- select "Single option", from: "Type"
130
- click_button "Add answer option"
131
- end
132
- end
133
-
134
- page.all(".questionnaire-question").each_with_index do |question, idx|
135
- question.all(".questionnaire-question-answer-option").each_with_index do |question_answer_option, aidx|
136
- within question_answer_option do
137
- fill_in find_nested_form_field_locator("body_en"), with: answer_options_body[idx][aidx]
138
- end
139
- end
140
- end
141
-
142
- click_button "Save"
143
- end
144
-
145
- expect(page).to have_admin_callout("successfully")
146
-
147
- visit_questionnaire_edit_path_and_expand_all
148
-
149
- expect(page).to have_selector("input[value='This is the first question']")
150
- expect(page).to have_selector("input[value='This is the Q1 first option']")
151
- expect(page).to have_selector("input[value='This is the Q1 second option']")
152
- expect(page).to have_selector("input[value='This is the Q1 third option']")
153
- expect(page).to have_selector("input[value='This is the second question']")
154
- expect(page).to have_selector("input[value='This is the Q2 first option']")
155
- expect(page).to have_selector("input[value='This is the Q2 second option']")
156
- expect(page).to have_selector("input[value='This is the Q2 third option']")
157
- end
158
-
159
- it "adds a sane number of options for each attribute type" do
160
- click_button "Add question"
161
- expand_all_questions
162
-
163
- select "Long answer", from: "Type"
164
- expect(page).to have_no_selector(".questionnaire-question-answer-option")
165
- expect(page).to have_no_selector(".questionnaire-question-matrix-row")
166
-
167
- select "Single option", from: "Type"
168
- expect(page).to have_selector(".questionnaire-question-answer-option", count: 2)
169
- expect(page).to have_no_selector(".questionnaire-question-matrix-row")
170
-
171
- select "Multiple option", from: "Type"
172
- expect(page).to have_selector(".questionnaire-question-answer-option", count: 2)
173
- expect(page).to have_no_selector(".questionnaire-question-matrix-row")
174
-
175
- select "Matrix (Multiple option)", from: "Type"
176
- expect(page).to have_selector(".questionnaire-question-answer-option", count: 2)
177
- expect(page).to have_selector(".questionnaire-question-matrix-row", count: 2)
178
-
179
- select "Short answer", from: "Type"
180
- expect(page).to have_no_selector(".questionnaire-question-answer-option")
181
- expect(page).to have_no_selector(".questionnaire-question-matrix-row")
182
-
183
- select "Matrix (Single option)", from: "Type"
184
- expect(page).to have_selector(".questionnaire-question-answer-option", count: 2)
185
- expect(page).to have_selector(".questionnaire-question-matrix-row", count: 2)
186
- end
187
-
188
- it "does not incorrectly reorder when clicking answer options" do
189
- click_button "Add question"
190
- expand_all_questions
191
-
192
- select "Single option", from: "Type"
193
- 2.times { click_button "Add answer option" }
194
-
195
- within ".questionnaire-question-answer-option:first-of-type" do
196
- fill_in find_nested_form_field_locator("body_en"), with: "Something"
197
- end
198
-
199
- within ".questionnaire-question-answer-option:last-of-type" do
200
- fill_in find_nested_form_field_locator("body_en"), with: "Else"
201
- end
202
-
203
- # If JS events for option reordering are incorrectly bound, clicking on
204
- # the field to gain focus can cause the options to get inverted... :S
205
- within ".questionnaire-question-answer-option:first-of-type" do
206
- find_nested_form_field("body_en").click
207
- end
208
-
209
- within ".questionnaire-question-answer-option:first-of-type" do
210
- expect(page).to have_nested_field("body_en", with: "Something")
211
- end
212
-
213
- within ".questionnaire-question-answer-option:last-of-type" do
214
- expect(page).to have_nested_field("body_en", with: "Else")
215
- end
216
- end
217
-
218
- it "does not incorrectly reorder when clicking matrix rows" do
219
- # Unable to find visible select box "Type" that is not disabled and Unable to find input box with datalist completion "Type" that is not disabled
220
-
221
- click_button "Add question"
222
- expand_all_questions
223
-
224
- select "Matrix (Multiple option)", from: "Type"
225
- 2.times { click_button "Add row" }
226
-
227
- within ".questionnaire-question-matrix-row:first-of-type" do
228
- fill_in find_nested_form_field_locator("body_en"), with: "Something"
229
- end
230
-
231
- within ".questionnaire-question-matrix-row:last-of-type" do
232
- fill_in find_nested_form_field_locator("body_en"), with: "Else"
233
- end
234
-
235
- # If JS events for option reordering are incorrectly bound, clicking on
236
- # the field to gain focus can cause the options to get inverted... :S
237
- within ".questionnaire-question-matrix-row:first-of-type" do
238
- find_nested_form_field("body_en").click
239
- end
240
-
241
- within ".questionnaire-question-matrix-row:first-of-type" do
242
- expect(page).to have_nested_field("body_en", with: "Something")
243
- end
244
-
245
- within ".questionnaire-question-matrix-row:last-of-type" do
246
- expect(page).to have_nested_field("body_en", with: "Else")
247
- end
248
- end
249
-
250
- it "preserves question form across submission failures" do
251
- click_button "Add question"
252
- expand_all_questions
253
-
254
- select "Long answer", from: "Type"
255
- click_button "Save"
256
-
257
- expand_all_questions
258
- expect(page).to have_select("Type", selected: "Long answer")
259
- end
260
-
261
- it "does not preserve spurious answer options from previous type selections" do
262
- click_button "Add question"
263
- expand_all_questions
264
-
265
- select "Single option", from: "Type"
266
-
267
- within ".questionnaire-question-answer-option:first-of-type" do
268
- fill_in find_nested_form_field_locator("body_en"), with: "Something"
269
- end
270
-
271
- select "Long answer", from: "Type"
272
-
273
- click_button "Save"
274
- expand_all_questions
275
-
276
- select "Single option", from: "Type"
277
-
278
- within ".questionnaire-question-answer-option:first-of-type" do
279
- expect(page).to have_no_nested_field("body_en", with: "Something")
280
- end
281
- end
282
-
283
- it "does not preserve spurious matrix rows from previous type selections" do
284
- click_button "Add question"
285
- expand_all_questions
286
-
287
- select "Matrix (Single option)", from: "Type"
288
-
289
- within ".questionnaire-question-matrix-row:first-of-type" do
290
- fill_in find_nested_form_field_locator("body_en"), with: "Something"
291
- end
292
-
293
- select "Long answer", from: "Type"
294
-
295
- click_button "Save"
296
- expand_all_questions
297
-
298
- select "Matrix (Single option)", from: "Type"
299
-
300
- within ".questionnaire-question-matrix-row:first-of-type" do
301
- expect(page).to have_no_nested_field("body_en", with: "Something")
302
- end
303
- end
304
-
305
- it "preserves answer options form across submission failures" do
306
- click_button "Add question"
307
- expand_all_questions
308
-
309
- select "Multiple option", from: "Type"
310
-
311
- within ".questionnaire-question-answer-option:first-of-type" do
312
- fill_in find_nested_form_field_locator("body_en"), with: "Something"
313
- end
314
-
315
- click_button "Add answer option"
316
-
317
- within ".questionnaire-question-answer-option:last-of-type" do
318
- fill_in find_nested_form_field_locator("body_en"), with: "Else"
319
- end
320
-
321
- select "3", from: "Maximum number of choices"
322
-
323
- click_button "Save"
324
- expand_all_questions
325
-
326
- within ".questionnaire-question-answer-option:first-of-type" do
327
- expect(page).to have_nested_field("body_en", with: "Something")
328
- end
329
-
330
- within ".questionnaire-question-answer-option:last-of-type" do
331
- fill_in find_nested_form_field_locator("body_en"), with: "Else"
332
- end
333
-
334
- expect(page).to have_select("Maximum number of choices", selected: "3")
335
- end
336
-
337
- it "preserves matrix rows form across submission failures" do
338
- click_button "Add question"
339
- expand_all_questions
340
-
341
- select "Matrix (Multiple option)", from: "Type"
342
-
343
- within ".questionnaire-question-matrix-row:first-of-type" do
344
- fill_in find_nested_form_field_locator("body_en"), with: "Something"
345
- end
346
-
347
- click_button "Add row"
348
-
349
- click_button "Save"
350
- expand_all_questions
351
-
352
- within ".questionnaire-question-matrix-row:first-of-type" do
353
- expect(page).to have_nested_field("body_en", with: "Something")
354
- end
355
- end
356
-
357
- it "allows switching translated field tabs after form failures" do
358
- click_button "Add question"
359
- click_button "Save"
360
-
361
- expand_all_questions
362
-
363
- within ".questionnaire-question:first-of-type" do
364
- fill_in find_nested_form_field_locator("body_en"), with: "Bye"
365
- click_link "Català", match: :first
366
-
367
- fill_in find_nested_form_field_locator("body_ca"), with: "Adeu"
368
- click_link "English", match: :first
369
-
370
- expect(page).to have_nested_field("body_en", with: "Bye")
371
- expect(page).to have_no_selector(nested_form_field_selector("body_ca"))
372
- expect(page).to have_no_content("Adeu")
373
- end
374
- end
375
-
376
- context "when adding a multiple option question" do
377
- before do
378
- visit questionnaire_edit_path
379
-
380
- within "form.edit_questionnaire" do
381
- click_button "Add question"
382
-
383
- expand_all_questions
384
-
385
- within ".questionnaire-question" do
386
- fill_in find_nested_form_field_locator("body_en"), with: "This is the first question"
387
- end
388
-
389
- expect(page).to have_no_content "Add answer option"
390
- expect(page).to have_no_select("Maximum number of choices")
391
- end
392
- end
393
-
394
- it "updates the free text option selector according to the selected question type" do
395
- expect(page).to have_no_selector("input[type=checkbox][id$=_free_text]")
396
-
397
- select "Multiple option", from: "Type"
398
- expect(page).to have_selector("input[type=checkbox][id$=_free_text]")
399
-
400
- select "Short answer", from: "Type"
401
- expect(page).to have_no_selector("input[type=checkbox][id$=_free_text]")
402
-
403
- select "Single option", from: "Type"
404
- expect(page).to have_selector("input[type=checkbox][id$=_free_text]")
405
- end
406
-
407
- it "updates the max choices selector according to the configured options" do
408
- expect(page).to have_no_select("Maximum number of choices")
409
-
410
- select "Multiple option", from: "Type"
411
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2))
412
-
413
- click_button "Add answer option"
414
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2 3))
415
-
416
- click_button "Add answer option"
417
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2 3 4))
418
-
419
- within(".questionnaire-question-answer-option:last-of-type") { click_button "Remove" }
420
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2 3))
421
-
422
- within(".questionnaire-question-answer-option:last-of-type") { click_button "Remove" }
423
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2))
424
-
425
- click_button "Add question"
426
- expand_all_questions
427
-
428
- within(".questionnaire-question:last-of-type") do
429
- select "Multiple option", from: "Type"
430
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2))
431
-
432
- select "Single option", from: "Type"
433
- expect(page).to have_no_select("Maximum number of choices")
434
- end
435
- end
436
- end
437
-
438
- context "when adding a matrix question" do
439
- before do
440
- visit questionnaire_edit_path
441
-
442
- within "form.edit_questionnaire" do
443
- click_button "Add question"
444
- expand_all_questions
445
-
446
- within ".questionnaire-question" do
447
- fill_in find_nested_form_field_locator("body_en"), with: "This is the first question"
448
- end
449
-
450
- expect(page).to have_no_content "Add answer option"
451
- expect(page).to have_no_content "Add row"
452
- expect(page).to have_no_select("Maximum number of choices")
453
- end
454
- end
455
-
456
- it "updates the free text option selector according to the selected question type" do
457
- expect(page).to have_no_selector("input[type=checkbox][id$=_free_text]")
458
-
459
- select "Matrix (Multiple option)", from: "Type"
460
- expect(page).to have_selector("input[type=checkbox][id$=_free_text]")
461
-
462
- select "Short answer", from: "Type"
463
- expect(page).to have_no_selector("input[type=checkbox][id$=_free_text]")
464
-
465
- select "Matrix (Single option)", from: "Type"
466
- expect(page).to have_selector("input[type=checkbox][id$=_free_text]")
467
- end
468
-
469
- it "updates the max choices selector according to the configured options" do
470
- expect(page).to have_no_select("Maximum number of choices")
471
-
472
- select "Matrix (Multiple option)", from: "Type"
473
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2))
474
-
475
- click_button "Add answer option"
476
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2 3))
477
-
478
- click_button "Add answer option"
479
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2 3 4))
480
-
481
- within(".questionnaire-question-answer-option:last-of-type") { click_button "Remove" }
482
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2 3))
483
-
484
- within(".questionnaire-question-answer-option:last-of-type") { click_button "Remove" }
485
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2))
486
-
487
- click_button "Add question"
488
- expand_all_questions
489
-
490
- within(".questionnaire-question:last-of-type") do
491
- select "Matrix (Multiple option)", from: "Type"
492
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2))
493
-
494
- select "Matrix (Single option)", from: "Type"
495
- expect(page).to have_no_select("Maximum number of choices")
496
- end
497
- end
498
- end
499
-
500
- context "when a questionnaire has an existing question" do
501
- let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, body: body) }
502
-
503
- before do
504
- visit questionnaire_edit_path
505
- expand_all_questions
506
- end
507
-
508
- it "modifies the question when the information is valid" do
509
- within "form.edit_questionnaire" do
510
- within ".questionnaire-question" do
511
- fill_in "questionnaire_questions_#{question.id}_body_en", with: "Modified question"
512
- check "Mandatory"
513
- select "Long answer", from: "Type"
514
- end
515
-
516
- click_button "Save"
517
- end
518
-
519
- expect(page).to have_admin_callout("successfully")
520
-
521
- visit_questionnaire_edit_path_and_expand_all
522
-
523
- expect(page).to have_selector("input[value='Modified question']")
524
- expect(page).to have_no_selector("input[value='This is the first question']")
525
- expect(page).to have_selector("input#questionnaire_questions_#{question.id}_mandatory[checked]")
526
- expect(page).to have_selector("select#questionnaire_questions_#{question.id}_question_type option[value='long_answer'][selected]")
527
- end
528
-
529
- it "re-renders the form when the information is invalid and displays errors" do
530
- expand_all_questions
531
-
532
- within "form.edit_questionnaire" do
533
- within ".questionnaire-question" do
534
- expect(page).to have_content("Statement*")
535
- fill_in "questionnaire_questions_#{question.id}_body_en", with: ""
536
- check "Mandatory"
537
- select "Matrix (Multiple option)", from: "Type"
538
- select "2", from: "Maximum number of choices"
539
- end
540
-
541
- click_button "Save"
542
- end
543
-
544
- expand_all_questions
545
-
546
- expect(page).to have_admin_callout("There was a problem saving")
547
- expect(page).to have_content("can't be blank", count: 5) # emtpy question, 2 empty default answer options, 2 empty default matrix rows
548
-
549
- expect(page).to have_selector("input[value='']")
550
- expect(page).to have_no_selector("input[value='This is the first question']")
551
- expect(page).to have_selector("input#questionnaire_questions_#{question.id}_mandatory[checked]")
552
- expect(page).to have_select("Maximum number of choices", selected: "2")
553
- expect(page).to have_selector("select#questionnaire_questions_#{question.id}_question_type option[value='matrix_multiple'][selected]")
554
- end
555
-
556
- it "preserves deleted status across submission failures" do
557
- within "form.edit_questionnaire" do
558
- within ".questionnaire-question" do
559
- click_button "Remove"
560
- end
561
- end
562
-
563
- click_button "Add question"
564
-
565
- click_button "Save"
566
-
567
- expect(page).to have_selector(".questionnaire-question", count: 1)
568
-
569
- within ".questionnaire-question" do
570
- expect(page).to have_selector(".card-title", text: "#1")
571
- expect(page).to have_no_button("Up")
572
- end
573
- end
574
-
575
- it "removes the question" do
576
- within "form.edit_questionnaire" do
577
- within ".questionnaire-question" do
578
- click_button "Remove"
579
- end
580
-
581
- click_button "Save"
582
- end
583
-
584
- expect(page).to have_admin_callout("successfully")
585
-
586
- visit questionnaire_edit_path
587
-
588
- within "form.edit_questionnaire" do
589
- expect(page).to have_selector(".questionnaire-question", count: 0)
590
- end
591
- end
592
-
593
- it "cannot be moved up" do
594
- within "form.edit_questionnaire" do
595
- within ".questionnaire-question" do
596
- expect(page).to have_no_button("Up")
597
- end
598
- end
599
- end
600
-
601
- it "cannot be moved down" do
602
- within "form.edit_questionnaire" do
603
- within ".questionnaire-question" do
604
- expect(page).to have_no_button("Down")
605
- end
606
- end
607
- end
608
- end
609
-
610
- context "when a questionnaire has an existing question with answer options" do
611
- let!(:question) do
612
- create(
613
- :questionnaire_question,
614
- questionnaire: questionnaire,
615
- body: body,
616
- question_type: "single_option",
617
- options: [
618
- { "body" => { "en" => "cacarua" } },
619
- { "body" => { "en" => "cat" } },
620
- { "body" => { "en" => "dog" } }
621
-
622
- ]
623
- )
624
- end
625
-
626
- before do
627
- visit questionnaire_edit_path
628
- end
629
-
630
- it "allows deleting answer options" do
631
- expand_all_questions
632
-
633
- within ".questionnaire-question-answer-option:last-of-type" do
634
- click_button "Remove"
635
- end
636
-
637
- click_button "Save"
638
-
639
- visit_questionnaire_edit_path_and_expand_all
640
-
641
- expect(page).to have_selector(".questionnaire-question-answer-option", count: 2)
642
- end
643
-
644
- it "still removes the question even if previous editions rendered the options invalid" do
645
- within "form.edit_questionnaire" do
646
- expect(page).to have_selector(".questionnaire-question", count: 1)
647
-
648
- expand_all_questions
649
-
650
- within ".questionnaire-question-answer-option:first-of-type" do
651
- fill_in find_nested_form_field_locator("body_en"), with: ""
652
- end
653
-
654
- within ".questionnaire-question" do
655
- click_button "Remove", match: :first
656
- end
657
-
658
- click_button "Save"
659
- end
660
-
661
- expect(page).to have_admin_callout("successfully")
662
-
663
- visit_questionnaire_edit_path_and_expand_all
664
-
665
- within "form.edit_questionnaire" do
666
- expect(page).to have_selector(".questionnaire-question", count: 0)
667
- end
668
- end
669
- end
670
-
671
- context "when a questionnaire has an existing question with matrix rows" do
672
- let!(:other_question) { create(:questionnaire_question, questionnaire: questionnaire, position: 1) }
673
- let!(:question) do
674
- create(
675
- :questionnaire_question,
676
- questionnaire: questionnaire,
677
- body: body,
678
- question_type: "matrix_single",
679
- position: 2,
680
- options: [
681
- { "body" => { "en" => "cacarua" } },
682
- { "body" => { "en" => "cat" } },
683
- { "body" => { "en" => "dog" } }
684
- ],
685
- rows: [
686
- { "body" => { "en" => "cute" } },
687
- { "body" => { "en" => "ugly" } },
688
- { "body" => { "en" => "meh" } }
689
- ]
690
- )
691
- end
692
-
693
- before do
694
- visit_questionnaire_edit_path_and_expand_all
695
- end
696
-
697
- it "allows deleting matrix rows" do
698
- within ".questionnaire-question-matrix-row:last-of-type" do
699
- click_button "Remove"
700
- end
701
-
702
- click_button "Save"
703
-
704
- visit_questionnaire_edit_path_and_expand_all
705
-
706
- within ".questionnaire-question:last-of-type" do
707
- expect(page).to have_selector(".questionnaire-question-matrix-row", count: 2)
708
- expect(page).to have_selector(".questionnaire-question-answer-option", count: 3)
709
- end
710
- end
711
-
712
- it "still removes the question even if previous editions rendered the rows invalid" do
713
- within "form.edit_questionnaire" do
714
- expect(page).to have_selector(".questionnaire-question", count: 2)
715
-
716
- within ".questionnaire-question-matrix-row:first-of-type" do
717
- fill_in find_nested_form_field_locator("body_en"), with: ""
718
- end
719
-
720
- within ".questionnaire-question:last-of-type" do
721
- click_button "Remove", match: :first
722
- end
723
-
724
- click_button "Save"
725
- end
726
-
727
- expect(page).to have_admin_callout("successfully")
728
-
729
- visit_questionnaire_edit_path_and_expand_all
730
-
731
- within "form.edit_questionnaire" do
732
- expect(page).to have_selector(".questionnaire-question", count: 1)
733
- end
734
- end
735
- end
736
-
737
- context "when a questionnaire has multiple existing questions" do
738
- let!(:question_1) do
739
- create(:questionnaire_question, questionnaire: questionnaire, body: first_body, position: 0)
740
- end
741
-
742
- let!(:question_2) do
743
- create(:questionnaire_question, questionnaire: questionnaire, body: second_body, position: 1)
744
- end
745
-
746
- let(:first_body) do
747
- { en: "First", ca: "Primera", es: "Primera" }
748
- end
749
-
750
- let(:second_body) do
751
- { en: "Second", ca: "Segunda", es: "Segunda" }
752
- end
753
-
754
- before do
755
- visit questionnaire_edit_path
756
- expand_all_questions
757
- end
758
-
759
- shared_examples_for "switching questions order" do
760
- it "properly reorders the questions" do
761
- within ".questionnaire-question:first-of-type" do
762
- expect(page).to have_nested_field("body_en", with: "Second")
763
- expect(page).to look_like_first_question
764
- end
765
-
766
- within ".questionnaire-question:last-of-type" do
767
- expect(page).to have_nested_field("body_en", with: "First")
768
- expect(page).to look_like_last_question
769
- end
770
- end
771
- end
772
-
773
- context "when moving a question up" do
774
- before do
775
- within ".questionnaire-question:last-of-type" do
776
- click_button "Up"
777
- end
778
- end
779
-
780
- it_behaves_like "switching questions order"
781
- end
782
-
783
- context "when moving a question down" do
784
- before do
785
- within ".questionnaire-question:first-of-type" do
786
- click_button "Down"
787
- end
788
- end
789
-
790
- it_behaves_like "switching questions order"
791
- end
792
-
793
- describe "collapsible questions" do
794
- context "when clicking on Expand all button" do
795
- it "expands all questions" do
796
- click_button "Expand all questions"
797
- expect(page).to have_selector(".collapsible", visible: :visible)
798
- expect(page).to have_selector(".question--collapse .icon-collapse", count: questionnaire.questions.count)
799
- end
800
- end
801
-
802
- context "when clicking on Collapse all button" do
803
- it "collapses all questions" do
804
- click_button "Collapse all questions"
805
- expect(page).not_to have_selector(".collapsible", visible: :visible)
806
- expect(page).to have_selector(".question--collapse .icon-expand", count: questionnaire.questions.count)
807
- end
808
- end
809
-
810
- shared_examples_for "collapsing a question" do
811
- it "changes the toggle button" do
812
- within ".questionnaire-question:last-of-type" do
813
- expect(page).to have_selector(".icon-expand")
814
- end
815
- end
816
-
817
- it "hides the question card section" do
818
- within ".questionnaire-question:last-of-type" do
819
- expect(page).not_to have_selector(".collapsible", visible: :visible)
820
- end
821
- end
822
- end
823
-
824
- shared_examples_for "uncollapsing a question" do
825
- it "changes the toggle button" do
826
- within ".questionnaire-question:last-of-type" do
827
- expect(page).to have_selector(".icon-collapse")
828
- end
829
- end
830
-
831
- it "shows the question card section" do
832
- expect(page).to have_selector(".collapsible", visible: :visible)
833
- end
834
- end
835
-
836
- context "when collapsing an existing question" do
837
- before do
838
- expand_all_questions
839
- within ".questionnaire-question:last-of-type" do
840
- page.find(".question--collapse").click
841
- end
842
- end
843
-
844
- it_behaves_like "collapsing a question"
845
- end
846
-
847
- context "when adding a new question" do
848
- before do
849
- click_button "Add question"
850
- expand_all_questions
851
-
852
- within ".questionnaire-question:last-of-type" do
853
- page.find(".question--collapse").click
854
- end
855
- end
856
-
857
- it_behaves_like "collapsing a question"
858
- end
859
- end
860
-
861
- it "properly decides which button to show after adding/removing questions" do
862
- click_button "Add question"
863
- expand_all_questions
864
-
865
- expect(page.find(".questionnaire-question:nth-of-type(1)")).to look_like_first_question
866
- expect(page.find(".questionnaire-question:nth-of-type(2)")).to look_like_intermediate_question
867
- expect(page.find(".questionnaire-question:nth-of-type(3)")).to look_like_last_question
868
-
869
- within ".questionnaire-question:first-of-type" do
870
- click_button "Remove"
871
- end
872
-
873
- expect(page.all(".questionnaire-question").first).to look_like_first_question
874
- expect(page.all(".questionnaire-question").last).to look_like_last_question
875
- end
876
-
877
- it "does not duplicate editors when adding new questions" do
878
- expect do
879
- click_button "Add question"
880
- expand_all_questions
881
- end.to change { page.all(".ql-toolbar").size }.by(1)
882
- end
883
-
884
- it "properly decides which button to show after adding/removing answer options" do
885
- click_button "Add question"
886
- expand_all_questions
887
-
888
- within ".questionnaire-question:last-of-type" do
889
- select "Single option", from: "Type"
890
-
891
- within ".questionnaire-question-answer-options-list" do
892
- expect(page).to have_no_button("Remove")
893
- end
894
-
895
- click_button "Add answer option"
896
-
897
- expect(page.all(".questionnaire-question-answer-option")).to all(have_button("Remove"))
898
-
899
- within ".questionnaire-question-answer-option:first-of-type" do
900
- click_button "Remove"
901
- end
902
-
903
- within ".questionnaire-question-answer-options-list" do
904
- expect(page).to have_no_button("Remove")
905
- end
906
- end
907
-
908
- click_button "Save"
909
- expand_all_questions
910
-
911
- within ".questionnaire-question:last-of-type" do
912
- within ".questionnaire-question-answer-options-list" do
913
- expect(page).to have_no_button("Remove")
914
- end
915
- end
916
- end
917
-
918
- private
919
-
920
- def look_like_first_question
921
- have_no_button("Up").and have_button("Down")
922
- end
923
-
924
- def look_like_intermediate_question
925
- have_button("Up").and have_button("Down")
926
- end
927
-
928
- def look_like_last_question
929
- have_button("Up").and have_no_button("Down")
930
- end
931
- end
45
+ it_behaves_like "add questions"
46
+ it_behaves_like "update questions"
47
+ it_behaves_like "add display conditions"
48
+ it_behaves_like "update display conditions"
932
49
  end
933
50
 
934
51
  context "when the questionnaire is already answered" do
@@ -952,11 +69,11 @@ shared_examples_for "manage questionnaires" do
952
69
 
953
70
  private
954
71
 
955
- def find_nested_form_field_locator(attribute, visible: true)
72
+ def find_nested_form_field_locator(attribute, visible: :visible)
956
73
  find_nested_form_field(attribute, visible: visible)["id"]
957
74
  end
958
75
 
959
- def find_nested_form_field(attribute, visible: true)
76
+ def find_nested_form_field(attribute, visible: :visible)
960
77
  current_scope.find(nested_form_field_selector(attribute), visible: visible)
961
78
  end
962
79
 
@@ -972,6 +89,16 @@ shared_examples_for "manage questionnaires" do
972
89
  "[id$=#{attribute}]"
973
90
  end
974
91
 
92
+ def within_add_display_condition
93
+ within ".questionnaire-question:last-of-type" do
94
+ click_button "Add display condition"
95
+
96
+ within ".questionnaire-question-display-condition:last-of-type" do
97
+ yield
98
+ end
99
+ end
100
+ end
101
+
975
102
  def expand_all_questions
976
103
  find(".button.expand-all").click
977
104
  end