solidus_core 3.1.6 → 3.2.0

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/spree/products_helper.rb +1 -1
  3. data/app/models/concerns/spree/active_storage_adapter/attachment.rb +23 -10
  4. data/app/models/concerns/spree/active_storage_adapter.rb +1 -1
  5. data/app/models/concerns/spree/user_address_book.rb +11 -1
  6. data/app/models/concerns/spree/user_methods.rb +20 -1
  7. data/app/models/spree/adjustment.rb +1 -0
  8. data/app/models/spree/carton.rb +1 -1
  9. data/app/models/spree/log_entry.rb +74 -1
  10. data/app/models/spree/option_value.rb +9 -0
  11. data/app/models/spree/order.rb +68 -29
  12. data/app/models/spree/order_contents.rb +2 -1
  13. data/app/models/spree/order_inventory.rb +1 -1
  14. data/app/models/spree/order_merger.rb +2 -2
  15. data/app/models/spree/order_taxation.rb +6 -4
  16. data/app/models/spree/order_updater.rb +4 -3
  17. data/app/models/spree/payment_method.rb +11 -0
  18. data/app/models/spree/price.rb +1 -1
  19. data/app/models/spree/product/scopes.rb +21 -3
  20. data/app/models/spree/product.rb +1 -1
  21. data/app/models/spree/promotion/actions/create_adjustment.rb +4 -0
  22. data/app/models/spree/promotion/actions/create_item_adjustments.rb +5 -6
  23. data/app/models/spree/promotion/rules/product.rb +20 -8
  24. data/app/models/spree/promotion/rules/store.rb +4 -0
  25. data/app/models/spree/promotion/rules/taxon.rb +4 -0
  26. data/app/models/spree/promotion/rules/user.rb +4 -0
  27. data/app/models/spree/promotion.rb +34 -23
  28. data/app/models/spree/promotion_action.rb +4 -0
  29. data/app/models/spree/promotion_code.rb +8 -4
  30. data/app/models/spree/promotion_handler/cart.rb +26 -6
  31. data/app/models/spree/promotion_rule.rb +5 -0
  32. data/app/models/spree/reimbursement.rb +2 -2
  33. data/app/models/spree/return_item.rb +1 -2
  34. data/app/models/spree/stock/allocator/on_hand_first.rb +2 -2
  35. data/app/models/spree/stock/quantifier.rb +12 -8
  36. data/app/models/spree/stock/simple_coordinator.rb +2 -1
  37. data/app/models/spree/tax/item_tax.rb +3 -2
  38. data/app/models/spree/tax/order_tax.rb +3 -1
  39. data/app/models/spree/tax/tax_location.rb +4 -7
  40. data/app/models/spree/tax_rate.rb +2 -0
  41. data/app/models/spree/variant.rb +1 -1
  42. data/app/subscribers/spree/mailer_subscriber.rb +4 -0
  43. data/app/subscribers/spree/order_mailer_subscriber.rb +35 -0
  44. data/config/i18n-tasks.yml +134 -0
  45. data/config/locales/en.yml +391 -257
  46. data/db/migrate/20201127212108_add_type_before_removal_to_spree_payment_methods.rb +7 -0
  47. data/db/migrate/20220317165036_set_promotions_with_any_policy_to_all_if_possible.rb +20 -0
  48. data/lib/generators/solidus/install/install_generator/bundler_context.rb +97 -0
  49. data/lib/generators/solidus/install/install_generator/install_frontend.rb +53 -0
  50. data/lib/generators/solidus/install/install_generator/support_solidus_frontend_extraction.rb +48 -0
  51. data/lib/generators/solidus/install/install_generator.rb +58 -50
  52. data/lib/generators/solidus/install/templates/config/initializers/spree.rb.tt +6 -16
  53. data/lib/generators/solidus/install/templates/vendor/assets/javascripts/spree/backend/all.js +2 -2
  54. data/lib/spree/app_configuration.rb +43 -0
  55. data/lib/spree/bus.rb +20 -0
  56. data/lib/spree/core/controller_helpers/auth.rb +9 -1
  57. data/lib/spree/core/controller_helpers/current_host.rb +1 -3
  58. data/lib/spree/core/controller_helpers/order.rb +10 -10
  59. data/lib/spree/core/controller_helpers/search.rb +1 -1
  60. data/lib/spree/core/engine.rb +39 -8
  61. data/lib/spree/core/state_machines/order.rb +1 -1
  62. data/lib/spree/core/stock_configuration.rb +18 -0
  63. data/lib/spree/core/validators/email.rb +3 -1
  64. data/lib/spree/core/version.rb +2 -2
  65. data/lib/spree/core.rb +20 -0
  66. data/lib/spree/event/subscriber_registry.rb +4 -6
  67. data/lib/spree/event.rb +1 -1
  68. data/lib/spree/migrations.rb +1 -1
  69. data/lib/spree/permission_sets/default_customer.rb +8 -1
  70. data/lib/spree/permitted_attributes.rb +4 -4
  71. data/lib/spree/preferences/configuration.rb +34 -12
  72. data/lib/spree/preferences/preferable_class_methods.rb +1 -1
  73. data/lib/spree/preferences/preference_differentiator.rb +2 -1
  74. data/lib/spree/preferences/static_model_preferences.rb +0 -2
  75. data/lib/spree/rails_compatibility.rb +99 -0
  76. data/lib/spree/testing_support/bus_helpers.rb +101 -0
  77. data/lib/spree/testing_support/common_rake.rb +47 -19
  78. data/lib/spree/testing_support/dummy_app/assets/javascripts/spree/backend/all.js +1 -1
  79. data/lib/spree/testing_support/dummy_app/assets/javascripts/spree/frontend/all.js +1 -1
  80. data/lib/spree/testing_support/dummy_app.rb +6 -2
  81. data/lib/spree/testing_support/factories/address_factory.rb +7 -2
  82. data/lib/spree/testing_support/factories/inventory_unit_factory.rb +1 -1
  83. data/lib/spree/testing_support/factories/order_factory.rb +8 -4
  84. data/lib/spree/testing_support/factories/product_factory.rb +4 -1
  85. data/lib/spree/testing_support/factories/store_credit_factory.rb +4 -4
  86. data/lib/spree/testing_support/factories/user_factory.rb +6 -0
  87. data/lib/spree/testing_support/factory_bot.rb +1 -1
  88. data/lib/spree/testing_support/order_walkthrough.rb +5 -4
  89. data/lib/spree/testing_support/silence_deprecations.rb +9 -0
  90. data/lib/tasks/payment_method.rake +29 -0
  91. data/lib/tasks/solidus/delete_prices_with_nil_amount.rake +2 -2
  92. data/lib/tasks/solidus/split_promotions_with_any_match_policy.rake +33 -0
  93. data/solidus_core.gemspec +7 -2
  94. metadata +90 -24
  95. data/lib/generators/solidus/install/templates/vendor/assets/javascripts/spree/frontend/all.js +0 -10
  96. data/lib/generators/solidus/install/templates/vendor/assets/stylesheets/spree/frontend/all.css +0 -9
