decidim-forms 0.23.1 → 0.24.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/decidim/forms/forms.js.es6 +4 -4
- data/app/commands/decidim/forms/admin/update_questionnaire.rb +2 -1
- data/app/commands/decidim/forms/answer_questionnaire.rb +43 -1
- data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +10 -2
- data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +13 -6
- data/app/forms/decidim/forms/admin/question_form.rb +2 -0
- data/app/forms/decidim/forms/answer_form.rb +27 -0
- data/app/helpers/decidim/forms/admin/application_helper.rb +1 -6
- data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_url_helper.rb +3 -3
- data/app/helpers/decidim/forms/admin/questionnaire_answers_helper.rb +5 -2
- data/app/jobs/decidim/forms/export_questionnaire_answers_job.rb +1 -1
- data/app/models/decidim/forms/answer.rb +8 -0
- data/app/models/decidim/forms/question.rb +9 -3
- data/app/models/decidim/forms/questionnaire.rb +11 -0
- data/app/presenters/decidim/forms/admin/questionnaire_answer_presenter.rb +20 -0
- data/app/presenters/decidim/forms/admin/questionnaire_participant_presenter.rb +4 -4
- data/app/queries/decidim/forms/questionnaire_user_answers.rb +2 -1
- data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +3 -3
- data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +11 -0
- data/app/views/decidim/forms/admin/questionnaires/edit.html.erb +1 -1
- data/app/views/decidim/forms/questionnaires/_answer.html.erb +1 -1
- data/app/views/decidim/forms/questionnaires/answers/_files.html.erb +1 -0
- data/app/views/decidim/forms/questionnaires/answers/_long_answer.html.erb +1 -1
- data/app/views/decidim/forms/questionnaires/answers/_matrix_multiple.html.erb +2 -1
- data/app/views/decidim/forms/questionnaires/answers/_matrix_single.html.erb +2 -1
- data/app/views/decidim/forms/questionnaires/answers/_multiple_option.html.erb +2 -1
- data/app/views/decidim/forms/questionnaires/answers/_short_answer.html.erb +1 -1
- data/app/views/decidim/forms/questionnaires/answers/_single_option.html.erb +2 -1
- data/app/views/decidim/forms/questionnaires/show.html.erb +1 -1
- data/config/initializers/wicked_pdf.rb +2 -0
- data/config/locales/ca.yml +8 -2
- data/config/locales/cs.yml +10 -4
- data/config/locales/de.yml +10 -2
- data/config/locales/el.yml +1 -1
- data/config/locales/en.yml +8 -2
- data/config/locales/es-MX.yml +8 -2
- data/config/locales/es-PY.yml +8 -2
- data/config/locales/es.yml +8 -2
- data/config/locales/fi-plain.yml +8 -2
- data/config/locales/fi.yml +8 -2
- data/config/locales/fr-CA.yml +8 -2
- data/config/locales/fr.yml +10 -4
- data/config/locales/it.yml +1 -2
- data/config/locales/ja.yml +3 -3
- data/config/locales/lv.yml +1 -1
- data/config/locales/nl.yml +4 -5
- data/config/locales/no.yml +1 -1
- data/config/locales/pl.yml +11 -2
- data/config/locales/pt.yml +1 -2
- data/config/locales/ro-RO.yml +1 -2
- data/config/locales/si-LK.yml +1 -0
- data/config/locales/sv.yml +1 -2
- data/config/locales/sw-KE.yml +1 -0
- data/config/locales/tr-TR.yml +88 -1
- data/config/locales/zh-CN.yml +1 -2
- data/db/migrate/20201110152921_add_salt_to_decidim_forms_questionnaires.rb +16 -0
- data/db/migrate/20210208094442_add_max_characters_to_decidim_forms_questions.rb +7 -0
- data/lib/decidim/api/answer_option_type.rb +13 -0
- data/lib/decidim/api/question_type.rb +21 -0
- data/lib/decidim/api/questionnaire_entity_interface.rb +5 -5
- data/lib/decidim/api/questionnaire_type.rb +19 -0
- data/lib/decidim/exporters/form_pdf_controller_helper.rb +2 -0
- data/lib/decidim/forms.rb +1 -1
- data/lib/decidim/forms/api.rb +3 -0
- data/lib/decidim/forms/data_portability_user_answers_serializer.rb +7 -1
- data/lib/decidim/forms/test/factories.rb +13 -2
- data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +38 -5
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +5 -4
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_display_conditions.rb +7 -3
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_questions.rb +1 -1
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_questions.rb +5 -0
- data/lib/decidim/forms/user_answers_serializer.rb +10 -2
- data/lib/decidim/forms/version.rb +1 -1
- metadata +23 -18
- data/app/types/decidim/forms/answer_option_type.rb +0 -14
- data/app/types/decidim/forms/question_type.rb +0 -23
- data/app/types/decidim/forms/questionnaire_type.rb +0 -22
@@ -0,0 +1 @@
|
|
1
|
+
si:
|
data/config/locales/sv.yml
CHANGED
@@ -76,7 +76,6 @@ sv:
|
|
76
76
|
collapse: Komprimera alla frågor
|
77
77
|
expand: Expandera alla frågor
|
78
78
|
preview: Förhandsgranska
|
79
|
-
title: Redigera formulär
|
80
79
|
unpublished_warning: Formuläret är inte publicerat. Du kan ändra dess frågor, men det kommer att ta bort aktuella svar.
|
81
80
|
matrix_row:
|
82
81
|
matrix_row: Rad
|
@@ -107,7 +106,7 @@ sv:
|
|
107
106
|
answer:
|
108
107
|
body: Kroppen kan inte vara to
|
109
108
|
files:
|
110
|
-
|
109
|
+
extension_allowlist: 'Godkända format:'
|
111
110
|
images:
|
112
111
|
dimensions: "%{width} x %{height} px"
|
113
112
|
dimensions_info: 'Denna bild kommer att vara:'
|
@@ -0,0 +1 @@
|
|
1
|
+
sw:
|
data/config/locales/tr-TR.yml
CHANGED
@@ -3,6 +3,8 @@ tr:
|
|
3
3
|
attributes:
|
4
4
|
answer:
|
5
5
|
body: Cevap
|
6
|
+
choices: Seçenekler
|
7
|
+
selected_choices: Seçilmiş seçenekler
|
6
8
|
question:
|
7
9
|
max_choices: Maksimum seçenek sayısı
|
8
10
|
question_type: tip
|
@@ -15,6 +17,8 @@ tr:
|
|
15
17
|
choices:
|
16
18
|
missing: tamamlanmadı
|
17
19
|
too_many: çok fazla
|
20
|
+
questionnaire:
|
21
|
+
request_invalid: İsteği işlerken bir hata oluştu. Lütfen tekrar deneyin
|
18
22
|
decidim:
|
19
23
|
forms:
|
20
24
|
admin:
|
@@ -23,42 +27,108 @@ tr:
|
|
23
27
|
description: Açıklama
|
24
28
|
tos: Kullanım Şartları
|
25
29
|
questionnaires:
|
30
|
+
actions:
|
31
|
+
back: Sorulara geri dön
|
32
|
+
show: Yanıtları göster
|
26
33
|
answer_option:
|
27
34
|
answer_option: Cevap seçeneği
|
28
35
|
free_text: Ücretsiz Metin
|
29
36
|
remove: Kaldır
|
30
37
|
statement: Beyan
|
38
|
+
answers:
|
39
|
+
actions:
|
40
|
+
back: Yanıtlara dön
|
41
|
+
export: Dışa aktar
|
42
|
+
show: Cevapları göster
|
43
|
+
empty: Henüz cevap bulunmuyor
|
44
|
+
export:
|
45
|
+
answer:
|
46
|
+
title: '#%{number} yanıt'
|
47
|
+
export_response:
|
48
|
+
title: survey_user_answers _%{token}
|
49
|
+
index:
|
50
|
+
title: "%{total} toplam yanıt"
|
51
|
+
show:
|
52
|
+
title: '%{number} cevap'
|
53
|
+
display_condition:
|
54
|
+
answer_option: Cevap seçeneği
|
55
|
+
condition_question: Soru
|
56
|
+
condition_type: Durum
|
57
|
+
condition_types:
|
58
|
+
answered: Cevaplanmış
|
59
|
+
equal: Eşittir
|
60
|
+
match: Metin içerir
|
61
|
+
not_answered: Cevaplanmadı
|
62
|
+
not_equal: Eşit değil
|
63
|
+
condition_value: Metin içerir
|
64
|
+
display_condition: Görüntüleme koşulları
|
65
|
+
mandatory: Bu koşul, diğer koşulların durumuna bakılmaksızın her zaman yerine getirilmelidir
|
66
|
+
remove: Kaldır
|
67
|
+
save_warning: Görüntüleme koşullarını yapılandırmadan önce formu kaydetmeyi unutmayın
|
68
|
+
select_answer_option: Cevap seçeneğini seçin
|
69
|
+
select_condition_question: Bir soru seçin
|
70
|
+
select_condition_type: Bir koşul türü seçin
|
31
71
|
edit:
|
32
72
|
save: Kayıt etmek
|
73
|
+
title: Anketi düzenleyin
|
33
74
|
form:
|
34
75
|
add_question: Soru ekle
|
76
|
+
add_separator: Ayırıcı ekle
|
35
77
|
already_answered_warning: Form, bazı kullanıcılar tarafından zaten yanıtlandı, bu nedenle sorularını değiştiremezsiniz.
|
78
|
+
collapse: Tüm soruları daraltın
|
79
|
+
expand: Tüm soruları genişletin
|
80
|
+
preview: Önizleme
|
81
|
+
title: '%{questionnaire_for} için formu düzenleyin'
|
82
|
+
unpublished_warning: Form yayınlanmadı. Sorularını değiştirebilirsiniz, ancak bunu yapmak mevcut cevapları silecektir.
|
36
83
|
matrix_row:
|
84
|
+
matrix_row: Satır
|
37
85
|
remove: Kaldır
|
38
86
|
statement: Beyan
|
39
87
|
question:
|
40
88
|
add_answer_option: Cevap seçeneği ekle
|
89
|
+
add_display_condition: Görüntü koşulu ekle
|
90
|
+
add_display_condition_info: Görüntüleme koşullarını yapılandırmak için formu kaydedin
|
91
|
+
add_matrix_row: Satır ekle
|
41
92
|
any: herhangi
|
93
|
+
collapse: Daralt
|
42
94
|
description: Açıklama
|
43
95
|
down: Aşağı
|
96
|
+
expand: Genişlet
|
44
97
|
question: Soru
|
45
98
|
remove: Kaldır
|
46
99
|
statement: Beyan
|
47
100
|
up: yukarı
|
101
|
+
separator:
|
102
|
+
down: Aşağı
|
103
|
+
remove: Kaldır
|
104
|
+
separator: Ayraç
|
105
|
+
up: Yukarı
|
48
106
|
update:
|
49
107
|
invalid: Formu kaydederken bir sorun oluştu.
|
108
|
+
success: Başarıyla kaydedildi.
|
50
109
|
errors:
|
51
110
|
answer:
|
52
111
|
body: Vücut boş olamaz
|
112
|
+
files:
|
113
|
+
extension_allowlist: 'Kabul edilen biçimler:'
|
114
|
+
images:
|
115
|
+
dimensions: "%{width} x %{height} px"
|
116
|
+
dimensions_info: 'Bu resim:'
|
117
|
+
processors:
|
118
|
+
resize_and_pad: Yeniden boyutlandırıldı ve dolduruldu
|
119
|
+
resize_to_fit: Sığacak şekilde yeniden boyutlandırıldı
|
53
120
|
question_types:
|
54
121
|
long_answer: Uzun cevap
|
122
|
+
matrix_multiple: Matris (Çoklu seçenek)
|
123
|
+
matrix_single: Matris (Tek seçenek)
|
55
124
|
multiple_option: Çoklu seçenek
|
56
125
|
short_answer: Kısa cevap
|
57
126
|
single_option: Tek seçenek
|
58
|
-
sorting:
|
127
|
+
sorting: Sıralama
|
59
128
|
questionnaires:
|
60
129
|
answer:
|
61
130
|
invalid: Formu yanıtlarken bir sorun oluştu.
|
131
|
+
max_choices_alert: Çok fazla seçenek seçilmiş
|
62
132
|
success: Form başarıyla cevaplandı.
|
63
133
|
question:
|
64
134
|
max_choices: 'Maksimum seçenek: %{n}'
|
@@ -66,6 +136,8 @@ tr:
|
|
66
136
|
answer_questionnaire:
|
67
137
|
anonymous_user_message: <a href="%{sign_in_link}">Formu yanıtlamak için</a> veya <a href="%{sign_up_link}">hesabınızla giriş yapın</a>.
|
68
138
|
title: Formu cevapla
|
139
|
+
current_step: '%{step} adım'
|
140
|
+
of_total_steps: '%{total_steps}'
|
69
141
|
questionnaire_answered:
|
70
142
|
body: Bu formu zaten cevapladınız.
|
71
143
|
title: Zaten cevaplandı
|
@@ -75,11 +147,26 @@ tr:
|
|
75
147
|
questionnaire_for_private_users:
|
76
148
|
body: Form yalnızca özel kullanıcılar tarafından kullanılabilir
|
77
149
|
title: Form kapatıldı
|
150
|
+
questionnaire_js_disabled:
|
151
|
+
body: Bu formun bazı özellikleri devre dışı bırakılacak. Deneyiminizi iyileştirmek için lütfen tarayıcınızda JavaScript'i etkinleştirin.
|
152
|
+
title: JavaScript devre dışı
|
153
|
+
questionnaire_not_published:
|
154
|
+
body: Bu form henüz yayınlanmadı.
|
78
155
|
tos_agreement: Katılarak Hizmet Şartlarını kabul etmiş olursunuz.
|
79
156
|
step_navigation:
|
80
157
|
show:
|
81
158
|
are_you_sure: Bu işlem geri alınamaz ve cevaplarınızı düzenleyemezsiniz. Emin misiniz?
|
159
|
+
back: Geri
|
160
|
+
continue: Devam et
|
82
161
|
submit: Gönder
|
83
162
|
user_answers_serializer:
|
163
|
+
body: Cevap
|
164
|
+
completion: Tamamlanma
|
84
165
|
created_at: Yanıtlandı
|
85
166
|
id: Cevap kimliği
|
167
|
+
ip_hash: IP Hash
|
168
|
+
question: Soru
|
169
|
+
registered: Kayıtlı
|
170
|
+
session_token: Kullanıcı tanımlayıcı
|
171
|
+
unregistered: Kayıtlı değil
|
172
|
+
user_status: Kullanıcı durumu
|
data/config/locales/zh-CN.yml
CHANGED
@@ -78,7 +78,6 @@ zh-CN:
|
|
78
78
|
collapse: 收起所有问题
|
79
79
|
expand: 展开所有问题
|
80
80
|
preview: 预览
|
81
|
-
title: 编辑表单
|
82
81
|
unpublished_warning: 表单未发布。您可以修改它的问题,但这样做将删除当前答案。
|
83
82
|
matrix_row:
|
84
83
|
matrix_row: 行
|
@@ -110,7 +109,7 @@ zh-CN:
|
|
110
109
|
answer:
|
111
110
|
body: 主体不能为空
|
112
111
|
files:
|
113
|
-
|
112
|
+
extension_allowlist: '接受的格式:'
|
114
113
|
images:
|
115
114
|
dimensions: "%{width} x %{height} px"
|
116
115
|
dimensions_info: '这张图片将是:'
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AddSaltToDecidimFormsQuestionnaires < ActiveRecord::Migration[5.2]
|
4
|
+
class Questionnaire < ApplicationRecord
|
5
|
+
self.table_name = :decidim_forms_questionnaires
|
6
|
+
end
|
7
|
+
|
8
|
+
def change
|
9
|
+
add_column :decidim_forms_questionnaires, :salt, :string
|
10
|
+
|
11
|
+
Questionnaire.find_each do |questionnaire|
|
12
|
+
questionnaire.salt = Decidim::Tokenizer.random_salt
|
13
|
+
questionnaire.save!
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Forms
|
5
|
+
class AnswerOptionType < Decidim::Api::Types::BaseObject
|
6
|
+
description "An answer option for a multi-choice question in a questionnaire"
|
7
|
+
|
8
|
+
field :id, GraphQL::Types::ID, "ID of this answer option", null: false
|
9
|
+
field :body, Decidim::Core::TranslatedFieldType, "The text answer response option.", null: false
|
10
|
+
field :free_text, GraphQL::Types::Boolean, "Whether if this answer accepts any free text from the user.", null: false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Forms
|
5
|
+
class QuestionType < Decidim::Api::Types::BaseObject
|
6
|
+
description "A question in a questionnaire"
|
7
|
+
|
8
|
+
implements Decidim::Core::TimestampsInterface
|
9
|
+
|
10
|
+
field :id, GraphQL::Types::ID, "ID of this question", null: false
|
11
|
+
field :body, Decidim::Core::TranslatedFieldType, "What is being asked in this question.", null: false
|
12
|
+
field :description, Decidim::Core::TranslatedFieldType, "The description of this question.", null: true
|
13
|
+
field :mandatory, GraphQL::Types::Boolean, "Whether if this question is mandatory.", null: false
|
14
|
+
field :position, GraphQL::Types::Int, "Order position of the question in the questionnaire", null: true
|
15
|
+
field :max_choices, GraphQL::Types::Int, "On questions with answer options, maximum number of choices the user has", null: true
|
16
|
+
field :max_characters, GraphQL::Types::Int, "On questions with free text answers, maximum number of characters the answer can have (0 if no limit)", null: false
|
17
|
+
field :question_type, GraphQL::Types::String, "Type of question.", null: true
|
18
|
+
field :answer_options, [AnswerOptionType, { null: true }], "List of answer options in multi-choice questions.", null: false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -4,15 +4,15 @@ module Decidim
|
|
4
4
|
module Forms
|
5
5
|
# This interface should be implemented by any Type that can be linked to a questionnaire
|
6
6
|
# The only requirement is to have an ID and the Type name be the class.name + Type
|
7
|
-
QuestionnaireEntityInterface
|
8
|
-
|
7
|
+
module QuestionnaireEntityInterface
|
8
|
+
include Decidim::Api::Types::BaseInterface
|
9
9
|
description "An interface that can be used in objects with questionnaires"
|
10
10
|
|
11
|
-
field :id,
|
11
|
+
field :id, GraphQL::Types::ID, "ID of this entity", null: false
|
12
12
|
|
13
|
-
resolve_type
|
13
|
+
def self.resolve_type(obj, _ctx)
|
14
14
|
"#{obj.class.name}Type".constantize
|
15
|
-
|
15
|
+
end
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Forms
|
5
|
+
class QuestionnaireType < Decidim::Api::Types::BaseObject
|
6
|
+
description "A questionnaire"
|
7
|
+
|
8
|
+
implements Decidim::Core::TimestampsInterface
|
9
|
+
|
10
|
+
field :id, GraphQL::Types::ID, "ID of this questionnaire", null: false
|
11
|
+
field :title, Decidim::Core::TranslatedFieldType, "The title of this questionnaire.", null: false
|
12
|
+
field :description, Decidim::Core::TranslatedFieldType, "The description of this questionnaire.", null: true
|
13
|
+
field :tos, Decidim::Core::TranslatedFieldType, "The Terms of Service for this questionnaire.", null: true
|
14
|
+
field :for_type, GraphQL::Types::String, "Type of entity using this questionnaire.", method: :questionnaire_for_type, null: true
|
15
|
+
field :for_entity, QuestionnaireEntityInterface, "Entity using this questionnaire.", method: :questionnaire_for, null: true
|
16
|
+
field :questions, [Decidim::Forms::QuestionType, { null: true }], "Questions in this questionnaire.", null: false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -2,8 +2,10 @@
|
|
2
2
|
|
3
3
|
module Decidim
|
4
4
|
module Exporters
|
5
|
+
# rubocop: disable Rails/ApplicationController
|
5
6
|
# A dummy controller to render views while exporting questionnaires
|
6
7
|
class FormPDFControllerHelper < ActionController::Base
|
8
|
+
# rubocop: enable Rails/ApplicationController
|
7
9
|
helper Decidim::TranslationsHelper
|
8
10
|
helper Decidim::Forms::Admin::QuestionnaireAnswersHelper
|
9
11
|
end
|
data/lib/decidim/forms.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "decidim/forms/admin"
|
4
|
+
require "decidim/forms/api"
|
4
5
|
require "decidim/forms/engine"
|
5
6
|
require "decidim/forms/admin_engine"
|
6
|
-
require "decidim/forms/api"
|
7
7
|
|
8
8
|
module Decidim
|
9
9
|
# This namespace holds the logic of the `Forms`.
|
data/lib/decidim/forms/api.rb
CHANGED
@@ -3,5 +3,8 @@
|
|
3
3
|
module Decidim
|
4
4
|
module Forms
|
5
5
|
autoload :QuestionnaireEntityInterface, "decidim/api/questionnaire_entity_interface"
|
6
|
+
autoload :AnswerOptionType, "decidim/api/answer_option_type"
|
7
|
+
autoload :QuestionType, "decidim/api/question_type"
|
8
|
+
autoload :QuestionnaireType, "decidim/api/questionnaire_type"
|
6
9
|
end
|
7
10
|
end
|
@@ -30,7 +30,13 @@ module Decidim
|
|
30
30
|
private
|
31
31
|
|
32
32
|
def normalize_body(resource)
|
33
|
-
resource.body || resource.choices.pluck(:body)
|
33
|
+
attachments_for(resource) || resource.body || resource.choices.pluck(:body)
|
34
|
+
end
|
35
|
+
|
36
|
+
def attachments_for(resource)
|
37
|
+
return if resource.attachments.blank?
|
38
|
+
|
39
|
+
resource.attachments.map(&:url)
|
34
40
|
end
|
35
41
|
end
|
36
42
|
end
|
@@ -13,13 +13,17 @@ FactoryBot.define do
|
|
13
13
|
end
|
14
14
|
tos { generate_localized_title }
|
15
15
|
questionnaire_for { build(:participatory_process) }
|
16
|
+
salt { SecureRandom.hex(32) }
|
16
17
|
|
17
18
|
trait :with_questions do
|
18
19
|
questions do
|
20
|
+
position = 0
|
19
21
|
qs = %w(short_answer long_answer).collect do |text_question_type|
|
20
|
-
build(:questionnaire_question, question_type: text_question_type)
|
22
|
+
q = build(:questionnaire_question, question_type: text_question_type, position: position)
|
23
|
+
position += 1
|
24
|
+
q
|
21
25
|
end
|
22
|
-
qs << build(:questionnaire_question, :with_answer_options, question_type: :single_option)
|
26
|
+
qs << build(:questionnaire_question, :with_answer_options, question_type: :single_option, position: position)
|
23
27
|
qs
|
24
28
|
end
|
25
29
|
end
|
@@ -90,6 +94,13 @@ FactoryBot.define do
|
|
90
94
|
question { create(:questionnaire_question, questionnaire: questionnaire) }
|
91
95
|
user { create(:user, organization: questionnaire.questionnaire_for.organization) }
|
92
96
|
session_token { Digest::MD5.hexdigest(user.id.to_s) }
|
97
|
+
|
98
|
+
trait :with_attachments do
|
99
|
+
after(:create) do |answer, _evaluator|
|
100
|
+
create :attachment, :with_image, attached_to: answer
|
101
|
+
create :attachment, :with_pdf, attached_to: answer
|
102
|
+
end
|
103
|
+
end
|
93
104
|
end
|
94
105
|
|
95
106
|
factory :answer_option, class: "Decidim::Forms::AnswerOption" do
|
@@ -194,6 +194,28 @@ shared_examples_for "has questionnaire" do
|
|
194
194
|
end
|
195
195
|
end
|
196
196
|
|
197
|
+
shared_examples_for "question has a character limit" do
|
198
|
+
context "when max_characters value is positive" do
|
199
|
+
let(:max_characters) { 30 }
|
200
|
+
|
201
|
+
it "shows a message indicating number of characters left" do
|
202
|
+
visit questionnaire_public_path
|
203
|
+
|
204
|
+
expect(page).to have_content("30 characters left")
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context "when max_characters value is 0" do
|
209
|
+
let(:max_characters) { 0 }
|
210
|
+
|
211
|
+
it "doesn't show message indicating number of characters left" do
|
212
|
+
visit questionnaire_public_path
|
213
|
+
|
214
|
+
expect(page).not_to have_content("characters left")
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
197
219
|
describe "leaving a blank question (without js)", driver: :rack_test do
|
198
220
|
include_context "when a non multiple choice question is mandatory"
|
199
221
|
|
@@ -268,12 +290,13 @@ shared_examples_for "has questionnaire" do
|
|
268
290
|
|
269
291
|
describe "free text options" do
|
270
292
|
let(:answer_option_bodies) { Array.new(3) { Decidim::Faker::Localized.sentence } }
|
271
|
-
|
293
|
+
let(:max_characters) { 0 }
|
272
294
|
let!(:question) do
|
273
295
|
create(
|
274
296
|
:questionnaire_question,
|
275
297
|
questionnaire: questionnaire,
|
276
298
|
question_type: question_type,
|
299
|
+
max_characters: max_characters,
|
277
300
|
position: 1,
|
278
301
|
options: [
|
279
302
|
{ "body" => answer_option_bodies[0] },
|
@@ -346,6 +369,8 @@ shared_examples_for "has questionnaire" do
|
|
346
369
|
|
347
370
|
expect(page).to have_field("questionnaire_responses_0_choices_2_custom_body", with: "Cacatua")
|
348
371
|
end
|
372
|
+
|
373
|
+
it_behaves_like "question has a character limit"
|
349
374
|
end
|
350
375
|
|
351
376
|
context "when question is multiple_option type" do
|
@@ -392,27 +417,35 @@ shared_examples_for "has questionnaire" do
|
|
392
417
|
|
393
418
|
expect(page).to have_field("questionnaire_responses_0_choices_2_custom_body", with: "Cacatua")
|
394
419
|
end
|
420
|
+
|
421
|
+
it_behaves_like "question has a character limit"
|
395
422
|
end
|
396
423
|
end
|
397
424
|
|
398
425
|
context "when question type is long answer" do
|
399
|
-
let
|
426
|
+
let(:max_characters) { 0 }
|
427
|
+
let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, question_type: "long_answer", max_characters: max_characters) }
|
400
428
|
|
401
429
|
it "renders the answer as a textarea" do
|
402
430
|
visit questionnaire_public_path
|
403
431
|
|
404
432
|
expect(page).to have_selector("textarea#questionnaire_responses_0")
|
405
433
|
end
|
434
|
+
|
435
|
+
it_behaves_like "question has a character limit"
|
406
436
|
end
|
407
437
|
|
408
438
|
context "when question type is short answer" do
|
409
|
-
let
|
439
|
+
let(:max_characters) { 0 }
|
440
|
+
let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, question_type: "short_answer", max_characters: max_characters) }
|
410
441
|
|
411
442
|
it "renders the answer as a text field" do
|
412
443
|
visit questionnaire_public_path
|
413
444
|
|
414
445
|
expect(page).to have_selector("input[type=text]#questionnaire_responses_0")
|
415
446
|
end
|
447
|
+
|
448
|
+
it_behaves_like "question has a character limit"
|
416
449
|
end
|
417
450
|
|
418
451
|
context "when question type is single option" do
|
@@ -665,7 +698,7 @@ shared_examples_for "has questionnaire" do
|
|
665
698
|
end
|
666
699
|
|
667
700
|
radio_buttons = page.all(".radio-button-collection input[type=radio]")
|
668
|
-
expect(radio_buttons.
|
701
|
+
expect(radio_buttons.pluck(:checked)).to eq([nil, "true", nil, nil])
|
669
702
|
end
|
670
703
|
|
671
704
|
context "when the question is mandatory and the answer is not complete" do
|
@@ -830,7 +863,7 @@ shared_examples_for "has questionnaire" do
|
|
830
863
|
end
|
831
864
|
|
832
865
|
checkboxes = page.all(".check-box-collection input[type=checkbox]")
|
833
|
-
expect(checkboxes.
|
866
|
+
expect(checkboxes.pluck(:checked)).to eq(["true", "true", "true", nil, nil, "true"])
|
834
867
|
end
|
835
868
|
end
|
836
869
|
end
|