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
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FiltersHelpers
4
+ def click_filter_item(text)
5
+ find("label.filter", text:).click
6
+ end
7
+ end
8
+
9
+ RSpec.configure do |config|
10
+ config.include FiltersHelpers, type: :system
11
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FormsValidationsHelpers
4
+ MESSAGES = {
5
+ text: "Please fill out this field.",
6
+ select: "Please select an item in the list."
7
+ }.freeze
8
+
9
+ def expect_blank_field_validation_message(selector, opts = {})
10
+ type = opts.fetch(:type, :text).to_sym
11
+ expected_message = opts.fetch(:message, MESSAGES[type])
12
+ message = page.find(selector).native.attribute("validationMessage")
13
+
14
+ expect(message).to eq expected_message
15
+ end
16
+ end
17
+
18
+ RSpec.configure do |config|
19
+ config.include FormsValidationsHelpers, type: :system
20
+ end
@@ -49,7 +49,7 @@ module Decidim::Map::Provider
49
49
  def self.add_stub(address, coordinates)
50
50
  stubs.push(
51
51
  properties: address.is_a?(Hash) ? address : { street: address },
52
- geometry: { coordinates: coordinates }
52
+ geometry: { coordinates: coordinates.reverse }
53
53
  )
54
54
  end
55
55
 
@@ -62,8 +62,8 @@ module Decidim::Map::Provider
62
62
  end
63
63
 
64
64
  class Builder < Decidim::Map::Autocomplete::Builder
65
- def javascript_snippets
66
- template.javascript_pack_tag("decidim_geocoding_provider_photon", defer: false)
65
+ def append_assets
66
+ template.append_javascript_pack_tag("decidim_geocoding_provider_photon")
67
67
  end
68
68
  end
69
69
  end
@@ -90,7 +90,7 @@ RSpec.configure do |config|
90
90
  # otherwise the utilities could remain unregistered which causes issues with
91
91
  # further tests.
92
92
  Decidim::Core::Engine.initializers.each do |i|
93
- next unless i.name == "decidim.maps"
93
+ next unless i.name == "decidim_core.maps"
94
94
 
95
95
  i.run
96
96
  break
@@ -125,7 +125,7 @@ RSpec.configure do |config|
125
125
  country: "Country1"
126
126
  },
127
127
  geometry: {
128
- coordinates: [1.123, 2.234]
128
+ coordinates: [2.234, 1.123]
129
129
  }
130
130
  },
131
131
  {
@@ -136,7 +136,7 @@ RSpec.configure do |config|
136
136
  country: "Country2"
137
137
  },
138
138
  geometry: {
139
- coordinates: [3.345, 4.456]
139
+ coordinates: [4.456, 3.345]
140
140
  }
141
141
  },
142
142
  {
@@ -148,7 +148,7 @@ RSpec.configure do |config|
148
148
  country: "Country3"
149
149
  },
150
150
  geometry: {
151
- coordinates: [5.567, 6.678]
151
+ coordinates: [6.678, 5.567]
152
152
  }
153
153
  }
154
154
  ]
@@ -1,55 +1,208 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Helpers that get automatically included in component specs.
4
- module Decidim::ComponentTestHelpers
5
- def click_submenu_link(text)
6
- within ".secondary-nav--subnav" do
7
- click_link text
4
+ module Decidim
5
+ module ComponentTestHelpers
6
+ def click_submenu_link(text)
7
+ within ".secondary-nav--subnav" do
8
+ click_link text
9
+ end
8
10
  end
9
- end
10
11
 
11
- def within_user_menu
12
- within ".topbar__user__logged" do
13
- find("a", text: user.name).click
14
- yield
12
+ def within_user_menu
13
+ main_bar_selector = ".main-bar"
14
+
15
+ within main_bar_selector do
16
+ find("#trigger-dropdown-account").click
17
+
18
+ yield
19
+ end
15
20
  end
16
- end
17
21
 
18
- def within_language_menu
19
- within ".topbar__dropmenu.language-choose" do
20
- find("ul.dropdown.menu").click
21
- yield
22
+ def within_admin_sidebar_menu
23
+ within("[id='admin-sidebar-menu-settings']") do
24
+ yield
25
+ end
22
26
  end
