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
@@ -37,15 +37,19 @@ shared_examples_for "manage questionnaires" do
37
37
  visit questionnaire_edit_path
38
38
  end
39
39
 
40
- it "adds a few questions to the questionnaire" do
40
+ it "adds a few questions and separators to the questionnaire" do
41
41
  questions_body = ["This is the first question", "This is the second question"]
42
42
 
43
43
  within "form.edit_questionnaire" do
44
- 2.times { click_button "Add question" }
44
+ click_button "Add question"
45
+ click_button "Add separator"
46
+ click_button "Add question"
45
47
 
46
- expect(page).to have_selector(".questionnaire-question", count: 2)
48
+ expect(page).to have_selector(".questionnaire-question", count: 3)
47
49
 
48
- page.all(".questionnaire-question").each_with_index do |question, idx|
50
+ expand_all_questions
51
+
52
+ page.all(".questionnaire-question .collapsible").each_with_index do |question, idx|
49
53
  within question do
50
54
  fill_in find_nested_form_field_locator("body_en"), with: questions_body[idx]
51
55
  end
@@ -56,20 +60,22 @@ shared_examples_for "manage questionnaires" do
56
60
 
57
61
  expect(page).to have_admin_callout("successfully")
58
62
 
59
- visit questionnaire_edit_path
63
+ visit_questionnaire_edit_path_and_expand_all
60
64
 
61
65
  expect(page).to have_selector("input[value='This is the first question']")
62
66
  expect(page).to have_selector("input[value='This is the second question']")
67
+ expect(page).to have_content("Separator #2")
63
68
  end
64
69
 
65
70
  it "adds a question with a rich text description" do
66
71
  within "form.edit_questionnaire" do
67
72
  click_button "Add question"
73
+ expand_all_questions
68
74
 
69
75
  within ".questionnaire-question" do
70
76
  fill_in find_nested_form_field_locator("body_en"), with: "Body"
71
77
 
72
- fill_in_editor find_nested_form_field_locator("description_en", visible: false), with: "<b>Superkalifragilistic description</b>"
78
+ fill_in_editor find_nested_form_field_locator("description_en", visible: :all), with: "<b>Superkalifragilistic description</b>"
73
79
  end
74
80
 
75
81
  click_button "Save"
@@ -108,6 +114,7 @@ shared_examples_for "manage questionnaires" do
108
114
  within "form.edit_questionnaire" do
109
115
  click_button "Add question"
110
116
  click_button "Add question"
117
+ expand_all_questions
111
118
 
112
119
  page.all(".questionnaire-question").each_with_index do |question, idx|
113
120
  within question do
@@ -137,7 +144,7 @@ shared_examples_for "manage questionnaires" do
137
144
 
138
145
  expect(page).to have_admin_callout("successfully")
139
146
 
140
- visit questionnaire_edit_path
147
+ visit_questionnaire_edit_path_and_expand_all
141
148
 
142
149
  expect(page).to have_selector("input[value='This is the first question']")
143
150
  expect(page).to have_selector("input[value='This is the Q1 first option']")
@@ -151,25 +158,37 @@ shared_examples_for "manage questionnaires" do
151
158
 
152
159
  it "adds a sane number of options for each attribute type" do
153
160
  click_button "Add question"
161
+ expand_all_questions
154
162
 
155
163
  select "Long answer", from: "Type"
156
164
  expect(page).to have_no_selector(".questionnaire-question-answer-option")
165
+ expect(page).to have_no_selector(".questionnaire-question-matrix-row")
157
166
 
158
167
  select "Single option", from: "Type"
159
168
  expect(page).to have_selector(".questionnaire-question-answer-option", count: 2)
169
+ expect(page).to have_no_selector(".questionnaire-question-matrix-row")
160
170
 
161
171
  select "Multiple option", from: "Type"
162
172
  expect(page).to have_selector(".questionnaire-question-answer-option", count: 2)
173
+ expect(page).to have_no_selector(".questionnaire-question-matrix-row")
163
174
 
164
- select "Single option", from: "Type"
175
+ select "Matrix (Multiple option)", from: "Type"
165
176
  expect(page).to have_selector(".questionnaire-question-answer-option", count: 2)
177
+ expect(page).to have_selector(".questionnaire-question-matrix-row", count: 2)
166
178
 
167
179
  select "Short answer", from: "Type"
168
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)
169
186
  end
170
187
 
171
188
  it "does not incorrectly reorder when clicking answer options" do
172
189
  click_button "Add question"
190
+ expand_all_questions
191
+
173
192
  select "Single option", from: "Type"
174
193
  2.times { click_button "Add answer option" }
175
194
 
@@ -196,16 +215,53 @@ shared_examples_for "manage questionnaires" do
196
215
  end
197
216
  end
198
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
+
199
250
  it "preserves question form across submission failures" do
200
251
  click_button "Add question"
252
+ expand_all_questions
253
+
201
254
  select "Long answer", from: "Type"
202
255
  click_button "Save"
203
256
 
