decidim-dev 0.21.0 → 0.23.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/decidim/dummy.svg +1 -4
  3. data/app/assets/images/decidim/gamification/badges/test.svg +1 -145
  4. data/app/commands/decidim/dummy_resources/create_dummy_resource.rb +48 -0
  5. data/app/controllers/decidim/dummy_resources/dummy_resources_controller.rb +1 -0
  6. data/app/forms/decidim/dummy_resources/dummy_resource_form.rb +3 -0
  7. data/app/mailers/decidim/dummy_resources/dummy_resource_mailer.rb +17 -0
  8. data/app/views/decidim/dummy_resources/dummy_resources/show.html.erb +4 -0
  9. data/config/locales/am-ET.yml +1 -0
  10. data/config/locales/bg-BG.yml +56 -0
  11. data/config/locales/bg.yml +56 -0
  12. data/config/locales/ca.yml +15 -0
  13. data/config/locales/cs.yml +16 -1
  14. data/config/locales/da-DK.yml +1 -0
  15. data/config/locales/da.yml +1 -0
  16. data/config/locales/de.yml +17 -1
  17. data/config/locales/el.yml +55 -0
  18. data/config/locales/en.yml +15 -0
  19. data/config/locales/eo.yml +1 -0
  20. data/config/locales/es-MX.yml +15 -0
  21. data/config/locales/es-PY.yml +15 -0
  22. data/config/locales/es.yml +15 -0
  23. data/config/locales/et-EE.yml +1 -0
  24. data/config/locales/et.yml +1 -0
  25. data/config/locales/fi-plain.yml +15 -0
  26. data/config/locales/fi.yml +15 -0
  27. data/config/locales/fr-CA.yml +56 -0
  28. data/config/locales/fr.yml +15 -0
  29. data/config/locales/ga-IE.yml +1 -0
  30. data/config/locales/hr-HR.yml +1 -0
  31. data/config/locales/hr.yml +1 -0
  32. data/config/locales/hu.yml +9 -0
  33. data/config/locales/is.yml +21 -0
  34. data/config/locales/it.yml +17 -2
  35. data/config/locales/ja-JP.yml +56 -0
  36. data/config/locales/ja.yml +56 -0
  37. data/config/locales/ko-KR.yml +1 -0
  38. data/config/locales/ko.yml +1 -0
  39. data/config/locales/lt-LT.yml +1 -0
  40. data/config/locales/lt.yml +1 -0
  41. data/config/locales/lv.yml +54 -0
  42. data/config/locales/mt-MT.yml +1 -0
  43. data/config/locales/mt.yml +1 -0
  44. data/config/locales/nl.yml +15 -0
  45. data/config/locales/om-ET.yml +1 -0
  46. data/config/locales/pl.yml +26 -10
  47. data/config/locales/pt-BR.yml +1 -1
  48. data/config/locales/pt.yml +26 -10
  49. data/config/locales/ro-RO.yml +56 -0
  50. data/config/locales/si-LK.yml +1 -0
  51. data/config/locales/sk-SK.yml +47 -0
  52. data/config/locales/sk.yml +47 -0
  53. data/config/locales/sl.yml +5 -0
  54. data/config/locales/so-SO.yml +1 -0
  55. data/config/locales/sr-CS.yml +8 -0
  56. data/config/locales/sv.yml +15 -0
  57. data/config/locales/sw-KE.yml +1 -0
  58. data/config/locales/ti-ER.yml +1 -0
  59. data/config/locales/tr-TR.yml +25 -9
  60. data/config/locales/vi-VN.yml +1 -0
  61. data/config/locales/vi.yml +1 -0
  62. data/config/locales/zh-CN.yml +56 -0
  63. data/config/locales/zh-TW.yml +1 -0
  64. data/lib/decidim/dev.rb +2 -0
  65. data/lib/decidim/dev/assets/5000x5000.png +0 -0
  66. data/lib/decidim/dev/assets/assemblies.json +816 -0
  67. data/lib/decidim/dev/assets/assemblies_with_null.json +135 -0
  68. data/lib/decidim/dev/assets/city.jpeg +0 -0
  69. data/lib/decidim/dev/assets/city2.jpeg +0 -0
  70. data/lib/decidim/dev/assets/city3.jpeg +0 -0
  71. data/lib/decidim/dev/assets/geocoder_result_here.json +72 -0
  72. data/lib/decidim/dev/assets/geocoder_result_osm.json +150 -0
  73. data/lib/decidim/dev/assets/import_participatory_space_private_users_nok.csv +2 -0
  74. data/lib/decidim/dev/dummy_translator.rb +32 -0
  75. data/lib/decidim/dev/test/rspec_support/authorization.rb +3 -0
  76. data/lib/decidim/dev/test/rspec_support/capybara.rb +5 -1
  77. data/lib/decidim/dev/test/rspec_support/capybara_data_picker.rb +15 -5
  78. data/lib/decidim/dev/test/rspec_support/capybara_scopes_picker.rb +5 -5
  79. data/lib/decidim/dev/test/rspec_support/component.rb +111 -9
  80. data/lib/decidim/dev/test/rspec_support/component_context.rb +1 -2
  81. data/lib/decidim/dev/test/rspec_support/confirmation_helpers.rb +60 -0
  82. data/lib/decidim/dev/test/rspec_support/content_processing.rb +2 -2
  83. data/lib/decidim/dev/test/rspec_support/frontend.rb +20 -0
  84. data/lib/decidim/dev/test/rspec_support/geocoder.rb +150 -6
  85. data/lib/decidim/dev/test/rspec_support/helpers.rb +2 -2
  86. data/lib/decidim/dev/test/rspec_support/organization.rb +7 -0
  87. data/lib/decidim/dev/test/rspec_support/rake_tasks.rb +75 -0
  88. data/lib/decidim/dev/test/rspec_support/translation_helpers.rb +2 -0
  89. data/lib/decidim/dev/version.rb +1 -1
  90. data/lib/tasks/generators.rake +2 -1
  91. data/lib/tasks/locale_checker.rake +1 -1
  92. metadata +62 -14
  93. data/lib/decidim/dev/test/rspec_support/capybara_proposals_picker.rb +0 -51