@@ -15,6 +15,12 @@ module Spree
15
15
  generator.test_framework :rspec
16
16
  end
17
17
 
18
+ if ActiveRecord.respond_to?(:yaml_column_permitted_classes) || ActiveRecord::Base.respond_to?(:yaml_column_permitted_classes)
19
+ config.active_record.yaml_column_permitted_classes ||= []
20
+ config.active_record.yaml_column_permitted_classes |=
21
+ [Symbol, BigDecimal, ActiveSupport::HashWithIndifferentAccess]
22
+ end
23
+
18
24
  initializer "spree.environment", before: :load_config_initializers do |app|
19
25
  app.config.spree = Spree::Config.environment
20
26
  end
@@ -40,18 +46,33 @@ module Spree
40
46
  ]
41
47
  end
42
48
 
43
- initializer "spree.core.checking_migrations", before: :load_config_initializers do |_app|
49
+ initializer "spree.core.checking_migrations", after: :load_config_initializers do |_app|
44
50
  Migrations.new(config, engine_name).check
45
51
  end
46
52
 
47
- # Setup Event Subscribers
48
- initializer 'spree.core.initialize_subscribers' do |app|
49
- app.reloader.to_prepare do
50
- Spree::Event.activate_autoloadable_subscribers
51
- end
53
+ # Setup pub/sub
54
+ initializer 'spree.core.pub_sub' do |app|
55
+ if Spree::Config.use_legacy_events
56
+ app.reloader.to_prepare do
57
+ Spree::Event.activate_autoloadable_subscribers
58
+ end
59
+
60
+ app.reloader.before_class_unload do
61
+ Spree::Event.deactivate_all_subscribers
62
+ end
63
+ else
64
+ app.reloader.to_prepare do
65
+ Spree::Bus.clear
66
+
67
+ %i[
68
+ order_finalized
69
+ order_recalculated
70
+ reimbursement_reimbursed
71
+ reimbursement_errored
72
+ ].each { |event_name| Spree::Bus.register(event_name) }
52
73
 