257
+ expand_all_questions
204
258
  expect(page).to have_select("Type", selected: "Long answer")
205
259
  end
206
260
 
207
261
  it "does not preserve spurious answer options from previous type selections" do
208
262
  click_button "Add question"
263
+ expand_all_questions
264
+
209
265
  select "Single option", from: "Type"
210
266
 
211
267
  within ".questionnaire-question-answer-option:first-of-type" do
@@ -215,6 +271,7 @@ shared_examples_for "manage questionnaires" do
215
271
  select "Long answer", from: "Type"
216
272
 
217
273
  click_button "Save"
274
+ expand_all_questions
218
275
 
219
276
  select "Single option", from: "Type"
220
277
 
@@ -223,8 +280,32 @@ shared_examples_for "manage questionnaires" do
223
280
  end
224
281
  end
225
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
+
226
305
  it "preserves answer options form across submission failures" do
227
306
  click_button "Add question"
307
+ expand_all_questions
308
+
228
309
  select "Multiple option", from: "Type"
229
310
 
230
311
  within ".questionnaire-question-answer-option:first-of-type" do
@@ -240,6 +321,7 @@ shared_examples_for "manage questionnaires" do
240
321
  select "3", from: "Maximum number of choices"
241
322
 
242
323
  click_button "Save"
324
+ expand_all_questions
243
325
 
244
326
  within ".questionnaire-question-answer-option:first-of-type" do
245
327
  expect(page).to have_nested_field("body_en", with: "Something")
@@ -252,10 +334,32 @@ shared_examples_for "manage questionnaires" do
252
334
  expect(page).to have_select("Maximum number of choices", selected: "3")
253
335
  end
254
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
+
255
357
  it "allows switching translated field tabs after form failures" do
256
358
  click_button "Add question"
257
359
  click_button "Save"
258
360
 
361
+ expand_all_questions
362
+
259
363
  within ".questionnaire-question:first-of-type" do
260
364
  fill_in find_nested_form_field_locator("body_en"), with: "Bye"
261
365
  click_link "Català", match: :first
@@ -276,6 +380,8 @@ shared_examples_for "manage questionnaires" do
276
380
  within "form.edit_questionnaire" do
277
381
  click_button "Add question"
278
382
 
383
+ expand_all_questions
384
+
279
385
  within ".questionnaire-question" do
280
386
  fill_in find_nested_form_field_locator("body_en"), with: "This is the first question"
281
387
  end
@@ -317,6 +423,7 @@ shared_examples_for "manage questionnaires" do
317
423
  expect(page).to have_select("Maximum number of choices", options: %w(Any 2))
318
424
 
319
425
  click_button "Add question"
426
+ expand_all_questions
320
427
 
321
428
  within(".questionnaire-question:last-of-type") do
322
429
  select "Multiple option", from: "Type"
@@ -328,11 +435,74 @@ shared_examples_for "manage questionnaires" do
328
435
  end
329
436
  end
330
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
+
331
500
  context "when a questionnaire has an existing question" do
332
501
  let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, body: body) }
333
502
 
334
503
  before do
335
504
  visit questionnaire_edit_path
505
+ expand_all_questions
336
506
  end
337
507
 
338
508
  it "modifies the question when the information is valid" do
@@ -348,7 +518,7 @@ shared_examples_for "manage questionnaires" do
348
518
 
349
519
  expect(page).to have_admin_callout("successfully")
350
520
 
351
- visit questionnaire_edit_path
521
+ visit_questionnaire_edit_path_and_expand_all
352
522
 
353
523
  expect(page).to have_selector("input[value='Modified question']")
354
524
  expect(page).to have_no_selector("input[value='This is the first question']")
@@ -357,26 +527,30 @@ shared_examples_for "manage questionnaires" do
357
527
  end
358
528
 
359
529
  it "re-renders the form when the information is invalid and displays errors" do
530
+ expand_all_questions
531
+
360
532
  within "form.edit_questionnaire" do
361
533
  within ".questionnaire-question" do
362
534
  expect(page).to have_content("Statement*")
363
535
  fill_in "questionnaire_questions_#{question.id}_body_en", with: ""
364
536
  check "Mandatory"
365
- select "Multiple option", from: "Type"
537
+ select "Matrix (Multiple option)", from: "Type"
366
538
  select "2", from: "Maximum number of choices"
367
539
  end
368
540
 
369
541
  click_button "Save"
370
542
  end
371
543
 
544
+ expand_all_questions
545
+
372
546
  expect(page).to have_admin_callout("There was a problem saving")
373
- expect(page).to have_content("can't be blank", count: 3) # emtpy question, 2 empty default answer options
547
+ expect(page).to have_content("can't be blank", count: 5) # emtpy question, 2 empty default answer options, 2 empty default matrix rows
374
548
 
375
549
  expect(page).to have_selector("input[value='']")
376
550
  expect(page).to have_no_selector("input[value='This is the first question']")
377
551
  expect(page).to have_selector("input#questionnaire_questions_#{question.id}_mandatory[checked]")
378
552
  expect(page).to have_select("Maximum number of choices", selected: "2")
