decidim-dev 0.20.1 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/images/decidim/dummy.svg +1 -4
- data/app/assets/images/decidim/gamification/badges/test.svg +1 -145
- data/app/commands/decidim/dummy_resources/create_dummy_resource.rb +48 -0
- data/app/controllers/decidim/dummy_resources/dummy_resources_controller.rb +1 -0
- data/app/forms/decidim/dummy_resources/dummy_resource_form.rb +3 -0
- data/app/views/decidim/dummy_resources/dummy_resources/show.html.erb +4 -0
- data/config/locales/am-ET.yml +1 -0
- data/config/locales/bg-BG.yml +56 -0
- data/config/locales/bg.yml +56 -0
- data/config/locales/ca.yml +15 -0
- data/config/locales/cs.yml +16 -1
- data/config/locales/da-DK.yml +1 -0
- data/config/locales/da.yml +1 -0
- data/config/locales/de.yml +16 -0
- data/config/locales/el.yml +56 -0
- data/config/locales/en.yml +15 -0
- data/config/locales/eo.yml +1 -0
- data/config/locales/es-MX.yml +15 -0
- data/config/locales/es-PY.yml +15 -0
- data/config/locales/es.yml +15 -0
- data/config/locales/et-EE.yml +1 -0
- data/config/locales/et.yml +1 -0
- data/config/locales/fi-plain.yml +15 -0
- data/config/locales/fi.yml +15 -0
- data/config/locales/fr-CA.yml +56 -0
- data/config/locales/fr.yml +15 -0
- data/config/locales/ga-IE.yml +1 -0
- data/config/locales/hr-HR.yml +1 -0
- data/config/locales/hr.yml +1 -0
- data/config/locales/hu.yml +9 -0
- data/config/locales/is.yml +21 -0
- data/config/locales/it.yml +17 -2
- data/config/locales/ja-JP.yml +56 -0
- data/config/locales/ja.yml +56 -0
- data/config/locales/ko-KR.yml +1 -0
- data/config/locales/ko.yml +1 -0
- data/config/locales/lt-LT.yml +1 -0
- data/config/locales/lt.yml +1 -0
- data/config/locales/lv.yml +54 -0
- data/config/locales/mt-MT.yml +1 -0
- data/config/locales/mt.yml +1 -0
- data/config/locales/nl.yml +15 -0
- data/config/locales/om-ET.yml +1 -0
- data/config/locales/pl.yml +26 -10
- data/config/locales/pt-BR.yml +1 -1
- data/config/locales/pt.yml +26 -10
- data/config/locales/ro-RO.yml +56 -0
- data/config/locales/sk-SK.yml +47 -0
- data/config/locales/sk.yml +47 -0
- data/config/locales/sl.yml +5 -0
- data/config/locales/so-SO.yml +1 -0
- data/config/locales/sr-CS.yml +8 -0
- data/config/locales/sv.yml +15 -0
- data/config/locales/ti-ER.yml +1 -0
- data/config/locales/vi-VN.yml +1 -0
- data/config/locales/vi.yml +1 -0
- data/config/locales/zh-CN.yml +56 -0
- data/config/locales/zh-TW.yml +1 -0
- data/lib/decidim/dev.rb +2 -0
- data/lib/decidim/dev/assets/assemblies.json +816 -0
- data/lib/decidim/dev/assets/assemblies_with_null.json +135 -0
- data/lib/decidim/dev/assets/city.jpeg +0 -0
- data/lib/decidim/dev/assets/city2.jpeg +0 -0
- data/lib/decidim/dev/assets/city3.jpeg +0 -0
- data/lib/decidim/dev/assets/geocoder_result_here.json +72 -0
- data/lib/decidim/dev/assets/geocoder_result_osm.json +150 -0
- data/lib/decidim/dev/assets/import_participatory_space_private_users_nok.csv +2 -0
- data/lib/decidim/dev/dummy_translator.rb +32 -0
- data/lib/decidim/dev/test/base_spec_helper.rb +14 -0
- data/lib/decidim/dev/test/rspec_support/authorization.rb +3 -0
- data/lib/decidim/dev/test/rspec_support/capybara.rb +6 -2
- data/lib/decidim/dev/test/rspec_support/capybara_data_picker.rb +15 -5
- data/lib/decidim/dev/test/rspec_support/capybara_scopes_picker.rb +5 -5
- data/lib/decidim/dev/test/rspec_support/comments.rb +2 -2
- data/lib/decidim/dev/test/rspec_support/component.rb +104 -5
- data/lib/decidim/dev/test/rspec_support/component_context.rb +1 -2
- data/lib/decidim/dev/test/rspec_support/confirmation_helpers.rb +60 -0
- data/lib/decidim/dev/test/rspec_support/content_processing.rb +4 -4
- data/lib/decidim/dev/test/rspec_support/frontend.rb +20 -0
- data/lib/decidim/dev/test/rspec_support/geocoder.rb +150 -6
- data/lib/decidim/dev/test/rspec_support/helpers.rb +2 -2
- data/lib/decidim/dev/test/rspec_support/organization.rb +7 -0
- data/lib/decidim/dev/test/rspec_support/rake_tasks.rb +75 -0
- data/lib/decidim/dev/test/rspec_support/timezone.rb +7 -0
- data/lib/decidim/dev/test/rspec_support/translation_helpers.rb +2 -0
- data/lib/decidim/dev/version.rb +1 -1
- data/lib/tasks/generators.rake +2 -1
- data/lib/tasks/locale_checker.rake +1 -1
- metadata +91 -23
- data/lib/decidim/dev/test/rspec_support/capybara_proposals_picker.rb +0 -51
|
@@ -6,15 +6,13 @@ module Capybara
|
|
|
6
6
|
Struct.new(:data_picker, :global_value).new(find_data_picker(id, multiple: multiple), global_value)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
private
|
|
10
|
-
|
|
11
9
|
def find_data_picker(id, multiple: nil)
|
|
12
10
|
if multiple.nil?
|
|
13
|
-
expect(page).to have_selector("div.data-picker
|
|
11
|
+
expect(page).to have_selector("div.data-picker[id$='#{id}']")
|
|
14
12
|
else
|
|
15
|
-
expect(page).to have_selector("div.data-picker.picker-#{multiple ? "multiple" : "single"}
|
|
13
|
+
expect(page).to have_selector("div.data-picker.picker-#{multiple ? "multiple" : "single"}[id$='#{id}']")
|
|
16
14
|
end
|
|
17
|
-
|
|
15
|
+
first("div.data-picker[id$='#{id}']")
|
|
18
16
|
end
|
|
19
17
|
|
|
20
18
|
def data_picker_pick_current
|
|
@@ -22,5 +20,17 @@ module Capybara
|
|
|
22
20
|
expect(body).to have_selector("#data_picker-modal .picker-footer a[data-picker-choose]")
|
|
23
21
|
body.find("#data_picker-modal .picker-footer a[data-picker-choose]").click
|
|
24
22
|
end
|
|
23
|
+
|
|
24
|
+
def data_picker_choose_value(value)
|
|
25
|
+
body = find(:xpath, "//body")
|
|
26
|
+
expect(body).to have_selector("#data_picker-modal input[data-picker-choose][type=checkbox][value=\"#{value}\"]")
|
|
27
|
+
body.find("#data_picker-modal input[data-picker-choose][type=checkbox][value=\"#{value}\"]").click
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def data_picker_close
|
|
31
|
+
body = find(:xpath, "//body")
|
|
32
|
+
expect(body).to have_selector("#data_picker-modal .picker-footer a[data-close]")
|
|
33
|
+
body.find("#data_picker-modal .picker-footer a[data-close]").click
|
|
34
|
+
end
|
|
25
35
|
end
|
|
26
36
|
end
|
|
@@ -10,7 +10,7 @@ module Capybara
|
|
|
10
10
|
match do |scope_picker|
|
|
11
11
|
data_picker = scope_picker.data_picker
|
|
12
12
|
scope_name = expected ? translated(expected.name) : t("decidim.scopes.global")
|
|
13
|
-
expect(data_picker).to have_selector(".picker-values div input[value='#{expected&.id || scope_picker.global_value}']", visible:
|
|
13
|
+
expect(data_picker).to have_selector(".picker-values div input[value='#{expected&.id || scope_picker.global_value}']", visible: :all)
|
|
14
14
|
expect(data_picker).to have_selector(:xpath, "//div[contains(@class,'picker-values')]/div/a[text()[contains(.,'#{scope_name}')]]")
|
|
15
15
|
end
|
|
16
16
|
end
|
|
@@ -19,7 +19,7 @@ module Capybara
|
|
|
19
19
|
match do |scope_picker|
|
|
20
20
|
data_picker = scope_picker.data_picker
|
|
21
21
|
scope_name = expected ? translated(expected.name) : t("decidim.scopes.global")
|
|
22
|
-
expect(data_picker).not_to have_selector(".picker-values div input[value='#{expected&.id || scope_picker.global_value}']", visible:
|
|
22
|
+
expect(data_picker).not_to have_selector(".picker-values div input[value='#{expected&.id || scope_picker.global_value}']", visible: :all)
|
|
23
23
|
expect(data_picker).not_to have_selector(:xpath, "//div[contains(@class,'picker-values')]/div/a[text()[contains(.,'#{scope_name}')]]")
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -27,7 +27,7 @@ module Capybara
|
|
|
27
27
|
def scope_pick(scope_picker, scope)
|
|
28
28
|
data_picker = scope_picker.data_picker
|
|
29
29
|
# use scope_repick to change single scope picker selected scope
|
|
30
|
-
expect(data_picker).to have_selector(".picker-values:empty", visible:
|
|
30
|
+
expect(data_picker).to have_selector(".picker-values:empty", visible: :all) if data_picker.has_css?(".picker-single")
|
|
31
31
|
|
|
32
32
|
expect(data_picker).to have_selector(".picker-prompt")
|
|
33
33
|
data_picker.find(".picker-prompt").click
|
|
@@ -41,7 +41,7 @@ module Capybara
|
|
|
41
41
|
def scope_repick(scope_picker, old_scope, new_scope)
|
|
42
42
|
data_picker = scope_picker.data_picker
|
|
43
43
|
|
|
44
|
-
expect(data_picker).to have_selector(".picker-values div input[value='#{old_scope&.id || scope_picker.global_value}']", visible:
|
|
44
|
+
expect(data_picker).to have_selector(".picker-values div input[value='#{old_scope&.id || scope_picker.global_value}']", visible: :all)
|
|
45
45
|
data_picker.find(:xpath, "//div[contains(@class,'picker-values')]/div/input[@value='#{old_scope&.id || scope_picker.global_value}']/../a").click
|
|
46
46
|
|
|
47
47
|
# browse to lowest common parent between old and new scope
|
|
@@ -57,7 +57,7 @@ module Capybara
|
|
|
57
57
|
def scope_unpick(scope_picker, scope)
|
|
58
58
|
data_picker = scope_picker.data_picker
|
|
59
59
|
|
|
60
|
-
expect(data_picker).to have_selector(".picker-values div input[value='#{scope&.id || scope_picker.global_value}']", visible:
|
|
60
|
+
expect(data_picker).to have_selector(".picker-values div input[value='#{scope&.id || scope_picker.global_value}']", visible: :all)
|
|
61
61
|
data_picker.find(".picker-values div input[value='#{scope&.id || scope_picker.global_value}']").click
|
|
62
62
|
|
|
63
63
|
expect(scope_picker).to have_scope_not_picked(scope)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module CommentsHelpers
|
|
4
|
-
def have_comment_from(user, text)
|
|
4
|
+
def have_comment_from(user, text, opts = {})
|
|
5
5
|
within "#comments" do
|
|
6
|
-
have_content(user.name) && have_content(text)
|
|
6
|
+
have_content(user.name, opts) && have_content(text, opts)
|
|
7
7
|
end
|
|
8
8
|
end
|
|
9
9
|
|
|
@@ -29,6 +29,7 @@ module Decidim
|
|
|
29
29
|
root to: proc { [200, {}, ["DUMMY ENGINE"]] }
|
|
30
30
|
|
|
31
31
|
resources :dummy_resources do
|
|
32
|
+
resources :nested_dummy_resources
|
|
32
33
|
get :foo, on: :member
|
|
33
34
|
end
|
|
34
35
|
end
|
|
@@ -38,6 +39,10 @@ module Decidim
|
|
|
38
39
|
engine_name "dummy_admin"
|
|
39
40
|
|
|
40
41
|
routes do
|
|
42
|
+
resources :dummy_resources do
|
|
43
|
+
resources :nested_dummy_resources
|
|
44
|
+
end
|
|
45
|
+
|
|
41
46
|
root to: proc { [200, {}, ["DUMMY ADMIN ENGINE"]] }
|
|
42
47
|
end
|
|
43
48
|
end
|
|
@@ -53,7 +58,7 @@ module Decidim
|
|
|
53
58
|
include Reportable
|
|
54
59
|
include Authorable
|
|
55
60
|
include HasCategory
|
|
56
|
-
include
|
|
61
|
+
include ScopableResource
|
|
57
62
|
include Decidim::Comments::Commentable
|
|
58
63
|
include Followable
|
|
59
64
|
include Traceable
|
|
@@ -63,8 +68,12 @@ module Decidim
|
|
|
63
68
|
include Paddable
|
|
64
69
|
include Amendable
|
|
65
70
|
include Decidim::NewsletterParticipant
|
|
66
|
-
include
|
|
71
|
+
include ::Decidim::Endorsable
|
|
72
|
+
include Decidim::HasAttachments
|
|
73
|
+
include Decidim::ShareableWithToken
|
|
74
|
+
include Decidim::TranslatableResource
|
|
67
75
|
|
|
76
|
+
translatable_fields :title
|
|
68
77
|
searchable_fields(
|
|
69
78
|
scope_id: { scope: :id },
|
|
70
79
|
participatory_space: { component: :participatory_space },
|
|
@@ -103,6 +112,44 @@ module Decidim
|
|
|
103
112
|
.pluck(:decidim_author_id).flatten.compact.uniq
|
|
104
113
|
end
|
|
105
114
|
end
|
|
115
|
+
|
|
116
|
+
class NestedDummyResource < ApplicationRecord
|
|
117
|
+
include Decidim::Resourceable
|
|
118
|
+
belongs_to :dummy_resource
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
class CoauthorableDummyResource < ApplicationRecord
|
|
122
|
+
include ::Decidim::Coauthorable
|
|
123
|
+
include HasComponent
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
class OfficialAuthorPresenter
|
|
127
|
+
def name
|
|
128
|
+
self.class.name
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def nickname
|
|
132
|
+
UserBaseEntity.nicknamize(name)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def deleted?
|
|
136
|
+
false
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def respond_to_missing?
|
|
140
|
+
true
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def method_missing(method, *args)
|
|
144
|
+
if method.to_s.ends_with?("?")
|
|
145
|
+
false
|
|
146
|
+
elsif [:avatar_url, :profile_path, :badge, :followers_count].include?(method)
|
|
147
|
+
""
|
|
148
|
+
else
|
|
149
|
+
super
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
106
153
|
end
|
|
107
154
|
end
|
|
108
155
|
|
|
@@ -128,10 +175,14 @@ Decidim.register_component(:dummy) do |component|
|
|
|
128
175
|
component.newsletter_participant_entities = ["Decidim::DummyResources::DummyResource"]
|
|
129
176
|
|
|
130
177
|
component.settings(:global) do |settings|
|
|
178
|
+
settings.attribute :scopes_enabled, type: :boolean, default: false
|
|
179
|
+
settings.attribute :scope_id, type: :scope
|
|
131
180
|
settings.attribute :comments_enabled, type: :boolean, default: true
|
|
181
|
+
settings.attribute :comments_max_length, type: :integer, required: false
|
|
132
182
|
settings.attribute :resources_permissions_enabled, type: :boolean, default: true
|
|
133
183
|
settings.attribute :dummy_global_attribute_1, type: :boolean
|
|
134
|
-
settings.attribute :dummy_global_attribute_2, type: :boolean
|
|
184
|
+
settings.attribute :dummy_global_attribute_2, type: :boolean, readonly: ->(_context) { false }
|
|
185
|
+
settings.attribute :readonly_attribute, type: :boolean, default: true, readonly: ->(_context) { true }
|
|
135
186
|
settings.attribute :enable_pads_creation, type: :boolean, default: false
|
|
136
187
|
settings.attribute :amendments_enabled, type: :boolean, default: false
|
|
137
188
|
settings.attribute :dummy_global_translatable_text, type: :text, translated: true, editor: true, required: true
|
|
@@ -140,12 +191,15 @@ Decidim.register_component(:dummy) do |component|
|
|
|
140
191
|
component.settings(:step) do |settings|
|
|
141
192
|
settings.attribute :comments_blocked, type: :boolean, default: false
|
|
142
193
|
settings.attribute :dummy_step_attribute_1, type: :boolean
|
|
143
|
-
settings.attribute :dummy_step_attribute_2, type: :boolean
|
|
194
|
+
settings.attribute :dummy_step_attribute_2, type: :boolean, readonly: ->(_context) { false }
|
|
144
195
|
settings.attribute :dummy_step_translatable_text, type: :text, translated: true, editor: true, required: true
|
|
196
|
+
settings.attribute :readonly_step_attribute, type: :boolean, default: true, readonly: ->(_context) { true }
|
|
145
197
|
settings.attribute :amendment_creation_enabled, type: :boolean, default: true
|
|
146
198
|
settings.attribute :amendment_reaction_enabled, type: :boolean, default: true
|
|
147
199
|
settings.attribute :amendment_promotion_enabled, type: :boolean, default: true
|
|
148
200
|
settings.attribute :amendments_visibility, type: :string, default: "all"
|
|
201
|
+
settings.attribute :endorsements_enabled, type: :boolean, default: false
|
|
202
|
+
settings.attribute :endorsements_blocked, type: :boolean, default: false
|
|
149
203
|
end
|
|
150
204
|
|
|
151
205
|
component.register_resource(:dummy_resource) do |resource|
|
|
@@ -156,6 +210,19 @@ Decidim.register_component(:dummy) do |component|
|
|
|
156
210
|
resource.searchable = true
|
|
157
211
|
end
|
|
158
212
|
|
|
213
|
+
component.register_resource(:nested_dummy_resource) do |resource|
|
|
214
|
+
resource.name = :nested_dummy
|
|
215
|
+
resource.model_class_name = "Decidim::DummyResources::NestedDummyResource"
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
component.register_resource(:coauthorable_dummy_resource) do |resource|
|
|
219
|
+
resource.name = :coauthorable_dummy
|
|
220
|
+
resource.model_class_name = "Decidim::DummyResources::CoauthorableDummyResource"
|
|
221
|
+
resource.template = "decidim/coauthorabledummy_resource/linked_dummys"
|
|
222
|
+
resource.actions = %w(foo-coauthorable)
|
|
223
|
+
resource.searchable = false
|
|
224
|
+
end
|
|
225
|
+
|
|
159
226
|
component.register_stat :dummies_count_high, primary: true, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, _start_at, _end_at|
|
|
160
227
|
components.count * 10
|
|
161
228
|
end
|
|
@@ -179,13 +246,15 @@ RSpec.configure do |config|
|
|
|
179
246
|
unless ActiveRecord::Base.connection.data_source_exists?("decidim_dummy_resources_dummy_resources")
|
|
180
247
|
ActiveRecord::Migration.create_table :decidim_dummy_resources_dummy_resources do |t|
|
|
181
248
|
t.jsonb :translatable_text
|
|
182
|
-
t.
|
|
249
|
+
t.jsonb :title
|
|
183
250
|
t.string :body
|
|
184
251
|
t.text :address
|
|
185
252
|
t.float :latitude
|
|
186
253
|
t.float :longitude
|
|
187
254
|
t.datetime :published_at
|
|
188
255
|
t.integer :coauthorships_count, null: false, default: 0
|
|
256
|
+
t.integer :endorsements_count, null: false, default: 0
|
|
257
|
+
t.integer :comments_count, null: false, default: 0
|
|
189
258
|
|
|
190
259
|
t.references :decidim_component, index: false
|
|
191
260
|
t.integer :decidim_author_id, index: false
|
|
@@ -195,6 +264,36 @@ RSpec.configure do |config|
|
|
|
195
264
|
t.references :decidim_scope, index: false
|
|
196
265
|
t.string :reference
|
|
197
266
|
|
|
267
|
+
t.timestamps
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
unless ActiveRecord::Base.connection.data_source_exists?("decidim_dummy_resources_nested_dummy_resources")
|
|
271
|
+
ActiveRecord::Migration.create_table :decidim_dummy_resources_nested_dummy_resources do |t|
|
|
272
|
+
t.jsonb :translatable_text
|
|
273
|
+
t.string :title
|
|
274
|
+
|
|
275
|
+
t.references :dummy_resource, index: false
|
|
276
|
+
t.timestamps
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
unless ActiveRecord::Base.connection.data_source_exists?("decidim_dummy_resources_coauthorable_dummy_resources")
|
|
280
|
+
ActiveRecord::Migration.create_table :decidim_dummy_resources_coauthorable_dummy_resources do |t|
|
|
281
|
+
t.jsonb :translatable_text
|
|
282
|
+
t.string :title
|
|
283
|
+
t.string :body
|
|
284
|
+
t.text :address
|
|
285
|
+
t.float :latitude
|
|
286
|
+
t.float :longitude
|
|
287
|
+
t.datetime :published_at
|
|
288
|
+
t.integer :coauthorships_count, null: false, default: 0
|
|
289
|
+
t.integer :endorsements_count, null: false, default: 0
|
|
290
|
+
t.integer :comments_count, null: false, default: 0
|
|
291
|
+
|
|
292
|
+
t.references :decidim_component, index: false
|
|
293
|
+
t.references :decidim_category, index: false
|
|
294
|
+
t.references :decidim_scope, index: false
|
|
295
|
+
t.string :reference
|
|
296
|
+
|
|
198
297
|
t.timestamps
|
|
199
298
|
end
|
|
200
299
|
end
|
|
@@ -19,8 +19,7 @@ shared_context "with a component" do
|
|
|
19
19
|
participatory_space: participatory_space)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
let!(:category) { create :category, participatory_space:
|
|
23
|
-
|
|
22
|
+
let!(:category) { create :category, participatory_space: participatory_space }
|
|
24
23
|
let!(:scope) { create :scope, organization: organization }
|
|
25
24
|
|
|
26
25
|
before do
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Helpers that get automatically included in component specs.
|
|
4
|
+
module ConfirmationHelpers
|
|
5
|
+
# Overrides the Capybara default accept_confirm because we have replaced the
|
|
6
|
+
# system's own confirmation modal with foundation based modal.
|
|
7
|
+
#
|
|
8
|
+
# See:
|
|
9
|
+
# https://github.com/teamcapybara/capybara/blob/44621209496fe4dd352709799a0061a80d97d562/lib/capybara/session.rb#L647
|
|
10
|
+
def accept_confirm(_text = nil, **_options)
|
|
11
|
+
yield if block_given?
|
|
12
|
+
|
|
13
|
+
# The test can already be "within", so find the body using xpath
|
|
14
|
+
message = nil
|
|
15
|
+
body = find(:xpath, "/html/body")
|
|
16
|
+
within(body.find(".confirm-reveal")) do
|
|
17
|
+
message = find(".confirm-modal-content").text
|
|
18
|
+
find("a.button[data-confirm-ok]").click
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
message
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Overrides the Capybara default dismiss_confirm because we have replaced the
|
|
25
|
+
# system's own confirmation modal with foundation based modal.
|
|
26
|
+
#
|
|
27
|
+
# See:
|
|
28
|
+
# https://github.com/teamcapybara/capybara/blob/44621209496fe4dd352709799a0061a80d97d562/lib/capybara/session.rb#L657
|
|
29
|
+
def dismiss_confirm(_text = nil, **_options)
|
|
30
|
+
yield if block_given?
|
|
31
|
+
|
|
32
|
+
# The test can already be "within", so find the body using xpath
|
|
33
|
+
message = nil
|
|
34
|
+
body = find(:xpath, "/html/body")
|
|
35
|
+
within(body.find(".confirm-reveal")) do
|
|
36
|
+
message = find(".confirm-modal-content").text
|
|
37
|
+
find("a.button[data-confirm-cancel]").click
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
message
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Used to accept the "onbeforeunload" event's normal browser confirm modal
|
|
44
|
+
# as this cannot be overridden. Original confirm dismiss implementation in
|
|
45
|
+
# Capybara.
|
|
46
|
+
def accept_page_unload(text = nil, **options, &blk)
|
|
47
|
+
page.send(:accept_modal, :confirm, text, options, &blk)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Used to dismiss the "onbeforeunload" event's normal browser confirm modal
|
|
51
|
+
# as this cannot be overridden. Original confirm dismiss implementation in
|
|
52
|
+
# Capybara.
|
|
53
|
+
def dismiss_page_unload(text = nil, **options, &blk)
|
|
54
|
+
page.send(:dismiss_modal, :confirm, text, options, &blk)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
RSpec.configure do |config|
|
|
59
|
+
config.include ConfirmationHelpers, type: :system
|
|
60
|
+
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Decidim
|
|
4
4
|
class ContentParsers::DummyFooParser < ContentParsers::BaseParser
|
|
5
5
|
def rewrite
|
|
6
|
-
content.gsub("foo", "
|
|
6
|
+
content.gsub("foo", "%lorem%")
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def metadata
|
|
@@ -12,8 +12,8 @@ module Decidim
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
class ContentRenderers::DummyFooRenderer < ContentRenderers::BaseRenderer
|
|
15
|
-
def render
|
|
16
|
-
content.gsub("
|
|
15
|
+
def render(_options = nil)
|
|
16
|
+
content.gsub("%lorem%", "<em>neque dicta enim quasi</em>")
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -28,7 +28,7 @@ module Decidim
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
class ContentRenderers::DummyBarRenderer < ContentRenderers::BaseRenderer
|
|
31
|
-
def render
|
|
31
|
+
def render(_options = nil)
|
|
32
32
|
content.gsub("*ipsum*", "<em>illo qui voluptas</em>")
|
|
33
33
|
end
|
|
34
34
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FrontendHelpers
|
|
4
|
+
# Thanks to:
|
|
5
|
+
# https://medium.com/@coorasse/catch-javascript-errors-in-your-system-tests-89c2fe6773b1
|
|
6
|
+
def expect_no_js_errors
|
|
7
|
+
errors = page.driver.browser.manage.logs.get(:browser)
|
|
8
|
+
return if errors.blank?
|
|
9
|
+
|
|
10
|
+
aggregate_failures "javascript errors" do
|
|
11
|
+
errors.each do |error|
|
|
12
|
+
expect(error.level).not_to eq("SEVERE"), error.message
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
RSpec.configure do |config|
|
|
19
|
+
config.include FrontendHelpers, type: :system
|
|
20
|
+
end
|
|
@@ -8,6 +8,69 @@ module GeocoderHelpers
|
|
|
8
8
|
address,
|
|
9
9
|
result
|
|
10
10
|
)
|
|
11
|
+
Decidim::Map::Provider::Autocomplete::Test.add_stub(
|
|
12
|
+
address,
|
|
13
|
+
coordinates
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Waits for the front-end geocoding request to finish in order to ensure there
|
|
18
|
+
# are no pending requests when proceeding.
|
|
19
|
+
def fill_in_geocoding(attribute, options = {})
|
|
20
|
+
fill_in attribute, options
|
|
21
|
+
expect(page).to have_selector(".tribute-container ul#results", count: 1)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
module_function
|
|
25
|
+
|
|
26
|
+
public def configure_maps
|
|
27
|
+
# Set maps configuration in test mode
|
|
28
|
+
Decidim.maps = {
|
|
29
|
+
provider: :test,
|
|
30
|
+
api_key: "1234123412341234",
|
|
31
|
+
static: { url: "https://www.example.org/my_static_map" },
|
|
32
|
+
autocomplete: { url: "/photon_api" } # Locally drawn route for the tests
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
module Decidim::Map::Provider
|
|
38
|
+
module Geocoding
|
|
39
|
+
class Test < ::Decidim::Map::Geocoding; end
|
|
40
|
+
end
|
|
41
|
+
module Autocomplete
|
|
42
|
+
class Test < ::Decidim::Map::Autocomplete
|
|
43
|
+
def self.stubs
|
|
44
|
+
@stubs ||= []
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.add_stub(address, coordinates)
|
|
48
|
+
stubs.push(
|
|
49
|
+
properties: address.is_a?(Hash) ? address : { street: address },
|
|
50
|
+
geometry: { coordinates: coordinates }
|
|
51
|
+
)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.clear_stubs
|
|
55
|
+
@stubs = []
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def builder_options
|
|
59
|
+
{ url: configuration.fetch(:url, nil) }.compact
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
class Builder < Decidim::Map::Autocomplete::Builder
|
|
63
|
+
def javascript_snippets
|
|
64
|
+
template.javascript_include_tag("decidim/geocoding/provider/photon")
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
module DynamicMap
|
|
70
|
+
class Test < ::Decidim::Map::DynamicMap; end
|
|
71
|
+
end
|
|
72
|
+
module StaticMap
|
|
73
|
+
class Test < ::Decidim::Map::StaticMap; end
|
|
11
74
|
end
|
|
12
75
|
end
|
|
13
76
|
|
|
@@ -15,16 +78,97 @@ RSpec.configure do |config|
|
|
|
15
78
|
config.include GeocoderHelpers
|
|
16
79
|
|
|
17
80
|
config.before(:suite) do
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
81
|
+
GeocoderHelpers.configure_maps
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
config.after(:each, :configures_map) do
|
|
85
|
+
# Ensure the initializer is always re-run after the examples because
|
|
86
|
+
# otherwise the utilities could remain unregistered which causes issues with
|
|
87
|
+
# further tests.
|
|
88
|
+
Decidim::Core::Engine.initializers.each do |i|
|
|
89
|
+
next unless i.name == "decidim.maps"
|
|
90
|
+
|
|
91
|
+
i.run
|
|
92
|
+
break
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Ensure the utility configuration is reset after each example for it to be
|
|
96
|
+
# reloaded the next time.
|
|
97
|
+
Decidim::Map.reset_utility_configuration!
|
|
98
|
+
configure_maps
|
|
24
99
|
end
|
|
25
100
|
|
|
26
101
|
config.before(:each, :serves_map) do
|
|
27
102
|
stub_request(:get, %r{https://www\.example\.org/my_static_map})
|
|
28
103
|
.to_return(body: "map_data")
|
|
29
104
|
end
|
|
105
|
+
|
|
106
|
+
config.before(:each, :serves_geocoding_autocomplete) do
|
|
107
|
+
# Clear the autocomplete stubs
|
|
108
|
+
Decidim::Map::Provider::Autocomplete::Test.clear_stubs
|
|
109
|
+
|
|
110
|
+
photon_response = lambda do
|
|
111
|
+
{
|
|
112
|
+
features: [
|
|
113
|
+
{
|
|
114
|
+
properties: {
|
|
115
|
+
name: "Park",
|
|
116
|
+
street: "Street1",
|
|
117
|
+
housenumber: "1",
|
|
118
|
+
postcode: "123456",
|
|
119
|
+
city: "City1",
|
|
120
|
+
state: "State1",
|
|
121
|
+
country: "Country1"
|
|
122
|
+
},
|
|
123
|
+
geometry: {
|
|
124
|
+
coordinates: [1.123, 2.234]
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
properties: {
|
|
129
|
+
street: "Street2",
|
|
130
|
+
postcode: "654321",
|
|
131
|
+
city: "City2",
|
|
132
|
+
country: "Country2"
|
|
133
|
+
},
|
|
134
|
+
geometry: {
|
|
135
|
+
coordinates: [3.345, 4.456]
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
properties: {
|
|
140
|
+
street: "Street3",
|
|
141
|
+
housenumber: "3",
|
|
142
|
+
postcode: "142536",
|
|
143
|
+
city: "City3",
|
|
144
|
+
country: "Country3"
|
|
145
|
+
},
|
|
146
|
+
geometry: {
|
|
147
|
+
coordinates: [5.567, 6.678]
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
}.tap do |response|
|
|
152
|
+
Decidim::Map::Provider::Autocomplete::Test.stubs.length.positive? &&
|
|
153
|
+
response[:features] = Decidim::Map::Provider::Autocomplete::Test.stubs
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# The Photon API path needs to be mounted in the application itself because
|
|
158
|
+
# otherwise we would have to run a separate server for the API itself.
|
|
159
|
+
# Mocking the request would not work here because the call to the Photon API
|
|
160
|
+
# is initialized by the front-end to the URL specified for the maps
|
|
161
|
+
# geocoding autocompletion configuration which is not proxied by the
|
|
162
|
+
# headless browser running the Capybara tests.
|
|
163
|
+
Rails.application.routes.disable_clear_and_finalize = true
|
|
164
|
+
Rails.application.routes.draw do
|
|
165
|
+
get "photon_api", to: ->(_) { [200, { "Content-Type" => "application/json" }, [photon_response.call.to_json.to_s]] }
|
|
166
|
+
end
|
|
167
|
+
Rails.application.routes.disable_clear_and_finalize = false
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
config.after(:each, :serves_geocoding_autocomplete) do
|
|
171
|
+
# Reset the routes back to original
|
|
172
|
+
Rails.application.reload_routes!
|
|
173
|
+
end
|
|
30
174
|
end
|