decidim 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of decidim might be problematic. Click here for more details.

Files changed (322) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +3 -1
  3. data/.codeclimate.yml +2 -3
  4. data/.rubocop.yml +1 -48
  5. data/.travis.yml +1 -0
  6. data/Dockerfile +1 -0
  7. data/Gemfile +1 -0
  8. data/Gemfile.lock +119 -115
  9. data/README.md +24 -9
  10. data/Rakefile +14 -10
  11. data/decidim-admin/app/assets/javascripts/decidim/admin/application.js.es6 +21 -9
  12. data/decidim-admin/app/assets/javascripts/decidim/admin/sort_list.component.js.es6 +35 -0
  13. data/decidim-admin/app/assets/stylesheets/decidim/admin/extra/_language-chooser.scss +4 -0
  14. data/decidim-admin/app/assets/stylesheets/decidim/admin/extra/_sort.scss +12 -0
  15. data/decidim-admin/app/controllers/decidim/admin/application_controller.rb +1 -0
  16. data/decidim-admin/app/controllers/decidim/admin/participatory_process_attachments_controller.rb +4 -0
  17. data/decidim-admin/app/helpers/decidim/admin/menu_helper.rb +0 -1
  18. data/decidim-admin/app/models/decidim/admin/participatory_process_user_role.rb +2 -2
  19. data/decidim-admin/app/views/decidim/admin/categories/index.html.erb +7 -1
  20. data/decidim-admin/app/views/decidim/admin/exports/_dropdown.html.erb +1 -1
  21. data/decidim-admin/app/views/decidim/admin/moderations/index.html.erb +6 -2
  22. data/decidim-admin/app/views/decidim/admin/participatory_process_steps/index.html.erb +1 -0
  23. data/decidim-admin/app/views/layouts/decidim/admin/_title_bar.html.erb +10 -0
  24. data/decidim-admin/bin/rails +3 -3
  25. data/decidim-admin/config/locales/ca.yml +3 -1
  26. data/decidim-admin/config/locales/en.yml +3 -1
  27. data/decidim-admin/config/locales/es.yml +3 -1
  28. data/decidim-admin/config/locales/eu.yml +0 -1
  29. data/decidim-admin/config/locales/fi.yml +0 -1
  30. data/decidim-admin/config/locales/fr.yml +0 -1
  31. data/decidim-admin/config/locales/it.yml +490 -0
  32. data/decidim-admin/db/migrate/20161102144648_add_admin_participatory_process_user_roles.rb +5 -3
  33. data/decidim-admin/db/migrate/20170128112958_change_user_groups_verified_to_timestamp.rb +2 -0
  34. data/decidim-admin/decidim-admin.gemspec +2 -1
  35. data/decidim-admin/lib/decidim/admin/engine.rb +1 -1
  36. data/decidim-admin/lib/decidim/admin/test/manage_attachments_examples.rb +3 -3
  37. data/decidim-admin/spec/commands/reject_user_group_spec.rb +2 -2
  38. data/decidim-admin/spec/features/admin_copy_participatory_process_spec.rb +2 -2
  39. data/decidim-admin/spec/features/admin_invite_spec.rb +1 -1
  40. data/decidim-admin/spec/features/admin_manages_features_spec.rb +2 -2
  41. data/decidim-admin/spec/features/admin_manages_newsletters_spec.rb +4 -4
  42. data/decidim-admin/spec/features/admin_manages_organization_spec.rb +6 -6
  43. data/decidim-admin/spec/features/admin_manages_participatory_process_groups_spec.rb +4 -4
  44. data/decidim-admin/spec/features/admin_manages_participatory_processes_spec.rb +4 -4
  45. data/decidim-admin/spec/features/static_pages_spec.rb +4 -4
  46. data/decidim-admin/spec/forms/organization_form_spec.rb +1 -1
  47. data/decidim-admin/spec/shared/manage_process_categories_examples.rb +44 -29
  48. data/decidim-admin/spec/shared/manage_process_steps_examples.rb +3 -3
  49. data/decidim-admin/spec/shared/manage_processes_examples.rb +1 -1
  50. data/decidim-admin/spec/shared/participatory_admin_shared_context.rb +3 -3
  51. data/decidim-admin/spec/spec_helper.rb +3 -2
  52. data/decidim-api/bin/rails +3 -3
  53. data/decidim-api/decidim-api.gemspec +2 -1
  54. data/decidim-api/lib/decidim/api/engine.rb +1 -1
  55. data/decidim-api/spec/spec_helper.rb +3 -2
  56. data/decidim-budgets/app/controllers/decidim/budgets/application_controller.rb +1 -1
  57. data/decidim-budgets/app/models/decidim/budgets/line_item.rb +1 -2
  58. data/decidim-budgets/app/models/decidim/budgets/order.rb +2 -2
  59. data/decidim-budgets/app/views/decidim/budgets/projects/_linked_projects.html.erb +1 -1
  60. data/decidim-budgets/bin/rails +3 -3
  61. data/decidim-budgets/config/locales/it.yml +126 -0
  62. data/decidim-budgets/db/migrate/20170127114122_create_projects.rb +2 -0
  63. data/decidim-budgets/db/migrate/20170130095615_create_orders.rb +2 -0
  64. data/decidim-budgets/db/migrate/20170130101825_create_line_items.rb +2 -0
  65. data/decidim-budgets/db/migrate/20170207101750_remove_short_description_from_decidim_projects.rb +2 -0
  66. data/decidim-budgets/db/migrate/20170215132708_add_reference_to_projects.rb +2 -0
  67. data/decidim-budgets/db/migrate/20170410074214_remove_not_null_reference_budgets.rb +2 -0
  68. data/decidim-budgets/db/migrate/20170612101846_migrate_projects_category.rb +15 -0
  69. data/decidim-budgets/decidim-budgets.gemspec +3 -1
  70. data/decidim-budgets/lib/decidim/budgets/feature.rb +2 -2
  71. data/decidim-budgets/spec/features/admin_manages_project_attachments_spec.rb +5 -3
  72. data/decidim-budgets/spec/features/admin_manages_projects_spec.rb +5 -7
  73. data/decidim-budgets/spec/features/process_admin_manages_project_attachments_spec.rb +4 -4
  74. data/decidim-budgets/spec/features/process_admin_manages_projects_spec.rb +5 -8
  75. data/decidim-budgets/spec/shared/manage_attachments_examples.rb +0 -4
  76. data/decidim-budgets/spec/shared/manage_projects_examples.rb +3 -3
  77. data/decidim-budgets/spec/spec_helper.rb +2 -1
  78. data/decidim-comments/app/assets/javascripts/decidim/comments/bundle.js +0 -0
  79. data/decidim-comments/app/commands/decidim/comments/create_comment.rb +2 -2
  80. data/decidim-comments/app/frontend/comments/add_comment_form.component.tsx +1 -0
  81. data/decidim-comments/app/frontend/comments/comment.component.test.tsx +12 -1
  82. data/decidim-comments/app/frontend/comments/comment.component.tsx +42 -4
  83. data/decidim-comments/app/frontend/comments/comment_thread.component.test.tsx +11 -0
  84. data/decidim-comments/app/frontend/comments/comment_thread.component.tsx +5 -1
  85. data/decidim-comments/app/frontend/fragments/comment_data.fragment.graphql +3 -0
  86. data/decidim-comments/app/frontend/support/generate_comments_data.ts +3 -0
  87. data/decidim-comments/app/frontend/support/schema.ts +18 -12
  88. data/decidim-comments/app/mailers/decidim/comments/comment_notification_mailer.rb +6 -4
  89. data/decidim-comments/app/models/decidim/comments/comment.rb +6 -4
  90. data/decidim-comments/app/models/decidim/comments/comment_vote.rb +1 -2
  91. data/decidim-comments/app/models/decidim/comments/seed.rb +5 -2
  92. data/decidim-comments/app/resolvers/decidim/comments/vote_comment_resolver.rb +3 -0
  93. data/decidim-comments/app/types/decidim/comments/commentable_interface.rb +3 -3
  94. data/decidim-comments/app/views/decidim/comments/comment_notification_mailer/comment_created.html.erb +1 -1
  95. data/decidim-comments/app/views/decidim/comments/comment_notification_mailer/reply_created.html.erb +1 -1
  96. data/decidim-comments/bin/rails +3 -3
  97. data/decidim-comments/config/locales/ca.yml +5 -0
  98. data/decidim-comments/config/locales/en.yml +5 -0
  99. data/decidim-comments/config/locales/es.yml +5 -0
  100. data/decidim-comments/config/locales/it.yml +65 -0
  101. data/decidim-comments/db/migrate/20161130143508_create_comments.rb +2 -0
  102. data/decidim-comments/db/migrate/20161214082645_add_depth_to_comments.rb +2 -0
  103. data/decidim-comments/db/migrate/20161216102820_add_alignment_to_comments.rb +2 -0
  104. data/decidim-comments/db/migrate/20161219150806_create_comment_votes.rb +3 -1
  105. data/decidim-comments/db/migrate/20170123102043_add_user_group_id_to_comments.rb +2 -0
  106. data/decidim-comments/db/migrate/20170504085413_add_root_commentable_to_comments.rb +2 -0
  107. data/decidim-comments/db/migrate/20170510091348_update_root_commentable_for_comments.rb +3 -2
  108. data/decidim-comments/db/migrate/20170510091409_set_root_commentable_null_constraints.rb +2 -0
  109. data/decidim-comments/decidim-comments.gemspec +2 -1
  110. data/decidim-comments/lib/decidim/comments/comment_serializer.rb +1 -1
  111. data/decidim-comments/lib/decidim/comments/commentable.rb +4 -4
  112. data/decidim-comments/spec/commands/create_comment_spec.rb +2 -2
  113. data/decidim-comments/spec/features/admin_manages_comments_spec.rb +4 -9
  114. data/decidim-comments/spec/features/process_admin_manages_comments_spec.rb +5 -11
  115. data/decidim-comments/spec/mailers/comment_notification_mailer_spec.rb +12 -7
  116. data/decidim-comments/spec/shared/author_localised_email.rb +26 -0
  117. data/decidim-comments/spec/spec_helper.rb +1 -1
  118. data/decidim-dev/config/locales/it.yml +9 -0
  119. data/decidim-dev/decidim-dev.gemspec +8 -3
  120. data/decidim-dev/lib/decidim/dev.rb +1 -8
  121. data/decidim-dev/lib/decidim/dev/railtie.rb +1 -1
  122. data/decidim-dev/lib/decidim/dev/test/base_spec_helper.rb +6 -4
  123. data/decidim-dev/lib/decidim/dev/test/rspec_support/capybara.rb +2 -2
  124. data/decidim-dev/lib/decidim/dev/test/rspec_support/feature.rb +4 -2
  125. data/decidim-dev/lib/decidim/dev/test/rspec_support/feature_context.rb +28 -8
  126. data/decidim-dev/lib/decidim/dev/test/rspec_support/translation_helpers.rb +7 -2
  127. data/decidim-dev/lib/decidim/dev/test/spec_helper.rb +2 -2
  128. data/decidim-dev/lib/generators/decidim/dummy_generator.rb +1 -1
  129. data/decidim-meetings/README.md +1 -1
  130. data/decidim-meetings/app/controllers/decidim/meetings/application_controller.rb +1 -1
  131. data/decidim-meetings/app/views/decidim/meetings/meetings/_linked_meetings.html.erb +1 -1
  132. data/decidim-meetings/bin/rails +3 -3
  133. data/decidim-meetings/config/locales/it.yml +87 -0
  134. data/decidim-meetings/db/migrate/20161130121354_create_meetings.rb +2 -0
  135. data/decidim-meetings/db/migrate/20170110142105_close_a_meeting.rb +2 -0
  136. data/decidim-meetings/db/migrate/20170123151650_add_latitude_and_longitude_to_meetings.rb +2 -0
  137. data/decidim-meetings/db/migrate/20170129153716_remove_short_description_from_meetings.rb +2 -0
  138. data/decidim-meetings/db/migrate/20170215132546_add_reference_to_meetings.rb +2 -0
  139. data/decidim-meetings/db/migrate/20170410074252_remove_not_null_reference_meetings.rb +2 -0
  140. data/decidim-meetings/db/migrate/20170612101925_migrate_meetings_category.rb +15 -0
  141. data/decidim-meetings/decidim-meetings.gemspec +3 -1
  142. data/decidim-meetings/lib/decidim/meetings/feature.rb +2 -2
  143. data/decidim-meetings/spec/features/admin_manages_meetings_attachments_spec.rb +5 -1
  144. data/decidim-meetings/spec/features/admin_manages_meetings_spec.rb +5 -7
  145. data/decidim-meetings/spec/features/explore_meetings_spec.rb +32 -6
  146. data/decidim-meetings/spec/features/process_admin_manages_meetings_attachments_spec.rb +4 -2
  147. data/decidim-meetings/spec/features/process_admin_manages_meetings_spec.rb +5 -8
  148. data/decidim-meetings/spec/shared/manage_attachments_examples.rb +0 -3
  149. data/decidim-meetings/spec/shared/manage_meetings_examples.rb +11 -11
  150. data/decidim-meetings/spec/spec_helper.rb +2 -1
  151. data/decidim-pages/bin/rails +3 -3
  152. data/decidim-pages/config/locales/it.yml +22 -0
  153. data/decidim-pages/db/migrate/20161116121353_create_decidim_pages.rb +2 -0
  154. data/decidim-pages/db/migrate/20161214150429_add_commentable_to_pages.rb +2 -0
  155. data/decidim-pages/db/migrate/20170110145040_remove_commentable_flag_from_pages.rb +2 -0
  156. data/decidim-pages/db/migrate/20170220091402_remove_page_feature_titles.rb +2 -0
  157. data/decidim-pages/decidim-pages.gemspec +3 -1
  158. data/decidim-pages/spec/features/admin_spec.rb +1 -1
  159. data/decidim-pages/spec/spec_helper.rb +2 -3
  160. data/decidim-proposals/app/commands/decidim/proposals/unvote_proposal.rb +34 -0
  161. data/decidim-proposals/app/commands/decidim/proposals/vote_proposal.rb +39 -0
  162. data/decidim-proposals/app/controllers/concerns/decidim/proposals/orderable.rb +7 -3
  163. data/decidim-proposals/app/controllers/decidim/proposals/proposal_votes_controller.rb +18 -8
  164. data/decidim-proposals/app/models/decidim/proposals/proposal.rb +3 -3
  165. data/decidim-proposals/app/models/decidim/proposals/proposal_vote.rb +0 -1
  166. data/decidim-proposals/app/views/decidim/proposals/proposals/_author.html.erb +23 -0
  167. data/decidim-proposals/app/views/decidim/proposals/proposals/_linked_proposals.html.erb +2 -2
  168. data/decidim-proposals/app/views/decidim/proposals/proposals/_proposal.html.erb +1 -9
  169. data/decidim-proposals/app/views/decidim/proposals/proposals/_vote_button.html.erb +2 -6
  170. data/decidim-proposals/app/views/decidim/proposals/proposals/new.html.erb +1 -1
  171. data/decidim-proposals/app/views/decidim/proposals/proposals/show.html.erb +1 -11
  172. data/decidim-proposals/bin/rails +3 -3
  173. data/decidim-proposals/config/locales/ca.yml +6 -0
  174. data/decidim-proposals/config/locales/en.yml +6 -0
  175. data/decidim-proposals/config/locales/es.yml +6 -0
  176. data/decidim-proposals/config/locales/eu.yml +0 -2
  177. data/decidim-proposals/config/locales/fi.yml +0 -2
  178. data/decidim-proposals/config/locales/fr.yml +0 -2
  179. data/decidim-proposals/config/locales/it.yml +147 -0
  180. data/decidim-proposals/db/migrate/20161212110850_create_decidim_proposals.rb +2 -0
  181. data/decidim-proposals/db/migrate/20170112115253_create_proposal_votes.rb +3 -1
  182. data/decidim-proposals/db/migrate/20170113114245_add_text_search_indexes.rb +2 -0
  183. data/decidim-proposals/db/migrate/20170118120151_add_counter_cache_votes_to_proposals.rb +2 -0
  184. data/decidim-proposals/db/migrate/20170120151202_add_user_group_id_to_proposals.rb +2 -0
  185. data/decidim-proposals/db/migrate/20170131092413_add_answers_to_proposals.rb +2 -0
  186. data/decidim-proposals/db/migrate/20170205082832_add_index_to_decidim_proposals_proposals_proposal_votes_count.rb +2 -0
  187. data/decidim-proposals/db/migrate/20170215113152_create_proposal_reports.rb +2 -0
  188. data/decidim-proposals/db/migrate/20170215131720_add_report_count_to_proposals.rb +2 -0
  189. data/decidim-proposals/db/migrate/20170215132030_add_reference_to_proposals.rb +2 -0
  190. data/decidim-proposals/db/migrate/20170220152416_add_hidden_at_to_proposals.rb +2 -0
  191. data/decidim-proposals/db/migrate/20170228105156_add_geolocalization_fields_to_proposals.rb +2 -0
  192. data/decidim-proposals/db/migrate/20170307085300_migrate_proposal_reports_data_to_reports.rb +8 -10
  193. data/decidim-proposals/db/migrate/20170410073742_remove_not_null_reference_proposals.rb +2 -0
  194. data/decidim-proposals/db/migrate/20170612101809_migrate_proposals_category.rb +15 -0
  195. data/decidim-proposals/decidim-proposals.gemspec +4 -2
  196. data/decidim-proposals/lib/decidim/proposals/feature.rb +5 -1
  197. data/decidim-proposals/lib/decidim/proposals/proposal_serializer.rb +1 -6
  198. data/decidim-proposals/spec/commands/decidim/proposals/unvote_proposal_spec.rb +26 -0
  199. data/decidim-proposals/spec/commands/decidim/proposals/vote_proposal_spec.rb +47 -0
  200. data/decidim-proposals/spec/features/admin_manages_proposals_spec.rb +6 -11
  201. data/decidim-proposals/spec/features/process_admin_manages_proposals_spec.rb +6 -12
  202. data/decidim-proposals/spec/features/proposals_spec.rb +38 -12
  203. data/decidim-proposals/spec/shared/manage_proposals_examples.rb +3 -6
  204. data/decidim-proposals/spec/spec_helper.rb +2 -1
  205. data/decidim-results/app/controllers/decidim/results/application_controller.rb +1 -1
  206. data/decidim-results/app/views/decidim/results/results/_linked_results.html.erb +1 -1
  207. data/decidim-results/bin/rails +3 -3
  208. data/decidim-results/config/locales/it.yml +78 -0
  209. data/decidim-results/db/migrate/20170116104125_create_results.rb +2 -0
  210. data/decidim-results/db/migrate/20170129164553_remove_short_description_from_results.rb +2 -0
  211. data/decidim-results/db/migrate/20170215132624_add_reference_to_results.rb +2 -0
  212. data/decidim-results/db/migrate/20170410074358_remove_not_null_reference_results.rb +2 -0
  213. data/decidim-results/db/migrate/20170612101951_migrate_results_category.rb +15 -0
  214. data/decidim-results/decidim-results.gemspec +3 -1
  215. data/decidim-results/spec/features/admin_manages_results_spec.rb +5 -7
  216. data/decidim-results/spec/features/process_admin_manages_results_spec.rb +5 -8
  217. data/decidim-results/spec/shared/manage_results_examples.rb +3 -3
  218. data/decidim-results/spec/spec_helper.rb +2 -1
  219. data/decidim-surveys/README.md +24 -0
  220. data/decidim-surveys/Rakefile +3 -0
  221. data/decidim-surveys/app/assets/config/admin/decidim_surveys_manifest.js +1 -0
  222. data/decidim-surveys/app/assets/images/decidim/surveys/icon.svg +1 -0
  223. data/decidim-surveys/app/assets/javascripts/decidim/surveys/admin/auto_label_by_position.component.js.es6 +33 -0
  224. data/decidim-surveys/app/assets/javascripts/decidim/surveys/admin/dynamic_fields.component.js.es6 +95 -0
  225. data/decidim-surveys/app/assets/javascripts/decidim/surveys/admin/surveys.js.es6 +85 -0
  226. data/decidim-surveys/app/assets/stylesheets/decidim/surveys/surveys.scss +9 -0
  227. data/decidim-surveys/app/commands/decidim/surveys/admin/update_survey.rb +65 -0
  228. data/decidim-surveys/app/commands/decidim/surveys/answer_survey.rb +43 -0
  229. data/decidim-surveys/app/commands/decidim/surveys/create_survey.rb +19 -0
  230. data/decidim-surveys/app/controllers/decidim/surveys/admin/application_controller.rb +15 -0
  231. data/decidim-surveys/app/controllers/decidim/surveys/admin/surveys_controller.rb +55 -0
  232. data/decidim-surveys/app/controllers/decidim/surveys/application_controller.rb +13 -0
  233. data/decidim-surveys/app/controllers/decidim/surveys/surveys_controller.rb +39 -0
  234. data/decidim-surveys/app/forms/decidim/surveys/admin/survey_form.rb +19 -0
  235. data/decidim-surveys/app/forms/decidim/surveys/admin/survey_question_answer_option_form.rb +15 -0
  236. data/decidim-surveys/app/forms/decidim/surveys/admin/survey_question_form.rb +24 -0
  237. data/decidim-surveys/app/forms/decidim/surveys/survey_answer_form.rb +36 -0
  238. data/decidim-surveys/app/forms/decidim/surveys/survey_form.rb +22 -0
  239. data/decidim-surveys/app/helpers/decidim/surveys/admin/application_helper.rb +39 -0
  240. data/decidim-surveys/app/models/decidim/surveys/abilities/admin_user.rb +34 -0
  241. data/decidim-surveys/app/models/decidim/surveys/abilities/current_user.rb +47 -0
  242. data/decidim-surveys/app/models/decidim/surveys/abilities/process_admin_user.rb +44 -0
  243. data/decidim-surveys/app/models/decidim/surveys/application_record.rb +10 -0
  244. data/decidim-surveys/app/models/decidim/surveys/survey.rb +25 -0
  245. data/decidim-surveys/app/models/decidim/surveys/survey_answer.rb +27 -0
  246. data/decidim-surveys/app/models/decidim/surveys/survey_question.rb +18 -0
  247. data/decidim-surveys/app/queries/decidim/surveys/survey_user_answers.rb +28 -0
  248. data/decidim-surveys/app/views/decidim/surveys/admin/surveys/_answer_option.html.erb +23 -0
  249. data/decidim-surveys/app/views/decidim/surveys/admin/surveys/_form.html.erb +47 -0
  250. data/decidim-surveys/app/views/decidim/surveys/admin/surveys/_question.html.erb +57 -0
  251. data/decidim-surveys/app/views/decidim/surveys/admin/surveys/edit.html.erb +7 -0
  252. data/decidim-surveys/app/views/decidim/surveys/surveys/show.html.erb +102 -0
  253. data/decidim-surveys/bin/rails +15 -0
  254. data/decidim-surveys/config/i18n-tasks.yml +11 -0
  255. data/decidim-surveys/config/locales/ca.yml +69 -0
  256. data/decidim-surveys/config/locales/en.yml +73 -0
  257. data/decidim-surveys/config/locales/es.yml +69 -0
  258. data/decidim-surveys/config/locales/eu.yml +5 -0
  259. data/decidim-surveys/config/locales/fi.yml +5 -0
  260. data/decidim-surveys/config/locales/fr.yml +5 -0
  261. data/decidim-surveys/config/locales/it.yml +5 -0
  262. data/decidim-surveys/config/locales/nl.yml +5 -0
  263. data/decidim-surveys/db/migrate/20170511092231_create_decidim_surveys.rb +15 -0
  264. data/decidim-surveys/db/migrate/20170515090916_create_decidim_survey_questions.rb +12 -0
  265. data/decidim-surveys/db/migrate/20170515144119_create_decidim_survey_answers.rb +14 -0
  266. data/decidim-surveys/db/migrate/20170518085302_add_position_to_surveys_questions.rb +7 -0
  267. data/decidim-surveys/db/migrate/20170522075938_add_mandatory_to_surveys_questions.rb +7 -0
  268. data/decidim-surveys/db/migrate/20170524122229_add_question_type_to_surveys_questions.rb +7 -0
  269. data/decidim-surveys/db/migrate/20170525132233_add_answer_options_to_surveys_questions.rb +7 -0
  270. data/decidim-surveys/decidim-surveys.gemspec +22 -0
  271. data/decidim-surveys/lib/decidim/surveys.rb +14 -0
  272. data/decidim-surveys/lib/decidim/surveys/admin.rb +10 -0
  273. data/decidim-surveys/lib/decidim/surveys/admin_engine.rb +34 -0
  274. data/decidim-surveys/lib/decidim/surveys/engine.rb +25 -0
  275. data/decidim-surveys/lib/decidim/surveys/feature.rb +85 -0
  276. data/decidim-surveys/lib/decidim/surveys/survey_user_answers_serializer.rb +23 -0
  277. data/decidim-surveys/lib/decidim/surveys/test/factories.rb +39 -0
  278. data/decidim-surveys/spec/commands/decidim/surveys/admin/update_survey_spec.rb +147 -0
  279. data/decidim-surveys/spec/commands/decidim/surveys/answer_survey_spec.rb +71 -0
  280. data/decidim-surveys/spec/commands/decidim/surveys/create_survey_spec.rb +44 -0
  281. data/decidim-surveys/spec/factories.rb +3 -0
  282. data/decidim-surveys/spec/features/admin_manages_surveys_spec.rb +13 -0
  283. data/decidim-surveys/spec/features/process_admin_manages_surveys_spec.rb +13 -0
  284. data/decidim-surveys/spec/features/survey_spec.rb +235 -0
  285. data/decidim-surveys/spec/forms/decidim/surveys/admin/survey_form_spec.rb +64 -0
  286. data/decidim-surveys/spec/forms/decidim/surveys/admin/survey_question_form_spec.rb +36 -0
  287. data/decidim-surveys/spec/forms/decidim/surveys/survey_answer_form_spec.rb +36 -0
  288. data/decidim-surveys/spec/forms/decidim/surveys/survey_form_spec.rb +32 -0
  289. data/decidim-surveys/spec/models/decidim/surveys/abilities/admin_user_spec.rb +22 -0
  290. data/decidim-surveys/spec/models/decidim/surveys/abilities/current_user_spec.rb +19 -0
  291. data/decidim-surveys/spec/models/decidim/surveys/abilities/process_admin_user_spec.rb +23 -0
  292. data/decidim-surveys/spec/models/decidim/surveys/survey_answer_spec.rb +55 -0
  293. data/decidim-surveys/spec/models/decidim/surveys/survey_question_spec.rb +19 -0
  294. data/decidim-surveys/spec/models/decidim/surveys/survey_spec.rb +65 -0
  295. data/decidim-surveys/spec/queries/decidim/surveys/survey_user_answers_spec.rb +21 -0
  296. data/decidim-surveys/spec/services/decidim/surveys/surveys/survey_user_answer_serializer_spec.rb +34 -0
  297. data/decidim-surveys/spec/shared/edit_survey_examples.rb +213 -0
  298. data/decidim-surveys/spec/shared/export_survey_user_answers_examples.rb +47 -0
  299. data/decidim-surveys/spec/spec_helper.rb +4 -0
  300. data/decidim-system/app/controllers/decidim/system/devise/passwords_controller.rb +2 -0
  301. data/decidim-system/app/helpers/decidim/system/menu_helper.rb +0 -1
  302. data/decidim-system/bin/rails +3 -3
  303. data/decidim-system/config/locales/it.yml +66 -0
  304. data/decidim-system/db/migrate/20160919105637_devise_create_decidim_admins.rb +2 -0
  305. data/decidim-system/decidim-system.gemspec +2 -1
  306. data/decidim-system/spec/spec_helper.rb +3 -2
  307. data/decidim.gemspec +5 -4
  308. data/docs/geocoding.md +2 -2
  309. data/docs/how_to_create_a_plugin.md +11 -11
  310. data/lib/decidim.rb +1 -0
  311. data/lib/generators/decidim/app_generator.rb +3 -2
  312. data/lib/generators/decidim/demo_generator.rb +1 -1
  313. data/lib/generators/decidim/docker_generator.rb +2 -2
  314. data/lib/generators/decidim/install_generator.rb +3 -6
  315. data/lib/generators/decidim/templates/initializer.rb +2 -2
  316. metadata +130 -47
  317. data/decidim-admin/app/assets/javascripts/decidim/admin/sort_steps.js.es6 +0 -30
  318. data/decidim-budgets/spec/shared/admin_shared_context.rb +0 -13
  319. data/decidim-comments/spec/shared/admin_shared_context.rb +0 -13
  320. data/decidim-meetings/spec/shared/admin_shared_context.rb +0 -13
  321. data/decidim-proposals/spec/shared/admin_shared_context.rb +0 -13
  322. data/decidim-results/spec/shared/admin_shared_context.rb +0 -13
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Surveys
7
+ module Admin
8
+ describe SurveyForm do
9
+ let(:current_organization) { create(:organization) }
10
+
11
+ let(:description) do
12
+ {
13
+ "en" => "<p>Content</p>",
14
+ "ca" => "<p>Contingut</p>",
15
+ "es" => "<p>Contenido</p>"
16
+ }
17
+ end
18
+
19
+ let(:questions) do
20
+ [
21
+ {
22
+ body: {
23
+ "en" => "First question",
24
+ "ca" => "Primera pregunta",
25
+ "es" => "Primera pregunta"
26
+ },
27
+ position: 0,
28
+ question_type: "short_answer"
29
+ },
30
+ {
31
+ body: {
32
+ "en" => "Second question",
33
+ "ca" => "Segona pregunta",
34
+ "es" => "Segunda pregunta"
35
+ },
36
+ position: 1,
37
+ mandatory: true,
38
+ question_type: "short_answer"
39
+ }
40
+ ]
41
+ end
42
+
43
+ let(:attributes) do
44
+ {
45
+ "survey" => {
46
+ "description" => description,
47
+ "questions" => questions
48
+ }
49
+ }
50
+ end
51
+
52
+ subject do
53
+ described_class.from_params(attributes).with_context(
54
+ current_organization: current_organization
55
+ )
56
+ end
57
+
58
+ context "when everything is OK" do
59
+ it { is_expected.to be_valid }
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Surveys
7
+ module Admin
8
+ describe SurveyQuestionForm do
9
+ let!(:survey) { create(:survey) }
10
+ let!(:position) { 0 }
11
+ let!(:question_type) { SurveyQuestion::TYPES.first }
12
+ let!(:survey_question) { create(:survey_question, survey: survey, position: position, question_type: question_type) }
13
+
14
+ subject do
15
+ described_class.from_model(survey_question).with_context(current_feature: survey.feature)
16
+ end
17
+
18
+ context "when everything is OK" do
19
+ it { is_expected.to be_valid }
20
+ end
21
+
22
+ context "when the position is not present" do
23
+ let!(:position) { nil }
24
+
25
+ it { is_expected.not_to be_valid }
26
+ end
27
+
28
+ context "when the question_type is not known" do
29
+ let!(:question_type) { "foo" }
30
+
31
+ it { is_expected.not_to be_valid }
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Surveys
7
+ describe SurveyAnswerForm do
8
+ let!(:survey) { create(:survey) }
9
+ let!(:user) { create(:user, organization: survey.feature.participatory_process.organization) }
10
+ let!(:survey_question) { create(:survey_question, survey: survey) }
11
+ let!(:survey_answer) { create(:survey_answer, user: user, survey: survey, question: survey_question) }
12
+
13
+ subject do
14
+ described_class.from_model(survey_answer).with_context(current_feature: survey.feature)
15
+ end
16
+
17
+ context "when everything is OK" do
18
+ it { is_expected.to be_valid }
19
+ end
20
+
21
+ context "when the question is mandatory" do
22
+ let!(:survey_question) { create(:survey_question, survey: survey, mandatory: true) }
23
+
24
+ it "is not valid if body is not present" do
25
+ subject.body = nil
26
+ expect(subject).not_to be_valid
27
+ end
28
+
29
+ it "is not valid if body entries are all blank" do
30
+ subject.body = [""]
31
+ expect(subject).not_to be_valid
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Surveys
7
+ describe SurveyForm do
8
+ let!(:survey) { create(:survey) }
9
+ let!(:survey_question) { create(:survey_question, survey: survey) }
10
+
11
+ subject do
12
+ described_class.from_model(survey).with_context(current_feature: survey.feature)
13
+ end
14
+
15
+ it "builds empty answers for each question" do
16
+ expect(subject.answers.length).to eq(1)
17
+ end
18
+
19
+ context "when tos_agreement is not accepted" do
20
+ it { is_expected.not_to be_valid }
21
+ end
22
+
23
+ context "when tos_agreement is not accepted" do
24
+ before do
25
+ subject.tos_agreement = true
26
+ end
27
+
28
+ it { is_expected.to be_valid }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Decidim::Surveys::Abilities::AdminUser do
6
+ let(:user) { build(:user, :admin) }
7
+ let(:context) { {} }
8
+
9
+ subject { described_class.new(user, context) }
10
+
11
+ context "when the user is not an admin" do
12
+ let(:user) { build(:user) }
13
+
14
+ it "doesn't have any permission" do
15
+ expect(subject.permissions[:can]).to be_empty
16
+ expect(subject.permissions[:cannot]).to be_empty
17
+ end
18
+ end
19
+
20
+ it { is_expected.to be_able_to(:manage, Decidim::Surveys::Survey) }
21
+ it { is_expected.to be_able_to(:answer, Decidim::Surveys::Survey) }
22
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Decidim::Surveys::Abilities::CurrentUser do
6
+ let(:organization) { build(:organization) }
7
+ let(:user) { build(:user, organization: organization) }
8
+ let(:participatory_process) { build(:participatory_process, organization: organization) }
9
+ let(:surveys_feature) { build(:surveys_feature, participatory_process: participatory_process) }
10
+ let(:context) do
11
+ {
12
+ current_feature: surveys_feature
13
+ }
14
+ end
15
+
16
+ subject { described_class.new(user, context) }
17
+
18
+ it { is_expected.to be_able_to(:answer, Decidim::Surveys::Survey) }
19
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Decidim::Surveys::Abilities::ProcessAdminUser do
6
+ let(:user) { build(:user) }
7
+ let(:user_process) { create :participatory_process, organization: user.organization }
8
+ let(:context) { {} }
9
+
10
+ subject { described_class.new(user, context) }
11
+
12
+ context "when the user is an admin" do
13
+ let(:user) { build(:user, :admin) }
14
+
15
+ it "doesn't have any permission" do
16
+ expect(subject.permissions[:can]).to be_empty
17
+ expect(subject.permissions[:cannot]).to be_empty
18
+ end
19
+ end
20
+
21
+ it { is_expected.to be_able_to(:manage, Decidim::Surveys::Survey) }
22
+ it { is_expected.to be_able_to(:answer, Decidim::Surveys::Survey) }
23
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Surveys
7
+ describe SurveyAnswer do
8
+ let(:organization) { create(:organization) }
9
+ let(:user) { create(:user, organization: organization) }
10
+ let(:participatory_process) { create(:participatory_process, organization: organization) }
11
+ let(:feature) { create(:surveys_feature, participatory_process: participatory_process) }
12
+ let(:survey) { create(:survey, feature: feature) }
13
+ let(:survey_question) { create(:survey_question, survey: survey) }
14
+ let(:survey_answer) { create(:survey_answer, survey: survey, question: survey_question, user: user) }
15
+ subject { survey_answer }
16
+
17
+ it { is_expected.to be_valid }
18
+
19
+ it "has an association of survey" do
20
+ expect(subject.survey).to eq(survey)
21
+ end
22
+
23
+ it "has an association of question" do
24
+ expect(subject.question).to eq(survey_question)
25
+ end
26
+
27
+ it "has an association of user" do
28
+ expect(subject.user).to eq(user)
29
+ end
30
+
31
+ context "when the user doesn't belong to the same organization" do
32
+ it "is not valid" do
33
+ subject.user = create(:user)
34
+ expect(subject).not_to be_valid
35
+ end
36
+ end
37
+
38
+ context "when question doesn't belong to the survey" do
39
+ it "is not valid" do
40
+ subject.question = create(:survey_question)
41
+ expect(subject).not_to be_valid
42
+ end
43
+ end
44
+
45
+ context "when question is mandatory" do
46
+ let(:survey_question) { create(:survey_question, survey: survey, mandatory: true) }
47
+
48
+ it "is not valid with an empty body" do
49
+ subject.body = ""
50
+ expect(subject).not_to be_valid
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Surveys
7
+ describe SurveyQuestion do
8
+ let(:survey) { create(:survey) }
9
+ let(:survey_question) { create(:survey_question, survey: survey) }
10
+ subject { survey_question }
11
+
12
+ it { is_expected.to be_valid }
13
+
14
+ it "has an association of survey" do
15
+ expect(subject.survey).to eq(survey)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Surveys
7
+ describe Survey do
8
+ let(:survey) { create(:survey) }
9
+ subject { survey }
10
+
11
+ include_examples "has feature"
12
+
13
+ it { is_expected.to be_valid }
14
+
15
+ it "has an association of questions" do
16
+ subject.questions << create(:survey_question)
17
+ subject.questions << create(:survey_question)
18
+ expect(subject.questions.count).to eq(2)
19
+ end
20
+
21
+ it "has an association of answers" do
22
+ create(:survey_answer, survey: subject, user: create(:user, organization: survey.feature.organization))
23
+ create(:survey_answer, survey: subject, user: create(:user, organization: survey.feature.organization))
24
+ expect(subject.reload.answers.count).to eq(2)
25
+ end
26
+
27
+ context "without a feature" do
28
+ let(:survey) { build :survey, feature: nil }
29
+
30
+ it { is_expected.not_to be_valid }
31
+ end
32
+
33
+ context "without a valid feature" do
34
+ let(:survey) { build :survey, feature: build(:feature, manifest_name: "proposals") }
35
+
36
+ it { is_expected.not_to be_valid }
37
+ end
38
+
39
+ it "has an associated feature" do
40
+ expect(survey.feature).to be_a(Decidim::Feature)
41
+ end
42
+
43
+ context "#questions_editable?" do
44
+ it "returns false when survey has already answers" do
45
+ create(:survey_answer, survey: survey)
46
+ expect(subject.reload).not_to be_questions_editable
47
+ end
48
+ end
49
+
50
+ context "#answered_by?" do
51
+ let!(:user) { create(:user, organization: survey.feature.participatory_process.organization) }
52
+ let!(:question) { create(:survey_question, survey: survey) }
53
+
54
+ it "returns false if the given user has not answered the survey" do
55
+ expect(survey.answered_by?(user)).to be_falsy
56
+ end
57
+
58
+ it "returns true if the given user has answered the survey" do
59
+ create(:survey_answer, survey: survey, question: question, user: user)
60
+ expect(survey.answered_by?(user)).to be_truthy
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Decidim::Surveys::SurveyUserAnswers do
6
+ let!(:survey) { create(:survey) }
7
+ let!(:user_1) { create(:user, organization: survey.feature.organization) }
8
+ let!(:user_2) { create(:user, organization: survey.feature.organization) }
9
+ let!(:survey_questions) { 3.downto(1).map { |n| create :survey_question, survey: survey, position: n } }
10
+ let!(:survey_answers_user_1) { survey_questions.map { |question| create :survey_answer, user: user_1, survey: survey, question: question } }
11
+ let!(:survey_answers_user_2) { survey_questions.map { |question| create :survey_answer, user: user_2, survey: survey, question: question } }
12
+
13
+ subject { described_class.new(survey) }
14
+
15
+ it "returns the user answers for each user" do
16
+ result = subject.query
17
+
18
+ expect(result[0]).to eq(survey_answers_user_1.sort { |answer| answer.question.position })
19
+ expect(result[1]).to eq(survey_answers_user_2.sort { |answer| answer.question.position })
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Surveys
7
+ describe SurveyUserAnswersSerializer do
8
+ let!(:survey) { create(:survey) }
9
+ let!(:user) { create(:user, organization: survey.feature.organization) }
10
+ let!(:survey_questions) { create_list :survey_question, 3, survey: survey }
11
+ let!(:survey_answers) do
12
+ survey_questions.map do |question|
13
+ create :survey_answer, survey: survey, question: question, user: user
14
+ end
15
+ end
16
+
17
+ subject do
18
+ described_class.new(survey_answers)
19
+ end
20
+
21
+ describe "#serialize" do
22
+ let(:serialized) { subject.serialize }
23
+
24
+ it "includes the answer for each question" do
25
+ survey_questions.each_with_index do |question, idx|
26
+ expect(serialized).to include(
27
+ "#{idx + 1}. #{translated(question.body, locale: I18n.locale)}" => survey_answers[idx].body
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,213 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ RSpec.shared_examples "edit surveys" do
5
+ let(:body) do
6
+ {
7
+ en: "This is the first question",
8
+ ca: "Aquesta es la primera pregunta",
9
+ es: "Esta es la primera pregunta"
10
+ }
11
+ end
12
+
13
+ it "updates the survey" do
14
+ visit_feature_admin
15
+
16
+ new_description = {
17
+ en: "<p>New description</p>",
18
+ ca: "<p>Nova descripció</p>",
19
+ es: "<p>Nueva descripción</p>"
20
+ }
21
+
22
+ within "form.edit_survey" do
23
+ fill_in_i18n_editor(:survey_description, "#survey-description-tabs", new_description)
24
+ click_button "Save"
25
+ end
26
+
27
+ within ".callout-wrapper" do
28
+ expect(page).to have_content("successfully")
29
+ end
30
+
31
+ visit_feature
32
+
33
+ expect(page).to have_content("New description")
34
+ end
35
+
36
+ context "when the survey is not already answered" do
37
+ it "adds a few questions to the survey" do
38
+ visit_feature_admin
39
+
40
+ questions_body = [
41
+ {
42
+ en: "This is the first question",
43
+ ca: "Aquesta es la primera pregunta",
44
+ es: "Esta es la primera pregunta"
45
+ },
46
+ {
47
+ en: "This is the second question",
48
+ ca: "Aquesta es la segona pregunta",
49
+ es: "Esta es la segunda pregunta"
50
+ }
51
+ ]
52
+
53
+ within "form.edit_survey" do
54
+ 2.times { click_button "Add question" }
55
+
56
+ expect(page).to have_selector(".survey-question", count: 2)
57
+
58
+ page.all(".survey-question").each_with_index do |survey_question, idx|
59
+ questions_body[idx].each do |locale, value|
60
+ within survey_question do
61
+ click_link I18n.with_locale(locale) { I18n.t("name", scope: "locale") }
62
+ find("input[name='survey[questions][][body_#{locale}]']").send_keys value
63
+ end
64
+ end
65
+ end
66
+
67
+ click_button "Save"
68
+ end
69
+
70
+ within ".callout-wrapper" do
71
+ expect(page).to have_content("successfully")
72
+ end
73
+
74
+ visit_feature_admin
75
+
76
+ expect(page).to have_selector("input[value='This is the first question']")
77
+ expect(page).to have_selector("input[value='This is the second question']")
78
+ end
79
+
80
+ it "adds a question with answer options" do
81
+ visit_feature_admin
82
+
83
+ question_body = {
84
+ en: "This is the first question",
85
+ ca: "Aquesta es la primera pregunta",
86
+ es: "Esta es la primera pregunta"
87
+ }
88
+
89
+ answer_options_body = [
90
+ {
91
+ en: "This is the first option",
92
+ ca: "Aquesta es la primera opció",
93
+ es: "Esta es la primera opción"
94
+ },
95
+ {
96
+ en: "This is the second option",
97
+ ca: "Aquesta es la segona opció",
98
+ es: "Esta es la segunda opción"
99
+ }
100
+ ]
101
+
102
+ within "form.edit_survey" do
103
+ click_button "Add question"
104
+
105
+ expect(page).to have_selector(".survey-question", count: 1)
106
+
107
+ question_body.each do |locale, value|
108
+ within ".survey-question" do
109
+ click_link I18n.with_locale(locale) { I18n.t("name", scope: "locale") }
110
+ find("input[name='survey[questions][][body_#{locale}]']").send_keys value
111
+ end
112
+ end
113
+
114
+ expect(page).not_to have_content "Add answer option"
115
+
116
+ select "Single option", from: "Type"
117
+
118
+ expect(page).to have_content "Add answer option"
119
+
120
+ 2.times { click_button "Add answer option" }
121
+
122
+ page.all(".survey-question-answer-option").each_with_index do |survey_question_answer_option, idx|
123
+ answer_options_body[idx].each do |locale, value|
124
+ within survey_question_answer_option do
125
+ click_link I18n.with_locale(locale) { I18n.t("name", scope: "locale") }
126
+ find("input[name='survey[questions][][answer_options][][body_#{locale}]']").send_keys value
127
+ end
128
+ end
129
+ end
130
+
131
+ click_button "Save"
132
+ end
133
+
134
+ within ".callout-wrapper" do
135
+ expect(page).to have_content("successfully")
136
+ end
137
+
138
+ visit_feature_admin
139
+
140
+ expect(page).to have_selector("input[value='This is the first question']")
141
+ expect(page).to have_selector("input[value='This is the first option']")
142
+ expect(page).to have_selector("input[value='This is the second option']")
143
+ end
144
+
145
+ describe "when a survey has an existing question" do
146
+ let!(:survey_question) { create(:survey_question, survey: survey, body: body) }
147
+
148
+ it "modifies the question" do
149
+ visit_feature_admin
150
+
151
+ within "form.edit_survey" do
152
+ expect(page).to have_selector(".survey-question", count: 1)
153
+
154
+ within ".survey-question" do
155
+ fill_in "survey-question-#{survey_question.id}_body_en", with: "Modified question"
156
+ check "Mandatory"
157
+ select "Long answer", from: "Type"
158
+ end
159
+
160
+ click_button "Save"
161
+ end
162
+
163
+ within ".callout-wrapper" do
164
+ expect(page).to have_content("successfully")
165
+ end
166
+
167
+ visit_feature_admin
168
+
169
+ expect(page).to have_selector("input[value='Modified question']")
170
+ expect(page).not_to have_selector("input[value='This is the first question']")
171
+ expect(page).to have_selector("input#survey_questions_#{survey_question.id}_mandatory[checked]")
172
+ expect(page).to have_selector("select#survey_questions_#{survey_question.id}_question_type option[value='long_answer'][selected]")
173
+ end
174
+
175
+ it "removes the question" do
176
+ visit_feature_admin
177
+
178
+ within "form.edit_survey" do
179
+ expect(page).to have_selector(".survey-question", count: 1)
180
+
181
+ within ".survey-question" do
182
+ click_button "Remove question"
183
+ end
184
+
185
+ click_button "Save"
186
+ end
187
+
188
+ within ".callout-wrapper" do
189
+ expect(page).to have_content("successfully")
190
+ end
191
+
192
+ visit_feature_admin
193
+
194
+ within "form.edit_survey" do
195
+ expect(page).to have_selector(".survey-question", count: 0)
196
+ end
197
+ end
198
+ end
199
+ end
200
+
201
+ context "when the survey is already answered" do
202
+ let!(:survey_question) { create(:survey_question, survey: survey, body: body) }
203
+ let!(:survey_answer) { create(:survey_answer, survey: survey, question: survey_question) }
204
+
205
+ it "cannot modify survey questions" do
206
+ visit_feature_admin
207
+
208
+ expect(page).not_to have_content("Add question")
209
+ expect(page).not_to have_content("Remove question")
210
+ expect(page).to have_selector("input[value='This is the first question'][disabled]")
211
+ end
212
+ end
213
+ end