53
- app.reloader.before_class_unload do
54
- Spree::Event.deactivate_all_subscribers
74
+ Spree::OrderMailerSubscriber.new.subscribe_to(Spree::Bus)
75
+ end
55
76
  end
56
77
  end
57
78
 
@@ -75,6 +96,16 @@ module Spree
75
96
  Spree::UsersController.protect_from_forgery with: :exception
76
97
  end
77
98
  end
99
+
100
+ config.after_initialize do
101
+ if Spree::Config.use_legacy_events && !ENV['CI']
102
+ Spree::Deprecation.warn <<~MSG
103
+ Your Solidus store is using the legacy event system. You're
104
+ encouraged to switch to the new event bus. After you're done, you
105
+ can remove the `use_legacy_events` setting from `spree.rb`.
106
+ MSG
107
+ end
108
+ end
78
109
  end
79
110
  end
80
111
  end
@@ -119,7 +119,7 @@ module Spree
119
119
  before_transition to: :complete, do: :process_payments_before_complete
120
120
  end
121
121
 
122
- after_transition to: :complete, do: :finalize!
122
+ after_transition to: :complete, do: :finalize
123
123
  after_transition to: :resumed, do: :after_resume
124
124
  after_transition to: :canceled, do: :after_cancel
125
125
 
@@ -8,6 +8,9 @@ module Spree
8
8
  attr_writer :location_filter_class
9
9
  attr_writer :location_sorter_class
10
10
  attr_writer :allocator_class
11
+ attr_writer :inventory_unit_builder_class
12
+ attr_writer :availability_validator_class
13
+ attr_writer :inventory_validator_class
11
14
 
12
15
  def coordinator_class
13
16
  @coordinator_class ||= '::Spree::Stock::SimpleCoordinator'
@@ -33,6 +36,21 @@ module Spree
33
36
  @allocator_class ||= '::Spree::Stock::Allocator::OnHandFirst'
34
37
  @allocator_class.constantize
35
38
  end
39
+
40
+ def inventory_unit_builder_class
41
+ @inventory_unit_builder_class ||= '::Spree::Stock::InventoryUnitBuilder'
42
+ @inventory_unit_builder_class.constantize
43
+ end
44
+
45
+ def availability_validator_class
46
+ @availability_validator_class ||= '::Spree::Stock::AvailabilityValidator'
47
+ @availability_validator_class.constantize
48
+ end
49
+
50
+ def inventory_validator_class
51
+ @inventory_validator_class ||= '::Spree::Stock::InventoryValidator'
52
+ @inventory_validator_class.constantize
53
+ end
36
54
  end
37
55
  end
38
56
  end
@@ -13,9 +13,11 @@ module Spree
13
13
  #
14
14
  class EmailValidator < ActiveModel::EachValidator
15
15
  EMAIL_REGEXP = URI::MailTo::EMAIL_REGEXP
16
+ # Use Spree::Config.default_email_regexp instead
17
+ deprecate_constant :EMAIL_REGEXP
16
18
 
17
19
  def validate_each(record, attribute, value)
18
- unless EMAIL_REGEXP.match? value
20
+ unless Spree::Config.default_email_regexp.match? value
19
21
  record.errors.add(attribute, :invalid, **{ value: value }.merge!(options))
20
22
  end
21
23
  end
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Spree
4
- VERSION = "3.1.6"
4
+ VERSION = "3.2.0"
5
5
 
6
6
  def self.solidus_version
7
7
  VERSION
8
8
  end
9
9
 
10
10
  def self.previous_solidus_minor_version
