decidim-dev 0.27.4 → 0.28.0.rc5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/app/commands/decidim/{dummy_resources → dev}/create_dummy_resource.rb +1 -2
  3. data/app/controllers/decidim/{dummy_resources → dev}/dummy_resources_controller.rb +2 -2
  4. data/app/events/decidim/dev/dummy_resource_event.rb +10 -0
  5. data/app/forms/decidim/{dummy_resources → dev}/dummy_resource_form.rb +1 -1
  6. data/app/jobs/decidim/dev/hide_all_created_by_author_job.rb +13 -0
  7. data/app/mailers/decidim/{dummy_resources → dev}/dummy_resource_mailer.rb +1 -1
  8. data/app/models/decidim/dev/application_record.rb +9 -0
  9. data/app/models/decidim/dev/coauthorable_dummy_resource.rb +10 -0
  10. data/app/models/decidim/dev/dummy_resource.rb +93 -0
  11. data/app/models/decidim/dev/nested_dummy_resource.rb +10 -0
  12. data/app/packs/src/decidim/dev/accessibility.js +3 -3
  13. data/app/packs/src/decidim/dev/test/custom_map_factory.js +1 -1
  14. data/app/packs/stylesheets/decidim/dev/_accessibility.scss +24 -24
  15. data/app/packs/stylesheets/decidim/dev/_map.scss +10 -0
  16. data/app/packs/stylesheets/decidim/dev.scss +1 -0
  17. data/app/presenters/decidim/dev/official_author_presenter.rb +33 -0
  18. data/app/serializers/decidim/dev/dummy_serializer.rb +21 -0
  19. data/app/views/decidim/dev/dummy_resources/show.html.erb +25 -0
  20. data/config/environment.rb +3 -0
  21. data/config/locales/ar.yml +0 -1
  22. data/config/locales/bg.yml +0 -1
  23. data/config/locales/cs.yml +4 -4
  24. data/config/locales/de.yml +2 -2
  25. data/config/locales/el.yml +0 -1
  26. data/config/locales/en.yml +1 -1
  27. data/config/locales/es-MX.yml +1 -1
  28. data/config/locales/es-PY.yml +1 -1
  29. data/config/locales/eu.yml +14 -8
  30. data/config/locales/gl.yml +0 -1
  31. data/config/locales/hu.yml +0 -1
  32. data/config/locales/id-ID.yml +0 -1
  33. data/config/locales/it.yml +0 -1
  34. data/config/locales/lv.yml +0 -1
  35. data/config/locales/nl.yml +0 -1
  36. data/config/locales/no.yml +0 -1
  37. data/config/locales/pl.yml +0 -1
  38. data/config/locales/pt-BR.yml +0 -1
  39. data/config/locales/pt.yml +0 -1
  40. data/config/locales/ru.yml +0 -1
  41. data/config/locales/sk.yml +0 -1
  42. data/config/locales/sq-AL.yml +1 -0
  43. data/config/locales/sv.yml +1 -1
  44. data/config/locales/th-TH.yml +1 -0
  45. data/config/locales/tr-TR.yml +0 -1
  46. data/config/locales/zh-CN.yml +0 -1
  47. data/config/rubocop/disabled.yml +11 -0
  48. data/config/rubocop/faker.yml +480 -0
  49. data/config/rubocop/rails.yml +105 -0
  50. data/config/rubocop/rspec.yml +69 -0
  51. data/config/rubocop/ruby.yml +1207 -0
  52. data/lib/decidim/dev/admin.rb +8 -0
  53. data/lib/decidim/dev/admin_engine.rb +43 -0
  54. data/lib/decidim/dev/assets/import_participatory_space_private_users.csv +2 -2
  55. data/lib/decidim/dev/assets/import_participatory_space_private_users_invalid_col_sep.csv +2 -0
  56. data/lib/decidim/dev/assets/import_participatory_space_private_users_nok.csv +2 -2
  57. data/lib/decidim/dev/assets/import_participatory_space_private_users_with_bom.csv +1 -1
  58. data/lib/decidim/dev/assets/iso-8859-15.md +1 -1
  59. data/lib/decidim/dev/assets/participatory_text.md +4 -2
  60. data/lib/decidim/dev/assets/verify_user_groups.csv +22 -22
  61. data/lib/decidim/dev/component.rb +94 -0
  62. data/lib/decidim/dev/engine.rb +21 -3
  63. data/lib/decidim/dev/test/base_spec_helper.rb +1 -0
  64. data/lib/decidim/dev/test/factories.rb +50 -0
  65. data/lib/decidim/dev/test/form_to_param_shared_examples.rb +1 -1
  66. data/lib/decidim/dev/test/promoted_participatory_processes_shared_examples.rb +9 -9
  67. data/lib/decidim/dev/test/rspec_support/accessibility_examples.rb +119 -1
  68. data/lib/decidim/dev/test/rspec_support/attachment_helpers.rb +2 -2
  69. data/lib/decidim/dev/test/rspec_support/bullet.rb +32 -0
  70. data/lib/decidim/dev/test/rspec_support/capybara.rb +26 -21
  71. data/lib/decidim/dev/test/rspec_support/cell_matchers.rb +1 -1
  72. data/lib/decidim/dev/test/rspec_support/component.rb +7 -317
  73. data/lib/decidim/dev/test/rspec_support/component_context.rb +10 -10
  74. data/lib/decidim/dev/test/rspec_support/confirmation_helpers.rb +18 -14
  75. data/lib/decidim/dev/test/rspec_support/data_consent.rb +2 -2
  76. data/lib/decidim/dev/test/rspec_support/dynamic_attach.rb +19 -4
  77. data/lib/decidim/dev/test/rspec_support/editor_context.rb +35 -0
  78. data/lib/decidim/dev/test/rspec_support/engine_examples.rb +15 -0
  79. data/lib/decidim/dev/test/rspec_support/filters.rb +11 -0
  80. data/lib/decidim/dev/test/rspec_support/forms_validations.rb +20 -0
  81. data/lib/decidim/dev/test/rspec_support/geocoder.rb +7 -7
  82. data/lib/decidim/dev/test/rspec_support/helpers.rb +187 -34
  83. data/lib/decidim/dev/test/rspec_support/imports_controller_shared_examples.rb +13 -13
  84. data/lib/decidim/dev/test/rspec_support/tom_select.rb +26 -0
  85. data/lib/decidim/dev/test/rspec_support/translation_helpers.rb +8 -8
  86. data/lib/decidim/dev/test/rspec_support/warden.rb +1 -1
  87. data/lib/decidim/dev/test/rspec_support/webpacker.rb +10 -0
  88. data/lib/decidim/dev/test/spec_helper.rb +15 -4
  89. data/lib/decidim/dev/test/w3c_rspec_validators_overrides.rb +1 -5
  90. data/lib/decidim/dev/version.rb +1 -1
  91. data/lib/decidim/dev.rb +22 -0
  92. data/lib/decidim-dev.rb +1 -1
  93. data/lib/tasks/lighthouse_report.rake +29 -7
  94. data/rubocop-decidim.yml +13 -0
  95. metadata +125 -71
  96. data/app/views/decidim/dummy_resources/dummy_resources/show.html.erb +0 -15
  97. data/lib/decidim/dev/test/rspec_support/capybara_data_picker.rb +0 -36
  98. data/lib/decidim/dev/test/rspec_support/capybara_scopes_picker.rb +0 -92
  99. data/lib/decidim/dev/test/rspec_support/summary_notification.rb +0 -51
  100. data/lib/rubocop/cop/decidim/hash_shorthand_syntax_backports.rb +0 -175
  101. data/lib/rubocop/cop/decidim.rb +0 -9
  102. /data/app/views/decidim/{dummy_resources → dev}/dummy_resources/foo.html.erb +0 -0
