decidim-forms 0.19.1 → 0.23.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/assets/config/admin/decidim_forms_manifest.css +3 -0
  4. data/app/assets/config/admin/decidim_forms_manifest.js +1 -0
  5. data/app/assets/config/decidim_forms_manifest.css +1 -0
  6. data/app/assets/images/decidim/surveys/icon.svg +1 -19
  7. data/app/assets/javascripts/decidim/forms/admin/auto_select_options_from_url.component.js.es6 +40 -0
  8. data/app/assets/javascripts/decidim/forms/admin/collapsible_questions.js.es6 +13 -0
  9. data/app/assets/javascripts/decidim/forms/admin/forms.js.es6 +260 -16
  10. data/app/assets/javascripts/decidim/forms/admin/live_text_update.component.js.es6 +52 -0
  11. data/app/assets/javascripts/decidim/forms/autosortable_checkboxes.component.js.es6 +54 -34
  12. data/app/assets/javascripts/decidim/forms/display_conditions.component.js.es6 +204 -0
  13. data/app/assets/javascripts/decidim/forms/forms.js.es6 +49 -1
  14. data/app/assets/javascripts/decidim/forms/max_choices_alert.component.js.es6 +44 -0
  15. data/app/assets/stylesheets/decidim/forms/forms.scss +39 -0
  16. data/app/assets/stylesheets/decidim/forms/questionnaire-answers-pdf.scss +69 -0
  17. data/app/cells/decidim/forms/matrix_readonly/show.erb +5 -0
  18. data/app/cells/decidim/forms/matrix_readonly_cell.rb +12 -0
  19. data/app/cells/decidim/forms/question_readonly/show.erb +5 -1
  20. data/app/cells/decidim/forms/question_readonly_cell.rb +5 -0
  21. data/app/cells/decidim/forms/step_navigation/show.erb +35 -0
  22. data/app/cells/decidim/forms/step_navigation_cell.rb +46 -0
  23. data/app/commands/decidim/forms/admin/update_questionnaire.rb +33 -1
  24. data/app/commands/decidim/forms/answer_questionnaire.rb +7 -2
  25. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +52 -2
  26. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire_answers.rb +97 -0
  27. data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +58 -2
  28. data/app/forms/decidim/forms/admin/display_condition_form.rb +100 -0
  29. data/app/forms/decidim/forms/admin/question_form.rb +21 -1
  30. data/app/forms/decidim/forms/admin/question_matrix_row_form.rb +26 -0
  31. data/app/forms/decidim/forms/answer_choice_form.rb +1 -0
  32. data/app/forms/decidim/forms/answer_form.rb +31 -2
  33. data/app/forms/decidim/forms/questionnaire_form.rb +33 -3
  34. data/app/helpers/decidim/forms/admin/application_helper.rb +37 -0
  35. data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_pagination_helper.rb +49 -0
  36. data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_url_helper.rb +40 -0
  37. data/app/helpers/decidim/forms/admin/questionnaire_answers_helper.rb +27 -0
  38. data/app/jobs/decidim/forms/export_questionnaire_answers_job.rb +19 -0
  39. data/app/models/decidim/forms/answer.rb +2 -5
  40. data/app/models/decidim/forms/answer_choice.rb +7 -0
  41. data/app/models/decidim/forms/answer_option.rb +14 -0
  42. data/app/models/decidim/forms/display_condition.rb +51 -0
  43. data/app/models/decidim/forms/question.rb +52 -2
  44. data/app/models/decidim/forms/question_matrix_row.rb +15 -0
  45. data/app/models/decidim/forms/questionnaire.rb +13 -2
  46. data/app/presenters/decidim/forms/admin/questionnaire_answer_presenter.rb +43 -0
  47. data/app/presenters/decidim/forms/admin/questionnaire_participant_presenter.rb +60 -0
  48. data/app/presenters/decidim/forms/answer_option_presenter.rb +20 -0
  49. data/app/presenters/decidim/forms/question_presenter.rb +16 -0
  50. data/app/queries/decidim/forms/questionnaire_participant.rb +35 -0
  51. data/app/queries/decidim/forms/questionnaire_participants.rb +43 -0
  52. data/app/queries/decidim/forms/questionnaire_user_answers.rb +1 -1
  53. data/app/types/decidim/forms/answer_option_type.rb +14 -0
  54. data/app/types/decidim/forms/question_type.rb +23 -0
  55. data/app/types/decidim/forms/questionnaire_type.rb +22 -0
  56. data/app/views/decidim/forms/admin/questionnaires/_answer_option_template.html.erb +1 -1
  57. data/app/views/decidim/forms/admin/questionnaires/_display_condition.html.erb +88 -0
  58. data/app/views/decidim/forms/admin/questionnaires/_display_condition_template.html.erb +7 -0
  59. data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +67 -8
  60. data/app/views/decidim/forms/admin/questionnaires/_matrix_row.html.erb +34 -0
  61. data/app/views/decidim/forms/admin/questionnaires/_matrix_row_template.html.erb +7 -0
  62. data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +45 -6
  63. data/app/views/decidim/forms/admin/questionnaires/_separator.html.erb +41 -0
  64. data/app/views/decidim/forms/admin/questionnaires/answers/export/_answer.html.erb +31 -0
  65. data/app/views/decidim/forms/admin/questionnaires/answers/export/pdf.html.erb +13 -0
  66. data/app/views/decidim/forms/admin/questionnaires/answers/index.html.erb +53 -0
  67. data/app/views/decidim/forms/admin/questionnaires/answers/show.html.erb +48 -0
  68. data/app/views/decidim/forms/admin/questionnaires/edit.html.erb +9 -5
  69. data/app/views/decidim/forms/questionnaires/_answer.html.erb +28 -99
  70. data/app/views/decidim/forms/questionnaires/answers/_long_answer.html.erb +1 -0
  71. data/app/views/decidim/forms/questionnaires/answers/_matrix_multiple.html.erb +43 -0
  72. data/app/views/decidim/forms/questionnaires/answers/_matrix_single.html.erb +43 -0
  73. data/app/views/decidim/forms/questionnaires/answers/_multiple_option.html.erb +23 -0
  74. data/app/views/decidim/forms/questionnaires/answers/_separator.html.erb +1 -0
  75. data/app/views/decidim/forms/questionnaires/answers/_short_answer.html.erb +1 -0
  76. data/app/views/decidim/forms/questionnaires/answers/_single_option.html.erb +30 -0
  77. data/app/views/decidim/forms/questionnaires/answers/_sorting.html.erb +23 -0
  78. data/app/views/decidim/forms/questionnaires/show.html.erb +81 -28
  79. data/app/views/layouts/decidim/forms/admin/questionnaires/questionnaire_answers.html.erb +12 -0
  80. data/config/initializers/wicked_pdf.rb +25 -0
  81. data/config/locales/am-ET.yml +1 -0
  82. data/config/locales/ar.yml +12 -4
  83. data/config/locales/bg-BG.yml +14 -0
  84. data/config/locales/bg.yml +14 -0
  85. data/config/locales/ca.yml +98 -8
  86. data/config/locales/cs.yml +94 -4
  87. data/config/locales/da-DK.yml +1 -0
  88. data/config/locales/da.yml +1 -0
  89. data/config/locales/de.yml +92 -4
  90. data/config/locales/el-GR.yml +1 -0
  91. data/config/locales/el.yml +118 -0
  92. data/config/locales/en.yml +94 -4
  93. data/config/locales/eo.yml +1 -0
  94. data/config/locales/es-MX.yml +94 -4
  95. data/config/locales/es-PY.yml +94 -4
  96. data/config/locales/es.yml +94 -4
  97. data/config/locales/et-EE.yml +1 -0
  98. data/config/locales/et.yml +1 -0
  99. data/config/locales/eu.yml +7 -4
  100. data/config/locales/fi-plain.yml +94 -4
  101. data/config/locales/fi.yml +94 -4
  102. data/config/locales/fr-CA.yml +172 -0
  103. data/config/locales/fr.yml +94 -4
  104. data/config/locales/ga-IE.yml +1 -0
  105. data/config/locales/gl.yml +7 -4
  106. data/config/locales/hr-HR.yml +1 -0
  107. data/config/locales/hr.yml +1 -0
  108. data/config/locales/hu.yml +16 -4
  109. data/config/locales/id-ID.yml +7 -4
  110. data/config/locales/is-IS.yml +1 -0
  111. data/config/locales/is.yml +1 -0
  112. data/config/locales/it.yml +95 -5
  113. data/config/locales/ja-JP.yml +170 -0
  114. data/config/locales/ja.yml +170 -0
  115. data/config/locales/ko-KR.yml +1 -0
  116. data/config/locales/ko.yml +1 -0
  117. data/config/locales/lt-LT.yml +1 -0
  118. data/config/locales/lt.yml +1 -0
  119. data/config/locales/lv.yml +118 -0
  120. data/config/locales/mt-MT.yml +1 -0
  121. data/config/locales/mt.yml +1 -0
  122. data/config/locales/nl.yml +97 -7
  123. data/config/locales/no.yml +98 -1
  124. data/config/locales/om-ET.yml +1 -0
  125. data/config/locales/pl.yml +113 -26
  126. data/config/locales/pt-BR.yml +8 -5
  127. data/config/locales/pt.yml +111 -24
  128. data/config/locales/ro-RO.yml +167 -0
  129. data/config/locales/ru.yml +4 -2
  130. data/config/locales/sk-SK.yml +88 -0
  131. data/config/locales/sk.yml +90 -0
  132. data/config/locales/sl.yml +12 -0
  133. data/config/locales/so-SO.yml +1 -0
  134. data/config/locales/sr-CS.yml +1 -0
  135. data/config/locales/sv.yml +91 -4
  136. data/config/locales/ti-ER.yml +1 -0
  137. data/config/locales/tr-TR.yml +7 -4
  138. data/config/locales/vi-VN.yml +1 -0
  139. data/config/locales/vi.yml +1 -0
  140. data/config/locales/zh-CN.yml +172 -0
  141. data/config/locales/zh-TW.yml +1 -0
  142. data/db/migrate/20190315203056_add_session_token_to_decidim_forms_answers.rb +17 -0
  143. data/db/migrate/20190930094710_add_ip_hash_to_decidim_form_answers.rb +12 -0
  144. data/db/migrate/20200130194123_create_decidim_forms_display_conditions.rb +20 -0
  145. data/db/migrate/20200225123810_create_decidim_forms_question_matrix_rows.rb +11 -0
  146. data/db/migrate/20200304152939_add_matrix_row_id_to_decidim_forms_answer_choices.rb +11 -0
  147. data/lib/decidim/api/questionnaire_entity_interface.rb +18 -0
  148. data/lib/decidim/exporters/form_pdf.rb +33 -0
  149. data/lib/decidim/exporters/form_pdf_controller_helper.rb +11 -0
  150. data/lib/decidim/forms.rb +6 -0
  151. data/lib/decidim/forms/admin_engine.rb +1 -1
  152. data/lib/decidim/forms/api.rb +7 -0
  153. data/lib/decidim/forms/test.rb +6 -0
  154. data/lib/decidim/forms/test/factories.rb +80 -6
  155. data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +924 -66
  156. data/lib/decidim/forms/test/shared_examples/manage_questionnaire_answers.rb +108 -0
  157. data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +33 -575
  158. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_display_conditions.rb +179 -0
  159. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_questions.rb +463 -0
  160. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_display_conditions.rb +93 -0
  161. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_questions.rb +461 -0
  162. data/lib/decidim/forms/user_answers_serializer.rb +23 -4
  163. data/lib/decidim/forms/version.rb +1 -1
  164. metadata +136 -9
