decidim-dev 0.28.2 → 0.29.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/app/packs/stylesheets/decidim/dev/_accessibility.scss +1 -1
  3. data/app/packs/stylesheets/decidim/dev/_bullet.scss +4 -0
  4. data/app/packs/stylesheets/decidim/dev/_rack_profiler.scss +4 -0
  5. data/app/packs/stylesheets/decidim/dev.scss +2 -0
  6. data/config/rubocop/disabled.yml +60 -0
  7. data/config/rubocop/performance.yml +154 -0
  8. data/config/rubocop/rspec.yml +7 -2
  9. data/config/rubocop/ruby.yml +5 -5
  10. data/decidim-dev.gemspec +11 -6
  11. data/lib/decidim/dev/assets/assemblies.json +1 -34
  12. data/lib/decidim/dev/assets/assemblies_with_null.json +1 -2
  13. data/lib/decidim/dev/assets/participatory_processes.json +1 -34
  14. data/lib/decidim/dev/assets/participatory_processes_with_null.json +0 -1
  15. data/lib/decidim/dev/assets/participatory_text.md +0 -2
  16. data/lib/decidim/dev/component.rb +2 -2
  17. data/lib/decidim/dev/dummy_translator.rb +1 -1
  18. data/lib/decidim/dev/engine.rb +11 -0
  19. data/lib/decidim/dev/test/map_server.rb +125 -0
  20. data/lib/decidim/dev/test/rspec_support/autocomplete_select.rb +2 -2
  21. data/lib/decidim/dev/test/rspec_support/bullet.rb +4 -0
  22. data/lib/decidim/dev/test/rspec_support/capybara.rb +18 -7
  23. data/lib/decidim/dev/test/rspec_support/cell_matchers.rb +1 -1
  24. data/lib/decidim/dev/test/rspec_support/component_context.rb +1 -1
  25. data/lib/decidim/dev/test/rspec_support/data_consent.rb +6 -6
  26. data/lib/decidim/dev/test/rspec_support/datepicker_date_fill.rb +25 -0
  27. data/lib/decidim/dev/test/rspec_support/datepicker_time_fill.rb +23 -0
  28. data/lib/decidim/dev/test/rspec_support/dynamic_attach.rb +2 -2
  29. data/lib/decidim/dev/test/rspec_support/geocoder.rb +8 -72
  30. data/lib/decidim/dev/test/rspec_support/helpers.rb +4 -4
  31. data/lib/decidim/dev/test/rspec_support/tom_select.rb +1 -1
  32. data/lib/decidim/dev/test/rspec_support/translation_helpers.rb +5 -5
  33. data/lib/decidim/dev/test/rspec_support/webmock.rb +7 -1
  34. data/lib/decidim/dev/test/rspec_support/wicked_pdf_assets_mock.rb +2 -2
  35. data/lib/decidim/dev/test/spec_helper.rb +2 -1
  36. data/lib/decidim/dev/version.rb +1 -1
  37. data/lib/decidim/dev.rb +0 -9
  38. data/lib/decidim-dev.rb +2 -0
  39. data/lib/tasks/lighthouse_report.rake +1 -1
  40. data/rubocop-decidim.yml +6 -0
  41. metadata +97 -21
  42. /data/app/views/decidim/dummy_resource/{_linked_dummys.html.erb → _linked_dummies.html.erb} +0 -0
  43. /data/{app/controllers/concerns → lib}/decidim/dev/needs_development_tools.rb +0 -0
@@ -9,9 +9,9 @@ module Capybara
9
9
  expect(page).to have_css("#autoComplete_list_1") # select should be open now
10
10
 
11
11
  expect(page).to have_css("#autoComplete_result_0", text: value)
12
- find("#autoComplete_result_0", text: value).hover
12
+ find_by_id("autoComplete_result_0", text: value).hover
13
13
  expect(page).to have_css("#autoComplete_result_0", text: value)