23
- end
24
27
 
25
- def stripped(text)
26
- text.gsub(/^<p>/, "").gsub(%r{</p>$}, "")
27
- end
28
+ def within_admin_menu
29
+ click_button "Manage"
30
+ within("[id*='dropdown-menu-settings']") do
31
+ yield
32
+ end
33
+ end
34
+
35
+ def within_language_menu(options = {})
36
+ within(options[:admin] ? ".topbar__dropmenu.language-choose" : "footer") do
37
+ find(options[:admin] ? "#admin-menu-trigger" : "#trigger-dropdown-language-chooser").click
38
+ yield
39
+ end
40
+ end
41
+
42
+ def stripped(text)
43
+ text.gsub(/^<p>/, "").gsub(%r{</p>$}, "")
44
+ end
28
45
 
29
- def within_flash_messages
30
- within ".flash" do
31
- yield
46
+ def within_flash_messages
47
+ within ".flash", match: :first do
48
+ yield
49
+ end
50
+ end
51
+
52
+ def expect_user_logged
53
+ expect(page).to have_css(".main-bar #trigger-dropdown-account")
54
+ end
55
+
56
+ def have_admin_callout(text)
57
+ within_flash_messages do
58
+ have_content text
59
+ end
60
+ end
61
+
62
+ def stub_get_request_with_format(rq_url, rs_format)
63
+ stub_request(:get, rq_url)
64
+ .with(
65
+ headers: {
66
+ "Accept" => "*/*",
67
+ "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3",
68
+ "User-Agent" => "Ruby"
69
+ }
70
+ )
71
+ .to_return(status: 200, body: "", headers: { content_type: rs_format })
32
72
  end
33
73
  end
34
74
 