@@ -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,579 +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 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
- 2.times { click_button "Add question" }
45
-
46
- expect(page).to have_selector(".questionnaire-question", count: 2)
47
-
48
- page.all(".questionnaire-question").each_with_index do |question, idx|
49
- within question do
50
- fill_in find_nested_form_field_locator("body_en"), with: questions_body[idx]
51
- end
52
- end
53
-
54
- click_button "Save"
55
- end
56
-
57
- expect(page).to have_admin_callout("successfully")
58
-
59
- visit questionnaire_edit_path
60
-
61
- expect(page).to have_selector("input[value='This is the first question']")
62
- expect(page).to have_selector("input[value='This is the second question']")
63
- end
64
-
65
- it "adds a question with a rich text description" do
66
- within "form.edit_questionnaire" do
67
- click_button "Add question"
68
-
69
- within ".questionnaire-question" do
70
- fill_in find_nested_form_field_locator("body_en"), with: "Body"
71
-
72
- fill_in_editor find_nested_form_field_locator("description_en", visible: false), with: "<b>Superkalifragilistic description</b>"
73
- end
74
-
75
- click_button "Save"
76
- end
77
-
78
- expect(page).to have_admin_callout("successfully")
79
-
80
- component.update!(
81
- step_settings: {
82
- component.participatory_space.active_step.id => {
83
- allow_answers: true
84
- }
85
- }
86
- )
87
-
88
- visit questionnaire_public_path
89
-
90
- expect(page).to have_selector("strong", text: "Superkalifragilistic description")
91
- end
92
-
93
- it "adds a question with answer options" do
94
- question_body = ["This is the first question", "This is the second question"]
95
- answer_options_body = [
96
- [
97
- "This is the Q1 first option",
98
- "This is the Q1 second option",
99
- "This is the Q1 third option"
100
- ],
101
- [
102
- "This is the Q2 first option",
103
- "This is the Q2 second option",
104
- "This is the Q2 third option"
105
- ]
106
- ]
107
-
108
- within "form.edit_questionnaire" do
109
- click_button "Add question"
110
- click_button "Add question"
111
-
112
- page.all(".questionnaire-question").each_with_index do |question, idx|
113
- within question do
114
- fill_in find_nested_form_field_locator("body_en"), with: question_body[idx]
115
- end
116
- end
117
-
118
- expect(page).to have_no_content "Add answer option"
119
-
120
- page.all(".questionnaire-question").each do |question|
121
- within question do
122
- select "Single option", from: "Type"
123
- click_button "Add answer option"
124
- end
125
- end
126
-
127
- page.all(".questionnaire-question").each_with_index do |question, idx|
128
- question.all(".questionnaire-question-answer-option").each_with_index do |question_answer_option, aidx|
129
- within question_answer_option do
130
- fill_in find_nested_form_field_locator("body_en"), with: answer_options_body[idx][aidx]
131
- end
132
- end
133
- end
134
-
135
- click_button "Save"
136
- end
137
-
138
- expect(page).to have_admin_callout("successfully")
139
-
140
- visit questionnaire_edit_path
141
-
142
- expect(page).to have_selector("input[value='This is the first question']")
143
- expect(page).to have_selector("input[value='This is the Q1 first option']")
144
- expect(page).to have_selector("input[value='This is the Q1 second option']")
145
- expect(page).to have_selector("input[value='This is the Q1 third option']")
146
- expect(page).to have_selector("input[value='This is the second question']")
147
- expect(page).to have_selector("input[value='This is the Q2 first option']")
148
- expect(page).to have_selector("input[value='This is the Q2 second option']")
149
- expect(page).to have_selector("input[value='This is the Q2 third option']")
150
- end
151
-
152
- it "adds a sane number of options for each attribute type" do
153
- click_button "Add question"
154
-
155
- select "Long answer", from: "Type"
156
- expect(page).to have_no_selector(".questionnaire-question-answer-option")
157
-
158
- select "Single option", from: "Type"
159
- expect(page).to have_selector(".questionnaire-question-answer-option", count: 2)
160
-
161
- select "Multiple option", from: "Type"
162
- expect(page).to have_selector(".questionnaire-question-answer-option", count: 2)
163
-
164
- select "Single option", from: "Type"
165
- expect(page).to have_selector(".questionnaire-question-answer-option", count: 2)
166
-
167
- select "Short answer", from: "Type"
168
- expect(page).to have_no_selector(".questionnaire-question-answer-option")
169
- end
170
-
171
- it "does not incorrectly reorder when clicking answer options" do
172
- click_button "Add question"
173
- select "Single option", from: "Type"
174
- 2.times { click_button "Add answer option" }
175
-
176
- within ".questionnaire-question-answer-option:first-of-type" do
177
- fill_in find_nested_form_field_locator("body_en"), with: "Something"
178
- end
179
-
180
- within ".questionnaire-question-answer-option:last-of-type" do
181
- fill_in find_nested_form_field_locator("body_en"), with: "Else"
182
- end
183
-
184
- # If JS events for option reordering are incorrectly bound, clicking on
185
- # the field to gain focus can cause the options to get inverted... :S
186
- within ".questionnaire-question-answer-option:first-of-type" do
187
- find_nested_form_field("body_en").click
188
- end
189
-
190
- within ".questionnaire-question-answer-option:first-of-type" do
191
- expect(page).to have_nested_field("body_en", with: "Something")
192
- end
193
-
194
- within ".questionnaire-question-answer-option:last-of-type" do
195
- expect(page).to have_nested_field("body_en", with: "Else")
196
- end
197
- end
198
-
199
- it "preserves question form across submission failures" do
200
- click_button "Add question"
201
- select "Long answer", from: "Type"
202
- click_button "Save"
203
-
204
- expect(page).to have_select("Type", selected: "Long answer")
205
- end
206
-
207
- it "does not preserve spurious answer options from previous type selections" do
208
- click_button "Add question"
209
- select "Single option", from: "Type"
210
-
211
- within ".questionnaire-question-answer-option:first-of-type" do
212
- fill_in find_nested_form_field_locator("body_en"), with: "Something"
213
- end
214
-
215
- select "Long answer", from: "Type"
216
-
217
- click_button "Save"
218
-
219
- select "Single option", from: "Type"
220
-
221
- within ".questionnaire-question-answer-option:first-of-type" do
222
- expect(page).to have_no_nested_field("body_en", with: "Something")
223
- end
224
- end
225
-
226
- it "preserves answer options form across submission failures" do
227
- click_button "Add question"
228
- select "Multiple option", from: "Type"
229
-
230
- within ".questionnaire-question-answer-option:first-of-type" do
231
- fill_in find_nested_form_field_locator("body_en"), with: "Something"
232
- end
233
-
234
- click_button "Add answer option"
235
-
236
- within ".questionnaire-question-answer-option:last-of-type" do
237
- fill_in find_nested_form_field_locator("body_en"), with: "Else"
238
- end
239
-
240
- select "3", from: "Maximum number of choices"
241
-
242
- click_button "Save"
243
-
244
- within ".questionnaire-question-answer-option:first-of-type" do
245
- expect(page).to have_nested_field("body_en", with: "Something")
246
- end
247
-
248
- within ".questionnaire-question-answer-option:last-of-type" do
249
- fill_in find_nested_form_field_locator("body_en"), with: "Else"
250
- end
251
-
252
- expect(page).to have_select("Maximum number of choices", selected: "3")
253
- end
254
-
255
- it "allows switching translated field tabs after form failures" do
256
- click_button "Add question"
257
- click_button "Save"
258
-
259
- within ".questionnaire-question:first-of-type" do
260
- fill_in find_nested_form_field_locator("body_en"), with: "Bye"
261
- click_link "Català", match: :first
262
-
263
- fill_in find_nested_form_field_locator("body_ca"), with: "Adeu"
264
- click_link "English", match: :first
265
-
266
- expect(page).to have_nested_field("body_en", with: "Bye")
267
- expect(page).to have_no_selector(nested_form_field_selector("body_ca"))
268
- expect(page).to have_no_content("Adeu")
269
- end
270
- end
271
-
272
- context "when adding a multiple option question" do
273
- before do
274
- visit questionnaire_edit_path
275
-
276
- within "form.edit_questionnaire" do
277
- click_button "Add question"
278
-
279
- within ".questionnaire-question" do
280
- fill_in find_nested_form_field_locator("body_en"), with: "This is the first question"
281
- end
282
-
283
- expect(page).to have_no_content "Add answer option"
284
- expect(page).to have_no_select("Maximum number of choices")
285
- end
286
- end
287
-
288
- it "updates the free text option selector according to the selected question type" do
289
- expect(page).to have_no_selector("input[type=checkbox][id$=_free_text]")
290
-
291
- select "Multiple option", from: "Type"
292
- expect(page).to have_selector("input[type=checkbox][id$=_free_text]")
293
-
294
- select "Short answer", from: "Type"
295
- expect(page).to have_no_selector("input[type=checkbox][id$=_free_text]")
296
-
297
- select "Single option", from: "Type"
298
- expect(page).to have_selector("input[type=checkbox][id$=_free_text]")
299
- end
300
-
301
- it "updates the max choices selector according to the configured options" do
302
- expect(page).to have_no_select("Maximum number of choices")
303
-
304
- select "Multiple option", from: "Type"
305
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2))
306
-
307
- click_button "Add answer option"
308
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2 3))
309
-
310
- click_button "Add answer option"
311
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2 3 4))
312
-
313
- within(".questionnaire-question-answer-option:last-of-type") { click_button "Remove" }
314
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2 3))
315
-
316
- within(".questionnaire-question-answer-option:last-of-type") { click_button "Remove" }
317
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2))
318
-
319
- click_button "Add question"
320
-
321
- within(".questionnaire-question:last-of-type") do
322
- select "Multiple option", from: "Type"
323
- expect(page).to have_select("Maximum number of choices", options: %w(Any 2))
324
-
325
- select "Single option", from: "Type"
326
- expect(page).to have_no_select("Maximum number of choices")
327
- end
328
- end
329
- end
330
-
331
- context "when a questionnaire has an existing question" do
332
- let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, body: body) }
333
-
334
- before do
335
- visit questionnaire_edit_path
336
- end
337
-
338
- it "modifies the question when the information is valid" do
339
- within "form.edit_questionnaire" do
340
- within ".questionnaire-question" do
341
- fill_in "questionnaire_questions_#{question.id}_body_en", with: "Modified question"
342
- check "Mandatory"
343
- select "Long answer", from: "Type"
344
- end
345
-
346
- click_button "Save"
347
- end
348
-
349
- expect(page).to have_admin_callout("successfully")
350
-
351
- visit questionnaire_edit_path
352
-
353
- expect(page).to have_selector("input[value='Modified question']")
354
- expect(page).to have_no_selector("input[value='This is the first question']")
355
- expect(page).to have_selector("input#questionnaire_questions_#{question.id}_mandatory[checked]")
356
- expect(page).to have_selector("select#questionnaire_questions_#{question.id}_question_type option[value='long_answer'][selected]")
357
- end
358
-
359
- it "re-renders the form when the information is invalid and displays errors" do
360
- within "form.edit_questionnaire" do
361
- within ".questionnaire-question" do
362
- expect(page).to have_content("Statement*")
363
- fill_in "questionnaire_questions_#{question.id}_body_en", with: ""
364
- check "Mandatory"
365
- select "Multiple option", from: "Type"
366
- select "2", from: "Maximum number of choices"
367
- end
368
-
369
- click_button "Save"
370
- end
371
-
372
- 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
374
-
375
- expect(page).to have_selector("input[value='']")
376
- expect(page).to have_no_selector("input[value='This is the first question']")
377
- expect(page).to have_selector("input#questionnaire_questions_#{question.id}_mandatory[checked]")
378
- 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]")
380
- end
381
-
382
- it "preserves deleted status across submission failures" do
383
- within "form.edit_questionnaire" do
384
- within ".questionnaire-question" do
385
- click_button "Remove"
386
- end
387
- end
388
-
389
- click_button "Add question"
390
-
391
- click_button "Save"
392
-
393
- expect(page).to have_selector(".questionnaire-question", count: 1)
394
-
395
- within ".questionnaire-question" do
396
- expect(page).to have_selector(".card-title", text: "#1")
397
- expect(page).to have_no_button("Up")
398
- end
399
- end
400
-
401
- it "removes the question" do
402
- within "form.edit_questionnaire" do
403
- within ".questionnaire-question" do
404
- click_button "Remove"
405
- end
406
-
407
- click_button "Save"
408
- end
409
-
410
- expect(page).to have_admin_callout("successfully")
411
-
412
- visit questionnaire_edit_path
413
-
414
- within "form.edit_questionnaire" do
415
- expect(page).to have_selector(".questionnaire-question", count: 0)
416
- end
417
- end
418
-
419
- it "cannot be moved up" do
420
- within "form.edit_questionnaire" do
421
- within ".questionnaire-question" do
422
- expect(page).to have_no_button("Up")
423
- end
424
- end
425
- end
426
-
427
- it "cannot be moved down" do
428
- within "form.edit_questionnaire" do
429
- within ".questionnaire-question" do
430
- expect(page).to have_no_button("Down")
431
- end
432
- end
433
- end
434
- end
435
-
436
- context "when a questionnaire has an existing question with answer options" do
437
- let!(:question) do
438
- create(
439
- :questionnaire_question,
440
- questionnaire: questionnaire,
441
- body: body,
442
- question_type: "single_option",
443
- answer_options: [
444
- { "body" => { "en" => "cacarua" } },
445
- { "body" => { "en" => "cat" } },
446
- { "body" => { "en" => "dog" } }
447
-
448
- ]
449
- )
450
- end
451
-
452
- before do
453
- visit questionnaire_edit_path
454
- end
455
-
456
- it "allows deleting answer options" do
457
- within ".questionnaire-question-answer-option:last-of-type" do
458
- click_button "Remove"
459
- end
460
-
461
- click_button "Save"
462
-
463
- visit questionnaire_edit_path
464
-
465
- expect(page).to have_selector(".questionnaire-question-answer-option", count: 2)
466
- end
467
-
468
- it "still removes the question even if previous editions rendered the options invalid" do
469
- within "form.edit_questionnaire" do
470
- expect(page).to have_selector(".questionnaire-question", count: 1)
471
-
472
- within ".questionnaire-question-answer-option:first-of-type" do
473
- fill_in find_nested_form_field_locator("body_en"), with: ""
474
- end
475
-
476
- within ".questionnaire-question" do
477
- click_button "Remove", match: :first
478
- end
479
-
480
- click_button "Save"
481
- end
482
-
483
- expect(page).to have_admin_callout("successfully")
484
-
485
- visit questionnaire_edit_path
486
-
487
- within "form.edit_questionnaire" do
488
- expect(page).to have_selector(".questionnaire-question", count: 0)
489
- end
490
- end
491
- end
492
-
493
- context "when a questionnaire has multiple existing questions" do
494
- let!(:question_1) do
495
- create(:questionnaire_question, questionnaire: questionnaire, body: first_body, position: 0)
496
- end
497
-
498
- let!(:question_2) do
499
- create(:questionnaire_question, questionnaire: questionnaire, body: second_body, position: 1)
500
- end
501
-
502
- let(:first_body) do
503
- { en: "First", ca: "Primera", es: "Primera" }
504
- end
505
-
506
- let(:second_body) do
507
- { en: "Second", ca: "Segunda", es: "Segunda" }
508
- end
509
-
510
- before do
511
- visit questionnaire_edit_path
512
- end
513
-
514
- shared_examples_for "switching questions order" do
515
- it "properly reorders the questions" do
516
- within ".questionnaire-question:first-of-type" do
517
- expect(page).to have_nested_field("body_en", with: "Second")
518
- expect(page).to look_like_first_question
519
- end
520
-
521
- within ".questionnaire-question:last-of-type" do
522
- expect(page).to have_nested_field("body_en", with: "First")
523
- expect(page).to look_like_last_question
524
- end
525
- end
526
- end
527
-
528
- context "when moving a question up" do
529
- before do
530
- within ".questionnaire-question:last-of-type" do
531
- click_button "Up"
532
- end
533
- end
534
-
535
- it_behaves_like "switching questions order"
536
- end
537
-
538
- context "when moving a question down" do
539
- before do
540
- within ".questionnaire-question:first-of-type" do
541
- click_button "Down"
542
- end
543
- end
544
-
545
- it_behaves_like "switching questions order"
546
- end
547
-
548
- it "properly decides which button to show after adding/removing questions" do
549
- click_button "Add question"
550
-
551
- expect(page.find(".questionnaire-question:nth-of-type(1)")).to look_like_first_question
552
- expect(page.find(".questionnaire-question:nth-of-type(2)")).to look_like_intermediate_question
553
- expect(page.find(".questionnaire-question:nth-of-type(3)")).to look_like_last_question
554
-
555
- within ".questionnaire-question:first-of-type" do
556
- click_button "Remove"
557
- end
558
-
559
- expect(page.all(".questionnaire-question").first).to look_like_first_question
560
- expect(page.all(".questionnaire-question").last).to look_like_last_question
561
- end
562
-
563
- 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)
565
- end
566
-
567
- it "properly decides which button to show after adding/removing answer options" do
568
- click_button "Add question"
569
-
570
- within ".questionnaire-question:last-of-type" do
571
- select "Single option", from: "Type"
572
-
573
- within ".questionnaire-question-answer-options-list" do
574
- expect(page).to have_no_button("Remove")
575
- end
576
-
577
- click_button "Add answer option"
578
-
579
- expect(page.all(".questionnaire-question-answer-option")).to all(have_button("Remove"))
580
-
581
- within ".questionnaire-question-answer-option:first-of-type" do
582
- click_button "Remove"
583
- end
584
-
585
- within ".questionnaire-question-answer-options-list" do
586
- expect(page).to have_no_button("Remove")
587
- end
588
- end
589
-
590
- click_button "Save"
591
-
592
- within ".questionnaire-question:last-of-type" do
593
- within ".questionnaire-question-answer-options-list" do
594
- expect(page).to have_no_button("Remove")
595
- end
596
- end
597
- end
598
-
599
- private
600
-
601
- def look_like_first_question
602
- have_no_button("Up").and have_button("Down")
603
- end
604
-
605
- def look_like_intermediate_question
606
- have_button("Up").and have_button("Down")
607
- end
608
-
609
- def look_like_last_question
610
- have_button("Up").and have_no_button("Down")
611
- end
612
- 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"
613
49
  end
