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.
- checksums.yaml +4 -4
- data/app/commands/decidim/{dummy_resources → dev}/create_dummy_resource.rb +1 -2
- data/app/controllers/decidim/{dummy_resources → dev}/dummy_resources_controller.rb +2 -2
- data/app/events/decidim/dev/dummy_resource_event.rb +10 -0
- data/app/forms/decidim/{dummy_resources → dev}/dummy_resource_form.rb +1 -1
- data/app/jobs/decidim/dev/hide_all_created_by_author_job.rb +13 -0
- data/app/mailers/decidim/{dummy_resources → dev}/dummy_resource_mailer.rb +1 -1
- data/app/models/decidim/dev/application_record.rb +9 -0
- data/app/models/decidim/dev/coauthorable_dummy_resource.rb +10 -0
- data/app/models/decidim/dev/dummy_resource.rb +93 -0
- data/app/models/decidim/dev/nested_dummy_resource.rb +10 -0
- data/app/packs/src/decidim/dev/accessibility.js +3 -3
- data/app/packs/src/decidim/dev/test/custom_map_factory.js +1 -1
- data/app/packs/stylesheets/decidim/dev/_accessibility.scss +24 -24
- data/app/packs/stylesheets/decidim/dev/_map.scss +10 -0
- data/app/packs/stylesheets/decidim/dev.scss +1 -0
- data/app/presenters/decidim/dev/official_author_presenter.rb +33 -0
- data/app/serializers/decidim/dev/dummy_serializer.rb +21 -0
- data/app/views/decidim/dev/dummy_resources/show.html.erb +25 -0
- data/config/environment.rb +3 -0
- data/config/locales/ar.yml +0 -1
- data/config/locales/bg.yml +0 -1
- data/config/locales/cs.yml +4 -4
- data/config/locales/de.yml +2 -2
- data/config/locales/el.yml +0 -1
- data/config/locales/en.yml +1 -1
- data/config/locales/es-MX.yml +1 -1
- data/config/locales/es-PY.yml +1 -1
- data/config/locales/eu.yml +14 -8
- data/config/locales/gl.yml +0 -1
- data/config/locales/hu.yml +0 -1
- data/config/locales/id-ID.yml +0 -1
- data/config/locales/it.yml +0 -1
- data/config/locales/lv.yml +0 -1
- data/config/locales/nl.yml +0 -1
- data/config/locales/no.yml +0 -1
- data/config/locales/pl.yml +0 -1
- data/config/locales/pt-BR.yml +0 -1
- data/config/locales/pt.yml +0 -1
- data/config/locales/ru.yml +0 -1
- data/config/locales/sk.yml +0 -1
- data/config/locales/sq-AL.yml +1 -0
- data/config/locales/sv.yml +1 -1
- data/config/locales/th-TH.yml +1 -0
- data/config/locales/tr-TR.yml +0 -1
- data/config/locales/zh-CN.yml +0 -1
- data/config/rubocop/disabled.yml +11 -0
- data/config/rubocop/faker.yml +480 -0
- data/config/rubocop/rails.yml +105 -0
- data/config/rubocop/rspec.yml +69 -0
- data/config/rubocop/ruby.yml +1207 -0
- data/lib/decidim/dev/admin.rb +8 -0
- data/lib/decidim/dev/admin_engine.rb +43 -0
- data/lib/decidim/dev/assets/import_participatory_space_private_users.csv +2 -2
- data/lib/decidim/dev/assets/import_participatory_space_private_users_invalid_col_sep.csv +2 -0
- data/lib/decidim/dev/assets/import_participatory_space_private_users_nok.csv +2 -2
- data/lib/decidim/dev/assets/import_participatory_space_private_users_with_bom.csv +1 -1
- data/lib/decidim/dev/assets/iso-8859-15.md +1 -1
- data/lib/decidim/dev/assets/participatory_text.md +4 -2
- data/lib/decidim/dev/assets/verify_user_groups.csv +22 -22
- data/lib/decidim/dev/component.rb +94 -0
- data/lib/decidim/dev/engine.rb +21 -3
- data/lib/decidim/dev/test/base_spec_helper.rb +1 -0
- data/lib/decidim/dev/test/factories.rb +50 -0
- data/lib/decidim/dev/test/form_to_param_shared_examples.rb +1 -1
- data/lib/decidim/dev/test/promoted_participatory_processes_shared_examples.rb +9 -9
- data/lib/decidim/dev/test/rspec_support/accessibility_examples.rb +119 -1
- data/lib/decidim/dev/test/rspec_support/attachment_helpers.rb +2 -2
- data/lib/decidim/dev/test/rspec_support/bullet.rb +32 -0
- data/lib/decidim/dev/test/rspec_support/capybara.rb +26 -21
- data/lib/decidim/dev/test/rspec_support/cell_matchers.rb +1 -1
- data/lib/decidim/dev/test/rspec_support/component.rb +7 -317
- data/lib/decidim/dev/test/rspec_support/component_context.rb +10 -10
- data/lib/decidim/dev/test/rspec_support/confirmation_helpers.rb +18 -14
- data/lib/decidim/dev/test/rspec_support/data_consent.rb +2 -2
- data/lib/decidim/dev/test/rspec_support/dynamic_attach.rb +19 -4
- data/lib/decidim/dev/test/rspec_support/editor_context.rb +35 -0
- data/lib/decidim/dev/test/rspec_support/engine_examples.rb +15 -0
- data/lib/decidim/dev/test/rspec_support/filters.rb +11 -0
- data/lib/decidim/dev/test/rspec_support/forms_validations.rb +20 -0
- data/lib/decidim/dev/test/rspec_support/geocoder.rb +7 -7
- data/lib/decidim/dev/test/rspec_support/helpers.rb +187 -34
- data/lib/decidim/dev/test/rspec_support/imports_controller_shared_examples.rb +13 -13
- data/lib/decidim/dev/test/rspec_support/tom_select.rb +26 -0
- data/lib/decidim/dev/test/rspec_support/translation_helpers.rb +8 -8
- data/lib/decidim/dev/test/rspec_support/warden.rb +1 -1
- data/lib/decidim/dev/test/rspec_support/webpacker.rb +10 -0
- data/lib/decidim/dev/test/spec_helper.rb +15 -4
- data/lib/decidim/dev/test/w3c_rspec_validators_overrides.rb +1 -5
- data/lib/decidim/dev/version.rb +1 -1
- data/lib/decidim/dev.rb +22 -0
- data/lib/decidim-dev.rb +1 -1
- data/lib/tasks/lighthouse_report.rake +29 -7
- data/rubocop-decidim.yml +13 -0
- metadata +125 -71
- data/app/views/decidim/dummy_resources/dummy_resources/show.html.erb +0 -15
- data/lib/decidim/dev/test/rspec_support/capybara_data_picker.rb +0 -36
- data/lib/decidim/dev/test/rspec_support/capybara_scopes_picker.rb +0 -92
- data/lib/decidim/dev/test/rspec_support/summary_notification.rb +0 -51
- data/lib/rubocop/cop/decidim/hash_shorthand_syntax_backports.rb +0 -175
- data/lib/rubocop/cop/decidim.rb +0 -9
- /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 "
|
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 =
|
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
|
-
|
56
|
+
options:
|
45
57
|
)
|
46
58
|
end
|
47
59
|
|
48
|
-
|
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 =
|
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
|
-
#
|
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
|
-
|
88
|
+
options:
|
84
89
|
)
|
85
90
|
end
|
86
91
|
|
87
92
|
Capybara.register_driver :iphone do |app|
|
88
|
-
options =
|
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
|
-
|
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
|
133
|
+
domain:,
|
129
134
|
name: Decidim.consent_cookie_name,
|
130
135
|
value: { essential: true }.to_json,
|
131
136
|
path: "/",
|
@@ -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?("
|
321
|
-
ActiveRecord::Migration.create_table :
|
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?("
|
346
|
-
ActiveRecord::Migration.create_table :
|
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?("
|
355
|
-
ActiveRecord::Migration.create_table :
|
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
|
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:
|
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:
|
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
|
38
|
-
participatory_space:
|
37
|
+
manifest:,
|
38
|
+
participatory_space:)
|
39
39
|
end
|
40
40
|
|
41
|
-
let!(:category) { create :category, participatory_space:
|
42
|
-
let!(:scope) { create :scope, 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:
|
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
|
108
|
-
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
|
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
|
-
|
17
|
-
|
18
|
-
|
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
|
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
|
-
|
36
|
-
|
37
|
-
|
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, &
|
47
|
-
page.send(:accept_modal, :confirm, text, options, &
|
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, &
|
54
|
-
page.send(:dismiss_modal, :confirm, text, options, &
|
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 "
|
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(".
|
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
|
-
|
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(
|
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(
|
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
|