35
- def expect_user_logged
36
- expect(page).to have_css(".topbar__user__logged")
75
+ module FrontEndDataTestHelpers
76
+ def paste_content(content, target_selector)
77
+ page.execute_script(
78
+ <<~JS
79
+ var dt = new DataTransfer();
80
+ dt.setData("text/html", #{content.to_json});
81
+ dt.setData("text/plain", #{content.to_json});
82
+
83
+ var element = document.querySelector("#{target_selector}");
84
+ element.dispatchEvent(new ClipboardEvent("paste", { clipboardData: dt }));
85
+ JS
86
+ )
87
+ end
37
88
  end
38
89
 
39
- def have_admin_callout(text)
40
- have_selector(".callout--full", text: text)
90
+ module FrontEndPointerTestHelpers
91
+ def drag(selector, mode: "mouse", direction: nil, amount: 0)
92
+ move =
93
+ case direction
94
+ when "left"
95
+ "x -= #{amount}"
96
+ when "right"
97
+ "x += #{amount}"
98
+ when "top"
99
+ "y -= #{amount}"
100
+ when "bottom"
101
+ "y += #{amount}"
102
+ end
103
+
104
+ events =
105
+ if mode == "touch"
106
+ <<~JS
107
+ var evStart = new Event("touchstart");
108
+ evStart.touches = [{ pageX: rect.x, pageY: rect.y }];
109
+ var evMove = new Event("touchmove");
110
+ evMove.touches = [{ pageX: x, pageY: y }];
111
+
112
+ element.dispatchEvent(evStart);
113
+ document.dispatchEvent(evMove);
114
+ document.dispatchEvent(new Event("touchend"));
115
+ JS
116
+ else
117
+ <<~JS
118
+ element.dispatchEvent(new MouseEvent("mousedown", { clientX: rect.x, clientY: rect.y }));
119
+ document.dispatchEvent(new MouseEvent("mousemove", { clientX: x, clientY: y }));
120
+ document.dispatchEvent(new MouseEvent("mouseup"));
121
+ JS
122
+ end
123
+
124
+ page.execute_script(
125
+ <<~JS
126
+ var element = document.querySelector("#{selector}");
127
+ var rect = element.getBoundingClientRect();
128
+
129
+ var x = rect.x;
130
+ var y = rect.y;
131
+ #{move};
132
+
133
+ #{events}
134
+ JS
135
+ )
136
+ end
41
137
  end
42
138
 
43
- def stub_get_request_with_format(rq_url, rs_format)
44
- stub_request(:get, rq_url)
45
- .with(
46
- headers: {
47
- "Accept" => "*/*",
48
- "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3",
49
- "User-Agent" => "Ruby"
50
- }
139
+ module FrontEndFileTestHelpers
140
+ def file_to_frontend(filename)
141
+ filepath = Decidim::Dev.asset(filename)
142
+ mime = MiniMime.lookup_by_filename(filepath).content_type
143
+ encoded = Base64.encode64(File.read(filepath))
144
+
145
+ {
146
+ filename:,
147
+ data_url: "data:application/octet-binary;base64,#{encoded.gsub("\n", "")}",
148
+ mime_type: mime
149
+ }
150
+ end
151
+
152
+ def add_file(filename, target_selector, event)
153
+ file = file_to_frontend(filename)
154
+
155
+ page.execute_script(
156
+ <<~JS
157
+ var dataUrl = "#{file[:data_url]}";
158
+ fetch(dataUrl).then(function(res) { return res.arrayBuffer(); }).then(function (buffer) {
159
+ var file = new File([buffer], "#{filename}", { type: "#{file[:mime_type]}" });
160
+ var dropzone = document.querySelector("#{target_selector}");
161
+
162
+ var dt = new DataTransfer();
163
+ dt.items.add(file);
164
+
165
+ if ("#{event}" === "drop") {
166
+ var ev = new Event("drop");
167
+ ev.dataTransfer = dt;
168
+ dropzone.dispatchEvent(ev);
169
+ } else {
170
+ // Simulates selecting the file through the browser's file selector
171
+ var input = dropzone.querySelector("input[type='file']");
172
+ input.files = dt.files;
173
+ input.dispatchEvent(new Event("change", { bubbles: true }));
174
+ }
175
+ });
176
+ JS
177
+ )
178
+
179
+ # Wait for the file to be uploaded
180
+ within "[data-dropzone-items]" do
181
+ expect(page).to have_content(filename)
182
+ end
183
+ end
184
+
185
+ def paste_file(filename, target_selector)
186
+ file = file_to_frontend(filename)
187
+
188
+ page.execute_script(
189
+ <<~JS
190
+ var dataUrl = "#{file[:data_url]}";
191
+ fetch(dataUrl).then(function(res) { return res.arrayBuffer(); }).then(function (buffer) {
192
+ var file = new File([buffer], "#{filename}", { type: "#{file[:mime_type]}" });
193
+
194
+ var dt = new DataTransfer();
195
+ dt.items.add(file);
196
+
197
+ var element = document.querySelector("#{target_selector}");
198
+ element.dispatchEvent(new ClipboardEvent("paste", { clipboardData: dt }));
199
+ });
200
+ JS
51
201
  )
52
- .to_return(status: 200, body: "", headers: { content_type: rs_format })
202
+
203
+ # Wait for the file to be uploaded
204
+ sleep 1
205
+ end
53
206
  end
54
207
  end
55
208
 
@@ -2,8 +2,8 @@
2
2
 
3
3
  shared_examples "admin imports controller" do
4
4
  let!(:organization) { create(:organization) }
5
- let!(:user) { create(:user, :admin, :confirmed, organization: organization) }
6
- let!(:component) { create(:component, participatory_space: participatory_space, manifest_name: "dummy") }
5
+ let!(:user) { create(:user, :admin, :confirmed, organization:) }
6
+ let!(:component) { create(:component, participatory_space:, manifest_name: "dummy") }
7
7
 
8
8
  let(:default_params) do
9
9
  {
@@ -23,16 +23,16 @@ shared_examples "admin imports controller" do
23
23
  # will always create a record for each data row regardless of the data.
24
24
  let(:file) { upload_test_file(Decidim::Dev.test_file("import_proposals.csv", "text/csv")) }
25
25
  let(:params) do
26
- default_params.merge(extra_params).merge(file: file)
26
+ default_params.merge(extra_params).merge(file:)
27
27
  end
28
28
 
29
29
  it "imports dummies" do
30
- post(:create, params: params)
30
+ post(:create, params:)
31
31
  expect(response).to have_http_status(:found)
32
32
  expect(flash[:notice]).not_to be_empty
33
33
 
34
- expect(Decidim::DummyResources::DummyResource.count).to eq(3)
35
- Decidim::DummyResources::DummyResource.find_each do |dummy|
34
+ expect(Decidim::Dev::DummyResource.count).to eq(3)
35
+ Decidim::Dev::DummyResource.find_each do |dummy|
36
36
  expect(dummy.title).to eq("en" => "Dummy")
37
37
  expect(dummy.author).to eq(user)
38
38
  expect(dummy.component).to eq(component)
@@ -42,14 +42,14 @@ shared_examples "admin imports controller" do
42
42
 
43
43
  describe "GET example" do
44
44
  let(:params) do
45
- default_params.merge(extra_params).merge(format: format)
45
+ default_params.merge(extra_params).merge(format:)
46
46
  end
47
47
 
48
48
  context "with CSV format" do
49
49
  let(:format) { "csv" }
50
50
 
51
51
  it "creates a correct CSV example file" do
52
- get(:example, params: params)
52
+ get(:example, params:)
53
53
 
54
54
  expect(response).to have_http_status(:ok)
55
55
  expect(response.content_type).to eq("text/csv")
@@ -66,7 +66,7 @@ shared_examples "admin imports controller" do
66
66
  let(:format) { "json" }
67
67
 
68
68
  it "creates a correct JSON example file" do
69
- get(:example, params: params)
69
+ get(:example, params:)
70
70
 
71
71
  expect(response).to have_http_status(:ok)
72
72
  expect(response.content_type).to eq("application/json")
@@ -83,7 +83,7 @@ shared_examples "admin imports controller" do
83
83
  let(:format) { "xlsx" }
84
84
 
85
85
  it "creates a correct XLSX example file" do
86
- get(:example, params: params)
86
+ get(:example, params:)
87
87
 
88
88
  expect(response).to have_http_status(:ok)
89
89
  expect(response.content_type).to eq(
@@ -109,7 +109,7 @@ shared_examples "admin imports controller" do
109
109
  let(:format) { "foo" }
110
110
 
111
111
  it "raises ActionController::UnknownFormat" do
112
- expect { get(:example, params: params) }.to raise_error(
112
+ expect { get(:example, params:) }.to raise_error(
113
113
  ActionController::UnknownFormat
114
114
  )
115
115
  end
@@ -124,7 +124,7 @@ shared_examples "admin imports controller" do
124
124
 
125
125
  describe "POST create" do
126
126
  it "raises ActionController::RoutingError" do
127
- expect { post(:create, params: params) }.to raise_error(
127
+ expect { post(:create, params:) }.to raise_error(
128
128
  ActionController::RoutingError
129
129
  )
130
130
  end
@@ -132,7 +132,7 @@ shared_examples "admin imports controller" do
132
132
 
133
133
  describe "GET example" do
134
134
  it "raises ActionController::RoutingError" do
135
- expect { get(:example, params: params) }.to raise_error(
135
+ expect { get(:example, params:) }.to raise_error(
136
136
  ActionController::RoutingError
137
137
  )
138
138
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://github.com/orchidjs/tom-select/discussions/71#discussioncomment-641757
4
+ module Capybara
5
+ module TomSelect
6
+ # A helper for Capyabara tests that need to set values from a tom-select.js input.
7
+ #
8
+ # This is a really hacky approach using execute_javascript, but it works. Not sure if there is
9
+ # a better way, we could try actually interacting with the on-screen tom-select-provided UI,
10
+ # but we are taking the easy way out for now.
11
+ #
12
+ # @param option_id can be the `id` value of an option in the select, OR for select multiple inputs,
13
+ # can be an array of such IDs.
14
+ #
15
+ # @example tom_select("#select_id", option_id: "2")
16
+ # @example tom_select("#select_id", option_id: ["2", "10"]) # `multiple` input.
17
+ def tom_select(select_selector, option_id:)
18
+ js_str = %(document.querySelector("#{select_selector}").tomselect.setValue(#{option_id.inspect}))
19
+ execute_script(js_str)
20
+ end
21
+ end
22
+ end
23
+
24
+ RSpec.configure do |config|
25
+ config.include Capybara::TomSelect, type: :system
26
+ end
@@ -4,7 +4,7 @@
4
4
  module TranslationHelpers
5
5
  # Allows using the `t` shortcut inside specs just like in views
6
6
  def t(key, scope: nil)
7
- I18n.t(key, scope: scope, raise: true)
7
+ I18n.t(key, scope:, raise: true)
8
8
  end
9
9
 
10
10
  # Gives the localized version of the attribute for the given locale. The
@@ -25,16 +25,16 @@ module TranslationHelpers
25
25
  # field - the field that holds the translations
26
26
  # upcase - a boolean to indicate whether the string must be checked upcased or not.
27
27
  def have_i18n_content(field, upcase: false, strip_tags: false)
28
- have_content(i18n_content(field, upcase: upcase, strip_tags: strip_tags))
28
+ have_content(i18n_content(field, upcase:, strip_tags:).strip)
29
29
  end
30
30
 
31
- # Checks that the current page doesn't have some translated content. It strips
31
+ # Checks that the current page does not have some translated content. It strips
32
32
  # the HTML tags from the field (in case there are any).
33
33
  #
34
34
  # field - the field that holds the translations
35
35
  # upcase - a boolean to indicate whether the string must be checked upcased or not.
36
36
  def have_no_i18n_content(field, upcase: false)
37
- have_no_content(i18n_content(field, upcase: upcase))
37
+ have_no_content(i18n_content(field, upcase:))
38
38
  end
39
39
 
40
40
  # Handles how to fill in i18n form fields.
@@ -90,8 +90,8 @@ module TranslationHelpers
90
90
  raise ArgumentError if params[:with].blank?
91
91
 
92
92
  page.execute_script <<-SCRIPT
93
- $('##{locator}').siblings('.editor-container').find('.ql-editor')[0].innerHTML = "#{params[:with]}";
94
- $('##{locator}').val("#{params[:with]}")
93
+ document.querySelector('##{locator} .editor-container .ProseMirror').innerHTML = `#{params[:with]}`;
94
+ document.querySelector('##{locator} input').value = `#{params[:with]}`;
95
95
  SCRIPT
96
96
  end
97
97
 
@@ -100,8 +100,8 @@ module TranslationHelpers
100
100
  # locator - The input field ID. The DOM element is selected using jQuery.
101
101
  def clear_editor(locator)
102
102
  page.execute_script <<-SCRIPT
103
- $('##{locator}').siblings('.editor-container').find('.ql-editor')[0].innerHTML = "<p><br></p>";
104
- $('##{locator}').val("")
103
+ document.querySelector('##{locator} .editor-container .ProseMirror').innerHTML = '<p><br class="ProseMirror-trailingBreak"></p>';
104
+ document.querySelector('##{locator} input').value = "";
105
105
  SCRIPT
106
106
  end
107
107
 
@@ -11,7 +11,7 @@ module Decidim
11
11
  def relogin_as(user, scope: :user)
12
12
  logout scope
13
13
 
14
- login_as user, scope: scope
14
+ login_as user, scope:
15
15
  end
16
16
  end
17
17
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.configure do |config|
4
+ config.before(:all, type: :system) do
5
+ Dir.chdir(Rails.root) { Webpacker.compile }
6
+ end
7
+ config.before(:all, type: :mailer) do
8
+ Dir.chdir(Rails.root) { Webpacker.compile }
9
+ end
10
+ end
@@ -5,9 +5,7 @@ require "rspec/rails"
5
5
  require "rspec/cells"
6
6
  require "byebug"
7
7
  require "wisper/rspec/stub_wisper_publisher"
8
- require "db-query-matchers"
9
8
  require "action_view/helpers/sanitize_helper"
10
- require "axe-rspec"
11
9
  require "w3c_rspec_validators"
12
10
  require "decidim/dev/test/w3c_rspec_validators_overrides"
13
11
 
@@ -15,7 +13,7 @@ require "decidim/dev/test/w3c_rspec_validators_overrides"
15
13
  # in ./rspec_support/ and its subdirectories.
16
14
  Dir["#{__dir__}/rspec_support/**/*.rb"].each { |f| require f }
17
15
 
18
- require_relative "factories"
16
+ require "decidim/dev/test/factories"
19
17
 
20
18
  RSpec.configure do |config|
21
19
  config.color = true
@@ -25,12 +23,25 @@ RSpec.configure do |config|
25
23
  config.order = :random
26
24
  config.raise_errors_for_deprecations!
27
25
  config.example_status_persistence_file_path = ".rspec-failures"
26
+ config.filter_run_when_matching :focus
27
+ config.profile_examples = 10
28
+ config.default_formatter = "doc" if config.files_to_run.one?
28
29
 
29
- # If you're not using ActiveRecord, or you'd prefer not to run each of your
30
+ # If you are not using ActiveRecord, or you'd prefer not to run each of your
30
31
  # examples within a transaction, comment the following line or assign false
31
32
  # instead of true.
32
33
  config.use_transactional_fixtures = true
33
34
 
34
35
  config.include ActionView::Helpers::SanitizeHelper
35
36
  config.include ERB::Util
37
+
38
+ config.before :all, type: :system do
39
+ ActiveStorage.service_urls_expire_in = 24.hours
40
+ end
41
+
42
+ config.before :all do
43
+ Decidim.content_security_policies_extra = {
44
+ "img-src": %w(https://via.placeholder.com)
45
+ }
46
+ end
36
47
  end
@@ -3,11 +3,8 @@
3
3
  # This is a temporary fix to ignore some HTML/CSS validation issues with the
4
4
  # Decidim HTML validation process.
5
5
  #
6
- # See:
7
- # - https://github.com/decidim/decidim/issues/8596
8
- # - https://github.com/decidim/decidim/pull/10014
6
+ # See: https://github.com/decidim/decidim/pull/10014
9
7
  # Related:
10
- # - https://github.com/w3c/css-validator/issues/355
11
8
  # - https://github.com/rails/rails/issues/46405
12
9
  # - https://github.com/foundation/foundation-sites/pull/12496
13
10
  module W3CValidators
@@ -22,7 +19,6 @@ module W3CValidators
22
19
 
23
20
  def ignore_errors
24
21
  @ignore_errors ||= [
25
- "CSS: “--content-height”: One operand must be a number.",
26
22
  "An “input” element with a “type” attribute whose value is “hidden” must not have an “autocomplete” attribute whose value is “on” or “off”.",
27
23
  "An “input” element with a “type” attribute whose value is “hidden” must not have any “aria-*” attributes."
28
24
  ]
@@ -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.27.4"
7
+ "0.28.0.rc5"
8
8
  end
9
9
  end
10
10
  end
data/lib/decidim/dev.rb CHANGED
@@ -2,13 +2,35 @@
2
2
 
3
3
  require "decidim/dev/railtie"
4
4
 
5
+ require "decidim/dev/admin"
6
+ require "decidim/dev/engine"
7
+ require "decidim/dev/admin_engine"
8
+ # We shall not load the component here, as it will complain there is no method register_component
9
+ # for Decidim module. To fix that we need to require 'decidim/core', which will cause a major
10
+ # performance setback, as this file is usually the first request in "spec_helpers".
11
+ # We load dev component by requiring it later in the stack within lib/decidim/dev/test/base_spec_helper,
12
+ # right after decidim/core is required
13
+ # This comment and the below line is added to preserve consistency across all modules supplied.
14
+ # Also, to avoid further headaches :)
15
+ # require "decidim/dev/component"
16
+
5
17
  module Decidim
6
18
  # Decidim::Dev holds all the convenience logic and libraries to be able to
7
19
  # create external libraries that create test apps and test themselves against
8
20
  # them.
9
21
  module Dev
22
+ include ActiveSupport::Configurable
10
23
  autoload :DummyTranslator, "decidim/dev/dummy_translator"
11
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
+
12
34
  # Public: Finds an asset.
13
35
  #
14
36
  # Returns a String with the path for a particular asset.
data/lib/decidim-dev.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "decidim/dev/engine" if Rails.env.development? || ENV.fetch("DECIDIM_DEV_ENGINE", nil)
3
+ require "decidim/dev"