@@ -6,7 +6,7 @@ module Decidim
6
6
  # Helpers meant to be used only during capybara test runs.
7
7
  module CapybaraTestHelpers
8
8
  def switch_to_host(host = "lvh.me")
9
- raise "Can't switch to a custom host unless it really exists. Use `whatever.lvh.me` as a workaround." unless /lvh\.me$/.match?(host)
9
+ raise "Cannot switch to a custom host unless it really exists. Use `whatever.lvh.me` as a workaround." unless /lvh\.me$/.match?(host)
10
10
 
11
11
  app_host = (host ? "#{protocol}://#{host}" : nil)
12
12
  Capybara.app_host = app_host
@@ -28,8 +28,20 @@ module Decidim
28
28
  end
29
29
  end
30
30
 
31
+ 1.step do
32
+ port = rand(5000..6999)
33
+ begin
34
+ Socket.tcp("127.0.0.1", port, connect_timeout: 5).close
35
+ rescue Errno::ECONNREFUSED
36
+ # When connection is refused, the port is available for use.
37
+ Capybara.server_port = port
38
+ break
39
+ end
40
+ end
41
+
31
42
  Capybara.register_driver :headless_chrome do |app|
32
- options = ::Selenium::WebDriver::Chrome::Options.new
43
+ options = Selenium::WebDriver::Chrome::Options.new
44
+ options.args << "--explicitly-allowed-ports=#{Capybara.server_port}"
33
45
  options.args << "--headless"
