workarea-core 3.5.11 → 3.5.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/app/models/workarea/checkout.rb +1 -5
  3. data/app/models/workarea/inventory/sku.rb +2 -2
  4. data/app/models/workarea/metrics/user.rb +24 -8
  5. data/app/models/workarea/order.rb +13 -3
  6. data/app/models/workarea/payment.rb +1 -6
  7. data/app/models/workarea/releasable.rb +3 -1
  8. data/app/models/workarea/release/changeset.rb +1 -0
  9. data/app/models/workarea/search/admin/pricing_discount.rb +1 -1
  10. data/app/models/workarea/search/storefront.rb +9 -1
  11. data/app/models/workarea/search/storefront/category_query.rb +1 -1
  12. data/app/models/workarea/search/storefront/product.rb +11 -2
  13. data/app/queries/workarea/product_releases.rb +6 -0
  14. data/app/services/workarea/direct_upload.rb +17 -13
  15. data/app/services/workarea/index_release_schedule_previews.rb +37 -0
  16. data/app/workers/workarea/index_category_changes.rb +16 -3
  17. data/app/workers/workarea/index_release_schedule_change.rb +32 -0
  18. data/app/workers/workarea/process_import.rb +3 -3
  19. data/app/workers/workarea/publish_release.rb +1 -0
  20. data/lib/tasks/search.rake +10 -4
  21. data/lib/workarea/configuration.rb +11 -0
  22. data/lib/workarea/configuration/administrable_options.rb +1 -5
  23. data/lib/workarea/core.rb +2 -0
  24. data/lib/workarea/ext/jbuilder/jbuilder_cache.rb +29 -0
  25. data/lib/workarea/queues_pauser.rb +26 -0
  26. data/lib/workarea/version.rb +1 -1
  27. data/lib/workarea/visit.rb +8 -1
  28. data/test/models/workarea/releasable_test.rb +13 -0
  29. data/test/models/workarea/search/storefront/category_query_test.rb +11 -0
  30. data/test/models/workarea/search/storefront/product_releases_test.rb +60 -0
  31. data/test/models/workarea/search/storefront_test.rb +13 -0
  32. data/test/queries/workarea/search/category_browse_test.rb +23 -0
  33. data/test/services/workarea/direct_upload_test.rb +20 -3
  34. data/test/services/workarea/index_release_schedule_previews_test.rb +28 -0
  35. data/test/workers/workarea/index_release_schedule_change_test.rb +107 -0
  36. data/test/workers/workarea/process_import_test.rb +6 -0
  37. data/test/workers/workarea/publish_release_test.rb +24 -0
  38. data/workarea-core.gemspec +5 -4
  39. metadata +31 -11
  40. data/test/queries/workarea/product_releases_test.rb +0 -56
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72fffa19332c0b8652c70135ef370a1704350ea0037845df1615c958bd9a8bc8
4
- data.tar.gz: 717aaef848a0ad75774fc0ed23b41c80362b8657c021d06630296dbdbe3e4dea
3
+ metadata.gz: 569f33ae16d992354fca8761ef67ed5473a12755dda710cfff057ebd2d7aa2b4
4
+ data.tar.gz: 24b32513e4215b2aa1c67a5f1d930ae5f8a81ee098be08234eab95f69a6bc574
5
5
  SHA512:
6
- metadata.gz: da8b605d36c1b60257fb73d8e65a3bee6e5b99f03d991861b4eef5ab9338fd00e8787eb1e32d6e1df3905bdc95ec349d3ab022a6b0a7e648e0006eb6341f444e
7
- data.tar.gz: '09fbd0f844ae5ff48b37f160981b9173982114a0f5584e6846a565be9459697812265e9c4224f82efabfe12265537b3e6bfb0f1c501ad0521bc632d9ca13f82e'
6
+ metadata.gz: 11b65e3f2de7268ec497fecb2019a10133e2a477cc5bf06cd64390976098baa97277a75a295633a4fd6e43b221d31453c6a4da99b1c05012534e19621a6c7d18
7
+ data.tar.gz: 614ed5b1d7970082ba8eb48b8448434737d194ed1fed7158537774b9e46dce862ab0cae2faafca35f40378a061e3a91c02b9ab4d36875201896ea33ff6b60991
@@ -47,11 +47,7 @@ module Workarea
47
47
  def inventory
48
48
  @inventory ||= Inventory::Transaction.from_order(
49
49
  order.id,
50
- order.items.inject({}) do |memo, item|
51
- memo[item.sku] ||= 0
52
- memo[item.sku] += item.quantity
53
- memo
54
- end
50
+ order.sku_quantities
55
51
  )
56
52
  end
57
53
 
@@ -142,11 +142,11 @@ module Workarea
142
142
  end
143
143
 
144
144
  def policy_class
145
- "Workarea::Inventory::Policies::#{policy.classify}".constantize
145
+ "Workarea::Inventory::Policies::#{policy.camelize}".constantize
146
146
  rescue NameError
147
147
  raise(
148
148
  InvalidPolicy,
149
- "Workarea::Inventory::Policies::#{policy.classify} must be a policy class"
149
+ "Workarea::Inventory::Policies::#{policy.camelize} must be a policy class"
150
150
  )
151
151
  end
152
152
 
@@ -110,14 +110,28 @@ module Workarea
110
110
  end
111
111
 
112
112
  def merge!(other)
113
- %w(orders revenue discounts cancellations refund).each do |field|
114
- self.send("#{field}=", send(field) + other.send(field))
115
- end
116
-
117
- self.first_order_at = [first_order_at, other.first_order_at].compact.min
118
- self.last_order_at = [last_order_at, other.last_order_at].compact.max
119
- self.average_order_value = average_order_value
120
- save!
113
+ # To recalculate average_order_value
114
+ self.orders += other.orders
115
+ self.revenue += other.revenue
116
+
117
+ update = {
118
+ '$set' => {
119
+ average_order_value: average_order_value,
120
+ updated_at: Time.current.utc
121
+ },
122
+ '$inc' => {
123
+ orders: other.orders,
124
+ revenue: other.revenue,
125
+ discounts: other.discounts,
126
+ cancellations: other.cancellations,
127
+ refund: other.refund
128
+ }
129
+ }
130
+
131
+ update['$min'] = { first_order_at: other.first_order_at.utc } if other.first_order_at.present?
132
+ update['$max'] = { last_order_at: other.last_order_at.utc } if other.last_order_at.present?
133
+
134
+ self.class.collection.update_one({ _id: id }, update, upsert: true)
121
135
 