379
- expect(page).to have_selector("select#questionnaire_questions_#{question.id}_question_type option[value='multiple_option'][selected]")
553
+ expect(page).to have_selector("select#questionnaire_questions_#{question.id}_question_type option[value='matrix_multiple'][selected]")
380
554
  end
381
555
 
382
556
  it "preserves deleted status across submission failures" do
@@ -454,13 +628,15 @@ shared_examples_for "manage questionnaires" do
454
628
  end
455
629
 
456
630
  it "allows deleting answer options" do
631
+ expand_all_questions
632
+
457
633
  within ".questionnaire-question-answer-option:last-of-type" do
458
634
  click_button "Remove"
459
635
  end
460
636
 
461
637
  click_button "Save"
462
638
 
463
- visit questionnaire_edit_path
639
+ visit_questionnaire_edit_path_and_expand_all
464
640
 
465
641
  expect(page).to have_selector(".questionnaire-question-answer-option", count: 2)
466
642
  end
@@ -469,6 +645,8 @@ shared_examples_for "manage questionnaires" do
469
645
  within "form.edit_questionnaire" do
470
646
  expect(page).to have_selector(".questionnaire-question", count: 1)
471
647
 
648
+ expand_all_questions
649
+
472
650
  within ".questionnaire-question-answer-option:first-of-type" do
473
651
  fill_in find_nested_form_field_locator("body_en"), with: ""
474
652
  end
@@ -482,7 +660,7 @@ shared_examples_for "manage questionnaires" do
482
660
 
483
661
  expect(page).to have_admin_callout("successfully")
484
662
 
485
- visit questionnaire_edit_path
663
+ visit_questionnaire_edit_path_and_expand_all
486
664
 
487
665
  within "form.edit_questionnaire" do
488
666
  expect(page).to have_selector(".questionnaire-question", count: 0)
@@ -490,6 +668,72 @@ shared_examples_for "manage questionnaires" do
490
668
  end
491
669
  end
492
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
+
493
737
  context "when a questionnaire has multiple existing questions" do
494
738
  let!(:question_1) do
495
739
  create(:questionnaire_question, questionnaire: questionnaire, body: first_body, position: 0)
@@ -509,6 +753,7 @@ shared_examples_for "manage questionnaires" do
509
753
 
510
754
  before do
511
755
  visit questionnaire_edit_path
756
+ expand_all_questions
512
757
  end
513
758
 
514
759
  shared_examples_for "switching questions order" do
@@ -545,8 +790,77 @@ shared_examples_for "manage questionnaires" do
545
790
  it_behaves_like "switching questions order"
546
791
  end
547
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
+
548
861
  it "properly decides which button to show after adding/removing questions" do
549
862
  click_button "Add question"
863
+ expand_all_questions
550
864
 
551
865
  expect(page.find(".questionnaire-question:nth-of-type(1)")).to look_like_first_question
552
866
  expect(page.find(".questionnaire-question:nth-of-type(2)")).to look_like_intermediate_question
@@ -561,11 +875,15 @@ shared_examples_for "manage questionnaires" do
561
875
  end
562
876
 
563
877
  it "does not duplicate editors when adding new questions" do
564
- expect { click_button "Add question" }.to change { page.all(".ql-toolbar").size }.by(1)
878
+ expect do
879
+ click_button "Add question"
880
+ expand_all_questions
881
+ end.to change { page.all(".ql-toolbar").size }.by(1)
565
882
  end
566
883
 
567
884
  it "properly decides which button to show after adding/removing answer options" do
568
885
  click_button "Add question"
886
+ expand_all_questions
569
887
 
570
888
  within ".questionnaire-question:last-of-type" do
571
889
  select "Single option", from: "Type"
@@ -588,6 +906,7 @@ shared_examples_for "manage questionnaires" do
588
906
  end
589
907
 
590
908
  click_button "Save"
909
+ expand_all_questions
591
910
 
592
911
  within ".questionnaire-question:last-of-type" do
593
912
  within ".questionnaire-question-answer-options-list" do
@@ -621,6 +940,9 @@ shared_examples_for "manage questionnaires" do
621
940
 
622
941
  expect(page).to have_no_content("Add question")
623
942
  expect(page).to have_no_content("Remove")
943
+
944
+ expand_all_questions
945
+
624
946
  expect(page).to have_selector("input[value='This is the first question'][disabled]")
625
947
  expect(page).to have_selector("select[id$=question_type][disabled]")
626
948
  expect(page).to have_selector("select[id$=max_choices][disabled]")
@@ -649,4 +971,13 @@ shared_examples_for "manage questionnaires" do
649
971
  def nested_form_field_selector(attribute)
650
972
  "[id$=#{attribute}]"
651
973
  end
974
+
975
+ def expand_all_questions
976
+ find(".button.expand-all").click
977
+ end
978
+
979
+ def visit_questionnaire_edit_path_and_expand_all
980
+ visit questionnaire_edit_path
981
+ expand_all_questions
982
+ end
652
983
  end