34
46
  options.args << "--no-sandbox"
35
47
  options.args << if ENV["BIG_SCREEN_SIZE"].present?
@@ -41,27 +53,20 @@ Capybara.register_driver :headless_chrome do |app|
41
53
  Capybara::Selenium::Driver.new(
42
54
  app,
43
55
  browser: :chrome,
44
- capabilities: [options]
56
+ options:
45
57
  )
46
58
  end
47
59
 
48
- 1.step do
49
- port = rand(5000..6999)
50
- begin
51
- Socket.tcp("127.0.0.1", port, connect_timeout: 5).close
52
- rescue Errno::ECONNREFUSED
53
- # When connection is refused, the port is available for use.
54
- Capybara.server_port = port
55
- break
56
- end
57
- end
58
-
59
- # In order to work with PWA apps, Chrome can't be run in headless mode, and requires
60
+ # In order to work with PWA apps, Chrome cannot be run in headless mode, and requires
60
61
  # setting up special prefs and flags
61
62
  Capybara.register_driver :pwa_chrome do |app|
62
- options = ::Selenium::WebDriver::Chrome::Options.new
63
+ options = Selenium::WebDriver::Chrome::Options.new
64
+ options.args << "--explicitly-allowed-ports=#{Capybara.server_port}"
65
+ # If we have a headless browser things like the offline navigation feature stop working,
66
+ # so we need to have have a headful/recapitated (aka not headless) browser for these specs
67
+ # options.args << "--headless"
63
68
  options.args << "--no-sandbox"
64
- # Don't limit browser resources
69
+ # Do not limit browser resources
65
70
  options.args << "--disable-dev-shm-usage"
66
71
  # Add pwa.lvh.me host as a secure origin
67
72
  options.args << "--unsafely-treat-insecure-origin-as-secure=http://pwa.lvh.me:#{Capybara.server_port}"
@@ -80,12 +85,12 @@ Capybara.register_driver :pwa_chrome do |app|
80
85
  Capybara::Selenium::Driver.new(
81
86
  app,
82
87
  browser: :chrome,
83
- capabilities: [options]
88
+ options:
84
89
  )
85
90
  end
86
91
 
87
92
  Capybara.register_driver :iphone do |app|
88
- options = ::Selenium::WebDriver::Chrome::Options.new
93
+ options = Selenium::WebDriver::Chrome::Options.new
89
94
  options.args << "--headless"
90
95
  options.args << "--no-sandbox"
91
96
  options.add_emulation(device_name: "iPhone 6")
@@ -93,7 +98,7 @@ Capybara.register_driver :iphone do |app|
93
98
  Capybara::Selenium::Driver.new(
94
99
  app,
95
100
  browser: :chrome,
96
- capabilities: [options]
101
+ options:
97
102
  )
98
103
  end
99
104
 
@@ -125,7 +130,7 @@ RSpec.configure do |config|
125
130
  domain = ".#{domain}" unless domain == "localhost"
