decidim-dev 0.21.0 → 0.23.2

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.
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