122
136
  self.class.save_affinity(
123
137
  id: id,
@@ -133,6 +147,8 @@ module Workarea
133
147
  category_ids: other.purchased.category_ids,
134
148
  search_ids: other.purchased.search_ids
135
149
  )
150
+
151
+ reload
136
152
  end
137
153
  end
138
154
  end
@@ -47,13 +47,13 @@ module Workarea
47
47
  {
48
48
  placed_at: 1,
49
49
  reminded_at: 1,
50
+ fraud_suspected_at: 1,
50
51
  checkout_started_at: 1,
51
52
  email: 1,
52
- "items[0]._id": 1,
53
- fraud_suspected_at: 1
53
+ "items[0]._id": 1
54
54
  },
55
55
  {
56
- name: 'abandoned_order_email_with_fraud_index',
56
+ name: 'abandoned_order_email_with_fraud_index_v2',
57
57
  background: true
58
58
  }
59
59
  )
@@ -375,6 +375,16 @@ module Workarea
375
375
  )
376
376
  end
377
377
 
378
+ # A hash with the quantity of each SKU in the order
379
+ #
380
+ # @return [Hash]
381
+ #
382
+ def sku_quantities
383
+ items.each_with_object(Hash.new(0)) do |item, quantities|
384
+ quantities[item.sku] += item.quantity
385
+ end
386
+ end
387
+
378
388
  private
379
389
 
380
390
  def item_count_limit
@@ -80,12 +80,7 @@ module Workarea
80
80
  build_credit_card unless credit_card
81
81
  credit_card.saved_card_id = nil
82
82
  credit_card.attributes = attrs.slice(
83
- :month,
84
- :year,
85
- :saved_card_id,
86
- :number,
87
- :cvv,
88
- :amount
83
+ *Workarea.config.credit_card_attributes
89
84
  )
90
85
  save
91
86
  end
@@ -72,7 +72,9 @@ module Workarea
72
72
  release.preview.changesets_for(self).each { |cs| cs.apply_to(result) }
73
73
  result
74
74
  else
75
- Release.with_current(release) { self.class.find(id) }
75
+ Release.with_current(release) do
76
+ Mongoid::QueryCache.uncached { self.class.find(id) }
77
+ end
76
78
  end
77
79
  end
78
80
 
@@ -18,6 +18,7 @@ module Workarea
18
18
  index({ 'document_path.type' => 1, 'document_path.document_id' => 1 })
19
19
  index('changeset.product_ids' => 1)
20
20
  index('original.product_ids' => 1)
21
+ index('releasable_type' => 1, 'releasable_id' => 1)
21
22
 
22
23
  # Finds changeset by whether the passed document is in the document
23
24
  # path of the changeset. Useful for showing embedded changes in the
@@ -21,7 +21,7 @@ module Workarea
21
21
  end
22
22
 
23
23
  def keywords
24
- super + model.promo_codes
24
+ super + Array.wrap(model.try(:promo_codes))
25
25
  end
26
26
 
27
27
  def facets
@@ -82,6 +82,14 @@ module Workarea
82
82
  @changesets ||= Array.wrap(model.try(:changesets_with_children))
83
83
  end
84
84
 
85
+ def releases
86
+ changesets
87
+ .uniq(&:release)
88
+ .reject { |cs| cs.release.blank? }
89
+ .flat_map { |cs| [cs.release] + cs.release.scheduled_after }
90
+ .uniq
91
+ end
92
+
85
93
  def as_document
86
94
  Release.with_current(release_id) do