126
131
  page.driver.browser.execute_cdp(
127
132
  "Network.setCookie",
128
- domain: domain,
133
+ domain:,
129
134
  name: Decidim.consent_cookie_name,
130
135
  value: { essential: true }.to_json,
131
136
  path: "/",
@@ -4,7 +4,7 @@ module Decidim
4
4
  module CellMatchers
5
5
  RSpec::Matchers.define :render_nothing do |_expected_value|
6
6
  match do |actual_value|
7
- expect(actual_value).to have_no_selector("html")
7
+ expect(actual_value).not_to have_selector("html")
8
8
  end
9
9
 
10
10
  diffable
@@ -2,323 +2,13 @@
2
2
 
3
3
  require "decidim/component_validator"
4
4
  require "decidim/comments"
5
-
6
- module Decidim
7
- class DummyResourceEvent < Events::BaseEvent
8
- include Decidim::Events::EmailEvent
9
- include Decidim::Events::NotificationEvent
10
- end
11
-
12
- module DummyResources
13
- include ActiveSupport::Configurable
14
-
15
- # Settings needed to compare emendations in Decidim::SimilarEmendations
16
- config_accessor :similarity_threshold do
17
- 0.25
18
- end
19
- config_accessor :similarity_limit do
20
- 10
21
- end
22
-
23
- # Dummy engine to be able to test components.
24
- class DummyEngine < Rails::Engine
25
- engine_name "dummy"
26
- isolate_namespace Decidim::DummyResources
27
-
28
- routes do
29
- root to: proc { [200, {}, ["DUMMY ENGINE"]] }
30
-
31
- resources :dummy_resources do
32
- resources :nested_dummy_resources
33
- get :foo, on: :member
34
- end
35
- end
36
- end
37
-
38
- class DummyAdminEngine < Rails::Engine
39
- engine_name "dummy_admin"
40
-
41
- routes do
42
- resources :dummy_resources do
43
- resources :nested_dummy_resources
44
- end
45
-
46
- root to: proc { [200, {}, ["DUMMY ADMIN ENGINE"]] }
47
- end
48
-
49
- initializer "dummy_admin.imports" do
50
- class ::DummyCreator < Decidim::Admin::Import::Creator
51
- def self.resource_klass
52
- Decidim::DummyResources::DummyResource
53
- end
54
-
55
- def produce
56
- resource
57
- end
58
-
59
- private
60
-
61
- def resource
62
- @resource ||= Decidim::DummyResources::DummyResource.new(
63
- title: { en: "Dummy" },
64
- author: context[:current_user],
65
- component: component
66
- )
67
- end
68
-
69
- def component
70
- context[:current_component]
71
- end
72
- end
73
- end
74
- end
75
-
76
- class ApplicationRecord < ActiveRecord::Base
77
- self.abstract_class = true
78
- end
79
-
80
- class DummyResource < ApplicationRecord
81
- include HasComponent
82
- include HasReference
83
- include Resourceable
84
- include Reportable
85
- include Authorable
86
- include HasCategory
87
- include ScopableResource
88
- include Decidim::Comments::Commentable
89
- include Followable
90
- include Traceable
91
- include Publicable
92
- include Decidim::DownloadYourData
93
- include Searchable
94
- include Paddable
95
- include Amendable
96
- include Decidim::NewsletterParticipant
97
- include ::Decidim::Endorsable
98
- include Decidim::HasAttachments
99
- include Decidim::ShareableWithToken
100
- include Decidim::TranslatableResource
101
-
102
- translatable_fields :title
103
- searchable_fields(
104
- scope_id: { scope: :id },
105
- participatory_space: { component: :participatory_space },
106
- A: [:title],
107
- D: [:address],
108
- datetime: :published_at
109
- )
110
-
111
- amendable(
112
- fields: [:title],
113
- form: "Decidim::DummyResources::DummyResourceForm"
114
- )
115
-
116
- component_manifest_name "dummy"
117
-
118
- def reported_content_url
119
- ResourceLocatorPresenter.new(self).url
120
- end
121
-
122
- def reported_attributes
123
- [:title]
124
- end
125
-
126
- def reported_searchable_content_extras
127
- [normalized_author.name]
128
- end
129
-
130
- def allow_resource_permissions?
131
- component.settings.resources_permissions_enabled
132
- end
133
-
134
- # Public: Overrides the `commentable?` Commentable concern method.
135
- def commentable?
136
- component.settings.comments_enabled?
137
- end
138
-
139
- # Public: Whether the object can have new comments or not.
140
- def user_allowed_to_comment?(user)
141
- component.can_participate_in_space?(user)
142
- end
143
-
144
- # Public: Whether the object can have new comment votes or not.
145
- def user_allowed_to_vote_comment?(user)
146
- component.can_participate_in_space?(user)
147
- end
148
-
149
- def self.user_collection(user)
150
- where(decidim_author_id: user.id, decidim_author_type: "Decidim::User")
151
- end
152
-
153
- def self.export_serializer
154
- DummySerializer
155
- end
156
-
157
- def self.newsletter_participant_ids(component)
158
- authors_ids = Decidim::DummyResources::DummyResource.where(component: component)
159
- .where(decidim_author_type: Decidim::UserBaseEntity.name)
160
- .where.not(author: nil)
161
- .group(:decidim_author_id)
162
- .pluck(:decidim_author_id)
163
- commentators_ids = Decidim::Comments::Comment.user_commentators_ids_in(Decidim::DummyResources::DummyResource.where(component: component))
164
- (authors_ids + commentators_ids).flatten.compact.uniq
165
- end
166
- end
167
-
168
- class NestedDummyResource < ApplicationRecord
169
- include Decidim::Resourceable
170
- belongs_to :dummy_resource
171
- end
172
-
173
- class CoauthorableDummyResource < ApplicationRecord
174
- include ::Decidim::Coauthorable
175
- include HasComponent
176
- end
177
-
178
- class OfficialAuthorPresenter
179
- def name
180
- self.class.name
181
- end
182
-
183
- def nickname
184
- UserBaseEntity.nicknamize(name)
185
- end
186
-
187
- def deleted?
188
- false
189
- end
190
-
191
- def respond_to_missing?(*)
192
- true
193
- end
194
-
195
- def method_missing(method, *args)
196
- if method.to_s.ends_with?("?")
197
- false
198
- elsif [:avatar_url, :profile_path, :badge, :followers_count, :cache_key_with_version].include?(method)
199
- ""
200
- else
201
- super
202
- end
203
- end
204
- end
205
- end
206
- end
207
-
208
- class DummySerializer
209
- def initialize(id)
210
- @id = id
211
- end
212
-
213
- def run
214
- serialize
215
- end
216
-
217
- def serialize
218
- {
219
- id: @id
220
- }
221
- end
222
- end
223
-
224
- Decidim.register_component(:dummy) do |component|
225
- component.engine = Decidim::DummyResources::DummyEngine
226
- component.admin_engine = Decidim::DummyResources::DummyAdminEngine
227
- component.icon = "media/images/decidim_dev_dummy.svg"
228
-
229
- component.actions = %w(foo bar)
230
-
231
- component.newsletter_participant_entities = ["Decidim::DummyResources::DummyResource"]
232
-
233
- component.settings(:global) do |settings|
234
- settings.attribute :scopes_enabled, type: :boolean, default: false
235
- settings.attribute :scope_id, type: :scope
236
- settings.attribute :comments_enabled, type: :boolean, default: true
237
- settings.attribute :comments_max_length, type: :integer, required: false
238
- settings.attribute :resources_permissions_enabled, type: :boolean, default: true
239
- settings.attribute :dummy_global_attribute1, type: :boolean
240
- settings.attribute :dummy_global_attribute2, type: :boolean, readonly: ->(_context) { false }
241
- settings.attribute :readonly_attribute, type: :boolean, default: true, readonly: ->(_context) { true }
242
- settings.attribute :enable_pads_creation, type: :boolean, default: false
243
- settings.attribute :amendments_enabled, type: :boolean, default: false
244
- settings.attribute :dummy_global_translatable_text, type: :text, translated: true, editor: true, required: true
245
- end
246
-
247
- component.settings(:step) do |settings|
248
- settings.attribute :comments_blocked, type: :boolean, default: false
249
- settings.attribute :dummy_step_attribute1, type: :boolean
250
- settings.attribute :dummy_step_attribute2, type: :boolean, readonly: ->(_context) { false }
251
- settings.attribute :dummy_step_translatable_text, type: :text, translated: true, editor: true, required: true
252
- settings.attribute :readonly_step_attribute, type: :boolean, default: true, readonly: ->(_context) { true }
253
- settings.attribute :amendment_creation_enabled, type: :boolean, default: true
254
- settings.attribute :amendment_reaction_enabled, type: :boolean, default: true
255
- settings.attribute :amendment_promotion_enabled, type: :boolean, default: true
256
- settings.attribute :amendments_visibility, type: :string, default: "all"
257
- settings.attribute :endorsements_enabled, type: :boolean, default: false
258
- settings.attribute :endorsements_blocked, type: :boolean, default: false
259
- end
260
-
261
- component.register_resource(:dummy_resource) do |resource|
262
- resource.name = :dummy
263
- resource.model_class_name = "Decidim::DummyResources::DummyResource"
264
- resource.template = "decidim/dummy_resource/linked_dummys"
265
- resource.actions = %w(foo)
266
- resource.searchable = true
267
- end
268
-
269
- component.register_resource(:nested_dummy_resource) do |resource|
270
- resource.name = :nested_dummy
271
- resource.model_class_name = "Decidim::DummyResources::NestedDummyResource"
272
- end
273
-
274
- component.register_resource(:coauthorable_dummy_resource) do |resource|
275
- resource.name = :coauthorable_dummy
276
- resource.model_class_name = "Decidim::DummyResources::CoauthorableDummyResource"
277
- resource.template = "decidim/coauthorabledummy_resource/linked_dummys"
278
- resource.actions = %w(foo-coauthorable)
279
- resource.searchable = false
280
- end
281
-
282
- component.register_stat :dummies_count_high, primary: true, priority: Decidim::StatsRegistry::HIGH_PRIORITY do |components, _start_at, _end_at|
283
- components.count * 10
284
- end
285
-
286
- component.register_stat :dummies_count_medium, primary: true, priority: Decidim::StatsRegistry::MEDIUM_PRIORITY do |components, _start_at, _end_at|
287
- components.count * 100
288
- end
289
-
290
- component.exports :dummies do |exports|
291
- exports.collection do
292
- [1, 2, 3]
293
- end
294
-
295
- exports.serializer DummySerializer
296
- end
297
-
298
- component.imports :dummies do |imports|
299
- imports.messages do |msg|
300
- msg.set(:resource_name) { |count: 1| count == 1 ? "Dummy" : "Dummies" }
301
- msg.set(:title) { "Import dummies" }
302
- msg.set(:label) { "Import dummies from a file" }
303
- end
304
-
305
- imports.creator DummyCreator
306
- imports.example do |import_component|
307
- locales = import_component.organization.available_locales
308
- translated = ->(name) { locales.map { |l| "#{name}/#{l}" } }
309
- [
310
- translated.call("title") + %w(body) + translated.call("translatable_text") + %w(address latitude longitude),
311
- locales.map { "Title text" } + ["Body text"] + locales.map { "Translatable text" } + ["Fake street 1", 1.0, 1.0]
312
- ]
313
- end
314
- end
315
- end
5
+ require "decidim/dev"
316
6
 
317
7
  RSpec.configure do |config|
318
8
  config.before(:suite) do
319
9
  ActiveRecord::Migration.suppress_messages do
320
- unless ActiveRecord::Base.connection.data_source_exists?("decidim_dummy_resources_dummy_resources")
321
- ActiveRecord::Migration.create_table :decidim_dummy_resources_dummy_resources do |t|
10
+ unless ActiveRecord::Base.connection.data_source_exists?("decidim_dev_dummy_resources")
11
+ ActiveRecord::Migration.create_table :decidim_dev_dummy_resources do |t|
322
12
  t.jsonb :translatable_text
323
13
  t.jsonb :title
324
14
  t.string :body
@@ -342,8 +32,8 @@ RSpec.configure do |config|
342
32
  t.timestamps
343
33
  end
344
34
  end
345
- unless ActiveRecord::Base.connection.data_source_exists?("decidim_dummy_resources_nested_dummy_resources")
346
- ActiveRecord::Migration.create_table :decidim_dummy_resources_nested_dummy_resources do |t|
35
+ unless ActiveRecord::Base.connection.data_source_exists?("decidim_dev_nested_dummy_resources")
36
+ ActiveRecord::Migration.create_table :decidim_dev_nested_dummy_resources do |t|
347
37
  t.jsonb :translatable_text
348
38
  t.string :title
349
39
 
@@ -351,8 +41,8 @@ RSpec.configure do |config|
351
41
  t.timestamps
352
42
  end
353
43
  end
354
- unless ActiveRecord::Base.connection.data_source_exists?("decidim_dummy_resources_coauthorable_dummy_resources")
355
- ActiveRecord::Migration.create_table :decidim_dummy_resources_coauthorable_dummy_resources do |t|
44
+ unless ActiveRecord::Base.connection.data_source_exists?("decidim_dev_coauthorable_dummy_resources")
45
+ ActiveRecord::Migration.create_table :decidim_dev_coauthorable_dummy_resources do |t|
356
46
  t.jsonb :translatable_text
357
47
  t.string :title
358
48
  t.string :body
@@ -15,31 +15,31 @@ shared_examples "has mandatory config setting" do |mandatory_field|
15
15
  click_button "Update"
16
16
 
17
17
  within ".#{mandatory_field}_container" do
18
- expect(page).to have_content("There's an error in this field")
18
+ expect(page).to have_content("There is an error in this field")
19
19
  end
20
20
  end
21
21
  end
22
22
 
23
23
  shared_context "with a component" do
24
24
  let(:manifest) { Decidim.find_component_manifest(manifest_name) }
25
- let(:user) { create :user, :confirmed, organization: organization }
25
+ let(:user) { create :user, :confirmed, organization: }
26
26
 
27
27
  let!(:organization) { create(:organization, *organization_traits, available_authorizations: %w(dummy_authorization_handler another_dummy_authorization_handler)) }
28
28
 
29
29
  let(:participatory_process) do
30
- create(:participatory_process, :with_steps, organization: organization)
30
+ create(:participatory_process, :with_steps, organization:)
31
31
  end
32
32
 
33
33
  let(:participatory_space) { participatory_process }
34
34
 
35
35
  let!(:component) do
36
36
  create(:component,
37
- manifest: manifest,
38
- participatory_space: participatory_space)
37
+ manifest:,
38
+ participatory_space:)
39
39
  end
