workarea-api-storefront 4.4.6 → 4.5.4

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +52 -0
  3. data/README.md +4 -7
  4. data/app/controllers/workarea/api/storefront/analytics_controller.rb +31 -19
  5. data/app/controllers/workarea/api/storefront/application_controller.rb +15 -2
  6. data/app/controllers/workarea/api/storefront/authentication.rb +6 -9
  7. data/app/controllers/workarea/api/storefront/categories_controller.rb +3 -1
  8. data/app/controllers/workarea/api/storefront/checkouts_controller.rb +0 -1
  9. data/app/controllers/workarea/api/storefront/menus_controller.rb +3 -1
  10. data/app/controllers/workarea/api/storefront/pages_controller.rb +3 -1
  11. data/app/controllers/workarea/api/storefront/products_controller.rb +3 -1
  12. data/app/controllers/workarea/api/storefront/recent_views_controller.rb +13 -26
  13. data/app/controllers/workarea/api/storefront/recommendations_controller.rb +2 -8
  14. data/app/controllers/workarea/api/storefront/searches_controller.rb +0 -12
  15. data/app/views/workarea/api/storefront/categories/show.json.jbuilder +1 -1
  16. data/app/views/workarea/api/storefront/email_signups/show.json.jbuilder +1 -1
  17. data/app/views/workarea/api/storefront/menus/_menu.json.jbuilder +1 -1
  18. data/app/views/workarea/api/storefront/pages/show.json.jbuilder +1 -1
  19. data/app/views/workarea/api/storefront/recent_views/show.json.jbuilder +0 -1
  20. data/app/views/workarea/api/storefront/searches/show.json.jbuilder +1 -1
  21. data/app/views/workarea/api/storefront/system_content/show.json.jbuilder +1 -1
  22. data/config/initializers/config.rb +19 -0
  23. data/lib/workarea/api/storefront.rb +1 -0
  24. data/lib/workarea/api/storefront/visit.decorator +52 -0
  25. data/test/documentation/workarea/api/storefront/checkouts_documentation_test.rb +21 -0
  26. data/test/documentation/workarea/api/storefront/segmentation_documentation_test.rb +104 -0
  27. data/test/documentation/workarea/api/storefront/validation_documentation_test.rb +1 -1
  28. data/test/dummy/config/initializers/session_store.rb +3 -1
  29. data/test/integration/workarea/api/storefront/analytics_integration_test.rb +12 -7
  30. data/test/integration/workarea/api/storefront/recent_views_integration_test.rb +38 -33
  31. data/test/integration/workarea/api/storefront/recommendations_integration_test.rb +1 -1
  32. data/test/integration/workarea/api/storefront/searches_integration_test.rb +0 -36
  33. data/test/integration/workarea/api/storefront/segments_integration_test.rb +218 -0
  34. data/workarea-api-storefront.gemspec +8 -7
  35. metadata +19 -15
  36. data/app/controllers/workarea/api/storefront/user_activity.rb +0 -36
  37. data/app/view_models/workarea/api/storefront/search_suggestion_view_model.rb +0 -21
@@ -13,3 +13,4 @@ end
13
13
 
14
14
  require 'workarea/api/version'
15
15
  require 'workarea/api/storefront/engine'
16
+ require 'workarea/api/storefront/visit.decorator'
@@ -0,0 +1,52 @@
1
+ module Workarea
2
+ decorate Visit, with: 'storefront_api' do
3
+ def api?
4
+ return @api if defined?(@api)
5
+ @api = Workarea.config.is_api_visit.call(request)
6
+ end
7
+
8
+ def cookies
9
+ api? ? {} : super
10
+ end
11
+
12
+ def session
13
+ api? ? {} : super
14
+ end
15
+
16
+ def logged_in?
17
+ return super unless api?
18
+
19
+ regex = ActionController::HttpAuthentication::Token::TOKEN_REGEX
20
+ request.authorization.to_s[regex].present?
21
+ end
22
+
23
+ def current_email
24
+ return super unless api?
25
+ return request.params['email'] unless logged_in?
26
+ return @current_email if defined? @current_email
27
+
28
+ @current_email = current_user&.email
29
+ end
30
+
31
+ def current_user
32
+ token, options = ActionController::HttpAuthentication::Token.token_and_options(request)
33
+ @current_user ||= Api::Storefront::Authentication.find_user(token, options)
34
+ end
35
+
36
+ def sessions
37
+ api? ? request.params['sessions'].to_i : super
38
+ end
39
+
40
+ def current_metrics_id
41
+ return super unless api?
42
+
43
+ return @current_metrics_id if defined?(@current_metrics_id)
44
+ @current_metrics_id = current_email.presence || request.params['session_id']
45
+ end
46
+
47
+ def current_metrics_id=(value)
48
+ return super unless api?
49
+ # Unsupported in the API
50
+ end
51
+ end
52
+ end
@@ -85,6 +85,27 @@ module Workarea
85
85
  end