14
- find("#autoComplete_result_0", text: value).click
14
+ find_by_id("autoComplete_result_0", text: value).click
15
15
  expect(page).to have_css(".autocomplete__selected-item", text: value)
16
16
  end
17
17
  end
@@ -17,6 +17,10 @@ RSpec.configure do |config|
17
17
  Bullet.unused_eager_loading_enable = Decidim::Env.new("DECIDIM_BULLET_UNUSED_EAGER", "false").present?
18
18
  # Detect unnecessary COUNT queries which could be avoided with a counter_cache
19
19
  Bullet.counter_cache_enable = Decidim::Env.new("DECIDIM_BULLET_COUNTER_CACHE", "true").present?
20
+
21
+ # Having a counter cache for this column is too difficult, as this should also work for the Decidim::DummyResource
22
+ # model, and counter_cache needs a real table in the database.
23
+ Bullet.add_safelist type: :counter_cache, class_name: "Decidim::Proposals::Proposal", association: :attachments
20
24
  end
21
25
 
22
26
  if Bullet.enable?
@@ -10,6 +10,7 @@ module Decidim
10
10
 
11
11
  app_host = (host ? "#{protocol}://#{host}" : nil)
12
12
  Capybara.app_host = app_host
13
+ Rails.application.config.action_controller.asset_host = host
13
14
  end
14
15
 
15
16
  def switch_to_default_host
@@ -31,13 +32,23 @@ end
31
32
  1.step do
32
33
  port = rand(5000..6999)
33
34
  begin
34
- Socket.tcp("127.0.0.1", port, connect_timeout: 5).close
35
- warn "Port #{port} is already in use, trying another one."
36
- rescue Errno::ECONNREFUSED
37
- # When connection is refused, the port is available for use.
38
- Capybara.server_port = port
35
+ redis = Redis.new
36
+ reserved_ports = (redis.get("decidim_test_capybara_reserved_ports") || "").split(",").map(&:to_i)
37
+ unless reserved_ports.include?(port)
38
+ reserved_ports << port
39
+ if ParallelTests.last_process?
40
+ redis.del("decidim_test_capybara_reserved_ports")
41
+ else
42
+ redis.set("decidim_test_capybara_reserved_ports", reserved_ports.sort.join(","))
43
+ end
44
+ break
45
+ end
46
+ rescue Redis::CannotConnectError
47
+ # Redis is not available
39
48
  break
40
49
  end
50
+ ensure
51
+ Capybara.server_port = port
41
52
  end
42
53
 
43
54
  Capybara.register_driver :headless_chrome do |app|
@@ -66,7 +77,7 @@ Capybara.register_driver :pwa_chrome do |app|
66
77
  options = Selenium::WebDriver::Chrome::Options.new
67
78
  options.args << "--explicitly-allowed-ports=#{Capybara.server_port}"
68
79
  # If we have a headless browser things like the offline navigation feature stop working,
69
- # so we need to have have a headful/recapitated (aka not headless) browser for these specs
80
+ # so we need to have a headful/recapitated (aka not headless) browser for these specs
70
81
  # options.args << "--headless"
71
82
  options.args << "--no-sandbox"
72
83
  # Do not limit browser resources
@@ -156,7 +167,7 @@ RSpec.configure do |config|
156
167
  switch_to_default_host
157
168
  domain = (try(:organization) || try(:current_organization))&.host
158
169
  if domain
159
- # Javascript sets the cookie also for all subdomains but localhost is a
170
+ # JavaScript sets the cookie also for all subdomains but localhost is a
160
171
  # special case.
161
172
  domain = ".#{domain}" unless domain == "localhost"
162
173
  page.driver.browser.execute_cdp(
@@ -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).not_to have_selector("html")
7
+ expect(actual_value).to have_no_css("html")
8
8
  end
9
9
 
10
10
  diffable
@@ -12,7 +12,7 @@ shared_examples "has mandatory config setting" do |mandatory_field|
12
12
  end
13
13
 