40
40
 
41
- let!(:category) { create :category, participatory_space: participatory_space }
42
- let!(:scope) { create :scope, organization: organization }
41
+ let!(:category) { create :category, participatory_space: }
42
+ let!(:scope) { create :scope, organization: }
43
43
 
44
44
  let(:organization_traits) { [] }
45
45
 
@@ -94,7 +94,7 @@ shared_context "when managing a component as an admin" do
94
94
  create :user,
95
95
  :admin,
96
96
  :confirmed,
97
- organization: organization
97
+ organization:
98
98
  end
99
99
  end
100
100
 
@@ -104,7 +104,7 @@ shared_context "when managing a component as a process admin" do
104
104
  let(:user) do
105
105
  create :process_admin,
106
106
  :confirmed,
107
- organization: organization,
108
- participatory_process: participatory_process
107
+ organization:,
108
+ participatory_process:
109
109
  end
110
110
  end
@@ -7,15 +7,17 @@ module ConfirmationHelpers
7
7
  #
8
8
  # See:
9
9
  # https://github.com/teamcapybara/capybara/blob/44621209496fe4dd352709799a0061a80d97d562/lib/capybara/session.rb#L647
10
- def accept_confirm(_text = nil, **_options)
10
+ def accept_confirm(_text = nil)
11
11
  yield if block_given?