@@ -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: false)
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: false)
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: false) if data_picker.has_css?(".picker-single")
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: false)
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: false)
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)
@@ -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 ScopableComponent
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 Hashtaggable
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 },
@@ -97,10 +106,51 @@ module Decidim
97
106
  end
98
107
 
99
108
  def self.newsletter_participant_ids(component)
100
- Decidim::DummyResources::DummyResource.where(component: component).joins(:component)
101
- .where(decidim_author_type: Decidim::UserBaseEntity.name)
102
- .where.not(author: nil)
103
- .pluck(:decidim_author_id).flatten.compact.uniq
109
+ authors_ids = Decidim::DummyResources::DummyResource.where(component: component)
110
+ .where(decidim_author_type: Decidim::UserBaseEntity.name)
111
+ .where.not(author: nil)
112
+ .group(:decidim_author_id)
113
+ .pluck(:decidim_author_id)
114
+ commentators_ids = Decidim::Comments::Comment.user_commentators_ids_in(Decidim::DummyResources::DummyResource.where(component: component))
115
+ (authors_ids + commentators_ids).flatten.compact.uniq
116
+ end
117
+ end
118
+
119
+ class NestedDummyResource < ApplicationRecord
120
+ include Decidim::Resourceable
121
+ belongs_to :dummy_resource
122
+ end
123
+
124
+ class CoauthorableDummyResource < ApplicationRecord
125
+ include ::Decidim::Coauthorable
126
+ include HasComponent
127
+ end
128
+
129
+ class OfficialAuthorPresenter
130
+ def name
131
+ self.class.name
132
+ end
133
+
134
+ def nickname
135
+ UserBaseEntity.nicknamize(name)
136
+ end
137
+
138
+ def deleted?
139
+ false
140
+ end
141
+
142
+ def respond_to_missing?
143
+ true
144
+ end
145
+
146
+ def method_missing(method, *args)
147
+ if method.to_s.ends_with?("?")
148
+ false
149
+ elsif [:avatar_url, :profile_path, :badge, :followers_count].include?(method)
150
+ ""
151
+ else
152
+ super
153
+ end
104
154
  end
105
155
  end
106
156
  end
@@ -128,10 +178,14 @@ Decidim.register_component(:dummy) do |component|
128
178
  component.newsletter_participant_entities = ["Decidim::DummyResources::DummyResource"]
129
179
 
130
180
  component.settings(:global) do |settings|
181
+ settings.attribute :scopes_enabled, type: :boolean, default: false
182
+ settings.attribute :scope_id, type: :scope
131
183
  settings.attribute :comments_enabled, type: :boolean, default: true
184
+ settings.attribute :comments_max_length, type: :integer, required: false
132
185
  settings.attribute :resources_permissions_enabled, type: :boolean, default: true
133
186
  settings.attribute :dummy_global_attribute_1, type: :boolean
134
- settings.attribute :dummy_global_attribute_2, type: :boolean
187
+ settings.attribute :dummy_global_attribute_2, type: :boolean, readonly: ->(_context) { false }
188
+ settings.attribute :readonly_attribute, type: :boolean, default: true, readonly: ->(_context) { true }
135
189
  settings.attribute :enable_pads_creation, type: :boolean, default: false
136
190
  settings.attribute :amendments_enabled, type: :boolean, default: false
137
191
  settings.attribute :dummy_global_translatable_text, type: :text, translated: true, editor: true, required: true
@@ -140,12 +194,15 @@ Decidim.register_component(:dummy) do |component|
140
194
  component.settings(:step) do |settings|
141
195
  settings.attribute :comments_blocked, type: :boolean, default: false
142
196
  settings.attribute :dummy_step_attribute_1, type: :boolean