86
86
  end
87
87
 
88
+ def test_and_document_update_failure
89
+ description 'Failure to update a checkout'
90
+ route storefront_api.checkout_path(':id')
91
+ explanation <<-EOS
92
+ This is an example of what occurs when you fail to send in the correct parameters for your checkout.
93
+ EOS
94
+
95
+ record_request do
96
+ patch storefront_api.checkout_path(@order),
97
+ as: :json,
98
+ params: {
99
+ email: 'susanb@workarea.com',
100
+ shipping_address: address.except(:first_name),
101
+ billing_address: address.except(:last_name),
102
+ shipping_service: 'Express'
103
+ }
104
+
105
+ assert_equal(422, response.status)
106
+ end
107
+ end
108
+
88
109
  def test_and_document_complete
89
110
  description 'Completing a checkout'
90
111
  route storefront_api.complete_checkout_path(':id')
@@ -0,0 +1,104 @@
1
+ require 'test_helper'
2
+ require 'workarea/api/documentation_test'
3
+
4
+ module Workarea
5
+ module Api
6
+ module Storefront
7
+ class SegmentationDocumentationTest < DocumentationTest
8
+ resource 'Segmentation'
9
+
10
+ def test_and_document_session_count
11
+ description 'Specifying session count for segmentation'
12
+ route storefront_api.system_content_path('home_page')
13
+ explanation <<~EOS
14
+ Workarea supports segmenting users by number of sessions, e.g.
15
+ first-time vs returning visitors. To support this in the storefront
16
+ API, the client will be responsible for managing this since the API
17
+ is stateless (doesn't have cookies/session).
18
+
19
+ To get session-based segments functioning, you need to pass a
20
+ `sessions` parameter in each request. Workarea will use that as
21
+ the number of sessions for determing the segments for the response.
22
+ This works for all requests across the storefront API.
23
+
24
+ This example shows getting a home page with segmented content based
25
+ on the number of sessions.
26
+ EOS
27
+
28
+ first_time = Segment::FirstTimeVisitor.instance
29
+ returning = Segment::ReturningVisitor.instance
30
+
31
+ content = Content.for('Home Page')
32
+ content.blocks.create!(
33
+ type: 'text',
34
+ data: { text: 'Hello visitor!' },
35
+ active_segment_ids: [first_time.id]
36
+ )
37
+ content.blocks.create!(
38
+ type: 'text',
39
+ data: { text: 'Welcome back!' },
40
+ active_segment_ids: [returning.id]
41
+ )
42
+
43
+ record_request do
44
+ get storefront_api.system_content_path('home_page', sessions: 1)
45
+ assert_match(/Hello visitor!/, response.body)
46
+ assert(response.ok?)
47
+ end
48
+ record_request do
49
+ get storefront_api.system_content_path('home_page', sessions: 2)
50
+ assert_match(/Welcome back!/, response.body)
51
+ assert(response.ok?)
52
+ end
53
+ end
54
+
55
+ def test_and_document_session_ids
56
+ description 'Using session IDs for segmenting non-authenticated users'
57
+ route storefront_api.system_content_path('home_page')
58
+ explanation <<~EOS
59
+ Workarea supports segmenting users by number of orders, revenue, etc.
60
+ For this functionality to work for users without accounts, you'll
61
+ need to maintain and pass a `session_id` consistently throughout calls
62
+ to the API.
63
+
64
+ An instance of `Metrics::User` will be found or created for that
65
+ `session_id`, and data about the user will be tracked there.
66
+
67
+ Assuming use of the `session_id` consistently through checkout, this
68
+ example shows getting home page content for two different anonymous
69
+ users and getting segmented content back.
70
+ EOS
71
+
72
+ first_time = Segment::FirstTimeCustomer.instance
73
+ returning = Segment::ReturningCustomer.instance
74
+
75
+ Metrics::User.create!(id: 'session_1', orders: 1)
76
+ Metrics::User.create!(id: 'session_2', orders: 2)
77
+
78
+ content = Content.for('Home Page')
79
+ content.blocks.create!(
80
+ type: 'text',
81
+ data: { text: 'Thanks for your order!' },
82
+ active_segment_ids: [first_time.id]
83
+ )
84
+ content.blocks.create!(
85
+ type: 'text',
86
+ data: { text: 'Welcome back repeat customer!' },
87
+ active_segment_ids: [returning.id]
88
+ )
89
+
90
+ record_request do
91
+ get storefront_api.system_content_path('home_page', session_id: 'session_1')
92
+ assert_match(/Thanks/, response.body)
93
+ assert(response.ok?)
94
+ end
95
+ record_request do
96
+ get storefront_api.system_content_path('home_page', session_id: 'session_2')
97
+ assert_match(/Welcome back/, response.body)
98
+ assert(response.ok?)
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -72,7 +72,7 @@ module Workarea
72
72
  }
