@ordergroove/offers 2.26.11 → 2.27.1
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.
- package/CHANGELOG.md +34 -0
- package/README.md +34 -0
- package/build.js +3 -1
- package/dist/bundle-report.html +185 -116
- package/dist/offers.js +65 -76
- package/dist/offers.js.map +3 -3
- package/examples/cart.js +105 -0
- package/examples/index.html +2 -2
- package/examples/products/cheap-watch.js +183 -0
- package/examples/shopify-cart.html +26 -0
- package/examples/shopify-pdp.html +34 -0
- package/karma.conf.js +2 -1
- package/package.json +4 -4
- package/src/__tests__/offers.spec.js +35 -10
- package/src/components/FrequencyStatus.js +14 -11
- package/src/components/IncentiveText.js +2 -1
- package/src/components/Offer.js +14 -7
- package/src/components/OptinButton.js +1 -1
- package/src/components/OptinSelect.js +2 -2
- package/src/components/OptinToggle.js +2 -2
- package/src/components/OptoutButton.js +1 -1
- package/src/components/Price.js +7 -3
- package/src/components/Select.js +3 -13
- package/src/components/SelectFrequency.js +24 -6
- package/src/components/TestWizard.js +1 -1
- package/src/components/__tests__/OG.fspec.js +24 -0
- package/src/components/__tests__/Offer.spec.js +4 -4
- package/src/components/__tests__/OptinButton.spec.js +2 -2
- package/src/components/__tests__/OptinToggle.spec.js +2 -2
- package/src/components/__tests__/OptoutButton.spec.js +1 -1
- package/src/components/__tests__/SelectFrequency.fspec.js +1 -0
- package/src/components/__tests__/SelectFrequency.spec.js +1 -1
- package/src/components/__tests__/TestWizard.spec.js +2 -2
- package/src/components/__tests__/Text.spec.js +5 -1
- package/src/core/__tests__/actions.spec.js +6 -6
- package/src/core/actions.js +22 -17
- package/src/core/constants.js +21 -0
- package/src/core/descriptors.js +2 -1
- package/src/core/middleware.js +41 -1
- package/src/core/reducer.js +22 -21
- package/src/core/resolveProperties.js +2 -7
- package/src/core/selectors.js +1 -1
- package/src/core/store.js +17 -9
- package/src/core/utils.ts +67 -0
- package/src/index.js +46 -203
- package/src/make-api.js +195 -0
- package/src/platform.ts +9 -0
- package/src/shopify/__tests__/shopifyMiddleware.spec.js +126 -0
- package/src/shopify/__tests__/shopifyReducer.spec.js +489 -0
- package/src/shopify/shopifyBootstrap.ts +136 -0
- package/src/shopify/shopifyMiddleware.ts +336 -0
- package/src/shopify/shopifyReducer.js +254 -0
- package/tsconfig.json +35 -0
- package/examples/5starnutrition-main.js +0 -3
- package/examples/single-offer.html +0 -9
- package/src/init-test.js +0 -3
package/examples/cart.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{
|
|
2
|
+
"################################# README ":"This file is for Dev only and meant to match shopify /cart.js api. Should be json but with js extension",
|
|
3
|
+
"note": null,
|
|
4
|
+
"attributes": {},
|
|
5
|
+
"original_total_price": 2670,
|
|
6
|
+
"total_price": 2670,
|
|
7
|
+
"total_discount": 0,
|
|
8
|
+
"total_weight": 0.0,
|
|
9
|
+
"item_count": 3,
|
|
10
|
+
"items": [
|
|
11
|
+
{
|
|
12
|
+
"id": 40909392609469,
|
|
13
|
+
"properties": {
|
|
14
|
+
"_og-cart-interactions": [
|
|
15
|
+
"frequency change",
|
|
16
|
+
"frequency change",
|
|
17
|
+
"frequency change",
|
|
18
|
+
"frequency change",
|
|
19
|
+
"frequency change",
|
|
20
|
+
"frequency change"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"quantity": 3,
|
|
24
|
+
"variant_id": 40909392609469,
|
|
25
|
+
"key": "40909392609469:e0e784cd9cab078d741e3fb4a5f35a94",
|
|
26
|
+
"title": "Cheap Watch",
|
|
27
|
+
"price": 890,
|
|
28
|
+
"original_price": 890,
|
|
29
|
+
"discounted_price": 890,
|
|
30
|
+
"line_price": 2670,
|
|
31
|
+
"original_line_price": 2670,
|
|
32
|
+
"total_discount": 0,
|
|
33
|
+
"discounts": [],
|
|
34
|
+
"sku": "",
|
|
35
|
+
"grams": 0,
|
|
36
|
+
"vendor": "Clara's Clocks",
|
|
37
|
+
"taxable": true,
|
|
38
|
+
"product_id": 7032252694717,
|
|
39
|
+
"product_has_only_default_variant": true,
|
|
40
|
+
"gift_card": false,
|
|
41
|
+
"final_price": 890,
|
|
42
|
+
"final_line_price": 2670,
|
|
43
|
+
"url": "\/products\/cheap-watch?variant=40909392609469",
|
|
44
|
+
"featured_image": {
|
|
45
|
+
"aspect_ratio": 0.728,
|
|
46
|
+
"alt": "Cheap Watch",
|
|
47
|
+
"height": 717,
|
|
48
|
+
"url": "https:\/\/cdn.shopify.com\/s\/files\/1\/0596\/3526\/9821\/products\/71unaYjYidL._AC_UX522.jpg?v=1634657932",
|
|
49
|
+
"width": 522
|
|
50
|
+
},
|
|
51
|
+
"image": "https:\/\/cdn.shopify.com\/s\/files\/1\/0596\/3526\/9821\/products\/71unaYjYidL._AC_UX522.jpg?v=1634657932",
|
|
52
|
+
"handle": "cheap-watch",
|
|
53
|
+
"requires_shipping": true,
|
|
54
|
+
"product_type": "",
|
|
55
|
+
"product_title": "Cheap Watch",
|
|
56
|
+
"product_description": "A cheap rainbow watch.",
|
|
57
|
+
"variant_title": null,
|
|
58
|
+
"variant_options": ["Default Title"],
|
|
59
|
+
"options_with_values": [
|
|
60
|
+
{
|
|
61
|
+
"name": "Title",
|
|
62
|
+
"value": "Default Title"
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"line_level_discount_allocations": [],
|
|
66
|
+
"line_level_total_discount": 0,
|
|
67
|
+
"selling_plan_allocation": {
|
|
68
|
+
"price_adjustments": [
|
|
69
|
+
{
|
|
70
|
+
"position": 1,
|
|
71
|
+
"price": 890
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"price": 890,
|
|
75
|
+
"compare_at_price": 1000,
|
|
76
|
+
"per_delivery_price": 890,
|
|
77
|
+
"selling_plan": {
|
|
78
|
+
"id": 547455165,
|
|
79
|
+
"name": "Delivered every 3 months, get 11% off your first order",
|
|
80
|
+
"description": null,
|
|
81
|
+
"options": [
|
|
82
|
+
{
|
|
83
|
+
"name": "Delivery every",
|
|
84
|
+
"position": 1,
|
|
85
|
+
"value": "3 months"
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"recurring_deliveries": true,
|
|
89
|
+
"price_adjustments": [
|
|
90
|
+
{
|
|
91
|
+
"order_count": null,
|
|
92
|
+
"position": 1,
|
|
93
|
+
"value_type": "percentage",
|
|
94
|
+
"value": 11
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
],
|
|
101
|
+
"requires_shipping": true,
|
|
102
|
+
"currency": "USD",
|
|
103
|
+
"items_subtotal_price": 2670,
|
|
104
|
+
"cart_level_discount_applications": []
|
|
105
|
+
}
|
package/examples/index.html
CHANGED
|
@@ -121,8 +121,8 @@
|
|
|
121
121
|
|
|
122
122
|
<pre id="the-html"></pre>
|
|
123
123
|
<textarea id="the-js" readonly></textarea>
|
|
124
|
-
<script type="text/javascript" src="examples.js"></script>
|
|
124
|
+
<script type="text/javascript" src="../dist/examples.js"></script>
|
|
125
125
|
<!-- offers should be latest since it overides og.offers namespace -->
|
|
126
|
-
<script type="text/javascript" src="offers.js"></script>
|
|
126
|
+
<script type="text/javascript" src="../dist/offers.js"></script>
|
|
127
127
|
</body>
|
|
128
128
|
</html>
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
{
|
|
2
|
+
"################################# README ":"This file is for Dev only and meant to match shopify /products/<handle>.js api. Should be json but with js extension",
|
|
3
|
+
"id": 7032252694717,
|
|
4
|
+
"title": "Cheap Watch",
|
|
5
|
+
"handle": "cheap-watch",
|
|
6
|
+
"description": "A cheap rainbow watch.",
|
|
7
|
+
"published_at": "2021-10-19T11:38:52-04:00",
|
|
8
|
+
"created_at": "2021-10-19T11:38:51-04:00",
|
|
9
|
+
"vendor": "Clara's Clocks",
|
|
10
|
+
"type": "",
|
|
11
|
+
"tags": [],
|
|
12
|
+
"price": 1000,
|
|
13
|
+
"price_min": 1000,
|
|
14
|
+
"price_max": 1000,
|
|
15
|
+
"available": true,
|
|
16
|
+
"price_varies": false,
|
|
17
|
+
"compare_at_price": null,
|
|
18
|
+
"compare_at_price_min": 0,
|
|
19
|
+
"compare_at_price_max": 0,
|
|
20
|
+
"compare_at_price_varies": false,
|
|
21
|
+
"variants": [
|
|
22
|
+
{
|
|
23
|
+
"id": 40909392609469,
|
|
24
|
+
"title": "Default Title",
|
|
25
|
+
"option1": "Default Title",
|
|
26
|
+
"option2": null,
|
|
27
|
+
"option3": null,
|
|
28
|
+
"sku": "",
|
|
29
|
+
"requires_shipping": true,
|
|
30
|
+
"taxable": true,
|
|
31
|
+
"featured_image": null,
|
|
32
|
+
"available": true,
|
|
33
|
+
"name": "Cheap Watch",
|
|
34
|
+
"public_title": null,
|
|
35
|
+
"options": ["Default Title"],
|
|
36
|
+
"price": 1000,
|
|
37
|
+
"weight": 0,
|
|
38
|
+
"compare_at_price": null,
|
|
39
|
+
"inventory_management": null,
|
|
40
|
+
"barcode": "",
|
|
41
|
+
"requires_selling_plan": true,
|
|
42
|
+
"selling_plan_allocations": [
|
|
43
|
+
{
|
|
44
|
+
"price_adjustments": [
|
|
45
|
+
{
|
|
46
|
+
"position": 1,
|
|
47
|
+
"price": 890
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"price": 890,
|
|
51
|
+
"compare_at_price": 1000,
|
|
52
|
+
"per_delivery_price": 890,
|
|
53
|
+
"selling_plan_id": 547389629,
|
|
54
|
+
"selling_plan_group_id": "1a1dc6d22dd730c6851c3596f5c46e26ff776cc2"
|
|
55
|
+
}, {
|
|
56
|
+
"price_adjustments": [
|
|
57
|
+
{
|
|
58
|
+
"position": 1,
|
|
59
|
+
"price": 890
|
|
60
|
+
}
|
|
61
|
+
],
|
|
62
|
+
"price": 890,
|
|
63
|
+
"compare_at_price": 1000,
|
|
64
|
+
"per_delivery_price": 890,
|
|
65
|
+
"selling_plan_id": 547422397,
|
|
66
|
+
"selling_plan_group_id": "1a1dc6d22dd730c6851c3596f5c46e26ff776cc2"
|
|
67
|
+
}, {
|
|
68
|
+
"price_adjustments": [
|
|
69
|
+
{
|
|
70
|
+
"position": 1,
|
|
71
|
+
"price": 890
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"price": 890,
|
|
75
|
+
"compare_at_price": 1000,
|
|
76
|
+
"per_delivery_price": 890,
|
|
77
|
+
"selling_plan_id": 547455165,
|
|
78
|
+
"selling_plan_group_id": "1a1dc6d22dd730c6851c3596f5c46e26ff776cc2"
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
"images": ["//cdn.shopify.com/s/files/1/0596/3526/9821/products/71unaYjYidL._AC_UX522.jpg?v=1634657932"],
|
|
84
|
+
"featured_image": "//cdn.shopify.com/s/files/1/0596/3526/9821/products/71unaYjYidL._AC_UX522.jpg?v=1634657932",
|
|
85
|
+
"options": ["Title"],
|
|
86
|
+
"media": [
|
|
87
|
+
{
|
|
88
|
+
"alt": null,
|
|
89
|
+
"id": 22999019061437,
|
|
90
|
+
"position": 1,
|
|
91
|
+
"preview_image": {
|
|
92
|
+
"aspect_ratio": 0.728,
|
|
93
|
+
"height": 717,
|
|
94
|
+
"width": 522,
|
|
95
|
+
"src": "https://cdn.shopify.com/s/files/1/0596/3526/9821/products/71unaYjYidL._AC_UX522.jpg?v=1634657932"
|
|
96
|
+
},
|
|
97
|
+
"aspect_ratio": 0.728,
|
|
98
|
+
"height": 717,
|
|
99
|
+
"media_type": "image",
|
|
100
|
+
"src": "https://cdn.shopify.com/s/files/1/0596/3526/9821/products/71unaYjYidL._AC_UX522.jpg?v=1634657932",
|
|
101
|
+
"width": 522
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"requires_selling_plan": true,
|
|
105
|
+
"selling_plan_groups": [
|
|
106
|
+
{
|
|
107
|
+
"id": "1a1dc6d22dd730c6851c3596f5c46e26ff776cc2",
|
|
108
|
+
"name": "Subscribe and Save",
|
|
109
|
+
"options": [
|
|
110
|
+
{
|
|
111
|
+
"name": "Delivery every",
|
|
112
|
+
"position": 1,
|
|
113
|
+
"values": ["month", "2 months", "3 months"]
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
"selling_plans": [
|
|
117
|
+
{
|
|
118
|
+
"id": 547389629,
|
|
119
|
+
"name": "Delivered every month, get 11% off your first order",
|
|
120
|
+
"description": null,
|
|
121
|
+
"options": [
|
|
122
|
+
{
|
|
123
|
+
"name": "Delivery every",
|
|
124
|
+
"position": 1,
|
|
125
|
+
"value": "month"
|
|
126
|
+
}
|
|
127
|
+
],
|
|
128
|
+
"recurring_deliveries": true,
|
|
129
|
+
"price_adjustments": [
|
|
130
|
+
{
|
|
131
|
+
"order_count": null,
|
|
132
|
+
"position": 1,
|
|
133
|
+
"value_type": "percentage",
|
|
134
|
+
"value": 11
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
}, {
|
|
138
|
+
"id": 547422397,
|
|
139
|
+
"name": "Delivered every 2 months, get 11% off your first order",
|
|
140
|
+
"description": null,
|
|
141
|
+
"options": [
|
|
142
|
+
{
|
|
143
|
+
"name": "Delivery every",
|
|
144
|
+
"position": 1,
|
|
145
|
+
"value": "2 months"
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
"recurring_deliveries": true,
|
|
149
|
+
"price_adjustments": [
|
|
150
|
+
{
|
|
151
|
+
"order_count": null,
|
|
152
|
+
"position": 1,
|
|
153
|
+
"value_type": "percentage",
|
|
154
|
+
"value": 11
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
}, {
|
|
158
|
+
"id": 547455165,
|
|
159
|
+
"name": "Delivered every 3 months, get 11% off your first order",
|
|
160
|
+
"description": null,
|
|
161
|
+
"options": [
|
|
162
|
+
{
|
|
163
|
+
"name": "Delivery every",
|
|
164
|
+
"position": 1,
|
|
165
|
+
"value": "3 months"
|
|
166
|
+
}
|
|
167
|
+
],
|
|
168
|
+
"recurring_deliveries": true,
|
|
169
|
+
"price_adjustments": [
|
|
170
|
+
{
|
|
171
|
+
"order_count": null,
|
|
172
|
+
"position": 1,
|
|
173
|
+
"value_type": "percentage",
|
|
174
|
+
"value": 11
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
],
|
|
179
|
+
"app_id": null
|
|
180
|
+
}
|
|
181
|
+
],
|
|
182
|
+
"content": "A cheap rainbow watch."
|
|
183
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Ordergroove Offers</title>
|
|
5
|
+
</head>
|
|
6
|
+
<body id="single-offer" >
|
|
7
|
+
<h1>cart</h1>
|
|
8
|
+
<og-offer product="40909392609469" id="regular1" location="cart" cart></og-offer>
|
|
9
|
+
<!-- offers should be latest since it overides og.offers namespace -->
|
|
10
|
+
|
|
11
|
+
<script type="text/javascript">
|
|
12
|
+
var Shopify = {
|
|
13
|
+
routes: {
|
|
14
|
+
root: './'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
</script>
|
|
18
|
+
<script type="text/javascript" src="../dist/offers.js"></script>
|
|
19
|
+
<script type="text/javascript">
|
|
20
|
+
og
|
|
21
|
+
.offers
|
|
22
|
+
.initialize('0e5de2bedc5e11e3a2e4bc764e106cf4', 'staging')
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
</body>
|
|
26
|
+
</html>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Ordergroove Offers</title>
|
|
5
|
+
|
|
6
|
+
<meta property="og:type" content="product">
|
|
7
|
+
<meta property="og:url" content="https://claras-clocks.myshopify.com/products/cheap-watch">
|
|
8
|
+
|
|
9
|
+
</head>
|
|
10
|
+
<body id="single-offer" >
|
|
11
|
+
|
|
12
|
+
<form action="shopify-cart.html" menthod="POST">
|
|
13
|
+
<og-offer product="40909392609469" id="regular1"></og-offer>
|
|
14
|
+
<!-- offers should be latest since it overides og.offers namespace -->
|
|
15
|
+
<button> Add to cart</button>
|
|
16
|
+
</form>
|
|
17
|
+
|
|
18
|
+
<script type="text/javascript">
|
|
19
|
+
var Shopify = {
|
|
20
|
+
routes: {
|
|
21
|
+
root: './'
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<script type="text/javascript" src="../dist/offers.js"></script>
|
|
27
|
+
|
|
28
|
+
<script type="text/javascript">
|
|
29
|
+
og
|
|
30
|
+
.offers
|
|
31
|
+
.initialize('0e5de2bedc5e11e3a2e4bc764e106cf4', 'staging')
|
|
32
|
+
</script>
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|
package/karma.conf.js
CHANGED
|
@@ -9,8 +9,9 @@ module.exports = function(config) {
|
|
|
9
9
|
|
|
10
10
|
// list of files / patterns to load in the browser
|
|
11
11
|
files: [
|
|
12
|
+
// make sure is the first on the list that inits the offers module
|
|
12
13
|
{
|
|
13
|
-
pattern: 'src/
|
|
14
|
+
pattern: 'src/__tests__/offers.spec.js',
|
|
14
15
|
type: 'js',
|
|
15
16
|
included: true,
|
|
16
17
|
served: true
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ordergroove/offers",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.27.1",
|
|
4
4
|
"description": "offer state component",
|
|
5
5
|
"author": "Eugenio Lattanzio <eugenio63@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/ordergroove/plush-toys#readme",
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
14
|
"start": "npm run build -- --serve",
|
|
15
|
-
"build": "rm -rf dist && mkdir dist &&
|
|
15
|
+
"build": "rm -rf dist && mkdir dist && node build.js",
|
|
16
16
|
"build:prod": "rm -rf dist && node build.js --prod",
|
|
17
17
|
"bundlesize": "../../node_modules/.bin/bundlesize",
|
|
18
18
|
"lint": "../../node_modules/.bin/eslint --ignore-path ../../.gitignore ./src",
|
|
19
19
|
"prepublishOnly": "npm run -s build:prod && npm run -s bundlesize",
|
|
20
20
|
"test": "../../node_modules/.bin/karma start --single-run --log-level error --reporters progress && npm run build && ../../node_modules/.bin/karma start --single-run --log-level error --reporters progress karma-functional.conf.js",
|
|
21
21
|
"test:watch": "../../node_modules/.bin/karma start",
|
|
22
|
-
"test:watch:functional": "npm run build
|
|
22
|
+
"test:watch:functional": "npm run build && ../../node_modules/.bin/karma start karma-functional.conf.js",
|
|
23
23
|
"test:functional": "npm run test:watch:functional -- --single-run --log-level error --reporters progress",
|
|
24
24
|
"test:watch:silent": "../../node_modules/.bin/karma start --log-level error --reporters dots"
|
|
25
25
|
},
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@ordergroove/offers-templates": "^0.4.12"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "0a8ee052a83ef6c5a7936a08d9af27065764cf36"
|
|
49
49
|
}
|
|
@@ -1,6 +1,36 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as offersAll from '../index';
|
|
2
2
|
import { api } from '../core/api';
|
|
3
3
|
|
|
4
|
+
const offers = offersAll.offers;
|
|
5
|
+
|
|
6
|
+
describe('Offers API', () => {
|
|
7
|
+
// offers.initialize('some-merchant', 'staging');
|
|
8
|
+
const facade = jasmine.objectContaining({
|
|
9
|
+
store: jasmine.any(Object),
|
|
10
|
+
addOptinChangedCallback: jasmine.any(Function),
|
|
11
|
+
addTemplate: jasmine.any(Function),
|
|
12
|
+
clear: jasmine.any(Function),
|
|
13
|
+
config: jasmine.any(Function),
|
|
14
|
+
disableOptinChangedCallbacks: jasmine.any(Function),
|
|
15
|
+
getOptins: jasmine.any(Function),
|
|
16
|
+
getProductsForPurchasePost: jasmine.any(Function),
|
|
17
|
+
initialize: jasmine.any(Function),
|
|
18
|
+
previewMode: jasmine.any(Function),
|
|
19
|
+
register: jasmine.any(Function),
|
|
20
|
+
resolveSettings: jasmine.any(Function),
|
|
21
|
+
setAuthUrl: jasmine.any(Function),
|
|
22
|
+
setEnvironment: jasmine.any(Function),
|
|
23
|
+
setLocale: jasmine.any(Function),
|
|
24
|
+
setMerchantId: jasmine.any(Function),
|
|
25
|
+
setPublicPath: jasmine.any(Function),
|
|
26
|
+
setTemplates: jasmine.any(Function)
|
|
27
|
+
});
|
|
28
|
+
it('imported ', () => {
|
|
29
|
+
expect(offersAll).toEqual(facade);
|
|
30
|
+
expect(offers).toEqual(facade);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
4
34
|
describe('Offers', () => {
|
|
5
35
|
let register, fetchOfferSpy, mockStore;
|
|
6
36
|
// TODO revisit chunks
|
|
@@ -23,25 +53,20 @@ describe('Offers', () => {
|
|
|
23
53
|
});
|
|
24
54
|
|
|
25
55
|
it('should warn if attempting to initialize twice', () => {
|
|
56
|
+
const resolveSettings = spyOn(offers, 'resolveSettings');
|
|
26
57
|
const warn = spyOn(console, 'warn');
|
|
27
58
|
|
|
28
59
|
offers.initialize('0e5de2bedc5e11e3a2e4bc764e106cf4', 'staging');
|
|
29
60
|
expect(warn).not.toHaveBeenCalled();
|
|
30
|
-
|
|
31
|
-
offers.initialize('0e5de2bedc5e11e3a2e4bc764e106cf4', 'staging');
|
|
32
|
-
expect(warn).toHaveBeenCalledWith('og.offers has been initialized already. Skipping.');
|
|
33
|
-
expect(register).toHaveBeenCalledTimes(1);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('should warn if attempting to initialize twice', () => {
|
|
37
|
-
const resolveSettings = spyOn(offers, 'resolveSettings');
|
|
38
|
-
offers.initialize('0e5de2bedc5e11e3a2e4bc764e106cf4', 'staging');
|
|
39
61
|
expect(resolveSettings).toHaveBeenCalledWith(
|
|
40
62
|
'0e5de2bedc5e11e3a2e4bc764e106cf4',
|
|
41
63
|
'staging',
|
|
42
64
|
undefined,
|
|
43
65
|
offers.store
|
|
44
66
|
);
|
|
67
|
+
offers.initialize('0e5de2bedc5e11e3a2e4bc764e106cf4', 'staging');
|
|
68
|
+
expect(warn).toHaveBeenCalledWith('og.offers has been initialized already. Skipping.');
|
|
69
|
+
expect(register).not.toHaveBeenCalled();
|
|
45
70
|
});
|
|
46
71
|
|
|
47
72
|
describe('offers.resolveSettings', () => {
|
|
@@ -14,16 +14,17 @@ import { TemplateElement } from '../core/base';
|
|
|
14
14
|
|
|
15
15
|
export const frequencyText = (frequency, initial) => {
|
|
16
16
|
const { every, every_period: period } = parseFrequency(frequency);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
return every && period
|
|
18
|
+
? html`
|
|
19
|
+
${every}
|
|
20
|
+
<og-text key="frequencyPeriods" variant="${period}" pluralize="${every}"></og-text>
|
|
21
|
+
${initial && initial === frequency
|
|
22
|
+
? html`
|
|
23
|
+
<og-text key="defaultFrequencyCopy"></og-text>
|
|
24
|
+
`
|
|
25
|
+
: ''}
|
|
26
|
+
`
|
|
27
|
+
: frequency;
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
export class FrequencyStatus extends withProduct(TemplateElement) {
|
|
@@ -90,7 +91,9 @@ export const mapStateToProps = (state, ownProps) => ({
|
|
|
90
91
|
subscribed: makeOptedinSelector(ownProps.product)(state),
|
|
91
92
|
frequency: makeProductFrequencySelector(ownProps.product)(state),
|
|
92
93
|
productDefaultFrequency: makeProductDefaultFrequencySelector((ownProps.product || {}).id)(state),
|
|
93
|
-
|
|
94
|
+
configDefaultFrequency: state.config?.defaultFrequency,
|
|
95
|
+
frequenciesText: state.config?.frequenciesText,
|
|
96
|
+
...configSelector(state, ownProps, 'frequencies'),
|
|
94
97
|
...configSelector(state, ownProps, 'defaultFrequency'),
|
|
95
98
|
...templatesSelector(state, ownProps)
|
|
96
99
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LitElement, html } from 'lit-element';
|
|
2
2
|
import { connect } from '../core/connect';
|
|
3
3
|
import { withProduct } from '../core/resolveProperties';
|
|
4
|
+
import { safeProductId } from '../core/utils';
|
|
4
5
|
|
|
5
6
|
export class DiscountAmount {
|
|
6
7
|
constructor(value) {
|
|
@@ -121,7 +122,7 @@ export class IncentiveText extends withProduct(LitElement) {
|
|
|
121
122
|
}
|
|
122
123
|
|
|
123
124
|
export const mapStateToProps = (state, ownProps) => ({
|
|
124
|
-
incentives: (state.incentives || {})[ownProps && ownProps
|
|
125
|
+
incentives: (state.incentives || {})[ownProps && ownProps?.product && safeProductId(ownProps?.product?.id)] || {}
|
|
125
126
|
});
|
|
126
127
|
|
|
127
128
|
export const ConnectedIncentiveText = connect(mapStateToProps)(IncentiveText);
|
package/src/components/Offer.js
CHANGED
|
@@ -23,6 +23,8 @@ import {
|
|
|
23
23
|
} from '../core/selectors';
|
|
24
24
|
import { product as productProp, auth as authProp } from '../core/props';
|
|
25
25
|
import { TemplateElement } from '../core/base';
|
|
26
|
+
import { onReady } from '../core/utils';
|
|
27
|
+
import { DEFAULT_OFFER_MODULE } from '../core/constants';
|
|
26
28
|
|
|
27
29
|
const memoizeKey = (...args) => JSON.stringify(args);
|
|
28
30
|
|
|
@@ -49,7 +51,10 @@ export class Offer extends TemplateElement {
|
|
|
49
51
|
firstOrderPlaceDate: { type: String, attribute: 'first-order-place-date' },
|
|
50
52
|
productToSubscribe: { type: String, attribute: 'product-to-subscribe' },
|
|
51
53
|
subscribed: { type: Boolean, reflect: true },
|
|
52
|
-
frequency: { type: String, reflect: true }
|
|
54
|
+
frequency: { type: String, reflect: true },
|
|
55
|
+
productFrequency: { type: String },
|
|
56
|
+
isCart: { type: Boolean, attribute: 'cart' },
|
|
57
|
+
optedin: { type: Object }
|
|
53
58
|
};
|
|
54
59
|
}
|
|
55
60
|
|
|
@@ -141,11 +146,10 @@ export class Offer extends TemplateElement {
|
|
|
141
146
|
</div>
|
|
142
147
|
<div>
|
|
143
148
|
<og-optin-button>
|
|
144
|
-
|
|
145
|
-
|
|
146
149
|
<og-price discount>
|
|
147
150
|
<span slot="prepend">Subscribe and get</span>
|
|
148
151
|
<span slot="append">off</span>
|
|
152
|
+
<og-text key="offerOptInLabel" slot="fallback"></og-text>
|
|
149
153
|
</og-price>
|
|
150
154
|
<og-price regular></og-price>
|
|
151
155
|
<og-price subscription></og-price>
|
|
@@ -213,6 +217,7 @@ export class Offer extends TemplateElement {
|
|
|
213
217
|
The product is in your next upcomming order
|
|
214
218
|
</og-when>
|
|
215
219
|
</og-when>
|
|
220
|
+
|
|
216
221
|
`;
|
|
217
222
|
}
|
|
218
223
|
|
|
@@ -241,10 +246,10 @@ export class Offer extends TemplateElement {
|
|
|
241
246
|
if (changed.has('preview')) {
|
|
242
247
|
this.setPreview(this.preview, changed.get('preview'), this);
|
|
243
248
|
}
|
|
244
|
-
|
|
245
249
|
this.frequency = this.defaultFrequency;
|
|
250
|
+
|
|
246
251
|
if (changed.has('product') && this.product.id && !this.isPreview) {
|
|
247
|
-
this.fetchOffer(this.product.id);
|
|
252
|
+
onReady(() => this.fetchOffer(this.product.id, DEFAULT_OFFER_MODULE, this));
|
|
248
253
|
}
|
|
249
254
|
|
|
250
255
|
if (changed.has('firstOrderPlaceDate') && this.product.id && !this.isPreview) {
|
|
@@ -277,7 +282,7 @@ export class Offer extends TemplateElement {
|
|
|
277
282
|
changed.has('product')) &&
|
|
278
283
|
this.offerId &&
|
|
279
284
|
this.autoshipByDefault &&
|
|
280
|
-
this.location === 'cart' &&
|
|
285
|
+
(this.location === 'cart' || this.isCart) &&
|
|
281
286
|
this.product.id &&
|
|
282
287
|
this.optinProduct &&
|
|
283
288
|
!(this.optedin || []).find(product => isSameProduct(product, this.product))
|
|
@@ -287,7 +292,8 @@ export class Offer extends TemplateElement {
|
|
|
287
292
|
...this.product,
|
|
288
293
|
...(this.productComponents.length && { components: this.productComponents })
|
|
289
294
|
},
|
|
290
|
-
this.defaultFrequency
|
|
295
|
+
this.defaultFrequency,
|
|
296
|
+
this
|
|
291
297
|
);
|
|
292
298
|
}
|
|
293
299
|
}
|
|
@@ -329,6 +335,7 @@ export const mapStateToProps = (state, ownProps) => ({
|
|
|
329
335
|
subscribed: makeOptedinSelector(ownProps.product)(state),
|
|
330
336
|
...templatesSelector(state)
|
|
331
337
|
});
|
|
338
|
+
|
|
332
339
|
export const ConnectedOffer = connect(mapStateToProps, {
|
|
333
340
|
fetchOffer,
|
|
334
341
|
fetchOrders,
|
|
@@ -36,9 +36,9 @@ export class OptinSelect extends withChildOptions(OptinStatus) {
|
|
|
36
36
|
|
|
37
37
|
onOptinChange(value) {
|
|
38
38
|
if (value === 'optedOut') {
|
|
39
|
-
this.optoutProduct(this.product);
|
|
39
|
+
this.optoutProduct(this.product, this.offer);
|
|
40
40
|
} else {
|
|
41
|
-
this.productChangeFrequency(this.product, value);
|
|
41
|
+
this.productChangeFrequency(this.product, value, this.offer);
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -49,8 +49,8 @@ export class OptinToggle extends OptinStatus {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
handleClick(ev) {
|
|
52
|
-
if (this.subscribed) this.optoutProduct(this.product);
|
|
53
|
-
else this.optinProduct(this.product, this.frequency || this.defaultFrequency);
|
|
52
|
+
if (this.subscribed) this.optoutProduct(this.product, this.offer);
|
|
53
|
+
else this.optinProduct(this.product, this.frequency || this.defaultFrequency, this.offer);
|
|
54
54
|
ev.preventDefault();
|
|
55
55
|
}
|
|
56
56
|
|