87
95
  {
@@ -91,7 +99,7 @@ module Workarea
91
99
  active: active,
92
100
  active_segment_ids: active_segment_ids,
93
101
  release_id: release_id,
94
- changeset_release_ids: changesets.map(&:release_id),
102
+ changeset_release_ids: releases.map(&:id),
95
103
  suggestion_content: suggestion_content,
96
104
  created_at: model.created_at,
97
105
  updated_at: model.updated_at,
@@ -144,7 +144,7 @@ module Workarea
144
144
  .where(releasable_type: ProductRule.name)
145
145
  .any_in(releasable_id: category.product_rules.map(&:id))
146
146
  .includes(:release)
147
- .to_a
147
+ .select(&:release)
148
148
  end
149
149
  end
150
150
  end
@@ -122,12 +122,21 @@ module Workarea
122
122
  ProductPrimaryImageUrl.new(model).path
123
123
  end
124
124
 
125
- # Override to include release changesets for pricing, featured products, etc.
125
+ # All {Releasable}s that could affect the product's Elasticsearch document
126
+ # should add their changesets to this method.
127
+ #
128
+ # @example Add to the changesets affecting a product in a decorator
129
+ # def changesets
130
+ # super.merge(SomeReleasable.for_product(product.id).changesets_with_children)
131
+ # end
126
132
  #
127
133
  # @return [Mongoid::Criteria]
128
134
  #
129
135
  def changesets
130
- @product_changesets ||= ProductReleases.new(model).changesets
136
+ criteria = model.changesets_with_children
137
+ pricing.each { |ps| criteria.merge!(ps.changesets_with_children) }
138
+ criteria.merge!(FeaturedProducts.changesets(model.id))
139
+ criteria.includes(:release)
131
140
  end
132
141
 
133
142
  private
@@ -1,4 +1,10 @@
1
1
  module Workarea
2
+ #
3
+ # TODO remove in v3.6
4
+ #
5
+ # This is no longer used, this logic was moved into the search models to allow
6
+ # it to be used for any model (not just products).
7
+ #
2
8
  class ProductReleases
3
9
  attr_reader :product
4
10
 
@@ -6,22 +6,26 @@ module Workarea
6
6
  uri = URI.parse(request_url)
7
7
  url = "#{uri.scheme}://#{uri.host}"
8
8
  url += ":#{uri.port}" unless uri.port.in? [80, 443]
9
+ id = "direct_upload_#{url}"
9
10
 
10
- redis_key = "cors_#{url.optionize}"
11
- return if Workarea.redis.get(redis_key) == 'true'
11
+ response = begin
12
+ Workarea.s3.get_bucket_cors(Configuration::S3.bucket)
13
+ rescue Excon::Error::NotFound
14
+ Excon::Response.new(body: { 'CORSConfiguration' => [] })
15
+ end
12
16
 
13
- response = Workarea.s3.get_bucket_cors(Configuration::S3.bucket)
14
17
  cors = response.data[:body]
15
- cors['CORSConfiguration'] << {
16
- 'ID' => "direct_upload_#{url}",
17
- 'AllowedMethod' => 'PUT',
18
- 'AllowedOrigin' => url,
19
- 'AllowedHeader' => '*'
20
- }
21
- cors['CORSConfiguration'].uniq!
22
-
23
- Workarea.s3.put_bucket_cors(Configuration::S3.bucket, cors)
24
- Workarea.redis.set(redis_key, 'true')
18
+
19
+ unless cors['CORSConfiguration'].pluck('ID').include?(id)
20
+ cors['CORSConfiguration'] << {
21
+ 'ID' => id,
22
+ 'AllowedMethod' => 'PUT',
23
+ 'AllowedOrigin' => url,
24
+ 'AllowedHeader' => '*'
25
+ }
26
+
27
+ Workarea.s3.put_bucket_cors(Configuration::S3.bucket, cors)
28
+ end
25
29
  end
26
30
 
27
31
  attr_reader :type, :filename
@@ -0,0 +1,37 @@
1
+ module Workarea
2
+ class IndexReleaseSchedulePreviews
3
+ attr_reader :release, :starts_at, :ends_at
4
+
5
+ def initialize(release: nil, starts_at: nil, ends_at: nil)
6
+ @release = release
7
+ @starts_at = starts_at
8
+ @ends_at = ends_at
9
+ end
10
+
11
+ def affected_releases
12
+ result = Release
13
+ .scheduled(after: starts_at, before: ends_at)
14
+ .includes(:changesets)
15
+ .to_a
16
+
17
+ result << release if release.present?
18
+ result.uniq
19
+ end
20
+
21
+ def affected_models
22
+ affected_releases.flat_map(&:changesets).flat_map(&:releasable).compact
23
+ end
24
+
25
+ def perform
26
+ affected_releases.each do |release|
27
+ affected_models.each do |releasable|
28
+ Search::Storefront.new(releasable.in_release(release)).destroy
29
+
30
+ # Different models have different indexing workers, running callbacks
31
+ # ensures the appropriate worker is triggered
32
+ releasable.run_callbacks(:save_release_changes)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -4,16 +4,29 @@ module Workarea
4
4
  include Sidekiq::CallbacksWorker
5
5
 
6
6
  sidekiq_options(
7
- enqueue_on: { Catalog::Category => [:save, :save_release_changes], with: -> { [changes] } },
7
+ enqueue_on: {
8
+ Catalog::Category => [:save, :save_release_changes],
9
+ with: -> { [changes, Release.current.present?] }
10
+ },
8
11
  ignore_if: -> { changes['product_ids'].blank? },
9
12
  lock: :until_executing,
10
13
  query_cache: true
11
14
  )
12
15
 
13
- def perform(changes)
16
+ def perform(changes, for_release = false)
14
17
  return unless changes['product_ids'].present?
15
18
 
16
- ids = require_index_ids(*changes['product_ids'])
19
+ ids = if for_release
20
+ # This is a shortcut because if you're resorting products within a release,
21
+ # the `changes` hash doesn't reflect the repositioning within the release,
22
+ # only the difference between what's live and what's in the release.
23
+ #
24
+ # Reindexing all of them is a shortcut to having to manually build a diff
25
+ # between the changesets in the possible affected releases.
26
+ changes['product_ids'].flatten.uniq
27
+ else
28
+ require_index_ids(*changes['product_ids'])
29
+ end
17
30
 
18
31
  if ids.size > max_count
19
32
  ids.each { |id| IndexProduct.perform_async(id) }
@@ -0,0 +1,32 @@
1
+ module Workarea
2
+ class IndexReleaseScheduleChange
3
+ include Sidekiq::Worker
4
+ include Sidekiq::CallbacksWorker
5
+
6
+ sidekiq_options(
7
+ enqueue_on: {
8
+ Release => [:save, :destroy],
9
+ only_if: -> { publish_at_changed? || destroyed? },
10
+ with: -> { [id, publish_at_was, publish_at] }
11
+ },
12
+ queue: 'releases'
13
+ )
14
+
15
+ def perform(id, previous_publish_at, new_publish_at)
16
+ # When destroyed, changesets for the release ID will still exist and be used to update the index
17
+ rescheduled_release = Release.find_or_initialize_by(id: id)
18
+
19
+ earlier, later = if rescheduled_release.persisted? && previous_publish_at.present? && new_publish_at.present?
20
+ [previous_publish_at, new_publish_at].sort
21
+ elsif previous_publish_at.present?
22
+ [previous_publish_at, nil]
23
+ else
24
+ [new_publish_at, nil]
25
+ end
26
+
27
+ IndexReleaseSchedulePreviews
28
+ .new(release: rescheduled_release, starts_at: earlier, ends_at: later)
29
+ .perform
30
+ end
31
+ end
32
+ end
@@ -17,11 +17,11 @@ module Workarea
17
17
  import.process!
18
18
 
19
19
  ensure
20
- if import.error?
20
+ if import&.error?
21
21
  Admin::DataFileMailer.import_error(id).deliver_now
22
- elsif import.failure?
22
+ elsif import&.failure?
23
23
  Admin::DataFileMailer.import_failure(id).deliver_now
24
- else
24
+ elsif import.present?
25
25
  Admin::DataFileMailer.import(id).deliver_now
26
26
  end
27
27
  end
@@ -8,6 +8,7 @@ module Workarea
8
8
  system_user = User.find_system_user!(release.name, 'Release')
9
9
 
10
10
  Mongoid::AuditLog.record(system_user) { release.publish! }
11
+ IndexReleaseSchedulePreviews.new(release: release).perform
11
12
 
12
13
  rescue Mongoid::Errors::DocumentNotFound
13
14
  # Doesn't matter, release has been removed
@@ -16,7 +16,9 @@ namespace :workarea do
16
16
  task admin: :environment do
17
17
  setup
18
18
  puts 'Indexing admin...'
19
- Workarea::Search::Admin.reset_indexes!
19
+ Workarea::QueuesPauser.with_paused_queues do
20
+ Workarea::Search::Admin.reset_indexes!
21
+ end
20
22
 
21
23
  Mongoid.models.each do |klass|
22
24
  next unless Workarea::Search::Admin.for(klass.first).present?
@@ -36,8 +38,10 @@ namespace :workarea do
36
38
  setup
37
39
  puts 'Indexing storefront...'
38
40
 
39
- Workarea::Search::Storefront.reset_indexes!
40
- Workarea::Search::Storefront.ensure_dynamic_mappings
41
+ Workarea::QueuesPauser.with_paused_queues do
42
+ Workarea::Search::Storefront.reset_indexes!
43
+ Workarea::Search::Storefront.ensure_dynamic_mappings
44
+ end
41
45
 
42
46
  # This code finds all unique filters for products so we can index a sample
43
47
  # product for each to ensure the dynamic mappings get created.
@@ -83,7 +87,9 @@ namespace :workarea do
83
87
  setup
84
88
  puts 'Indexing help...'
85
89
 
86
- Workarea::Search::Help.reset_indexes!
90
+ Workarea::QueuesPauser.with_paused_queues do
91
+ Workarea::Search::Help.reset_indexes!
92
+ end
87
93
 
88
94
  Workarea::Help::Article.all.each_by(Workarea.config.bulk_index_batch_size) do |help_article|
89
95
  Workarea::Search::Help.new(help_article).save
@@ -1297,6 +1297,17 @@ module Workarea
1297
1297
 
1298
1298
  # The number of results that will show per-type in the admin jump to
1299
1299
  config.jump_to_results_per_type = 5
1300
+
1301
+ # Attributes that will be sliced out of params and persisted on
1302
+ # the credit card tender during checkout.
1303
+ config.credit_card_attributes = %i[
1304
+ month
1305
+ year
1306
+ saved_card_id
1307
+ number
1308
+ cvv
1309
+ amount
1310
+ ]
1300
1311
  end
1301
1312
  end
1302
1313
  end
@@ -1,7 +1,7 @@
1
1
  module Workarea
2
2
  module Configuration
3
3
  class AdministrableOptions < ActiveSupport::InheritableOptions
4
- def method_missing(name, *args)
4
+ def [](name)
5
5
  static_config = super
6
6
  return static_config if static_config.present? || static_config.to_s == 'false'
7
7
  return static_config unless check_fieldsets?(name)
@@ -9,10 +9,6 @@ module Workarea
9
9
  Configuration::Admin.instance.send(name)
10
10
  end
11
11
 
12
- def respond_to_missing?(name, include_private)
13
- true
14
- end
15
-
16
12
  private
17
13
 
18
14
  def check_fieldsets?(name)
@@ -146,6 +146,7 @@ require 'workarea/ext/mongoid/find_ordered'
146
146
  require 'workarea/ext/mongoid/embedded_children'
147
147
  require 'workarea/ext/sprockets/ruby_processor'
148
148
  require 'workarea/ext/jbuilder/jbuilder_append_partials'
149
+ require 'workarea/ext/jbuilder/jbuilder_cache'
149
150
 
150
151
  if Rails.env.development?
151
152
  require 'workarea/ext/freedom_patches/routes_reloader'
@@ -221,6 +222,7 @@ require 'workarea/mail_interceptor'
221
222
  require 'workarea/visit'
222
223
  require 'workarea/warnings'
223
224
  require 'workarea/latest_version'
225
+ require 'workarea/queues_pauser'
224
226
 
225
227
  #
226
228
  # Engines
@@ -0,0 +1,29 @@
1
+ decorate JbuilderTemplate, with: :workarea do
2
+ def _cache_fragment_for(*)
3
+ return yield if workarea_admin?
4
+
5
+ super
6
+ end
7
+
8
+ def _cache_key(*)
9
+ super.tap do |result|
10
+ result << workarea_cache_varies if workarea_cache_varies.present?
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def workarea_admin?
17
+ @context&.controller&.current_user&.admin?
18
+ rescue ::RuntimeError
19
+ false
20
+ end
21
+
22
+ def workarea_cache_varies
23
+ workarea_request_env['workarea.cache_varies']
24
+ end
25
+
26
+ def workarea_request_env
27
+ @context.controller.request.env || {}
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ module Workarea
2
+ module QueuesPauser
3
+ extend self
4
+
5
+ def pause_queues!
6
+ pauser = Sidekiq::Throttled::QueuesPauser.instance
7
+ queues.each { |queue| pauser.pause!(queue) }
8
+ end
9
+
10
+ def resume_queues!
11
+ pauser = Sidekiq::Throttled::QueuesPauser.instance
12
+ queues.each { |queue| pauser.resume!(queue) }
13
+ end
14
+
15
+ def with_paused_queues(&block)
16
+ pause_queues!
17
+ yield
18
+ ensure
19
+ resume_queues!
20
+ end
21
+
22
+ def queues
23
+ Configuration::Sidekiq.queues
24
+ end
25
+ end
26
+ end
@@ -2,7 +2,7 @@ module Workarea
2
2
  module VERSION
3
3
  MAJOR = 3
4
4
  MINOR = 5
5
- PATCH = 11
5
+ PATCH = 16
6
6
  PRE = nil
7
7
  STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
8
8
 
@@ -38,7 +38,10 @@ module Workarea
38
38
  end
39
39
 
40
40
  def current_email
41
- cookies.signed[:email]
41
+ # For performance, prefer to use the cookie. The fallback to looking it up
42
+ # by user is a failsafe against a blank email cookie (e.g. from a raised
43
+ # error or poor application coding).
44
+ cookies.signed[:email].presence || (email_from_user_id if logged_in?)
42
45
  end
43
46
 
44
47
  def metrics
@@ -91,5 +94,9 @@ module Workarea
91
94
  def blank_metrics
92
95
  @blank_metrics ||= Metrics::User.new
93
96
  end
97
+
98
+ def email_from_user_id
99
+ User.find(session[:user_id]).email rescue nil
100
+ end
94
101
  end
95
102
  end
@@ -375,6 +375,19 @@ module Workarea
375
375
  in_release = model.in_release(nil)
376
376
  assert_equal('Foo', in_release.name)
377
377
  refute_equal(in_release.object_id, model.object_id)
378
+
379
+ Mongoid::QueryCache.cache do
380
+ cached = Foo.find(model.id) # a find to ensure it's in the cache table
381
+ cached.name = 'Bar' # so the cache table's instance has a change
382
+
383
+ in_release = model.in_release(nil)
384
+ assert_equal('Foo', in_release.name)
385
+ refute_equal(in_release.object_id, model.object_id)
386
+ refute_equal(cached.object_id, model.object_id)
387
+ end
388
+
389
+ ensure
390
+ Mongoid::QueryCache.clear_cache
378
391
  end
379
392
 
380
393
  def test_skip_changeset
@@ -75,6 +75,17 @@ module Workarea
75
75
  assert_equal([@category.id.to_s], CategoryQuery.find_by_product(@product))
76
76
  end
77
77
  end
78
+
79
+ def test_deleted_releases
80
+ release = create_release
81
+ release.as_current do
82
+ @category.product_rules.first.update!(value: 'bar')
83
+ end
84
+
85
+ release.destroy
86
+ CategoryQuery.new(@category).update
87
+ assert_equal([@category.id.to_s], CategoryQuery.find_by_product(@product))
88
+ end
78
89
  end
79
90
  end
80
91
  end
@@ -0,0 +1,60 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ module Search
5
+ class Storefront
6
+ class ProductReleasesTest < TestCase
7
+ def test_product_changes
8
+ product = create_product(name: 'Foo')
9
+ release_one = create_release
10
+ release_one.as_current { product.update!(name: 'Bar') }
11
+
12
+ assert_equal([release_one], Product.new(product).releases)
13
+
14
+ release_one.update!(publish_at: 1.day.from_now)
15
+ release_two = create_release(publish_at: 3.days.from_now)
16
+ assert_equal([release_one, release_two], Product.new(product).releases)
17
+ end
18
+
19
+ def test_featured_product_changes
20
+ product = create_product
21
+ category = create_category
22
+
23
+ release_one = create_release
24
+ release_one.as_current { category.update!(product_ids: [product.id]) }
25
+ assert_equal([release_one], Product.new(product).releases)
26
+
27
+ release_one.update!(publish_at: 1.day.from_now)
28
+ release_two = create_release(publish_at: 3.days.from_now)
29
+ assert_equal([release_one, release_two], Product.new(product).releases)
30
+ end
31
+
32
+ def test_variant_changes
33
+ product = create_product(variants: [{ sku: 'SKU' }])
34
+ release = create_release
35
+ release.as_current { product.variants.first.update!(details: { color: 'Red' }) }
36
+ assert_equal([release], Product.new(product).releases)
37
+ end
38
+
39
+ def test_pricing_changes
40
+ product = create_product(variants: [{ sku: 'SKU' }])
41
+ pricing = Pricing::Sku.find('SKU')
42
+
43
+ release = create_release
44
+ release.as_current { pricing.prices.first.update!(regular: 10_000) }
45
+ assert_equal([release], Product.new(product).releases)
46
+ end
47
+
48
+ def test_changesets_with_missing_releases
49
+ product = create_product(name: 'Foo')
50
+ release = create_release
51
+ release.as_current { product.update!(name: 'Bar') }
52
+ release.delete
53
+
54
+ assert_nil(product.reload.changesets.first.release)
55
+ assert_equal([], Product.new(product).releases)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -25,6 +25,19 @@ module Workarea
25
25
  release.as_current { category.product_rules.first.update!(value: 'bar') }
26
26
  assert_equal(2, Storefront.new(category).changesets.size)
27
27
  end
28
+
29
+ def test_releases
30
+ category = create_category(name: 'Foo')
31
+ assert_empty(Storefront.new(category).as_document[:changeset_release_ids])
32
+
33
+ a = create_release(publish_at: 1.week.from_now)
34
+ a.as_current { category.update!(name: 'Bar') }
35
+ assert_equal([a.id], Storefront.new(category).as_document[:changeset_release_ids])
36
+
37
+ b = create_release(publish_at: 2.weeks.from_now)
38
+ assert_includes(Storefront.new(category).as_document[:changeset_release_ids], a.id)
39
+ assert_includes(Storefront.new(category).as_document[:changeset_release_ids], b.id)
40
+ end
28
41
  end
29
42
  end
30
43
  end
@@ -382,6 +382,29 @@ module Workarea
382
382
  refute_includes(result_ids, product_five.id)
383
383
  end
384
384
  end
385
+
386
+ def test_featured_product_changes_in_a_release
387
+ one = create_product
388
+ two = create_product
389
+ three = create_product(name: 'Foo', active: false)
390
+ category = create_category(product_ids: [one.id, two.id], product_rules: [])
391
+ release = create_release(publish_at: 1.week.from_now)
392
+
393
+ release.as_current do
394
+ three.update!(name: 'Bar', active: true, default_category_id: category.id)
395
+ category.update!(product_ids: [three.id, one.id, two.id])
396
+ search = CategoryBrowse.new(sort: %w(featured), category_ids: [category.id])
397
+ sorts = search.results.pluck(:raw).pluck('_source').pluck('sorts').pluck(category.id.to_s)
398
+ assert_equal([0, 1, 2], sorts)
399
+ end
400
+
401
+ release.as_current do
402
+ category.update!(product_ids: [one.id, two.id, three.id])
403
+ search = CategoryBrowse.new(sort: %w(featured), category_ids: [category.id])
404
+ sorts = search.results.pluck(:raw).pluck('_source').pluck('sorts').pluck(category.id.to_s)
405
+ assert_equal([0, 1, 2], sorts)
406
+ end
407
+ end
385
408
  end
386
409
  end
387
410
  end
@@ -108,11 +108,28 @@ module Workarea
108
108
  ).returns(true)