73
73
  }
74
74
 
75
- assert_equal(200, response.status)
75
+ assert_equal(422, response.status)
76
76
  end
77
77
  end
78
78
  end
@@ -1,3 +1,5 @@
1
1
  # Be sure to restart your server when you modify this file.
2
2
 
3
- Rails.application.config.session_store :cookie_store, key: '_dummy_session'
3
+ Rails.application.config.session_store :cookie_store,
4
+ key: '_dummy_session',
5
+ expire_after: 30.minutes
@@ -7,11 +7,19 @@ module Workarea
7
7
  def test_saving_category_view
8
8
  post storefront_api.analytics_category_view_path(category_id: 'foo')
9
9
  assert_equal(1, Metrics::CategoryByDay.first.views)
10
+
11
+ post storefront_api.analytics_category_view_path(category_id: 'foo', session_id: '1')
12
+ assert_equal(2, Metrics::CategoryByDay.first.views)
13
+ assert_equal(%w(foo), Metrics::User.find('1').viewed.category_ids)
10
14
  end
11
15
 
12
16
  def test_saving_product_view
13
17
  post storefront_api.analytics_product_view_path(product_id: 'foo')
14
18
  assert_equal(1, Metrics::ProductByDay.first.views)
19
+
20
+ post storefront_api.analytics_product_view_path(product_id: 'foo', session_id: '1')
21
+ assert_equal(2, Metrics::ProductByDay.first.views)
22
+ assert_equal(%w(foo), Metrics::User.find('1').viewed.product_ids)
15
23
  end
16
24
 
17
25
  def test_saving_search
@@ -21,14 +29,11 @@ module Workarea
21
29
  insights = Metrics::SearchByDay.first
22
30
  assert_equal(1, insights.searches)
23
31
  assert_equal(5, insights.total_results)
24
- end
25
32
 
26
- def test_saving_search_abandonment
27
- # Saving abandonment is deprecated, and this will be removed in v3.5
28
- end
29
-
30
- def test_saving_filters
31
- # Saving filters is deprecated, and this will be removed in v3.5
33
+ post storefront_api.analytics_search_path,
34
+ params: { q: 'foo', total_results: 5, session_id: '1' }
35
+ assert_equal(2, insights.reload.searches)
36
+ assert_equal(%w(foo), Metrics::User.find('1').viewed.search_ids)
32
37
  end
33
38
  end
34
39
  end
@@ -19,30 +19,38 @@ module Workarea
19
19
 
20
20
  def test_showing_recent_views_with_authentication
21
21
  user = create_user(first_name: 'Ben', last_name: 'Crouse')
22
- set_current_user(user)
22
+ post storefront_api.authentication_tokens_path,
23
+ params: { email: user.email, password: user.password }
24
+ token = JSON.parse(response.body)['token']
23
25
 