12
12
 
13
13
  # The test can already be "within", so find the body using xpath
14
- message = nil
15
14
  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
15
+ confirm_selector = "[data-confirm-modal-content]"
16
+ message = nil
17
+
18
+ within body do
19
+ message = find(confirm_selector).text
20
+ find("[data-confirm-ok]").click
19
21
  end
20
22
 
21
23
  message
@@ -26,15 +28,17 @@ module ConfirmationHelpers
26
28
  #
27
29
  # See:
28
30
  # https://github.com/teamcapybara/capybara/blob/44621209496fe4dd352709799a0061a80d97d562/lib/capybara/session.rb#L657
29
- def dismiss_confirm(_text = nil, **_options)
31
+ def dismiss_confirm(_text = nil)
30
32
  yield if block_given?
31
33
 
32
34
  # The test can already be "within", so find the body using xpath
33
- message = nil
34
35
  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
36
+ confirm_selector = "[data-confirm-modal-content]"
37
+ message = nil
38
+
39
+ within body do
40
+ message = find(confirm_selector).text
41
+ find("[data-confirm-cancel]").click
38
42
  end
39
43
 
40
44
  message
@@ -43,15 +47,15 @@ module ConfirmationHelpers
43
47
  # Used to accept the "onbeforeunload" event's normal browser confirm modal