11
- '3.0'
11
+ '3.1'
12
12
  end
13
13
 
14
14
  def self.solidus_gem_version
data/lib/spree/core.rb CHANGED
@@ -21,6 +21,7 @@ require 'ransack'
21
21
  require 'state_machines-activerecord'
22
22
 
23
23
  require 'spree/deprecation'
24
+ require 'spree/rails_compatibility'
24
25
 
25
26
  # This is required because ActiveModel::Validations#invalid? conflicts with the
26
27
  # invalid state of a Payment. In the future this should be removed.
@@ -84,6 +85,24 @@ module Spree
84
85
  end
85
86
  end
86
87
 
88
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.7")
89
+ Spree::Deprecation.warn <<~HEREDOC
90
+ Ruby 2.5 & Ruby 2.6 (both EOL) are deprecated and will not be supported anymore from the next Solidus version.
91
+ Please, upgrade to a more recent Ruby version.
92
+ Read more on the release notes for different Ruby versions here:
93
+ https://www.ruby-lang.org/en/downloads/releases/
94
+ HEREDOC
95
+ end
96
+
97
+ if Gem::Version.new(Rails.version) < Gem::Version.new('6.0')
98
+ Spree::Deprecation.warn <<~HEREDOC
99
+ Rails 5.2 (EOL) is deprecated and will not be supported anymore from the next Solidus version.
100
+ Please, upgrade to a more recent Rails version.
101
+ Read more on upgrading from Rails 5.2 to Rails 6.0 here:
102
+ https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#upgrading-from-rails-5-2-to-rails-6-0
103
+ HEREDOC
104
+ end
105
+
87
106
  require 'spree/core/version'
88
107
 
89
108
  require 'spree/core/active_merchant_dependencies'
@@ -95,6 +114,7 @@ require 'spree/core/environment'
95
114
  require 'spree/migrations'
96
115
  require 'spree/migration_helpers'
97
116
  require 'spree/event'
117
+ require 'spree/bus'
98
118
  require 'spree/core/engine'
99
119
 
100
120
  require 'spree/i18n'
@@ -64,13 +64,11 @@ module Spree
64
64
  # Loading the files has the side effect of adding their module to the
65
65
  # list in Spree::Event.subscribers.
66
66
  def require_subscriber_files
67
- pattern = "app/subscribers/**/*_subscriber.rb"
67
+ require_dependency(
68
+ Spree::Core::Engine.root.join('app', 'subscribers', 'spree', 'mailer_subscriber.rb')
69
+ )
68
70
 
69
- # Load Solidus subscribers
70
- # rubocop:disable Rails/DynamicFindBy
71
- solidus_core_dir = Gem::Specification.find_by_name('solidus_core').gem_dir
72
- # rubocop:enable Rails/DynamicFindBy
73
- Dir.glob(File.join(solidus_core_dir, pattern)) { |c| require_dependency(c.to_s) }
71
+ pattern = "app/subscribers/**/*_subscriber.rb"
74
72
 
75
73
  # Load application subscribers, only when the flag is set to true:
76
74
  if Spree::Config.events.autoload_subscribers
data/lib/spree/event.rb CHANGED
@@ -21,7 +21,7 @@ module Spree
21
21
  #
22
22
  # @example Trigger an event named 'order_finalized'
23
23
  # Spree::Event.fire 'order_finalized', order: @order do
24
- # @order.finalize!
24
+ # @order.complete!
25
25
  # end
26
26
  def fire(event_name, opts = {})
27
27
  adapter.fire normalize_name(event_name), opts do
@@ -66,7 +66,7 @@ module Spree
66
66
  end
67
67
 
68
68
  def app_dir
69
- "#{Rails.root}/db/migrate"
69
+ Spree::Config.migration_path
70
70
  end
71
71
 
72
72
  def engine_dir
@@ -7,7 +7,14 @@ module Spree
7
7
  can :read, Country
8
8
  can :read, OptionType
9
9
  can :read, OptionValue
10
- can :create, Order
10
+ can :create, Order do |order, token|
11
+ # same user, or both nil
12
+ order.user == user ||
13
+ # guest checkout order
14
+ order.email.present? ||
15
+ # via API, just like with show and update
16
+ (order.guest_token.present? && token == order.guest_token)
17
+ end
11
18
  can [:show, :update], Order, Order.where(user: user) do |order, token|
