decidim-forms 0.21.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/admin/decidim_forms_manifest.js +1 -0
  3. data/app/assets/images/decidim/surveys/icon.svg +1 -19
  4. data/app/assets/javascripts/decidim/forms/admin/collapsible_questions.js.es6 +13 -0
  5. data/app/assets/javascripts/decidim/forms/admin/forms.js.es6 +95 -7
  6. data/app/assets/javascripts/decidim/forms/admin/live_text_update.component.js.es6 +52 -0
  7. data/app/assets/javascripts/decidim/forms/forms.js.es6 +42 -1
  8. data/app/assets/javascripts/decidim/forms/max_choices_alert.component.js.es6 +44 -0
  9. data/app/assets/stylesheets/decidim/forms/forms.scss +39 -0
  10. data/app/cells/decidim/forms/matrix_readonly/show.erb +5 -0
  11. data/app/cells/decidim/forms/matrix_readonly_cell.rb +12 -0
  12. data/app/cells/decidim/forms/question_readonly/show.erb +5 -1
  13. data/app/cells/decidim/forms/question_readonly_cell.rb +5 -0
  14. data/app/cells/decidim/forms/step_navigation/show.erb +35 -0
  15. data/app/cells/decidim/forms/step_navigation_cell.rb +46 -0
  16. data/app/commands/decidim/forms/admin/update_questionnaire.rb +8 -0
  17. data/app/commands/decidim/forms/answer_questionnaire.rb +2 -1
  18. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +6 -2
  19. data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +11 -2
  20. data/app/forms/decidim/forms/admin/question_form.rb +20 -1
  21. data/app/forms/decidim/forms/admin/question_matrix_row_form.rb +26 -0
  22. data/app/forms/decidim/forms/answer_choice_form.rb +1 -0
  23. data/app/forms/decidim/forms/answer_form.rb +16 -2
  24. data/app/forms/decidim/forms/questionnaire_form.rb +25 -3
  25. data/app/helpers/decidim/forms/admin/application_helper.rb +16 -0
  26. data/app/models/decidim/forms/answer_choice.rb +7 -0
  27. data/app/models/decidim/forms/question.rb +18 -2
  28. data/app/models/decidim/forms/question_matrix_row.rb +12 -0
  29. data/app/views/decidim/forms/admin/questionnaires/_answer_option_template.html.erb +1 -1
  30. data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +37 -4
  31. data/app/views/decidim/forms/admin/questionnaires/_matrix_row.html.erb +34 -0
  32. data/app/views/decidim/forms/admin/questionnaires/_matrix_row_template.html.erb +7 -0
  33. data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +29 -6
  34. data/app/views/decidim/forms/admin/questionnaires/_separator.html.erb +41 -0
  35. data/app/views/decidim/forms/questionnaires/_answer.html.erb +21 -92
  36. data/app/views/decidim/forms/questionnaires/answers/_long_answer.html.erb +1 -0
  37. data/app/views/decidim/forms/questionnaires/answers/_matrix_multiple.html.erb +43 -0
  38. data/app/views/decidim/forms/questionnaires/answers/_matrix_single.html.erb +43 -0
  39. data/app/views/decidim/forms/questionnaires/answers/_multiple_option.html.erb +23 -0
  40. data/app/views/decidim/forms/questionnaires/answers/_separator.html.erb +1 -0
  41. data/app/views/decidim/forms/questionnaires/answers/_short_answer.html.erb +1 -0
  42. data/app/views/decidim/forms/questionnaires/answers/_single_option.html.erb +30 -0
  43. data/app/views/decidim/forms/questionnaires/answers/_sorting.html.erb +23 -0
  44. data/app/views/decidim/forms/questionnaires/show.html.erb +57 -25
  45. data/config/locales/ar.yml +7 -3
  46. data/config/locales/bg-BG.yml +16 -0
  47. data/config/locales/ca.yml +35 -3
  48. data/config/locales/cs.yml +35 -3
  49. data/config/locales/da-DK.yml +1 -0
  50. data/config/locales/de.yml +41 -3
  51. data/config/locales/el.yml +119 -0
  52. data/config/locales/en.yml +35 -3
  53. data/config/locales/es-MX.yml +35 -3
  54. data/config/locales/es-PY.yml +35 -3
  55. data/config/locales/es.yml +35 -3
  56. data/config/locales/et-EE.yml +1 -0
  57. data/config/locales/eu.yml +7 -3
  58. data/config/locales/fi-plain.yml +35 -3
  59. data/config/locales/fi.yml +36 -4
  60. data/config/locales/fr-CA.yml +120 -0
  61. data/config/locales/fr.yml +36 -4
  62. data/config/locales/ga-IE.yml +1 -0
  63. data/config/locales/gl.yml +7 -3
  64. data/config/locales/hr-HR.yml +1 -0
  65. data/config/locales/hu.yml +11 -3
  66. data/config/locales/id-ID.yml +7 -3
  67. data/config/locales/it.yml +36 -4
  68. data/config/locales/ja-JP.yml +120 -0
  69. data/config/locales/lt-LT.yml +1 -0
  70. data/config/locales/lv-LV.yml +119 -0
  71. data/config/locales/mt-MT.yml +1 -0
  72. data/config/locales/nl.yml +35 -3
  73. data/config/locales/no.yml +7 -3
  74. data/config/locales/pl.yml +63 -25
  75. data/config/locales/pt-BR.yml +8 -4
  76. data/config/locales/pt.yml +62 -24
  77. data/config/locales/ro-RO.yml +118 -0
  78. data/config/locales/ru.yml +4 -1
  79. data/config/locales/sk-SK.yml +88 -0
  80. data/config/locales/sk.yml +92 -0
  81. data/config/locales/sl.yml +5 -0
  82. data/config/locales/sr-CS.yml +1 -0
  83. data/config/locales/sv.yml +38 -6
  84. data/config/locales/tr-TR.yml +7 -3
  85. data/db/migrate/20200225123810_create_decidim_forms_question_matrix_rows.rb +11 -0
  86. data/db/migrate/20200304152939_add_matrix_row_id_to_decidim_forms_answer_choices.rb +11 -0
  87. data/lib/decidim/forms/test/factories.rb +20 -0
  88. data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +313 -36
  89. data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +346 -15
  90. data/lib/decidim/forms/user_answers_serializer.rb +21 -4
  91. data/lib/decidim/forms/version.rb +1 -1
  92. metadata +45 -8
@@ -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