614
50
 
615
51
  context "when the questionnaire is already answered" do
@@ -621,6 +57,9 @@ shared_examples_for "manage questionnaires" do
621
57
 
622
58
  expect(page).to have_no_content("Add question")
623
59
  expect(page).to have_no_content("Remove")
60
+
61
+ expand_all_questions
62
+
624
63
  expect(page).to have_selector("input[value='This is the first question'][disabled]")
625
64
  expect(page).to have_selector("select[id$=question_type][disabled]")
626
65
  expect(page).to have_selector("select[id$=max_choices][disabled]")
@@ -630,11 +69,11 @@ shared_examples_for "manage questionnaires" do
630
69
 
631
70
  private
632
71
 
633
- def find_nested_form_field_locator(attribute, visible: true)
72
+ def find_nested_form_field_locator(attribute, visible: :visible)
634
73
  find_nested_form_field(attribute, visible: visible)["id"]
635
74
  end
636
75
 
637
- def find_nested_form_field(attribute, visible: true)
76
+ def find_nested_form_field(attribute, visible: :visible)
638
77
  current_scope.find(nested_form_field_selector(attribute), visible: visible)
639
78
  end
640
79
 
@@ -649,4 +88,23 @@ shared_examples_for "manage questionnaires" do
649
88
  def nested_form_field_selector(attribute)
650
89
  "[id$=#{attribute}]"
651
90
  end
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
+
102
+ def expand_all_questions
103
+ find(".button.expand-all").click
104
+ end
105
+
106
+ def visit_questionnaire_edit_path_and_expand_all
107
+ visit questionnaire_edit_path
108
+ expand_all_questions
109
+ end
652
110
  end