24
- activity = create_user_activity(
25
- id: user.id,
26
+ Metrics::User.save_affinity(
27
+ id: user.email,
28
+ action: 'viewed',
26
29
  product_ids: [@product.id],
27
30
  category_ids: [@category.id],
28
- searches: ['foo']
31
+ at: Time.current,
32
+ search_ids: %w(foo)
29
33
  )
30
34
 
31
- get storefront_api.recent_views_path
35
+ get storefront_api.recent_views_path,
36
+ headers: { 'HTTP_AUTHORIZATION' => encode_credentials(token) }
32
37
 
33
38
  assert(response.ok?)
34
39
  result = JSON.parse(response.body)
35
40
 
36
- assert_equal(activity.id, result['id'])
41
+ assert_equal(user.email, result['id'])
37
42
  assert_equal(@product.id, result['products'].first['id'])
38
43
  assert_equal(@category.id.to_s, result['categories'].first['id'])
39
- assert_includes(result['searches'], 'foo')
40
44
  end
41
45
 
42
46
  def test_adding_recent_views_for_authentication
43
47
  user = create_user(first_name: 'Ben', last_name: 'Crouse')
44
- set_current_user(user)
48
+ post storefront_api.authentication_tokens_path,
49
+ params: { email: user.email, password: user.password }
50
+ token = JSON.parse(response.body)['token']
51
+
45
52
  patch storefront_api.recent_views_path,
53
+ headers: { 'HTTP_AUTHORIZATION' => encode_credentials(token) },
46
54
  params: {
47
55
  product_id: @product.id,
48
56
  category_id: @category.id,
@@ -51,54 +59,51 @@ module Workarea
51
59
 
52
60
  assert(response.ok?)
53
61
 
54
- user_activity = Recommendation::UserActivity.first
55
- assert_equal(user.id.to_s, user_activity.id.to_s)
56
- assert_includes(user_activity.product_ids, @product.id)
57
- assert_includes(user_activity.category_ids, @category.id.to_s)
58
- assert_includes(user_activity.searches, 'foo')
62
+ user_activity = Workarea::Storefront::UserActivityViewModel.wrap(
63
+ Metrics::User.first
64
+ )
65
+ assert_equal(user.email, user_activity.id)
66
+ assert_includes(user_activity.products, @product)
67
+ assert_includes(user_activity.categories, @category)
59
68
  end
60
69
 
61
70
  def test_showing_recent_views_with_session_id
62
- activity = create_user_activity(
71
+ Metrics::User.save_affinity(
72
+ id: BSON::ObjectId.new.to_s,
73
+ action: 'viewed',
63
74
  product_ids: [@product.id],
64
75
  category_ids: [@category.id],
65
- searches: ['bar']
76
+ search_ids: %w(foo)
66
77
  )
78
+ activity = Metrics::User.last
67
79
 
68
80
  get storefront_api.recent_views_path,
69
81
  params: { session_id: activity.id }
70
82
 
71
- assert(response.ok?)
83
+ assert_response(:success)
72
84
  result = JSON.parse(response.body)
73
85
 
74
- assert_equal(activity.id, result['id'])
75
- assert_equal(@product.id, result['products'].first['id'])
86
+ assert_equal(activity.id.to_s, result['id'])
87
+ assert_equal(@product.id.to_s, result['products'].first['id'])
76
88
  assert_equal(@category.id.to_s, result['categories'].first['id'])
77
- assert_includes(result['searches'], 'bar')
78
89
  end
79
90
 
80
91
  def test_adding_recent_views_for_session_id
81
- activity = create_user_activity(
82
- product_ids: [@product.id],
83
- category_ids: [@category.id],
84
- searches: ['bar']
85
- )
86
-
87
92
  patch storefront_api.recent_views_path,
88
93
  params: {
89
- session_id: activity.id,
94
+ session_id: BSON::ObjectId.new.to_s,
90
95
  product_id: @product.id,
91
96
  category_id: @category.id,
92
97
  search: 'bar'
93
98
  }
94
99
 
95
- assert(response.ok?)
100
+ assert_response(:success)
96
101
 
97
- user_activity = Recommendation::UserActivity.first
98
- assert_equal(activity.id, user_activity.id)
99
- assert_includes(user_activity.product_ids, @product.id)
100
- assert_includes(user_activity.category_ids, @category.id.to_s)
101
- assert_includes(user_activity.searches, 'bar')
102
+ user_activity = Workarea::Storefront::UserActivityViewModel.wrap(
103
+ Metrics::User.first
104
+ )
105
+ assert_includes(user_activity.products, @product)
106
+ assert_includes(user_activity.categories, @category)
102
107
  end
103
108
 
104
109
  def test_adding_without_id
@@ -110,7 +115,7 @@ module Workarea
110
115
  }
111
116
 
112
117
  refute(response.ok?)
113
- assert_equal(0, Recommendation::UserActivity.count)
118
+ assert_equal(0, Metrics::User.count)
114
119
  end
115
120
  end
116
121
  end
@@ -23,7 +23,7 @@ module Workarea
23
23
  end
24
24
 
25
25
  def set_user_activity
26
- @activity = create_user_activity
26
+ @activity = Metrics::User.create!
27
27
  end
28
28
 
29
29
  def test_showing_recommendations_with_authentication
@@ -4,42 +4,6 @@ module Workarea
4
4
  module Api
5
5
  module Storefront
6
6
  class SearchesIntegrationTest < IntegrationTest
7
- def test_showing_search_autocomplete
8
- create_product(name: 'Foo')
9
- create_category(name: 'Foo Category')
10
- create_page(name: 'Foo Page')
11
-
12
- Metrics::SearchByDay.save_search('foo', 3)
13
- travel_to 1.weeks.from_now
14
- GenerateInsights.generate_all!
15
- BulkIndexSearches.perform
16
-
17
- get storefront_api.searches_path(q: 'foo')
18
- results = JSON.parse(response.body)['results']
19
- assert_equal(4, results.length)
20
-
21
- search = results.detect { |r| r['type'] == 'Searches' }
22
- assert(search.present?)
23
- assert_equal('foo', search['value'])
24
- assert_equal(storefront_api.search_path(q: 'foo'), search['url'])
25
-
26
- product = results.detect { |r| r['type'] == 'Products' }
27
- assert(product.present?)
28
- assert_equal('Foo', product['value'])
29
- assert_match(/product_images/, product['image'])
30
- assert_equal(storefront_api.product_path('foo'), product['url'])
31
-
32
- category = results.detect { |r| r['type'] == 'Categories' }
33
- assert(category.present?)
34
- assert_equal('Foo Category', category['value'])
35
- assert_equal(storefront_api.category_path('foo-category'), category['url'])
36
-
37
- page = results.detect { |r| r['type'] == 'Pages' }
38
- assert(page.present?)
39
- assert_equal('Foo Page', page['value'])
40
- assert_equal(storefront_api.page_path('foo-page'), page['url'])
41
- end
42
-
43
7
  def test_shows_search_results
44
8
  Search::Settings.current.update_attributes!(terms_facets: %w(Color Size))
45
9
  create_product(
@@ -0,0 +1,218 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ module Api
5
+ module Storefront
6
+ class SegmentsIntegrationTest < IntegrationTest
7
+ include AuthenticationTest
8
+
9
+ def test_sessions_functionality
10
+ first_time = Segment::FirstTimeVisitor.instance
11
+ returning = Segment::ReturningVisitor.instance
12
+
13
+ get storefront_api.system_content_path('home_page')
14
+ assert_equal(first_time.id.to_s, response.headers['X-Workarea-Segments'])
15
+
16
+ get storefront_api.system_content_path('home_page'), params: { sessions: 1 }
17
+ assert_equal(first_time.id.to_s, response.headers['X-Workarea-Segments'])
18
+
19
+ get storefront_api.system_content_path('home_page'), params: { sessions: 2 }
20
+ assert_equal(returning.id.to_s, response.headers['X-Workarea-Segments'])
21
+ end
22
+
23
+ def test_current_email_functionality
24
+ first_time = Segment::FirstTimeCustomer.instance
25
+ returning = Segment::ReturningCustomer.instance
26
+
27
+ Metrics::User.save_order(email: 'first-time@workarea.com', revenue: 1.to_m)
28
+ Metrics::User.save_order(email: 'returning@workarea.com', revenue: 1.to_m)
29
+ Metrics::User.save_order(email: 'returning@workarea.com', revenue: 1.to_m)
30
+
31
+ get storefront_api.system_content_path('home_page')
32
+ assert(response.headers['X-Workarea-Segments'].blank?)
33
+
34
+ get storefront_api.system_content_path('home_page'), params: { email: 'first-time@workarea.com' }
35
+ assert_equal(first_time.id.to_s, response.headers['X-Workarea-Segments'])
36
+
37
+ get storefront_api.system_content_path('home_page'), params: { email: 'returning@workarea.com' }
38
+ assert_equal(returning.id.to_s, response.headers['X-Workarea-Segments'])
39
+ end
40
+
41
+ def test_session_ids_for_metrics
42
+ first_time = Segment::FirstTimeCustomer.instance
43
+ returning = Segment::ReturningCustomer.instance
44
+
45
+ Metrics::User.create!(id: '1', orders: 1)
46
+ Metrics::User.create!(id: '2', orders: 2)
47
+
48
+ get storefront_api.system_content_path('home_page')
49
+ assert(response.headers['X-Workarea-Segments'].blank?)
50
+
51
+ get storefront_api.system_content_path('home_page'), params: { session_id: '1' }
52
+ assert_equal(first_time.id.to_s, response.headers['X-Workarea-Segments'])
53
+
54
+ get storefront_api.system_content_path('home_page'), params: { session_id: '2' }
55
+ assert_equal(returning.id.to_s, response.headers['X-Workarea-Segments'])
56
+ end
57
+
58
+ def test_products_active_by_segment
59
+ segment_one = create_segment(rules: [Segment::Rules::Sessions.new(minimum: 1, maximum: 1)])
60
+ segment_two = create_segment(rules: [Segment::Rules::Sessions.new(minimum: 2, maximum: 2)])
61
+ product_one = create_product(active: true, active_segment_ids: [segment_two.id])
62
+ product_two = create_product(active: true, active_segment_ids: [segment_one.id])
63
+
64
+ assert_raise InvalidDisplay do
65
+ get storefront_api.product_path(product_one), params: { sessions: 0 }
66
+ assert(response.not_found?)
67
+ end
68
+
69
+ assert_raise InvalidDisplay do
70
+ get storefront_api.product_path(product_two), params: { sessions: 0 }
71
+ assert(response.not_found?)
72
+ end
73
+
74
+ get storefront_api.search_path(q: '*'), params: { sessions: 0 }
75
+ assert(JSON.parse(response.body)['products'].empty?)
76
+
77
+ assert_raise InvalidDisplay do
78
+ get storefront_api.product_path(product_one), params: { sessions: 1 }
79
+ assert(response.not_found?)
80
+ end
81
+
82
+ get storefront_api.product_path(product_two), params: { sessions: 1 }
83
+ assert(response.ok?)
84
+
85
+ get storefront_api.search_path(q: '*'), params: { sessions: 1 }
86
+ products = JSON.parse(response.body)['products']
87
+ assert_equal([product_two.id], products.map { |p| p['id'] })
88
+
89
+ get storefront_api.product_path(product_one), params: { sessions: 2 }
90
+ assert(response.ok?)
91
+
92
+ assert_raise InvalidDisplay do
93
+ get storefront_api.product_path(product_two), params: { sessions: 2 }
94
+ assert(response.not_found?)
95
+ end
96
+
97
+ get storefront_api.search_path(q: '*'), params: { sessions: 2 }
98
+ products = JSON.parse(response.body)['products']
99
+ assert_equal([product_one.id], products.map { |p| p['id'] })
100
+
101
+ segment_one.rules.first.update!(minimum: 1, maximum: nil)
102
+ segment_two.rules.first.update!(minimum: 1, maximum: nil)
103
+
104
+ get storefront_api.product_path(product_one), params: { sessions: 1 }
105
+ assert(response.ok?)
106
+
107
+ get storefront_api.product_path(product_two), params: { sessions: 1 }
108
+ assert(response.ok?)
109
+
110
+ get storefront_api.search_path(q: '*'), params: { sessions: 1 }
111
+ products = JSON.parse(response.body)['products']
112
+ assert_equal(2, products.count)
113
+ assert_includes(products.map { |r| r['id'] }, product_one.id)
114
+ assert_includes(products.map { |r| r['id'] }, product_two.id)
115
+ end
116
+
117
+ def test_content_active_by_segment
118
+ segment_one = create_segment(rules: [Segment::Rules::Sessions.new(minimum: 1, maximum: 1)])
119
+ segment_two = create_segment(rules: [Segment::Rules::Sessions.new(minimum: 2, maximum: 2)])
120
+
121
+ content = Content.for('home_page')
122
+ foo = content.blocks.create!(
123
+ type: 'html',
124
+ data: { 'html' => '<p>Foo</p>' },
125
+ active_segment_ids: [segment_one.id]
126
+ )
127
+ bar = content.blocks.create!(
128
+ type: 'html',
129
+ data: { 'html' => '<p>Bar</p>' },
130
+ active_segment_ids: [segment_two.id]
131
+ )
132
+
133
+ get storefront_api.system_content_path('home_page'), params: { sessions: 1 }
134
+ content_blocks = JSON.parse(response.body)['content_blocks']
135
+ assert_equal([foo.id.to_s], content_blocks.map { |cb| cb['id'] })
136
+
137
+ get storefront_api.system_content_path('home_page'), params: { sessions: 2 }
138
+ content_blocks = JSON.parse(response.body)['content_blocks']
139
+ assert_equal([bar.id.to_s], content_blocks.map { |cb| cb['id'] })
140
+
141
+ segment_one.rules.first.update!(minimum: 1, maximum: nil)
142
+ segment_two.rules.first.update!(minimum: 1, maximum: nil)
143
+
144
+ get storefront_api.system_content_path('home_page'), params: { sessions: 1 }
145
+ content_blocks = JSON.parse(response.body)['content_blocks']
146
+ assert_equal([foo.id.to_s, bar.id.to_s], content_blocks.map { |cb| cb['id'] })
147
+ end
148
+
149
+ def test_logged_in_based_segments
150
+ logged_in = create_segment(rules: [Segment::Rules::LoggedIn.new(logged_in: true)])
151
+ logged_out = create_segment(rules: [Segment::Rules::LoggedIn.new(logged_in: false)])
152
+
153
+ get storefront_api.system_content_path('home_page')
154
+ assert_equal(logged_out.id.to_s, response.headers['X-Workarea-Segments'])
155
+
156
+ user = create_user
157
+ post storefront_api.authentication_tokens_path,
158
+ params: { email: user.email, password: user.password }
159
+
160
+ token = JSON.parse(response.body)['token']
161
+ get storefront_api.system_content_path('home_page'),
162
+ headers: { 'HTTP_AUTHORIZATION' => encode_credentials(token) }
163
+ assert_equal(logged_in.id.to_s, response.headers['X-Workarea-Segments'])
164
+ end
165
+
166
+ def test_http_caching_headers_for_segmented_content
167
+ Workarea.config.strip_http_caching_in_tests = false
168
+ segment = create_segment(rules: [Segment::Rules::Sessions.new(maximum: 999)])
169
+
170
+ get storefront_api.system_content_path('home_page')
171
+ refute_match(/private/, response.headers['Cache-Control'])
172
+ assert_match(/public/, response.headers['Cache-Control'])
173
+ assert(response.headers['X-Workarea-Segmented-Content'].blank?)
174
+
175
+ content = Content.for('home_page')
176
+ content.blocks.create!(
177
+ type: 'html',
178
+ data: { 'html' => '<p>Foo</p>' },
179
+ active_segment_ids: [segment.id]
180
+ )
181
+
182
+ get storefront_api.system_content_path('home_page')
183
+ assert_match(/private/, response.headers['Cache-Control'])
184
+ refute_match(/public/, response.headers['Cache-Control'])
185
+ assert_equal('true', response.headers['X-Workarea-Segmented-Content'])
186
+
187
+ product = create_product(active: true, active_segment_ids: [])
188
+ get storefront_api.product_path(product)
189
+ assert(response.ok?)
190
+ refute_match(/private/, response.headers['Cache-Control'])
191
+ assert_match(/public/, response.headers['Cache-Control'])
192
+ assert(response.headers['X-Workarea-Segmented-Content'].blank?)
193
+
194
+ product.update!(active_segment_ids: [segment.id])
195
+ get storefront_api.product_path(product)
196
+ assert(response.ok?)
197
+ assert_match(/private/, response.headers['Cache-Control'])
198
+ refute_match(/public/, response.headers['Cache-Control'])
199
+ assert_equal('true', response.headers['X-Workarea-Segmented-Content'])
200
+
201
+ category = create_category(active: true, active_segment_ids: [])
202
+ get storefront_api.category_path(category)
203
+ assert(response.ok?)
204
+ refute_match(/private/, response.headers['Cache-Control'])
205
+ assert_match(/public/, response.headers['Cache-Control'])
206
+ assert(response.headers['X-Workarea-Segmented-Content'].blank?)
207
+
208
+ category.update!(product_ids: [product.id])
209
+ get storefront_api.category_path(category)
210
+ assert(response.ok?)
211
+ assert_match(/private/, response.headers['Cache-Control'])
212
+ refute_match(/public/, response.headers['Cache-Control'])
213
+ assert_equal('true', response.headers['X-Workarea-Segmented-Content'])
214
+ end
215
+ end
216
+ end
217
+ end
218
+ end