decidim-toggle 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/.erb-lint.yml +2134 -0
  3. data/.github/workflows/website.yml +57 -0
  4. data/.gitignore +13 -0
  5. data/.gitlab-ci.yml +165 -0
  6. data/.node-version +1 -0
  7. data/.rspec +1 -0
  8. data/.rubocop.yml +2 -0
  9. data/.ruby-version +1 -0
  10. data/.simplecov +18 -0
  11. data/CONTRIBUTING.md +17 -0
  12. data/Gemfile +33 -0
  13. data/Gemfile.lock +843 -0
  14. data/LICENSE.md +661 -0
  15. data/README.md +90 -0
  16. data/Rakefile +38 -0
  17. data/app/commands/decidim/toggle/update_authorizations_command.rb +31 -0
  18. data/app/commands/decidim/toggle/update_emails_command.rb +30 -0
  19. data/app/commands/decidim/toggle/update_file_upload_settings_command.rb +31 -0
  20. data/app/commands/decidim/toggle/update_locale_command.rb +47 -0
  21. data/app/commands/decidim/toggle/update_module_config_command.rb +31 -0
  22. data/app/commands/decidim/toggle/update_name_command.rb +31 -0
  23. data/app/commands/decidim/toggle/update_omniauth_command.rb +30 -0
  24. data/app/commands/decidim/toggle/update_security_command.rb +31 -0
  25. data/app/controllers/decidim_toggle/system/settings_tab_controller.rb +64 -0
  26. data/app/forms/decidim/toggle/update_authorizations_form.rb +54 -0
  27. data/app/forms/decidim/toggle/update_emails_form.rb +28 -0
  28. data/app/forms/decidim/toggle/update_file_upload_settings_form.rb +26 -0
  29. data/app/forms/decidim/toggle/update_locale_form.rb +116 -0
  30. data/app/forms/decidim/toggle/update_name_form.rb +63 -0
  31. data/app/forms/decidim/toggle/update_omniauth_form.rb +37 -0
  32. data/app/forms/decidim/toggle/update_security_form.rb +65 -0
  33. data/app/helpers/decidim/toggle/javascript_config_helper.rb +11 -0
  34. data/app/helpers/decidim/toggle/system_settings_tab_helper.rb +59 -0
  35. data/app/models/decidim/toggle/organization_module_config.rb +15 -0
  36. data/app/overrides/add_toggle_javascript_admin.rb +11 -0
  37. data/app/overrides/add_toggle_javascript_public.rb +11 -0
  38. data/app/packs/entrypoints/decidim_toggle.js +3 -0
  39. data/app/packs/src/decidim/toggle/organization_settings_tabs.js +114 -0
  40. data/app/packs/stylesheets/decidim/toggle/organization_settings.scss +160 -0
  41. data/app/views/decidim/system/organizations/edit.html.erb +20 -0
  42. data/app/views/decidim_toggle/system/organizations/_default_form_tab.html.erb +5 -0
  43. data/app/views/decidim_toggle/system/organizations/_encryption_not_configured_callout.html.erb +6 -0
  44. data/app/views/decidim_toggle/system/organizations/_settings_tab_active_tab_field.html.erb +1 -0
  45. data/app/views/decidim_toggle/system/organizations/_settings_tab_submit.html.erb +4 -0
  46. data/app/views/decidim_toggle/system/organizations/_settings_tabs.html.erb +31 -0
  47. data/app/views/decidim_toggle/system/organizations/tabs/_authorizations_tab.html.erb +9 -0
  48. data/app/views/decidim_toggle/system/organizations/tabs/_emails_tab.html.erb +5 -0
  49. data/app/views/decidim_toggle/system/organizations/tabs/_file_upload_tab.html.erb +5 -0
  50. data/app/views/decidim_toggle/system/organizations/tabs/_language_tab.html.erb +35 -0
  51. data/app/views/decidim_toggle/system/organizations/tabs/_omniauth_tab.html.erb +5 -0
  52. data/app/views/decidim_toggle/system/organizations/tabs/_security_tab.html.erb +20 -0
  53. data/app/views/layouts/decidim/toggle/_javascript_config.html.erb +3 -0
  54. data/bin/check +10 -0
  55. data/bin/i18n-tasks +27 -0
  56. data/bin/postversion +14 -0
  57. data/config/assets.rb +8 -0
  58. data/config/locales/decidim_toggle_en.yml +58 -0
  59. data/crowdin.yml +15 -0
  60. data/db/migrate/20260321120000_create_decidim_toggle_organization_module_configs.rb +20 -0
  61. data/decidim-toggle.gemspec +35 -0
  62. data/docker-compose.yml +41 -0
  63. data/lib/decidim/toggle/engine.rb +62 -0
  64. data/lib/decidim/toggle/expose_attributes_to_js.rb +26 -0
  65. data/lib/decidim/toggle/expose_attributes_to_js_validator.rb +32 -0
  66. data/lib/decidim/toggle/gem_registry.rb +15 -0
  67. data/lib/decidim/toggle/informative_callouts.rb +76 -0
  68. data/lib/decidim/toggle/javascript_config.rb +87 -0
  69. data/lib/decidim/toggle/module_config.rb +64 -0
  70. data/lib/decidim/toggle/module_config_form.rb +41 -0
  71. data/lib/decidim/toggle/module_config_i18n.rb +44 -0
  72. data/lib/decidim/toggle/module_configuration_presenter.rb +55 -0
  73. data/lib/decidim/toggle/organization_settings_tabs.rb +69 -0
  74. data/lib/decidim/toggle/settings_form_builder.rb +200 -0
  75. data/lib/decidim/toggle/settings_tab_item.rb +37 -0
  76. data/lib/decidim/toggle/settings_tab_registry.rb +109 -0
  77. data/lib/decidim/toggle/settings_tabs.rb +56 -0
  78. data/lib/decidim/toggle/tab_form.rb +20 -0
  79. data/lib/decidim/toggle/version.rb +14 -0
  80. data/lib/decidim/toggle.rb +36 -0
  81. data/lib/tasks/decidim/toggle/toggle_upgrade.rake +13 -0
  82. data/lib/tasks/decidim/toggle/toggle_webpacker.rake +60 -0
  83. data/log/.gitignore +2 -0
  84. data/package.json +18 -0
  85. data/prettier.config.js +15 -0
  86. data/spec/commands/decidim/toggle/update_authorizations_command_spec.rb +41 -0
  87. data/spec/commands/decidim/toggle/update_emails_command_spec.rb +84 -0
  88. data/spec/commands/decidim/toggle/update_file_upload_settings_command_spec.rb +28 -0
  89. data/spec/commands/decidim/toggle/update_locale_command_spec.rb +53 -0
  90. data/spec/commands/decidim/toggle/update_module_config_command_spec.rb +38 -0
  91. data/spec/commands/decidim/toggle/update_name_command_spec.rb +49 -0
  92. data/spec/commands/decidim/toggle/update_omniauth_command_spec.rb +80 -0
  93. data/spec/commands/decidim/toggle/update_security_command_spec.rb +25 -0
  94. data/spec/decidim/toggle/settings_tab_item_spec.rb +34 -0
  95. data/spec/decidim/toggle/settings_tab_registry_spec.rb +66 -0
  96. data/spec/decidim/toggle/settings_tabs_spec.rb +60 -0
  97. data/spec/forms/concerns/decidim/toggle/informative_callouts_spec.rb +48 -0
  98. data/spec/forms/decidim/toggle/update_authorizations_form_spec.rb +40 -0
  99. data/spec/forms/decidim/toggle/update_emails_form_spec.rb +35 -0
  100. data/spec/forms/decidim/toggle/update_file_upload_settings_form_spec.rb +20 -0
  101. data/spec/forms/decidim/toggle/update_locale_form_spec.rb +64 -0
  102. data/spec/forms/decidim/toggle/update_name_form_spec.rb +57 -0
  103. data/spec/forms/decidim/toggle/update_omniauth_form_spec.rb +56 -0
  104. data/spec/forms/decidim/toggle/update_security_form_spec.rb +32 -0
  105. data/spec/helpers/decidim/toggle/system_settings_tab_helper_spec.rb +99 -0
  106. data/spec/lib/decidim/toggle/expose_attributes_to_js_spec.rb +31 -0
  107. data/spec/lib/decidim/toggle/expose_attributes_to_js_validator_spec.rb +30 -0
  108. data/spec/lib/decidim/toggle/gem_registry_spec.rb +30 -0
  109. data/spec/lib/decidim/toggle/javascript_config_spec.rb +169 -0
  110. data/spec/lib/decidim/toggle/module_config_form_spec.rb +45 -0
  111. data/spec/lib/decidim/toggle/module_config_spec.rb +74 -0
  112. data/spec/lib/decidim/toggle/module_configuration_presenter_spec.rb +53 -0
  113. data/spec/lib/decidim/toggle/settings_form_builder_spec.rb +115 -0
  114. data/spec/requests/decidim_toggle/system/settings_tab_spec.rb +144 -0
  115. data/spec/spec_helper.rb +12 -0
  116. data/spec/support/decidim_factories.rb +3 -0
  117. data/spec/support/devise.rb +5 -0
  118. data/spec/system/decidim_toggle/javascript_config_spec.rb +56 -0
  119. data/website/.gitignore +4 -0
  120. data/website/docs/developer/_category_.json +8 -0
  121. data/website/docs/developer/code-of-conduct.md +99 -0
  122. data/website/docs/developer/contribute.md +50 -0
  123. data/website/docs/developer/deface-usage.md +37 -0
  124. data/website/docs/developer/documentation.md +58 -0
  125. data/website/docs/developer/error-handling.md +51 -0
  126. data/website/docs/developer/tab-registry.md +51 -0
  127. data/website/docs/developer/view-customization.md +49 -0
  128. data/website/docs/index.md +80 -0
  129. data/website/docs/integrate/_category_.json +8 -0
  130. data/website/docs/integrate/attributes.md +121 -0
  131. data/website/docs/integrate/customize-views.md +62 -0
  132. data/website/docs/integrate/index.md +38 -0
  133. data/website/docs/integrate/informative_callout.md +80 -0
  134. data/website/docs/integrate/javascript.md +84 -0
  135. data/website/docs/integrate/labels.md +91 -0
  136. data/website/docs/integrate/quickstart.md +77 -0
  137. data/website/docusaurus.config.ts +100 -0
  138. data/website/package.json +31 -0
  139. data/website/sidebars.ts +7 -0
  140. data/website/src/css/custom.css +37 -0
  141. data/website/static/img/logo.svg +1 -0
  142. data/website/static/img/schema_overview.png +0 -0
  143. data/website/static/img/screenshot_informative_callouts.png +0 -0
  144. data/website/static/img/screenshot_saved_flash.png +0 -0
  145. data/website/static/img/screenshots_locale_tab.png +0 -0
  146. data/website/static/img/screenshots_name_tab.png +0 -0
  147. data/website/static/img/screenshots_security_tab.png +0 -0
  148. data/website/tsconfig.json +6 -0
  149. data/website/yarn.lock +8336 -0
  150. data/yarn.lock +13 -0
  151. metadata +249 -0
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Toggle
5
+ # Recommended base for organization settings tab forms.
6
+ #
7
+ # class MyModule::AdminConfigForm < Decidim::Form
8
+ # include Decidim::Toggle::TabForm
9
+ # include Decidim::Toggle::ModuleConfigForm
10
+ # ...
11
+ # end
12
+ module TabForm
13
+ extend ActiveSupport::Concern
14
+
15
+ included do
16
+ include InformativeCallouts
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # This holds the decidim-toggle version.
5
+ module Toggle
6
+ def self.version
7
+ "0.1.3" # DO NOT UPDATE MANUALLY
8
+ end
9
+
10
+ def self.decidim_version
11
+ [">= 0.29", "< 0.33"].freeze
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/toggle/version"
4
+ require "decidim/toggle/gem_registry"
5
+ require "decidim/toggle/settings_tab_registry"
6
+ require "decidim/toggle/settings_tab_item"
7
+ require "decidim/toggle/settings_tabs"
8
+ require "decidim/toggle/module_config"
9
+ require "decidim/toggle/informative_callouts"
10
+ require "decidim/toggle/module_config_i18n"
11
+ require "decidim/toggle/module_config_form"
12
+ require "decidim/toggle/tab_form"
13
+ require "decidim/toggle/expose_attributes_to_js"
14
+ require "decidim/toggle/javascript_config"
15
+ require "decidim/toggle/engine"
16
+
17
+ module Decidim
18
+ module Toggle
19
+ def self.settings_tabs(name, &)
20
+ SettingsTabRegistry.register(name, &)
21
+ end
22
+
23
+ # @param gem_name [String, Symbol] Bundler gem name (e.g. +"decidim-space_page"+)
24
+ # @return [Boolean]
25
+ def self.gem_present?(gem_name)
26
+ GemRegistry.present?(gem_name)
27
+ end
28
+
29
+ # @param organization [Decidim::Organization, nil]
30
+ # @param registry_name [Symbol] settings tab registry (default +:organization_settings+)
31
+ # @return [Hash{String => Object}] flat keys like +"decidim_geo.enabled"+
32
+ def self.javascript_config_for(organization, registry_name: :organization_settings)
33
+ JavascriptConfig.for(organization, registry_name:)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rake::Task["decidim:choose_target_plugins"].enhance do
4
+ name = Decidim::Toggle::Engine.railtie_name
5
+ ENV["FROM"] = "#{ENV.fetch("FROM", nil)},#{name}" unless ENV["FROM"].to_s.include?(name)
6
+ end
7
+
8
+ if Rake::Task.task_defined?("decidim:upgrade")
9
+ Rake::Task["decidim:upgrade"].enhance do
10
+ name = Decidim::Toggle::Engine.railtie_name
11
+ Rake::Task["#{name}:webpacker:install"].invoke if Rake::Task.task_defined?("#{name}:webpacker:install")
12
+ end
13
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/gem_manager"
4
+
5
+ namespace :decidim_toggle do
6
+ namespace :webpacker do
7
+ desc "Installs Toggle webpacker files in Rails instance application"
8
+ task install: :environment do
9
+ raise "Decidim gem is not installed" if decidim_path.nil?
10
+
11
+ install_toggle_npm
12
+ end
13
+
14
+ desc "Adds Toggle dependencies in package.json"
15
+ task upgrade: :environment do
16
+ raise "Decidim gem is not installed" if decidim_path.nil?
17
+
18
+ install_toggle_npm
19
+ end
20
+
21
+ def install_toggle_npm
22
+ return if toggle_npm_dependencies.empty?
23
+
24
+ puts "install NPM packages. You can also do this manually with this command:"
25
+ puts "npm i #{toggle_npm_dependencies.join(" ")}"
26
+ toggle_system! "npm i #{toggle_npm_dependencies.join(" ")}"
27
+ end
28
+
29
+ def toggle_npm_dependencies
30
+ @toggle_npm_dependencies ||=
31
+ if toggle_path.nil? || !File.exist?(toggle_path.join("package.json"))
32
+ []
33
+ else
34
+ package_json = JSON.parse(File.read(toggle_path.join("package.json")))
35
+
36
+ (package_json["dependencies"] || {}).map { |package, version| "#{package}@#{version}" }
37
+ end
38
+ end
39
+
40
+ def toggle_path
41
+ @toggle_path ||= Pathname.new(toggle_gemspec.full_gem_path) if Gem.loaded_specs.has_key?(toggle_gem_name)
42
+ end
43
+
44
+ def rails_app_path
45
+ @rails_app_path ||= Rails.root
46
+ end
47
+
48
+ def toggle_system!(command)
49
+ system("cd #{rails_app_path} && #{command}") || abort("\n== Command #{command} failed ==")
50
+ end
51
+
52
+ def toggle_gemspec
53
+ @toggle_gemspec ||= Gem.loaded_specs[toggle_gem_name]
54
+ end
55
+
56
+ def toggle_gem_name
57
+ "decidim-toggle"
58
+ end
59
+ end
60
+ end
data/log/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *
2
+ !.gitignore
data/package.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "decidim-toggle",
3
+ "private": true,
4
+ "version": "0.1.3",
5
+ "description": "Decidim system settings tabbed UI",
6
+ "devDependencies": {
7
+ "@decidim/prettier-config": "0.29",
8
+ "prettier": "^2.3.2"
9
+ },
10
+ "scripts": {
11
+ "format": "prettier --write \"./app/packs/**/*.{js,scss,css}\" --no-error-on-unmatched-pattern",
12
+ "format:check": "prettier --check \"./app/packs/**/*.{js,scss,css}\" --no-error-on-unmatched-pattern",
13
+ "postversion": "bash bin/postversion",
14
+ "test": "echo \"Error: no test specified\" && exit 1"
15
+ },
16
+ "license": "AGPL-3.0-or-later",
17
+ "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
18
+ }
@@ -0,0 +1,15 @@
1
+ const decidimPrettier = require("@decidim/prettier-config");
2
+
3
+ module.exports = {
4
+ ...decidimPrettier,
5
+ overrides: [
6
+ ...(decidimPrettier.overrides || []),
7
+ {
8
+ files: "*.scss",
9
+ options: {
10
+ parser: "scss",
11
+ singleQuote: false
12
+ }
13
+ }
14
+ ]
15
+ };
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Toggle
7
+ describe UpdateAuthorizationsCommand do
8
+ let(:organization) { create(:organization, available_authorizations: []) }
9
+
10
+ it "updates available_authorizations when form is valid" do
11
+ form = UpdateAuthorizationsForm.from_params(
12
+ organization: { available_authorizations: %w(dummy_authorization_handler) }
13
+ ).with_context(current_organization: organization)
14
+
15
+ outcomes = []
16
+ cmd = described_class.new(organization, form)
17
+ cmd.on(:ok) { outcomes << :ok }
18
+ cmd.on(:invalid) { outcomes << :invalid }
19
+ cmd.call
20
+
21
+ expect(outcomes).to eq([:ok])
22
+ expect(organization.reload.available_authorizations).to eq(%w(dummy_authorization_handler))
23
+ end
24
+
25
+ it "broadcasts invalid when form is invalid" do
26
+ form = UpdateAuthorizationsForm.from_params(
27
+ organization: { available_authorizations: %w(not_a_real_workflow) }
28
+ ).with_context(current_organization: organization)
29
+
30
+ outcomes = []
31
+ cmd = described_class.new(organization, form)
32
+ cmd.on(:ok) { outcomes << :ok }
33
+ cmd.on(:invalid) { outcomes << :invalid }
34
+ cmd.call
35
+
36
+ expect(outcomes).to eq([:invalid])
37
+ expect(organization.reload.available_authorizations).to eq([])
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Toggle
7
+ describe UpdateEmailsCommand do
8
+ let(:organization) do
9
+ Struct.new(:smtp_settings) do
10
+ def save!
11
+ @saved = true
12
+ end
13
+
14
+ def saved?
15
+ !!@saved
16
+ end
17
+ end.new
18
+ end
19
+
20
+ it "updates smtp_settings when form is valid" do
21
+ form = instance_double(UpdateEmailsForm, invalid?: false, encrypted_smtp_settings: { "host" => "smtp.example" })
22
+
23
+ outcomes = []
24
+ expect(Decidim::OrganizationSettings).to receive(:reload).with(organization)
25
+
26
+ cmd = described_class.new(organization, form)
27
+ cmd.on(:ok) { outcomes << :ok }
28
+ cmd.on(:invalid) { outcomes << :invalid }
29
+
30
+ cmd.call
31
+
32
+ expect(outcomes).to eq([:ok])
33
+ expect(organization.smtp_settings).to eq({ "host" => "smtp.example" })
34
+ expect(organization).to be_saved
35
+ end
36
+
37
+ it "broadcasts invalid when the form is invalid" do
38
+ form = instance_double(UpdateEmailsForm, invalid?: true)
39
+
40
+ outcomes = []
41
+ expect(organization).not_to receive(:save!)
42
+ cmd = described_class.new(organization, form)
43
+ cmd.on(:ok) { outcomes << :ok }
44
+ cmd.on(:invalid) { outcomes << :invalid }
45
+
46
+ cmd.call
47
+
48
+ expect(outcomes).to eq([:invalid])
49
+ expect(organization.smtp_settings).to be_nil
50
+ end
51
+
52
+ it "broadcasts invalid when saving fails" do
53
+ errors = double("errors", full_messages: [])
54
+ invalid_record_class = Class.new do
55
+ def initialize(record_errors)
56
+ @errors = record_errors
57
+ end
58
+
59
+ def errors
60
+ @errors
61
+ end
62
+
63
+ def self.i18n_scope
64
+ "fake_scope"
65
+ end
66
+ end
67
+
68
+ invalid_record = invalid_record_class.new(errors)
69
+ allow(organization).to receive(:save!).and_raise(ActiveRecord::RecordInvalid.new(invalid_record))
70
+
71
+ form = instance_double(UpdateEmailsForm, invalid?: false, encrypted_smtp_settings: { "host" => "smtp.example" })
72
+
73
+ outcomes = []
74
+ cmd = described_class.new(organization, form)
75
+ cmd.on(:ok) { outcomes << :ok }
76
+ cmd.on(:invalid) { outcomes << :invalid }
77
+
78
+ cmd.call
79
+
80
+ expect(outcomes).to eq([:invalid])
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Toggle
7
+ describe UpdateFileUploadSettingsCommand do
8
+ let(:organization) { create(:organization) }
9
+
10
+ it "updates file_upload_settings when form is valid" do
11
+ form = UpdateFileUploadSettingsForm.from_model(organization)
12
+ form.file_upload_settings.maximum_file_size = {
13
+ default: 5.0,
14
+ avatar: 2.0
15
+ }
16
+
17
+ outcomes = []
18
+ cmd = described_class.new(organization, form)
19
+ cmd.on(:ok) { outcomes << :ok }
20
+ cmd.on(:invalid) { outcomes << :invalid }
21
+ cmd.call
22
+ expect(outcomes).to eq([:ok])
23
+ expect(organization.reload.file_upload_settings["maximum_file_size"]["default"]).to eq(5.0)
24
+ expect(organization.file_upload_settings["maximum_file_size"]["avatar"]).to eq(2.0)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Toggle
7
+ describe UpdateLocaleCommand do
8
+ let(:organization) { create(:organization) }
9
+ let(:rebuild_search_task) { instance_double(Rake::Task, invoke: nil, reenable: nil) }
10
+
11
+ before do
12
+ allow(Rails.application).to receive(:load_tasks)
13
+ allow(Rake::Task).to receive(:[]).and_call_original
14
+ allow(Rake::Task).to receive(:[]).with("decidim:locales:rebuild_search").and_return(rebuild_search_task)
15
+ end
16
+
17
+ it "updates locales and rebuilds search index" do
18
+ organization.update!(available_locales: %w(en ca), default_locale: "ca")
19
+
20
+ expect(Rails.application).to receive(:load_tasks).ordered
21
+ expect(rebuild_search_task).to receive(:reenable).ordered
22
+ expect(rebuild_search_task).to receive(:invoke).ordered
23
+
24
+ form = UpdateLocaleForm.from_params(
25
+ organization: { available_locales: { "en" => "1" }, default_locale: "en" }
26
+ ).with_context(current_organization: organization)
27
+
28
+ outcomes = []
29
+ cmd = described_class.new(organization, form)
30
+ cmd.on(:ok) { outcomes << :ok }
31
+ cmd.on(:invalid) { outcomes << :invalid }
32
+ cmd.call
33
+ expect(outcomes).to eq([:ok])
34
+ organization.reload
35
+ expect(organization.available_locales).to eq(%w(en))
36
+ expect(organization.default_locale).to eq("en")
37
+ end
38
+
39
+ it "broadcasts invalid when form is invalid" do
40
+ form = UpdateLocaleForm.from_model(organization)
41
+ form.available_locales = []
42
+ form.default_locale = ""
43
+
44
+ outcomes = []
45
+ cmd = described_class.new(organization, form)
46
+ cmd.on(:ok) { outcomes << :ok }
47
+ cmd.on(:invalid) { outcomes << :invalid }
48
+ cmd.call
49
+ expect(outcomes).to eq([:invalid])
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Toggle
7
+ describe UpdateModuleConfigCommand do
8
+ let(:organization) { create(:organization) }
9
+
10
+ let(:form_class) do
11
+ Class.new(Decidim::Form) do
12
+ include Decidim::Toggle::ModuleConfigForm
13
+
14
+ self.module_config_name = "decidim_geo"
15
+
16
+ mimic :organization
17
+ attribute :enabled, :boolean
18
+ end
19
+ end
20
+
21
+ describe "#call" do
22
+ it "broadcasts :ok and persists config" do
23
+ form = form_class.from_params(organization: { enabled: true }).with_context(current_organization: organization)
24
+
25
+ outcomes = []
26
+ cmd = described_class.new(organization, form)
27
+ cmd.on(:ok) { outcomes << :ok }
28
+ cmd.on(:invalid) { outcomes << :invalid }
29
+ cmd.call
30
+
31
+ expect(outcomes).to eq([:ok])
32
+ row = OrganizationModuleConfig.find_by!(decidim_organization_id: organization.id, module_name: "decidim_geo")
33
+ expect(row.config["enabled"]).to be(true)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Toggle
7
+ describe UpdateNameCommand do
8
+ let(:organization) { create(:organization) }
9
+
10
+ it "updates organization when form is valid" do
11
+ form = UpdateNameForm.from_params(
12
+ organization: {
13
+ name_en: "New org name",
14
+ host: "newhost.example.org",
15
+ secondary_hosts: "alias.example.org"
16
+ }
17
+ ).with_context(current_organization: organization)
18
+
19
+ outcomes = []
20
+ cmd = described_class.new(organization, form)
21
+ cmd.on(:ok) { outcomes << :ok }
22
+ cmd.on(:invalid) { outcomes << :invalid }
23
+ cmd.call
24
+ expect(outcomes).to eq([:ok])
25
+ organization.reload
26
+ expect(organization.name["en"]).to eq("New org name")
27
+ expect(organization.host).to eq("newhost.example.org")
28
+ expect(organization.secondary_hosts).to eq(["alias.example.org"])
29
+ end
30
+
31
+ it "broadcasts invalid when form is invalid" do
32
+ form = UpdateNameForm.from_params(
33
+ organization: {
34
+ name_en: "",
35
+ host: "",
36
+ secondary_hosts: ""
37
+ }
38
+ ).with_context(current_organization: organization)
39
+
40
+ outcomes = []
41
+ cmd = described_class.new(organization, form)
42
+ cmd.on(:ok) { outcomes << :ok }
43
+ cmd.on(:invalid) { outcomes << :invalid }
44
+ cmd.call
45
+ expect(outcomes).to eq([:invalid])
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Toggle
7
+ describe UpdateOmniauthCommand do
8
+ let(:organization) do
9
+ Struct.new(:omniauth_settings) do
10
+ def save!
11
+ @saved = true
12
+ end
13
+
14
+ def saved?
15
+ !!@saved
16
+ end
17
+ end.new
18
+ end
19
+
20
+ it "updates omniauth_settings when form is valid" do
21
+ form = instance_double(UpdateOmniauthForm, invalid?: false, encrypted_omniauth_settings: { "foo" => "bar" })
22
+
23
+ outcomes = []
24
+ expect(Decidim::OrganizationSettings).to receive(:reload).with(organization)
25
+
26
+ cmd = described_class.new(organization, form)
27
+ cmd.on(:ok) { outcomes << :ok }
28
+ cmd.on(:invalid) { outcomes << :invalid }
29
+ cmd.call
30
+
31
+ expect(outcomes).to eq([:ok])
32
+ expect(organization.omniauth_settings).to eq({ "foo" => "bar" })
33
+ expect(organization).to be_saved
34
+ end
35
+
36
+ it "broadcasts invalid when the form is invalid" do
37
+ form = instance_double(UpdateOmniauthForm, invalid?: true)
38
+
39
+ outcomes = []
40
+ expect(organization).not_to receive(:save!)
41
+ cmd = described_class.new(organization, form)
42
+ cmd.on(:ok) { outcomes << :ok }
43
+ cmd.on(:invalid) { outcomes << :invalid }
44
+ cmd.call
45
+
46
+ expect(outcomes).to eq([:invalid])
47
+ end
48
+
49
+ it "broadcasts invalid when saving fails" do
50
+ errors = double("errors", full_messages: [])
51
+ invalid_record_class = Class.new do
52
+ def initialize(record_errors)
53
+ @errors = record_errors
54
+ end
55
+
56
+ def errors
57
+ @errors
58
+ end
59
+
60
+ def self.i18n_scope
61
+ "fake_scope"
62
+ end
63
+ end
64
+
65
+ invalid_record = invalid_record_class.new(errors)
66
+ allow(organization).to receive(:save!).and_raise(ActiveRecord::RecordInvalid.new(invalid_record))
67
+
68
+ form = instance_double(UpdateOmniauthForm, invalid?: false, encrypted_omniauth_settings: { "foo" => "bar" })
69
+
70
+ outcomes = []
71
+ cmd = described_class.new(organization, form)
72
+ cmd.on(:ok) { outcomes << :ok }
73
+ cmd.on(:invalid) { outcomes << :invalid }
74
+ cmd.call
75
+
76
+ expect(outcomes).to eq([:invalid])
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Toggle
7
+ describe UpdateSecurityCommand do
8
+ let(:organization) { create(:organization) }
9
+
10
+ it "updates security fields when form is valid" do
11
+ form = UpdateSecurityForm.from_model(organization)
12
+ form.force_users_to_authenticate_before_access_organization = true
13
+ form.users_registration_mode = "enabled"
14
+
15
+ outcomes = []
16
+ cmd = described_class.new(organization, form)
17
+ cmd.on(:ok) { outcomes << :ok }
18
+ cmd.on(:invalid) { outcomes << :invalid }
19
+ cmd.call
20
+ expect(outcomes).to eq([:ok])
21
+ expect(organization.reload.force_users_to_authenticate_before_access_organization).to be true
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ module Decidim
6
+ module Toggle
7
+ describe SettingsTabItem do
8
+ it "detects form tabs" do
9
+ form = described_class.new(:f, "L", form_class: String, command_class: Integer)
10
+ expect(form).to be_form_tab
11
+ end
12
+
13
+ it "respects open? and visible?" do
14
+ open = described_class.new(:a, "A", open: true, if: true)
15
+ hidden = described_class.new(:b, "B", if: false)
16
+ expect(open).to be_open
17
+ expect(open).to be_visible
18
+ expect(hidden).not_to be_visible
19
+ end
20
+
21
+ it "allows form tab with form_layout_partial" do
22
+ item = described_class.new(
23
+ :lang,
24
+ "L",
25
+ form_class: String,
26
+ command_class: Integer,
27
+ form_layout_partial: "decidim_toggle/system/organizations/tabs/language_tab"
28
+ )
29
+ expect(item).to be_form_tab
30
+ expect(item.form_layout_partial).to include("language_tab")
31
+ end
32
+ end
33
+ end
34
+ end