decidim-forms 0.22.0 → 0.23.0

Sign up to get free protection for your applications and to get access to all the features.
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