12
19
  order.user == user || (order.guest_token.present? && token == order.guest_token)
13
20
  end
@@ -65,10 +65,10 @@ module Spree
65
65
 
66
66
  @@line_item_attributes = [:id, :variant_id, :quantity]
67
67
 
68
- @@option_type_attributes = [:name, :presentation, :option_values_attributes]
69
-
70
68
  @@option_value_attributes = [:name, :presentation]
71
69
 
70
+ @@option_type_attributes = [:name, :presentation, option_values_attributes: option_value_attributes]
71
+
72
72
  @@payment_attributes = [:amount, :payment_method_id, :payment_method]
73
73
 
74
74
  @@product_properties_attributes = [:property_name, :value, :position]
@@ -131,8 +131,8 @@ module Spree
131
131
  @@variant_attributes = [
132
132
  :name, :presentation, :cost_price, :lock_version,
133
133
  :position, :track_inventory,
134
- :product_id, :product, :option_values_attributes, :price,
135
- :weight, :height, :width, :depth, :sku, :cost_currency, option_value_ids: [], options: [:name, :value]
134
+ :product_id, :product, :price,
135
+ :weight, :height, :width, :depth, :sku, :cost_currency, :tax_category_id, option_value_ids: [], options: [:name, :value]
136
136
  ]
137
137
 