44
48
  # as this cannot be overridden. Original confirm dismiss implementation in
45
49
  # Capybara.
46
- def accept_page_unload(text = nil, **options, &blk)
47
- page.send(:accept_modal, :confirm, text, options, &blk)
50
+ def accept_page_unload(text = nil, **options, &)
51
+ page.send(:accept_modal, :confirm, text, options, &)
48
52
  end
49
53
 
50
54
  # Used to dismiss the "onbeforeunload" event's normal browser confirm modal
51
55
  # as this cannot be overridden. Original confirm dismiss implementation in
52
56
  # Capybara.
53
- def dismiss_page_unload(text = nil, **options, &blk)
54
- page.send(:dismiss_modal, :confirm, text, options, &blk)
57
+ def dismiss_page_unload(text = nil, **options, &)
58
+ page.send(:dismiss_modal, :confirm, text, options, &)
55
59
  end
56
60
  end
57
61
 
@@ -15,7 +15,7 @@ module Capybara
15
15
  if dialog_present
16
16
  click_button "Settings"
17
17
  else
18
- within ".footer" do
18
+ within "footer" do
19
19
  click_link "Cookie settings"
20
20
  end
21
21
  end
@@ -25,7 +25,7 @@ module Capybara
25
25
  elsif categories.is_a?(Array)