14
14
  it "does not allow updating the component" do
15
- click_button "Update"
15
+ click_on "Update"
16
16
 
17
17
  within ".#{mandatory_field}_container" do
18
18
  expect(page).to have_content("There is an error in this field")
@@ -7,30 +7,30 @@ module Capybara
7
7
  visit decidim.root_path if options[:visit_root]
8
8
 
9
9
  dialog_present = begin
10
- find("#dc-dialog-wrapper")
10
+ find_by_id("dc-dialog-wrapper")
11
11
  rescue Capybara::ElementNotFound => _e
12
12
  false
13
13
  end
14
14
 
15
15
  if dialog_present
16
- click_button "Settings"
16
+ click_on "Settings"
17
17
  else
18
18
  within "footer" do
19
- click_link "Cookie settings"
19
+ click_on "Cookie settings"
20
20
  end
21
21
  end
22
22
 
23
23
  if [true, "all"].include?(categories)
24
- click_button "Accept all"
24
+ click_on "Accept all"
25
25
  elsif categories.is_a?(Array)
26
26
  categories.each do |category|
27
27
  within "[data-id='#{category}']" do
28
28
  find(".cookies__category-toggle").click
29
29
  end
30
30
  end
31
- click_button "Save settings"
31
+ click_on "Save settings"
32
32
  elsif [false, "essential"].include?(categories)
33
- click_button "Accept only essential"
33
+ click_on "Accept only essential"
34
34
  end
35
35
  end
36
36
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capybara
4
+ module DatepickerDateFill
5
+ # fill datepicker field correctly
6
+
7
+ def fill_in_datepicker(locator = nil, with:, currently_with: nil, fill_options: {}, **find_options)
8
+ find_options[:with] = currently_with if currently_with
9
+ find_options[:allow_self] = true if locator.nil?
10
+ with.chars.each do |character|
11
+ if character == "/"
12
+ find(:fillable_field, locator, **find_options).send_keys(:divide, **fill_options)
13
+ elsif character == "."
14
+ find(:fillable_field, locator, **find_options).send_keys(:decimal, **fill_options)
15
+ else
16
+ find(:fillable_field, locator, **find_options).send_keys(character, **fill_options)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ RSpec.configure do |config|
24
+ config.include Capybara::DatepickerDateFill, type: :system
25
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capybara
4
+ module DatepickerTimeFill
5
+ # fill datepicker field correctly
6
+
7
+ def fill_in_timepicker(locator = nil, with:, currently_with: nil, fill_options: {}, **find_options)
8
+ find_options[:with] = currently_with if currently_with
9
+ find_options[:allow_self] = true if locator.nil?
10
+ with.chars.each do |character|
11
+ if character == ":"
12
+ find(:fillable_field, locator, **find_options).send_keys([:alt, ":"], **fill_options)
13
+ else
14
+ find(:fillable_field, locator, **find_options).send_keys(character, **fill_options)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ RSpec.configure do |config|
22
+ config.include Capybara::DatepickerTimeFill, type: :system
23
+ end
@@ -23,7 +23,7 @@ module Capybara
23
23
  expect(page).to have_content(filename.first(12)) if front_interface
24
24
  end
25
25
  all(title_input(front_interface)).last.set(options[:title]) if options.has_key?(:title)
26
- click_button("Save") unless options[:keep_modal_open]
26
+ click_on("Save") unless options[:keep_modal_open]
27
27
  end
28
28
  end
29
29
 
@@ -36,7 +36,7 @@ module Capybara
36
36
  end
37
37
 
38
38
  def click_remove(front_interface)
39
- front_interface ? click_button("Remove") : find(".remove-upload-item").click
39
+ front_interface ? click_on("Remove") : find(".remove-upload-item").click
40
40
  end
41
41
  end
42
42
  end
@@ -18,7 +18,7 @@ module GeocoderHelpers
18
18
  # are no pending requests when proceeding.
19
19
  def fill_in_geocoding(attribute, options = {})