138
138
  @@checkout_address_attributes = [
@@ -38,6 +38,7 @@ module Spree::Preferences
38
38
  # defaults. Set via {#load_defaults}
39
39
  attr_reader :loaded_defaults
40
40
 
41
+ # @api private
41
42
  attr_reader :load_defaults_called
42
43
 
43
44
  def initialize
@@ -45,9 +46,9 @@ module Spree::Preferences
45
46
  @load_defaults_called = false
46
47
  end
47
48
 
48
- # @param [String] Solidus version from which take defaults when not
49
- # overriden.
50
- # @see #load_defaults
49
+ # @param [String] Solidus version from which take defaults when preferences
50
+ # are not overriden by the user.
51
+ # @see #loaded_defaults
51
52
  def load_defaults(version)
52
53
  @loaded_defaults = version
53
54
  @load_defaults_called = true
@@ -118,21 +119,35 @@ module Spree::Preferences
118
119
  end
119
120
  end
120
121
 
121
- # Generates a different preference default depending on {#version_defaults}
122
+ def self.inherited(klass)
123
+ klass.instance_variable_set(:@versioned_preferences, [])
124
+ class << klass
125
+ attr_reader :versioned_preferences
126
+ end
127
+ end
128
+
129
+ # Adds a preference with different default depending on {#loaded_defaults}
122
130
  #
123
- # This method is meant to be used in the `default:` keyword argument for
124
- # {.preference}. For instance, in the example, `foo`'s default was `true`
125
- # until version 3.0.0.alpha, when it became `false`:
131
+ # This method is a specialized version of {.preference} that generates a
132
+ # different default value for different Solidus versions. For instance, in
133
+ # the example, `foo`'s default was `true` until version 3.0.0.alpha, when it
134
+ # became `false`:
126
135
  #
127
136
  # @example
128
- # preference :foo, :boolean, default: by_version(true, "3.0.0.alpha" => false)
137
+ # versioned_preference :foo, :boolean, initial_value: true, boundaries: { "3.0.0.alpha" => false }
129
138
  #
139
+ # @see .preference
130
140
  # @see #loaded_defaults
131
141
  # @see Spree::Core::VersionedValue
132
- def self.by_version(*args)
133
- proc do |loaded_defaults|
134
- Spree::Core::VersionedValue.new(*args).call(loaded_defaults)
135
- end
142
+ def self.versioned_preference(name, type, initial_value:, boundaries:, **options)
143
+ @versioned_preferences << name
144
+ preference(
145
+ name,
146
+ type,
147
+ options.merge(
148
+ default: by_version(initial_value, boundaries)
149
+ )
150
+ )
136
151
  end
137
152
 
138
153
  def self.preference(name, type, options = {})
@@ -160,6 +175,13 @@ module Spree::Preferences
160
175
  end
161
176
  end
162
177
 
178
+ def self.by_version(*args)
179
+ proc do |loaded_defaults|
180
+ Spree::Core::VersionedValue.new(*args).call(loaded_defaults)
181
+ end
182
+ end
183
+ private_class_method :by_version
184
+
163
185
  private
164
186
 
165
187
  def context_for_default
@@ -49,7 +49,7 @@ module Spree::Preferences
49
49
 
50
50
  If you want to branch on the provided Solidus version, you can do like the following:
51
51
 
52
- preference :foo, :string, default: by_version(true, "3.2.0" => false)
52
+ versioned_preference :foo, :string, initial_value: true, boundaries: { "3.2.0" => false }
53
53
 
54
54
  MSG
55
55
  ->(_default_context) { given.call }
@@ -12,7 +12,8 @@ module Spree
12
12
  def call(from:, to:)
13
13
  preferences_from = config_class.new.load_defaults(from)
14
14
  preferences_to = config_class.new.load_defaults(to)
15
- preferences_from.reduce({}) do |changes, (pref_key, value_from)|
15
+ config_class.versioned_preferences.reduce({}) do |changes, pref_key|
16
+ value_from = preferences_from[pref_key]
16
17
  value_to = preferences_to[pref_key]
17
18
  if value_from == value_to
18
19
  changes
@@ -36,8 +36,6 @@ module Spree
36
36
  end
37
37
 
38
38
  def add(klass, name, preferences)
39
- # We use class name instead of class to allow reloading in dev
40
- raise "Static model preference '#{name}' on #{klass} is already defined" if @store[klass.to_s][name]
41
39
  @store[klass.to_s][name] = Definition.new(klass, preferences)
42
40
  end
43
41
 
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ # Supported Rails versions compatibility
5
+ #
6
+ # This module is meant to wrap some Rails API changes between supported
7
+ # versions. It's also meant to contain compatibility for features that we use
8
+ # internally in the Solidus code base.
9
+ module RailsCompatibility
10
+ # Method `#to_fs`
11
+ #
12
+ # Available since Rails 7.0, substitutes `#to_s(format)`
13
+ #
14
+ # It includes:
15
+ #
16
+ # ActiveSupport::NumericWithFormat
17
+ # ActiveSupport::RangeWithFormat
18
+ # ActiveSupport::TimeWithZone
19
+ # Array
20
+ # Date
21
+ # DateTime
22
+ # Time
23
+ #
24
+ # See https://github.com/rails/rails/pull/43772 &
25
+ # https://github.com/rails/rails/pull/44354
26
+ #
27
+ # TODO: Remove when deprecating Rails 6.1
28
+ def self.to_fs(value, *args, **kwargs, &block)
29
+ if version_gte?('7.0')
30
+ value.to_fs(*args, **kwargs, &block)
31
+ else
32
+ value.to_s(*args, **kwargs, &block)
33
+ end
34
+ end
35
+
36
+ # `raise_on_missing_translations` config option
37
+ #
38
+ # Changed from ActionView to I18n on Rails 6.1
39
+ #
40
+ # See https://github.com/rails/rails/pull/31571
41
+ #
42
+ # TODO: Remove when deprecating Rails 6.0
43
+ def self.raise_on_missing_translations(value)
44
+ if version_gte?('6.1')
45
+ Rails.application.config.i18n.raise_on_missing_translations = value
46
+ else
47
+ Rails.application.config.action_view.raise_on_missing_translations = value
48
+ end
49
+ end
50
+
51
+ # Set current host for ActiveStorage in a controller
52
+ #
53
+ # Changed from `#host` to including a module in Rails 6
54
+ #
55
+ # See https://github.com/rails/rails/commit/e33c3cd8ccbecaca6c6af0438956431b02cb3fb2
56
+ #
57
+ # TODO: Remove when deprecating Rails 5.2
58
+ def self.active_storage_set_current(controller)
59
+ if version_gte?('6')
60
+ controller.include ActiveStorage::SetCurrent
61
+ else
62
+ controller.before_action do
63
+ ActiveStorage::Current.host = request.base_url
64
+ end
65
+ end
66
+ end
67
+
68
+ # Set current host for ActiveStorage
69
+ #
70
+ # Changed from `#host` to `#url_options` on Rails 7
71
+ #
72
+ # See https://github.com/rails/rails/issues/41388
73
+ #
74
+ # TODO: Remove when deprecating Rails 6.1
75
+ def self.active_storage_url_options_host(value)
76
+ if version_gte?('7')
77
+ ActiveStorage::Current.url_options = { host: value }
78
+ else
79
+ ActiveStorage::Current.host = value
80
+ end
81
+ end
82
+
83
+ # Default ActiveStorage variant processor
84
+ #
85
+ # Changed from `:mini_magick` to `vips` on Rails 7
86
+ #
87
+ # See https://github.com/rails/rails/issues/42744
88
+ #
89
+ # TODO: Remove when deprecating Rails 6.1
90
+ def self.variant_processor
91
+ version_gte?('7') ? :vips : :mini_magick
92
+ end
93
+
94
+ def self.version_gte?(version)
95
+ ::Rails.gem_version >= Gem::Version.new(version)
96
+ end
97
+ private_class_method :version_gte?
98
+ end
99
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spree/bus'
4
+
5
+ module Spree
6
+ module TestingSupport
7
+ # RSpec test helpers for the event bus
8
+ #
9
+ # If you want to use the methods defined in this module, include it in your
10
+ # specs:
11
+ #
12
+ # @example
13
+ # require 'rails_helper'
14
+ # require 'spree/testing_support/bus_helpers'
15
+ #
16
+ # RSpec.describe MyClass do
17
+ # include Spree::TestingSupport::BusHelpers
18
+ # end
19
+ #
20
+ # or, globally, in your `spec_helper.rb`:
21
+ #
22
+ # @example
23
+ # require 'spree/testing_support/bus_helpers'
24
+ #
25
+ # RSpec.configure do |config|
26
+ # config.include Spree::TestingSupport::BusHelpers
27
+ # end
28
+ module BusHelpers
29
+ extend RSpec::Matchers::DSL
30
+
31
+ # Stubs {Spree::Bus}
32
+ #
33
+ # After you have called this method in an example, {Spree::Bus} will no
34
+ # longer publish any event for the duration of that example. All the
35
+ # method invocations on it will be stubbed.
36
+ #
37
+ # Internally, it stubs {Spree::Bus#publish}.
38
+ #
39
+ # After you call this method, probably you'll want to call some of the
40
+ # matchers defined in this module.
41
+ def stub_spree_bus
42
+ allow(Spree::Bus).to receive(:publish)
43
+ end
44
+
45
+ # @!method have_been_published(event_name)
46
+ # Matcher to test that an event has been published via {Spree::Bus#publish}
47
+ #
48
+ # Before using this matcher, you need to call {#stub_spree_bus}.
49
+ #
50
+ # Remember that the event listeners won't be performed.
51
+ #
52
+ # @example
53
+ # it 'publishes foo event' do
54
+ # stub_spree_bus
55
+ #
56
+ # Spree::Bus.publish 'foo'
57
+ #
58
+ # expect('foo').to have_been_published
59
+ # end
60
+ #
61
+ # It can be chain through `with` to match with the published payload:
62
+ #
63
+ # @example
64
+ # it 'publishes foo event with the expected payload' do
65
+ # stub_spree_bus
66
+ #
67
+ # Spree::Bus.publish 'foo', bar: :baz, qux: :quux
68
+ #
69
+ # expect('foo').to have_been_published.with(a_hash_including(bar: :baz))
70
+ # end
71
+ #
72
+ # @param [Symbol] event_name
73
+ matcher :have_been_published do
74
+ chain :with, :payload
75
+
76
+ match do |expected_event|
77
+ expected_event = normalize_name(expected_event)
78
+ arguments = payload ? [expected_event, payload] : [expected_event, any_args]
79
+ expect(Spree::Bus).to have_received(:publish).with(*arguments)
80
+ end
81
+
82
+ failure_message do |expected_event|
83
+ <<~MSG
84
+ expected #{expected_event.inspect} to have been published.
85
+ Make sure that provided payload, if any, also matches.
86
+ MSG
87
+ end
88
+
89
+ def normalize_name(event_name)
90
+ if event_name.is_a?(Symbol)
91
+ eq(event_name)
92
+ else
93
+ raise ArgumentError, <<~MSG
94
+ "#{event_name.inspect} is not a valid event name. It must be a Symbol."
95
+ MSG
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -6,33 +6,61 @@ end
6
6
 
7
7
  require 'generators/spree/dummy/dummy_generator'
8
8
 
9
- namespace :common do
10
- task :test_app, :user_class do |_t, args|
11
- args.with_defaults(user_class: "Spree::LegacyUser")
12
- require ENV['LIB_NAME']
9
+ class CommonRakeTasks
10
+ include Rake::DSL
13
11
 
14
- ENV["RAILS_ENV"] = 'test'
12
+ def initialize
13
+ namespace :common do
14
+ task :test_app, :user_class do |_t, args|
15
+ args.with_defaults(user_class: "Spree::LegacyUser")
16
+ require ENV['LIB_NAME']
17
+
18
+ force_rails_environment_to_test
19
+
20
+ Spree::DummyGenerator.start ["--lib_name=#{ENV['LIB_NAME']}", "--quiet"]
21
+ Solidus::InstallGenerator.start ["--lib_name=#{ENV['LIB_NAME']}", "--auto-accept", "--with-authentication=false", "--payment-method=none", "--migrate=false", "--seed=false", "--sample=false", "--quiet", "--user_class=#{args[:user_class]}"]
22
+
23
+ puts "Setting up dummy database..."
15
24
 
16
- Spree::DummyGenerator.start ["--lib_name=#{ENV['LIB_NAME']}", "--quiet"]
17
- Solidus::InstallGenerator.start ["--lib_name=#{ENV['LIB_NAME']}", "--auto-accept", "--with-authentication=false", "--payment-method=none", "--migrate=false", "--seed=false", "--sample=false", "--quiet", "--user_class=#{args[:user_class]}"]
25
+ sh "bin/rails db:environment:set RAILS_ENV=test"
26
+ sh "bin/rails db:drop db:create db:migrate VERBOSE=false RAILS_ENV=test"
18
27
 
19
- puts "Setting up dummy database..."
28
+ if extension_installation_generator_exists?
29
+ puts 'Running extension installation generator...'
30
+ sh "bin/rails generate #{rake_generator_namespace}:install --auto-run-migrations"
31
+ end
32
+ end
20
33
 
21
- sh "bin/rails db:environment:set RAILS_ENV=test"
22
- sh "bin/rails db:drop db:create db:migrate VERBOSE=false RAILS_ENV=test"
34
+ task :seed do |_t, _args|
35
+ puts "Seeding ..."
23
36
 
24
- begin
25
- require "generators/#{ENV['LIB_NAME']}/install/install_generator"
26
- puts 'Running extension installation generator...'
27
- "#{ENV['LIB_NAMESPACE'] || ENV['LIB_NAME'].camelize}::Generators::InstallGenerator".constantize.start(["--auto-run-migrations"])
28
- rescue LoadError
29
- # No extension generator to run
37
+ sh "bundle exec rake db:seed RAILS_ENV=test"
38
+ end
30
39
  end
31
40
  end
32
41
 
33
- task :seed do |_t, _args|
34
- puts "Seeding ..."
42
+ private
35
43
 
36
- sh "bundle exec rake db:seed RAILS_ENV=test"
44
+ def force_rails_environment_to_test
45
+ ENV["RAILS_ENV"] = 'test'
46
+ Rails.env = 'test'
47
+ end
48
+
49
+ def extension_installation_generator_exists?
50
+ require "generators/#{generator_namespace}/install/install_generator"
51
+
52
+ true
53
+ rescue LoadError
54
+ false
55
+ end
56
+
57
+ def generator_namespace
58
+ "#{ENV['LIB_NAMESPACE']&.underscore || ENV['LIB_NAME']}"
59
+ end
60
+
61
+ def rake_generator_namespace
62
+ generator_namespace.gsub("/", ":")
37
63
  end
38
64
  end
65
+
66
+ CommonRakeTasks.new
@@ -1,5 +1,5 @@
1
1
  // This is a manifest file that'll be compiled into including all the files listed below.
2
- // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
2
+ // Add new JavaScript code in separate files in this directory and they'll automatically
3
3
  // be included in the compiled file accessible from http://example.com/assets/application.js
4
4
  // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
5
5
  // the compiled file.