26
26
  categories.each do |category|
27
27
  within "[data-id='#{category}']" do
28
- find(".switch-paddle").click
28
+ find(".cookies__category-toggle").click
29
29
  end
30
30
  end
31
31
  click_button "Save settings"
@@ -12,17 +12,32 @@ module Capybara
12
12
 
13
13
  yield if block_given?
14
14
 
15
+ front_interface = options.fetch(:front_interface, true)
16
+
15
17
  within ".upload-modal" do
16
- find(".remove-upload-item").click if options[:remove_before]
18
+ click_remove(front_interface) if options[:remove_before]
17
19
  input_element = find("input[type='file']", visible: :all)
18
20
  input_element.attach_file(file_location)
19
21
  within "[data-filename='#{filename}']" do
20
- expect(page).to have_css("div.progress-bar.filled", wait: 5)
22
+ expect(page).to have_css(filled_selector(front_interface), wait: 5)
23
+ expect(page).to have_content(filename.first(12)) if front_interface
21
24
  end
22
- all("input.attachment-title").last.set(options[:title]) if options.has_key?(:title)
23
- click_button "Save" unless options[:keep_modal_open]
25
+ all(title_input(front_interface)).last.set(options[:title]) if options.has_key?(:title)
26
+ click_button(front_interface ? "Next" : "Save") unless options[:keep_modal_open]
24
27
  end
25
28
  end
29
+
30
+ def filled_selector(front_interface)
31
+ front_interface ? "li progress[value='100']" : "div.progress-bar.filled"
32
+ end
33
+
34
+ def title_input(front_interface)
35
+ front_interface ? "input[type='text']" : "input.attachment-title"
36
+ end
37
+
38
+ def click_remove(front_interface)
39
+ front_interface ? click_button("Remove") : find(".remove-upload-item").click
40
+ end
26
41
  end
27
42
  end
28
43
 
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_context "with editor content containing hashtags and mentions" do
4
+ let(:hashtag) { create(:hashtag, organization:) }
5
+ let(:hashtag2) { create(:hashtag, organization:) }
6
+ let(:user) { create(:user, :confirmed, organization:) }
7
+ let(:user2) { create(:user, :confirmed, organization:) }
8
+ let(:user_group) { create(:user_group, :confirmed, organization:) }
9
+ let(:user_group2) { create(:user_group, :confirmed, organization:) }
10
+
11
+ let(:html) do
12
+ <<~HTML
13
+ <p>Paragraph with a hashtag #{hashtag.to_global_id} and another hashtag #{hashtag2.to_global_id}</p>
14
+ <p>Paragraph with a user mention #{user.to_global_id} and another user mention #{user2.to_global_id}</p>
15
+ <p>Paragraph with a user group mention #{user_group.to_global_id} and another user group mention #{user_group2.to_global_id}</p>
16
+ HTML
17
+ end
18
+ let(:editor_html) do
19
+ <<~HTML
20
+ <p>Paragraph with a hashtag #{html_hashtag(hashtag)} and another hashtag #{html_hashtag(hashtag2)}</p>
21
+ <p>Paragraph with a user mention #{html_mention(user)} and another user mention #{html_mention(user2)}</p>
22
+ <p>Paragraph with a user group mention #{html_mention(user_group)} and another user group mention #{html_mention(user_group2)}</p>
23
+ HTML
24
+ end
25
+
26
+ def html_hashtag(hashtag)
27
+ %(<span data-type="hashtag" data-label="##{hashtag.name}">##{hashtag.name}</span>)
28
+ end
29
+
30
+ def html_mention(mentionable)
31
+ mention = "@#{mentionable.nickname}"
32
+ label = "#{mention} (#{CGI.escapeHTML(mentionable.name)})"
33
+ %(<span data-type="mention" data-id="#{mention}" data-label="#{label}">#{label}</span>)
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples_for "clean engine" do
4
+ described_class.initializers.each do |initializer|
5
+ describe "'#{initializer.name}' initializer" do
6
+ let(:initializer_name_prefix) { described_class.to_s.sub(/::([A-Za-z]+)?Engine$/, "\\1").gsub("::", "").underscore }
7
+
8
+ it "is named correctly" do
9
+ expect(initializer.name).to start_with("#{initializer_name_prefix}.")
10
+ expect(initializer.name).to match(/^[a-z0-9_.]+$/)
11
+ expect(initializer.name).not_to start_with(".")
12
+ end
13
+ end
14
+ end
15
+ end