20
20
  fill_in attribute, **options
21
- expect(page).to have_selector(".autoComplete_wrapper ul#autoComplete_list_1", count: 1)
21
+ expect(page).to have_css(".autoComplete_wrapper ul#autoComplete_list_1", count: 1)
22
22
  find("li#autoComplete_result_0").click
23
23
  end
24
24
 
@@ -29,8 +29,13 @@ module GeocoderHelpers
29
29
  Decidim.maps = {
30
30
  provider: :test,
31
31
  api_key: "1234123412341234",
32
- static: { url: "https://www.example.org/my_static_map" },
33
- autocomplete: { url: "/photon_api" } # Locally drawn route for the tests
32
+ dynamic: {
33
+ tile_layer: {
34
+ url: Decidim::Dev::Test::MapServer.url(:tiles)
35
+ }
36
+ },
37
+ static: { url: Decidim::Dev::Test::MapServer.url(:static) },
38
+ autocomplete: { url: Decidim::Dev::Test::MapServer.url(:autocomplete) }
34
39
  }
35
40
  end
36
41
  end
@@ -102,77 +107,8 @@ RSpec.configure do |config|
102
107
  configure_maps
103
108
  end
104
109
 
105
- config.before(:each, :serves_map) do
106
- stub_request(:get, %r{https://www\.example\.org/my_static_map})
107
- .to_return(body: "map_data")
108
- end
109
-
110
110
  config.before(:each, :serves_geocoding_autocomplete) do
111
111
  # Clear the autocomplete stubs
112
112
  Decidim::Map::Provider::Autocomplete::Test.clear_stubs
113
-
114
- photon_response = lambda do
115
- {
116
- features: [
117
- {
118
- properties: {
119
- name: "Park",
120
- street: "Street1",
121
- housenumber: "1",
122
- postcode: "123456",
123
- city: "City1",
124
- state: "State1",
125
- country: "Country1"
126
- },
127
- geometry: {
128
- coordinates: [2.234, 1.123]
129
- }
130
- },
131
- {
132
- properties: {
133
- street: "Street2",
134
- postcode: "654321",
135
- city: "City2",
136
- country: "Country2"
137
- },
138
- geometry: {
139
- coordinates: [4.456, 3.345]
140
- }
141
- },
142
- {
143
- properties: {
144
- street: "Street3",
145
- housenumber: "3",
146
- postcode: "142536",
147
- city: "City3",
148
- country: "Country3"
149
- },
150
- geometry: {
151
- coordinates: [6.678, 5.567]
152
- }
153
- }
154
- ]
155
- }.tap do |response|
156
- Decidim::Map::Provider::Autocomplete::Test.stubs.length.positive? &&
157
- response[:features] = Decidim::Map::Provider::Autocomplete::Test.stubs
158
- end
159
- end
160
-
161
- # The Photon API path needs to be mounted in the application itself because
162
- # otherwise we would have to run a separate server for the API itself.
163
- # Mocking the request would not work here because the call to the Photon API
164
- # is initialized by the front-end to the URL specified for the maps
165
- # geocoding autocompletion configuration which is not proxied by the
166
- # headless browser running the Capybara tests.
167
- Rails.application.routes.disable_clear_and_finalize = true
168
- Rails.application.routes.draw do
169
- get "photon_api", to: ->(_) { [200, { "Content-Type" => "application/json" }, [photon_response.call.to_json.to_s]] }
170
- end
171
- Rails.application.routes.disable_clear_and_finalize = false
172
- end
173
-
174
- config.after(:each, :serves_geocoding_autocomplete) do
175
- # Reset the routes back to original
176
- Rails.application.reload_routes!
177
113
  end
178
114
  end
@@ -5,7 +5,7 @@ module Decidim
5
5
  module ComponentTestHelpers
6
6
  def click_submenu_link(text)
7
7
  within ".secondary-nav--subnav" do
8
- click_link text
8
+ click_on text
9
9
  end
10
10
  end
11
11
 
@@ -13,7 +13,7 @@ module Decidim
13
13
  main_bar_selector = ".main-bar"
14
14
 
15
15
  within main_bar_selector do
16
- find("#trigger-dropdown-account").click
16
+ find_by_id("trigger-dropdown-account").click
17
17
 
18
18
  yield
19
19
  end
@@ -26,14 +26,14 @@ module Decidim
26
26
  end
27
27
 
28
28
  def within_admin_menu
29
- click_button "Manage"
29
+ click_on "Manage"
30
30
  within("[id*='dropdown-menu-settings']") do
31
31
  yield
32
32
  end
33
33
  end
34
34
 
35
35
  def within_language_menu(options = {})
36
- within(options[:admin] ? ".topbar__dropmenu.language-choose" : "footer") do
36
+ within(options[:admin] ? ".language-choose" : "footer") do
37
37
  find(options[:admin] ? "#admin-menu-trigger" : "#trigger-dropdown-language-chooser").click
38
38
  yield
39
39
  end
@@ -3,7 +3,7 @@
3
3
  # https://github.com/orchidjs/tom-select/discussions/71#discussioncomment-641757
4
4
  module Capybara
5
5
  module TomSelect
6
- # A helper for Capyabara tests that need to set values from a tom-select.js input.
6
+ # A helper for Capybara tests that need to set values from a tom-select.js input.
7
7
  #
8
8
  # This is a really hacky approach using execute_javascript, but it works. Not sure if there is
9
9
  # a better way, we could try actually interacting with the on-screen tom-select-provided UI,
@@ -42,7 +42,7 @@ module TranslationHelpers
42
42
  # field - the name of the field that should be filled, without the
43
43
  # locale-related part (e.g. `:participatory_process_title`)
44
44
  # tab_selector - a String representing the ID of the HTML element that holds
45
- # the tabs for this input. It ususally is `"#<attribute_name>-tabs" (e.g.
45
+ # the tabs for this input. It usually is `"#<attribute_name>-tabs" (e.g.
46
46
  # "#title-tabs")
47
47
  # localized_values - a Hash where the keys are the locales IDs and the values
48
48
  # are the values that will be entered in the form field.
@@ -57,7 +57,7 @@ module TranslationHelpers
57
57
  # field - the name of the field that should be filled, without the
58
58
  # locale-related part (e.g. `:participatory_process_title`)
59
59
  # tab_selector - a String representing the ID of the HTML element that holds
60
- # the tabs for this input. It ususally is `"#<attribute_name>-tabs" (e.g.
60
+ # the tabs for this input. It usually is `"#<attribute_name>-tabs" (e.g.
61
61
  # "#title-tabs")
62
62
  # localized_values - a Hash where the keys are the locales IDs and the values
63
63
  # are the values that will be entered in the form field.
@@ -72,7 +72,7 @@ module TranslationHelpers
72
72
  # field - the name of the field that should be cleared, without the
73
73
  # locale-related part (e.g. `:participatory_process_title`)
74
74
  # tab_selector - a String representing the ID of the HTML element that holds
75
- # the tabs for this input. It ususally is `"#<attribute_name>-tabs" (e.g.
75
+ # the tabs for this input. It usually is `"#<attribute_name>-tabs" (e.g.
76
76
  # "#title-tabs")
77
77
  # locales - an Array with the locales IDs.
78
78
  def clear_i18n_editor(field, tab_selector, locales)
@@ -113,7 +113,7 @@ module TranslationHelpers
113
113
  scroll_to(find(tab_selector))
114
114
  localized_values.each do |locale, value|
115
115
  within tab_selector do
116
- click_link I18n.with_locale(locale) { t("name", scope: "locale") }
116
+ click_on I18n.with_locale(locale) { t("name", scope: "locale") }
117
117
  end
118
118
  yield "#{field}_#{locale}", value
119
119
  end
@@ -125,7 +125,7 @@ module TranslationHelpers
125
125
  scroll_to(find(tab_selector))
126
126
  locales.each do |locale|
127
127
  within tab_selector do
128
- click_link I18n.with_locale(locale) { t("name", scope: "locale") }
128
+ click_on I18n.with_locale(locale) { t("name", scope: "locale") }
129
129
  end
130
130
  yield "#{field}_#{locale}"
131
131
  end
@@ -2,4 +2,10 @@
2
2
 
3
3
  require "webmock/rspec"
4
4
 
5
- WebMock.disable_net_connect!(allow_localhost: true, allow: %r{https://validator\.w3\.org/})
5
+ WebMock.disable_net_connect!(
6
+ allow_localhost: true,
7
+ allow: [
8
+ %r{https://validator\.w3\.org/},
9
+ Decidim::Dev::Test::MapServer.host
10
+ ]
11
+ )
@@ -5,8 +5,8 @@ class WickedPdf
5
5
  module Assets
6
6
  # Force wicked_pdf styles to have a relative path, to prevent fetching
7
7
  # them from a host
8
- def wicked_pdf_stylesheet_pack_tag(*sources)
9
- stylesheet_pack_tag(*sources)
8
+ def wicked_pdf_stylesheet_pack_tag(*)
9
+ stylesheet_pack_tag(*)
10
10
  end
11
11
 
12
12
  # Disables the images in the PDFs as those requests would be jamming under
@@ -41,7 +41,8 @@ RSpec.configure do |config|
41
41
 
42
42
  config.before :all do
43
43
  Decidim.content_security_policies_extra = {
44
- "img-src": %w(https://via.placeholder.com)
44
+ "img-src": %W(https://via.placeholder.com #{Decidim::Dev::Test::MapServer.host}),
45
+ "connect-src": %W(#{Decidim::Dev::Test::MapServer.host})
45
46
  }
46
47
  end
47
48
  end
@@ -4,7 +4,7 @@ module Decidim
4
4
  # This holds the decidim-dev version.
5
5
  module Dev
6
6
  def self.version
7
- "0.28.2"
7
+ "0.29.0.rc1"
8
8
  end
9
9
  end
10
10
  end
data/lib/decidim/dev.rb CHANGED
@@ -22,15 +22,6 @@ module Decidim
22
22
  include ActiveSupport::Configurable
23
23
  autoload :DummyTranslator, "decidim/dev/dummy_translator"
24
24
 
25
- # Settings needed to compare emendations in Decidim::SimilarEmendations
26
- config_accessor :similarity_threshold do
27
- 0.25
28
- end
29
-
30
- config_accessor :similarity_limit do
31
- 10
32
- end
33
-
34
25
  # Public: Finds an asset.
35
26
  #
36
27
  # Returns a String with the path for a particular asset.
data/lib/decidim-dev.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # rubocop:disable Naming/FileName
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "decidim/dev"
5
+ # rubocop:enable Naming/FileName
@@ -4,7 +4,7 @@ namespace :decidim do
4
4
  namespace :lighthouse do
5
5
  desc "Prepares seeds for Lighthouse report"
6
6
  task prepare_urls: :environment do
7
- # Lighhouse report is executed in CI and should check:
7
+ # Lighthouse report is executed in CI and should check:
8
8
  # - homepage
9
9
  # - a participatory process page
10
10
  # - a meeting page
data/rubocop-decidim.yml CHANGED
@@ -5,7 +5,13 @@
5
5
  # For further details, see:
6
6
  # https://github.com/rubocop/rubocop/issues/4154#issuecomment-316004878
7
7
 
8
+ require:
9
+ - rubocop-rubycw
10
+ - rubocop-capybara
11
+ - rubocop-factory_bot
12
+
8
13
  inherit_from:
14
+ - config/rubocop/performance.yml
9
15
  - config/rubocop/ruby.yml
10
16
  - config/rubocop/rails.yml
11
17
  - config/rubocop/rspec.yml