143
- settings.attribute :dummy_step_attribute_2, type: :boolean
197
+ settings.attribute :dummy_step_attribute_2, type: :boolean, readonly: ->(_context) { false }
144
198
  settings.attribute :dummy_step_translatable_text, type: :text, translated: true, editor: true, required: true
199
+ settings.attribute :readonly_step_attribute, type: :boolean, default: true, readonly: ->(_context) { true }
145
200
  settings.attribute :amendment_creation_enabled, type: :boolean, default: true
146
201
  settings.attribute :amendment_reaction_enabled, type: :boolean, default: true
147
202
  settings.attribute :amendment_promotion_enabled, type: :boolean, default: true
148
203
  settings.attribute :amendments_visibility, type: :string, default: "all"
204
+ settings.attribute :endorsements_enabled, type: :boolean, default: false
205
+ settings.attribute :endorsements_blocked, type: :boolean, default: false
149
206
  end
150
207
 
151
208
  component.register_resource(:dummy_resource) do |resource|
@@ -156,6 +213,19 @@ Decidim.register_component(:dummy) do |component|
156
213
  resource.searchable = true
157
214
  end
158
215
 
216
+ component.register_resource(:nested_dummy_resource) do |resource|
217
+ resource.name = :nested_dummy
218
+ resource.model_class_name = "Decidim::DummyResources::NestedDummyResource"
219
+ end
220
+
221
+ component.register_resource(:coauthorable_dummy_resource) do |resource|
222
+ resource.name = :coauthorable_dummy
223
+ resource.model_class_name = "Decidim::DummyResources::CoauthorableDummyResource"
224
+ resource.template = "decidim/coauthorabledummy_resource/linked_dummys"
225
+ resource.actions = %w(foo-coauthorable)
226
+ resource.searchable = false
227
+ end
228
+
159
229
  component.register_stat :dummies_count_high, primary: true, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, _start_at, _end_at|
160
230
  components.count * 10
161
231
  end
@@ -179,13 +249,15 @@ RSpec.configure do |config|
179
249
  unless ActiveRecord::Base.connection.data_source_exists?("decidim_dummy_resources_dummy_resources")
180
250
  ActiveRecord::Migration.create_table :decidim_dummy_resources_dummy_resources do |t|
181
251
  t.jsonb :translatable_text
182
- t.string :title
252
+ t.jsonb :title
183
253
  t.string :body
184
254
  t.text :address
185
255
  t.float :latitude
186
256
  t.float :longitude
187
257
  t.datetime :published_at
188
258
  t.integer :coauthorships_count, null: false, default: 0
259
+ t.integer :endorsements_count, null: false, default: 0
260
+ t.integer :comments_count, null: false, default: 0
189
261
 
190
262
  t.references :decidim_component, index: false
191
263
  t.integer :decidim_author_id, index: false
@@ -195,6 +267,36 @@ RSpec.configure do |config|
195
267
  t.references :decidim_scope, index: false
196
268
  t.string :reference
197
269
 
270
+ t.timestamps
271
+ end
272
+ end
273
+ unless ActiveRecord::Base.connection.data_source_exists?("decidim_dummy_resources_nested_dummy_resources")
274
+ ActiveRecord::Migration.create_table :decidim_dummy_resources_nested_dummy_resources do |t|
275
+ t.jsonb :translatable_text
276
+ t.string :title
277
+
278
+ t.references :dummy_resource, index: false
279
+ t.timestamps
280
+ end
281
+ end
282
+ unless ActiveRecord::Base.connection.data_source_exists?("decidim_dummy_resources_coauthorable_dummy_resources")
283
+ ActiveRecord::Migration.create_table :decidim_dummy_resources_coauthorable_dummy_resources do |t|
284
+ t.jsonb :translatable_text
285
+ t.string :title
286
+ t.string :body
287
+ t.text :address
288
+ t.float :latitude
289
+ t.float :longitude
290
+ t.datetime :published_at
291
+ t.integer :coauthorships_count, null: false, default: 0
292
+ t.integer :endorsements_count, null: false, default: 0
293
+ t.integer :comments_count, null: false, default: 0
294
+
295
+ t.references :decidim_component, index: false
296
+ t.references :decidim_category, index: false
297
+ t.references :decidim_scope, index: false
298
+ t.string :reference
299
+
198
300
  t.timestamps
199
301
  end
200
302
  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: participatory_process }
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
@@ -12,7 +12,7 @@ module Decidim
12
12
  end
13
13
 
14
14
  class ContentRenderers::DummyFooRenderer < ContentRenderers::BaseRenderer
15
- def render
15
+ def render(_options = nil)
16
16
  content.gsub("%lorem%", "<em>neque dicta enim quasi</em>")
17
17
  end
18
18
  end
@@ -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
- # Set geocoder configuration in test mode
19
- Decidim.geocoder = {
20
- static_map_url: "https://www.example.org/my_static_map",
21
- here_api_key: "1234123412341234"
22
- }
23
- Geocoder.configure(lookup: :test)
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