109
109
 
110
110
  assert(DirectUpload.ensure_cors!('http://test.host/admin/content_assets'))
111
- assert_equal('true', Workarea.redis.get('cors_http_test_host'))
112
111
  assert(DirectUpload.ensure_cors!('http://localhost:3000/admin/content_assets'))
113
- assert_equal('true', Workarea.redis.get('cors_http_localhost_3000'))
114
112
  assert(DirectUpload.ensure_cors!('https://example.com/admin/direct_uploads'))
115
- assert_equal('true', Workarea.redis.get('cors_https_example_com'))
113
+ end
114
+
115
+ def test_ensure_cors_with_no_existing_configuration
116
+ Workarea.s3.expects(:get_bucket_cors)
117
+ .raises(Excon::Errors::NotFound.new('CORS configuration does not exist'))
118
+
119
+
120
+ Workarea.s3.expects(:put_bucket_cors).with(
121
+ Configuration::S3.bucket,
122
+ 'CORSConfiguration' => [
123
+ {
124
+ 'ID' => "direct_upload_http://test.host",
125
+ 'AllowedMethod' => 'PUT',
126
+ 'AllowedOrigin' => 'http://test.host',
127
+ 'AllowedHeader' => '*'
128
+ }
129
+ ]
130
+ ).returns(true)
131
+
132
+ assert(DirectUpload.ensure_cors!('http://test.host/admin/content_assets'))
116
133
  end
117
134
 
118
135
  private
@@ -0,0 +1,28 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ class IndexReleaseSchedulePreviewsTest < TestCase
5
+ def test_affected_releases
6
+ release = create_release
7
+ results = IndexReleaseSchedulePreviews.new(release: release).affected_releases
8
+ assert_equal([release], results)
9
+
10
+ a = create_release(publish_at: 1.week.from_now)
11
+ b = create_release(publish_at: 2.weeks.from_now)
12
+ c = create_release(publish_at: 4.weeks.from_now)
13
+ assert_equal([a, b, c], IndexReleaseSchedulePreviews.new.affected_releases)
14
+
15
+ results = IndexReleaseSchedulePreviews
16
+ .new(starts_at: 3.days.from_now, ends_at: 17.days.from_now)
17
+ .affected_releases
18
+
19
+ assert_equal([a, b], results)
20
+
21
+ results = IndexReleaseSchedulePreviews
22
+ .new(release: release, starts_at: 3.days.from_now, ends_at: 10.days.from_now)
23
+ .affected_releases
24
+
25
+ assert_equal([a, release], results)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,107 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ class IndexReleaseScheduleChangeTest < TestCase
5
+ include TestCase::SearchIndexing
6
+
7
+ setup :set_product
8
+
9
+ def set_product
10
+ @product = create_product(name: 'Foo')
11
+ end
12
+
13
+ def test_reschedule
14
+ a = create_release(name: 'A', publish_at: 1.week.from_now)
15
+ b = create_release(name: 'B', publish_at: 2.weeks.from_now)
16
+ c = create_release(name: 'C', publish_at: 4.weeks.from_now)
17
+
18
+ b.as_current { @product.update!(name: 'Bar') }
19
+ IndexProduct.perform(@product)
20
+
21
+ a.as_current { assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
22
+ b.as_current { assert_equal([@product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
23
+ c.as_current { assert_equal([@product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
24
+
25
+ # Changing publish_at via `update` causes the release to publish due to Sidekiq inline
26
+ previous_publish_at = b.publish_at
27
+ b.set(publish_at: 5.weeks.from_now)
28
+
29
+ Sidekiq::Callbacks.enable(IndexProduct) do
30
+ IndexReleaseScheduleChange.new.perform(b.id, previous_publish_at, b.publish_at)
31
+ end
32
+
33
+ a.as_current { assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
34
+ b.as_current { assert_equal([@product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
35
+ c.as_current { assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
36
+ end
37
+
38
+ def test_removing_from_schedule
39
+ a = create_release(name: 'A', publish_at: 1.week.from_now)
40
+ b = create_release(name: 'B', publish_at: 2.weeks.from_now)
41
+ c = create_release(name: 'C', publish_at: 4.weeks.from_now)
42
+
43
+ b.as_current { @product.update!(name: 'Bar') }
44
+ IndexProduct.perform(@product)
45
+
46
+ a.as_current { assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
47
+ b.as_current { assert_equal([@product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
48
+ c.as_current { assert_equal([@product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
49
+
50
+ # Changing publish_at via `update` causes the release to publish due to Sidekiq inline
51
+ previous_publish_at = b.publish_at
52
+ b.set(publish_at: nil)
53
+
54
+ Sidekiq::Callbacks.enable(IndexProduct) do
55
+ IndexReleaseScheduleChange.new.perform(b.id, previous_publish_at, nil)
56
+ end
57
+
58
+ a.as_current { assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
59
+ b.as_current { assert_equal([@product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
60
+ c.as_current { assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
61
+ end
62
+
63
+ def test_adding_to_schedule
64
+ a = create_release(name: 'A', publish_at: 1.week.from_now)
65
+ b = create_release(name: 'B')
66
+ c = create_release(name: 'C', publish_at: 4.weeks.from_now)
67
+
68
+ b.as_current { @product.update!(name: 'Bar') }
69
+ IndexProduct.perform(@product)
70
+
71
+ a.as_current { assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
72
+ b.as_current { assert_equal([@product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
73
+ c.as_current { assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
74
+
75
+ # Changing publish_at via `update` causes the release to publish due to Sidekiq inline
76
+ b.set(publish_at: 2.weeks.from_now)
77
+
78
+ Sidekiq::Callbacks.enable(IndexProduct) do
79
+ IndexReleaseScheduleChange.new.perform(b.id, nil, b.publish_at)
80
+ end
81
+
82
+ a.as_current { assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
83
+ b.as_current { assert_equal([@product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
84
+ c.as_current { assert_equal([@product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
85
+ end
86
+
87
+ def test_destroyed
88
+ a = create_release(name: 'A', publish_at: 1.week.from_now)
89
+ b = create_release(name: 'B', publish_at: 2.weeks.from_now)
90
+ c = create_release(name: 'C', publish_at: 4.weeks.from_now)
91
+
92
+ b.as_current { @product.update!(name: 'Bar') }
93
+ IndexProduct.perform(@product)
94
+
95
+ a.as_current { assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
96
+ b.as_current { assert_equal([@product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
97
+ c.as_current { assert_equal([@product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
98
+
99
+ Sidekiq::Callbacks.enable(IndexReleaseScheduleChange, IndexProduct) do
100
+ b.destroy
101
+ end
102
+
103
+ a.as_current { assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
104
+ c.as_current { assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
105
+ end
106
+ end
107
+ end
@@ -53,5 +53,11 @@ module Workarea
53
53
  t('workarea.admin.data_file_mailer.import_failure.errors')
54
54
  )
55
55
  end
56
+
57
+ def test_perform_with_missing_import
58
+ assert_raises Mongoid::Errors::DocumentNotFound do
59
+ ProcessImport.new.perform('foo')
60
+ end
61
+ end
56
62
  end
57
63
  end
@@ -2,6 +2,8 @@ require 'test_helper'
2
2
 
3
3
  module Workarea
4
4
  class PublishReleaseTest < TestCase
5
+ include TestCase::SearchIndexing
6
+
5
7
  def test_publishes_the_release
6
8
  release = create_release
7
9
  PublishRelease.new.perform(release.id)
@@ -16,5 +18,27 @@ module Workarea
16
18
  assert_equal(1, Mongoid::AuditLog::Entry.count)
17
19
  assert(Mongoid::AuditLog::Entry.first.modifier.system?)
18
20
  end
21
+
22
+ def test_reindexes_release_schedule
23
+ product = create_product(name: 'Foo')
24
+
25
+ a = create_release(publish_at: 1.week.from_now)
26
+ b = create_release(publish_at: 2.weeks.from_now)
27
+ c = create_release(publish_at: 4.weeks.from_now)
28
+
29
+ b.as_current { product.update!(name: 'Bar') }
30
+ IndexProduct.perform(product)
31
+
32
+ assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model))
33
+ a.as_current { assert_empty(Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
34
+ b.as_current { assert_equal([product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
35
+ c.as_current { assert_equal([product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
36
+
37
+ Sidekiq::Callbacks.enable(IndexProduct) { PublishRelease.new.perform(b.id) }
38
+
39
+ assert_equal([product], Search::ProductSearch.new(q: 'bar').results.pluck(:model))
40
+ a.as_current { assert_equal([product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
41
+ c.as_current { assert_equal([product], Search::ProductSearch.new(q: 'bar').results.pluck(:model)) }
42
+ end
19
43
  end
20
44
  end
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
25
25
  s.add_dependency 'mongoid-sample', '~> 0.1.0'
26
26
  s.add_dependency 'mongoid-encrypted', '~> 1.0.0'
27
27
  s.add_dependency 'elasticsearch', '~> 5.0.1'
28
- s.add_dependency 'kaminari', '~> 0.17.0'
28
+ s.add_dependency 'kaminari', '~> 1.2.1'
29
29
  s.add_dependency 'kaminari-mongoid', '~> 0.1.2'
30
30
  s.add_dependency 'activemerchant', '~> 1.52'
31
31
  s.add_dependency 'dragonfly', '~> 1.1.2'
@@ -33,7 +33,8 @@ Gem::Specification.new do |s|
33
33
  s.add_dependency 'sidekiq-cron', '~> 0.6.3'
34
34
  s.add_dependency 'sidekiq-unique-jobs', '~> 6.0.6'
35
35
  s.add_dependency 'sidekiq-throttled', '~> 0.8.2'
36
- s.add_dependency 'geocoder', '~> 1.4.4'
36
+ s.add_dependency 'geocoder', '~> 1.6.3'
37
+ s.add_dependency 'redis-rails', '~> 5.0.0'
37
38
  s.add_dependency 'redis-rack-cache', '~> 2.2.0'
38
39
  s.add_dependency 'easymon', '~> 1.4.0'
39
40
  s.add_dependency 'image_optim', '~> 0.26.0'
@@ -65,7 +66,7 @@ Gem::Specification.new do |s|
65
66
  s.add_dependency 'chart-horizontalbar-rails', '~> 1.0.4' # TODO remove v4
66
67
  s.add_dependency 'select2-rails', '~> 4.0.3'
67
68
  s.add_dependency 'wysihtml-rails', '~> 0.6.0.beta2'
68
- s.add_dependency 'rack-attack', '~> 5.0.1'
69
+ s.add_dependency 'rack-attack', '~> 6.3.1'
69
70
  s.add_dependency 'jquery-livetype-rails', '~> 0.1.0' # TODO remove v4
70
71
  s.add_dependency 'redcarpet', '~> 3.4.0'
71
72
  s.add_dependency 'jquery-unique-clone-rails', '~> 1.0.0'
@@ -93,7 +94,7 @@ Gem::Specification.new do |s|
93
94
  s.add_dependency 'chartkick', '~> 3.3.0'
94
95
  s.add_dependency 'browser', '~> 2.6.1'
95
96
  s.add_dependency 'puma', '>= 4.3.1'
96
- s.add_dependency 'rack', '>= 2.0.8'
97
+ s.add_dependency 'rack' , '>= 2.1.4'
97
98
 
98
99
  # HACK for vendoring active_shipping
99
100
  s.add_dependency 'active_utils', '~> 3.3.1'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: workarea-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.11
4
+ version: 3.5.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Crouse
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-13 00:00:00.000000000 Z
11
+ date: 2020-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -170,14 +170,14 @@ dependencies:
170
170
  requirements:
171
171
  - - "~>"
172
172
  - !ruby/object:Gem::Version
173
- version: 0.17.0
173
+ version: 1.2.1
174
174
  type: :runtime
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - "~>"
179
179
  - !ruby/object:Gem::Version
180
- version: 0.17.0
180
+ version: 1.2.1
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: kaminari-mongoid
183
183
  requirement: !ruby/object:Gem::Requirement
@@ -282,14 +282,28 @@ dependencies:
282
282
  requirements:
283
283
  - - "~>"
284
284
  - !ruby/object:Gem::Version
285
- version: 1.4.4
285
+ version: 1.6.3
286
286
  type: :runtime
287
287
  prerelease: false
288
288
  version_requirements: !ruby/object:Gem::Requirement
289
289
  requirements:
290
290
  - - "~>"
291
291
  - !ruby/object:Gem::Version
292
- version: 1.4.4
292
+ version: 1.6.3
293
+ - !ruby/object:Gem::Dependency
294
+ name: redis-rails
295
+ requirement: !ruby/object:Gem::Requirement
296
+ requirements:
297
+ - - "~>"
298
+ - !ruby/object:Gem::Version
299
+ version: 5.0.0
300
+ type: :runtime
301
+ prerelease: false
302
+ version_requirements: !ruby/object:Gem::Requirement
303
+ requirements:
304
+ - - "~>"
305
+ - !ruby/object:Gem::Version
306
+ version: 5.0.0
293
307
  - !ruby/object:Gem::Dependency
294
308
  name: redis-rack-cache
295
309
  requirement: !ruby/object:Gem::Requirement
@@ -730,14 +744,14 @@ dependencies:
730
744
  requirements:
731
745
  - - "~>"
732
746
  - !ruby/object:Gem::Version
733
- version: 5.0.1
747
+ version: 6.3.1
734
748
  type: :runtime
735
749
  prerelease: false
736
750
  version_requirements: !ruby/object:Gem::Requirement
737
751
  requirements:
738
752
  - - "~>"
739
753
  - !ruby/object:Gem::Version
740
- version: 5.0.1
754
+ version: 6.3.1
741
755
  - !ruby/object:Gem::Dependency
742
756
  name: jquery-livetype-rails
743
757
  requirement: !ruby/object:Gem::Requirement
@@ -1128,14 +1142,14 @@ dependencies:
1128
1142
  requirements:
1129
1143
  - - ">="
1130
1144
  - !ruby/object:Gem::Version
1131
- version: 2.0.8
1145
+ version: 2.1.4
1132
1146
  type: :runtime
1133
1147
  prerelease: false
1134
1148
  version_requirements: !ruby/object:Gem::Requirement
1135
1149
  requirements:
1136
1150
  - - ">="
1137
1151
  - !ruby/object:Gem::Version
1138
- version: 2.0.8
1152
+ version: 2.1.4
1139
1153
  - !ruby/object:Gem::Dependency
1140
1154
  name: active_utils
1141
1155
  requirement: !ruby/object:Gem::Requirement
@@ -1720,6 +1734,7 @@ files:
1720
1734
  - app/services/workarea/direct_upload/product_image.rb
1721
1735
  - app/services/workarea/export_report.rb
1722
1736
  - app/services/workarea/hash_update.rb
1737
+ - app/services/workarea/index_release_schedule_previews.rb
1723
1738
  - app/services/workarea/inventory_adjustment.rb
1724
1739
  - app/services/workarea/login.rb
1725
1740
  - app/services/workarea/new_discount.rb
@@ -1757,6 +1772,7 @@ files:
1757
1772
  - app/workers/workarea/index_product.rb
1758
1773
  - app/workers/workarea/index_product_children.rb
1759
1774
  - app/workers/workarea/index_product_rule.rb
1775
+ - app/workers/workarea/index_release_schedule_change.rb
1760
1776
  - app/workers/workarea/index_search_customizations.rb
1761
1777
  - app/workers/workarea/index_skus.rb
1762
1778
  - app/workers/workarea/keep_product_index_fresh.rb
@@ -1930,6 +1946,7 @@ files:
1930
1946
  - lib/workarea/ext/freedom_patches/string.rb
1931
1947
  - lib/workarea/ext/freedom_patches/uri.rb
1932
1948
  - lib/workarea/ext/jbuilder/jbuilder_append_partials.rb
1949
+ - lib/workarea/ext/jbuilder/jbuilder_cache.rb
1933
1950
  - lib/workarea/ext/mongoid/audit_log_entry.decorator
1934
1951
  - lib/workarea/ext/mongoid/each_by.rb
1935
1952
  - lib/workarea/ext/mongoid/embedded_children.rb
@@ -1964,6 +1981,7 @@ files:
1964
1981
  - lib/workarea/ping_home_base.rb
1965
1982
  - lib/workarea/plugin.rb
1966
1983
  - lib/workarea/plugin/asset_appends_helper.rb
1984
+ - lib/workarea/queues_pauser.rb
1967
1985
  - lib/workarea/routes_constraints/redirect.rb
1968
1986
  - lib/workarea/routes_constraints/super_admin.rb
1969
1987
  - lib/workarea/scheduled_jobs.rb
@@ -2314,6 +2332,7 @@ files:
2314
2332
  - test/models/workarea/search/storefront/product/inventory_test.rb
2315
2333
  - test/models/workarea/search/storefront/product/pricing_test.rb
2316
2334
  - test/models/workarea/search/storefront/product/text_test.rb
2335
+ - test/models/workarea/search/storefront/product_releases_test.rb
2317
2336
  - test/models/workarea/search/storefront/product_test.rb
2318
2337
  - test/models/workarea/search/storefront_test.rb
2319
2338
  - test/models/workarea/segment/life_cycle_test.rb
@@ -2365,7 +2384,6 @@ files:
2365
2384
  - test/queries/workarea/pricing_override_params_test.rb
2366
2385
  - test/queries/workarea/product_primary_image_url_test.rb
2367
2386
  - test/queries/workarea/product_primary_navigation_test.rb
2368
- - test/queries/workarea/product_releases_test.rb
2369
2387
  - test/queries/workarea/recommendation/order_based_test.rb
2370
2388
  - test/queries/workarea/recommendation/product_based_test.rb
2371
2389
  - test/queries/workarea/recommendation/searches_test.rb
@@ -2426,6 +2444,7 @@ files:
2426
2444
  - test/services/workarea/direct_upload_test.rb
2427
2445
  - test/services/workarea/export_report_test.rb
2428
2446
  - test/services/workarea/hash_update_test.rb
2447
+ - test/services/workarea/index_release_schedule_previews_test.rb
2429
2448
  - test/services/workarea/inventory_adjustment_test.rb
2430
2449
  - test/services/workarea/login_test.rb
2431
2450
  - test/services/workarea/order_merge_test.rb
@@ -2458,6 +2477,7 @@ files:
2458
2477
  - test/workers/workarea/index_payment_transactions_test.rb
2459
2478
  - test/workers/workarea/index_product_rule_test.rb
2460
2479
  - test/workers/workarea/index_product_test.rb
2480
+ - test/workers/workarea/index_release_schedule_change_test.rb
2461
2481
  - test/workers/workarea/index_skus_test.rb
2462
2482
  - test/workers/workarea/keep_product_index_fresh_test.rb
2463
2483
  - test/workers/workarea/mark_discounts_as_redeemed_test.rb
@@ -1,56 +0,0 @@
1
- require 'test_helper'
2
-
3
- module Workarea
4
- class ProductReleasesTest < TestCase
5
- def test_product_changes
6
- product = create_product(name: 'Foo')
7
- release_one = create_release
8
- release_one.as_current { product.update!(name: 'Bar') }
9
-
10
- assert_equal([release_one], ProductReleases.new(product).releases)
11
-
12
- release_one.update!(publish_at: 1.day.from_now)
13
- release_two = create_release(publish_at: 3.days.from_now)
14
- assert_equal([release_one, release_two], ProductReleases.new(product).releases)
15
- end
16
-
17
- def test_featured_product_changes
18
- product = create_product
19
- category = create_category
20
-
21
- release_one = create_release
22
- release_one.as_current { category.update!(product_ids: [product.id]) }
23
- assert_equal([release_one], ProductReleases.new(product).releases)
24
-
25
- release_one.update!(publish_at: 1.day.from_now)
26
- release_two = create_release(publish_at: 3.days.from_now)
27
- assert_equal([release_one, release_two], ProductReleases.new(product).releases)
28
- end
29
-
30
- def test_variant_changes
31
- product = create_product(variants: [{ sku: 'SKU' }])
32
- release = create_release
33
- release.as_current { product.variants.first.update!(details: { color: 'Red' }) }
34
- assert_equal([release], ProductReleases.new(product).releases)
35
- end
36
-
37
- def test_pricing_changes
38
- product = create_product(variants: [{ sku: 'SKU' }])
39
- pricing = Pricing::Sku.find('SKU')
40
-
41
- release = create_release
42
- release.as_current { pricing.prices.first.update!(regular: 10_000) }
43
- assert_equal([release], ProductReleases.new(product).releases)
44
- end
45
-
46
- def test_changesets_with_missing_releases
47
- product = create_product(name: 'Foo')
48
- release = create_release
49
- release.as_current { product.update!(name: 'Bar') }
50
- release.delete
51
-
52
- assert_nil(product.reload.changesets.first.release)
53
- assert_equal([], ProductReleases.new(product).releases)
54
- end
55
- end
56
- end