@ordergroove/offers 2.44.0 → 2.44.1-alpha-PR-1166-3.30
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/dist/bundle-report.html +52 -49
- package/dist/offers.js +38 -38
- package/dist/offers.js.map +4 -4
- package/package.json +2 -2
- package/src/components/FrequencyStatus.js +13 -10
- package/src/components/Offer.js +33 -14
- package/src/components/OptinButton.js +2 -2
- package/src/components/OptinSelect.js +5 -5
- package/src/components/OptinStatus.js +15 -9
- package/src/components/Price.js +3 -3
- package/src/components/SelectFrequency.js +11 -6
- package/src/components/TestWizard.js +45 -41
- package/src/components/UpsellModal.js +9 -3
- package/src/components/__tests__/Offer.spec.js +0 -19
- package/src/components/__tests__/OptinStatus.spec.js +17 -4
- package/src/core/__tests__/actions.spec.js +47 -1
- package/src/core/__tests__/base.spec.js +0 -77
- package/src/core/__tests__/offerRequest.spec.js +2 -1
- package/src/core/__tests__/selectors.spec.js +7 -7
- package/src/core/actions-preview.js +6 -3
- package/src/core/actions.js +22 -13
- package/src/core/base.js +0 -23
- package/src/core/offerRequest.js +1 -1
- package/src/core/{reducer.js → reducer.ts} +30 -10
- package/src/core/{selectors.js → selectors.ts} +73 -57
- package/src/core/types/api.ts +71 -0
- package/src/core/types/reducer.ts +95 -0
- package/src/core/types/utility.ts +1 -0
- package/src/core/utils.ts +32 -15
- package/src/make-api.js +1 -1
- package/src/shopify/__tests__/reducers/config.spec.js +497 -0
- package/src/shopify/__tests__/shopifyReducer.spec.js +65 -610
- package/src/shopify/__tests__/utils.spec.js +24 -1
- package/src/shopify/reducers/config.ts +223 -0
- package/src/shopify/shopifyMiddleware.ts +2 -9
- package/src/shopify/{shopifyReducer.js → shopifyReducer.ts} +45 -177
- package/src/shopify/utils.ts +25 -0
- package/src/types.ts +0 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ordergroove/offers",
|
|
3
|
-
"version": "2.44.
|
|
3
|
+
"version": "2.44.1-alpha-PR-1166-3.30+930d1b8c",
|
|
4
4
|
"description": "offer state component",
|
|
5
5
|
"author": "Eugenio Lattanzio <eugenio63@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/ordergroove/plush-toys#readme",
|
|
@@ -49,5 +49,5 @@
|
|
|
49
49
|
"@ordergroove/offers-templates": "^0.9.7",
|
|
50
50
|
"@types/lodash.memoize": "^4.1.9"
|
|
51
51
|
},
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "930d1b8c0307645ab97fbbc3a59ed98fae26bd6d"
|
|
53
53
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { html, css } from 'lit-element';
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
makeProductFrequencyOptedInSelector,
|
|
4
4
|
makeOptedinSelector,
|
|
5
|
-
|
|
5
|
+
getFallbackValue,
|
|
6
6
|
templatesSelector,
|
|
7
|
+
makeProductSpecificDefaultFrequencySelector,
|
|
8
|
+
makeProductFrequenciesSelector,
|
|
9
|
+
makeProductFrequencyOptionsSelector,
|
|
7
10
|
makeProductDefaultFrequencySelector
|
|
8
11
|
} from '../core/selectors';
|
|
9
12
|
import { connect } from '../core/connect';
|
|
@@ -89,14 +92,14 @@ export class FrequencyStatus extends withProduct(TemplateElement) {
|
|
|
89
92
|
|
|
90
93
|
export const mapStateToProps = (state, ownProps) => ({
|
|
91
94
|
subscribed: makeOptedinSelector(ownProps.product)(state),
|
|
92
|
-
frequency:
|
|
93
|
-
productDefaultFrequency:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
...
|
|
99
|
-
|
|
95
|
+
frequency: makeProductFrequencyOptedInSelector(ownProps.product)(state),
|
|
96
|
+
productDefaultFrequency: makeProductSpecificDefaultFrequencySelector((ownProps.product || {}).id)(state),
|
|
97
|
+
frequencies:
|
|
98
|
+
makeProductFrequencyOptionsSelector(ownProps.product?.id)(state) || getFallbackValue(ownProps, 'frequencies'),
|
|
99
|
+
defaultFrequency:
|
|
100
|
+
makeProductDefaultFrequencySelector(ownProps.product?.id)(state) || getFallbackValue(ownProps, 'defaultFrequency'),
|
|
101
|
+
...templatesSelector(state, ownProps),
|
|
102
|
+
productFrequencies: makeProductFrequenciesSelector(ownProps.product)(state)
|
|
100
103
|
});
|
|
101
104
|
|
|
102
105
|
export const ConnectedFrequencyStatus = connect(mapStateToProps)(FrequencyStatus);
|
package/src/components/Offer.js
CHANGED
|
@@ -12,14 +12,16 @@ import {
|
|
|
12
12
|
} from '../core/actions';
|
|
13
13
|
import {
|
|
14
14
|
isSameProduct,
|
|
15
|
-
|
|
15
|
+
getFallbackValue,
|
|
16
16
|
templatesSelector,
|
|
17
17
|
makeOptedoutSelector,
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
makeProductFrequencyOptedInSelector,
|
|
19
|
+
makeProductSpecificDefaultFrequencySelector,
|
|
20
20
|
optedinSelector,
|
|
21
21
|
autoshipSelector,
|
|
22
|
-
makeOptedinSelector
|
|
22
|
+
makeOptedinSelector,
|
|
23
|
+
kebabCase,
|
|
24
|
+
makeProductDefaultFrequencySelector
|
|
23
25
|
} from '../core/selectors';
|
|
24
26
|
import { product as productProp, auth as authProp } from '../core/props';
|
|
25
27
|
import { TemplateElement } from '../core/base';
|
|
@@ -339,12 +341,6 @@ export class Offer extends TemplateElement {
|
|
|
339
341
|
}
|
|
340
342
|
}
|
|
341
343
|
|
|
342
|
-
// product-specific frequency lists are not supported in cart offers
|
|
343
|
-
if (this.isCart && this.config?.hasProductSpecificFrequencies) {
|
|
344
|
-
logProductSpecificFrequencyListWarning();
|
|
345
|
-
return false;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
344
|
return true;
|
|
349
345
|
}
|
|
350
346
|
|
|
@@ -368,7 +364,27 @@ export class Offer extends TemplateElement {
|
|
|
368
364
|
return freq.currentFrequency;
|
|
369
365
|
}
|
|
370
366
|
|
|
371
|
-
|
|
367
|
+
// not certain if this logic was used or not -- the following code was inlined from a shared function that was only used here
|
|
368
|
+
const attributeValue = this.getValueFromAttribute('defaultFrequency');
|
|
369
|
+
if (attributeValue) {
|
|
370
|
+
return attributeValue;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (this.template && this.template.config && typeof this.template.config.defaultFrequency !== 'undefined') {
|
|
374
|
+
return this.template.config.defaultFrequency;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return this.configDefaultFrequency;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
getValueFromAttribute(key) {
|
|
381
|
+
const attrName = kebabCase(key);
|
|
382
|
+
if (this.hasAttribute(attrName)) {
|
|
383
|
+
const attr = this.getAttribute(attrName);
|
|
384
|
+
if (attr.toString().toLowerCase() === 'true') return true;
|
|
385
|
+
if (attr.toString().toLowerCase() === 'false') return false;
|
|
386
|
+
return attr;
|
|
387
|
+
}
|
|
372
388
|
}
|
|
373
389
|
}
|
|
374
390
|
|
|
@@ -376,9 +392,12 @@ export const mapStateToProps = (state, ownProps) => ({
|
|
|
376
392
|
config: state.config,
|
|
377
393
|
auth: state.auth,
|
|
378
394
|
offerId: ((state.productOffer || {})[(ownProps.product || {}).id] || [])[0],
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
395
|
+
configDefaultFrequency: makeProductDefaultFrequencySelector(ownProps.product?.id)(state),
|
|
396
|
+
productFrequency: makeProductFrequencyOptedInSelector(ownProps.product)(state),
|
|
397
|
+
productDefaultFrequency: makeProductSpecificDefaultFrequencySelector((ownProps.product || {}).id)(state),
|
|
398
|
+
autoshipByDefault:
|
|
399
|
+
(state.config && state.config.autoshipByDefault) ||
|
|
400
|
+
getFallbackValue(ownProps, 'autoshipByDefault', autoshipSelector(state)[(ownProps.product || {}).id]),
|
|
382
401
|
...(makeOptedoutSelector(ownProps.product)(state) && { autoshipByDefault: false }),
|
|
383
402
|
optedin: optedinSelector(state),
|
|
384
403
|
subscribed: makeOptedinSelector(ownProps.product)(state),
|
|
@@ -21,7 +21,7 @@ export class OptinButton extends OptinStatus {
|
|
|
21
21
|
if (changed.has('subscribed') || changed.has('frequencies')) {
|
|
22
22
|
if (platform.shopify_selling_plans && this.store) {
|
|
23
23
|
let buttonFreq = this.getAttribute('default-frequency');
|
|
24
|
-
buttonFreq = frequencyToSellingPlan(buttonFreq, this.
|
|
24
|
+
buttonFreq = frequencyToSellingPlan(buttonFreq, this.productFrequencies);
|
|
25
25
|
this.sellingPlanFreq = buttonFreq;
|
|
26
26
|
}
|
|
27
27
|
this.frequencyMatch = this.frequency === this.optinFrequency;
|
|
@@ -40,7 +40,7 @@ export class OptinButton extends OptinStatus {
|
|
|
40
40
|
freq = this.offer ? this.offer.defaultFrequency : this.defaultFrequency;
|
|
41
41
|
}
|
|
42
42
|
if (platform.shopify_selling_plans && this.store) {
|
|
43
|
-
freq = frequencyToSellingPlan(freq, this.
|
|
43
|
+
freq = frequencyToSellingPlan(freq, this.productFrequencies);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
return freq;
|
|
@@ -5,7 +5,7 @@ import { OptinStatus, mapStateToProps as mapStateToPropsOptinStatus } from './Op
|
|
|
5
5
|
import { mapStateToProps, frequencyText } from './FrequencyStatus';
|
|
6
6
|
import { connect } from '../core/connect';
|
|
7
7
|
import { defaultFrequency } from '../core/props';
|
|
8
|
-
import {
|
|
8
|
+
import { getFallbackValue, makeProductFrequencyOptionsSelector } from '../core/selectors';
|
|
9
9
|
|
|
10
10
|
export class OptinSelect extends withChildOptions(OptinStatus) {
|
|
11
11
|
static get properties() {
|
|
@@ -51,14 +51,13 @@ export class OptinSelect extends withChildOptions(OptinStatus) {
|
|
|
51
51
|
const { options: childOptions } = this.childOptions;
|
|
52
52
|
let options;
|
|
53
53
|
if (this.frequencies?.length) {
|
|
54
|
+
const { frequenciesText } = this.productFrequencies;
|
|
54
55
|
options = [
|
|
55
56
|
...([childOptions.find(option => option.value === 'optedOut')] || []),
|
|
56
57
|
...this.frequencies.map((value, ix) => ({
|
|
57
58
|
value,
|
|
58
59
|
text:
|
|
59
|
-
|
|
60
|
-
? this.frequenciesText[ix]
|
|
61
|
-
: frequencyText(value, this.defaultFrequency)
|
|
60
|
+
frequenciesText && ix in frequenciesText ? frequenciesText[ix] : frequencyText(value, this.defaultFrequency)
|
|
62
61
|
}))
|
|
63
62
|
];
|
|
64
63
|
} else {
|
|
@@ -79,7 +78,8 @@ export const ConnectedOptinSelect = connect(
|
|
|
79
78
|
(state, ownProps) => ({
|
|
80
79
|
...mapStateToPropsOptinStatus(state, ownProps),
|
|
81
80
|
...mapStateToProps(state, ownProps),
|
|
82
|
-
|
|
81
|
+
frequencies:
|
|
82
|
+
makeProductFrequencyOptionsSelector(ownProps.product?.id)(state) || getFallbackValue(ownProps, 'frequencies')
|
|
83
83
|
}),
|
|
84
84
|
{ productChangeFrequency, optoutProduct }
|
|
85
85
|
)(OptinSelect);
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { html, css } from 'lit-element';
|
|
2
2
|
import {
|
|
3
3
|
makeOptedinSelector,
|
|
4
|
-
|
|
4
|
+
makeProductSpecificDefaultFrequencySelector,
|
|
5
5
|
makeProductPrepaidShipmentsOptedInSelector,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
templatesSelector
|
|
6
|
+
makeProductFrequencyOptedInSelector,
|
|
7
|
+
getFallbackValue,
|
|
8
|
+
templatesSelector,
|
|
9
|
+
makeProductFrequenciesSelector,
|
|
10
|
+
makeProductDefaultFrequencySelector,
|
|
11
|
+
makeProductFrequencyOptionsSelector
|
|
9
12
|
} from '../core/selectors';
|
|
10
13
|
import { connect } from '../core/connect';
|
|
11
14
|
import { subscribed } from '../core/props';
|
|
@@ -130,12 +133,15 @@ export class OptinStatus extends withProduct(TemplateElement) {
|
|
|
130
133
|
|
|
131
134
|
export const mapStateToProps = (state, ownProps = {}) => ({
|
|
132
135
|
subscribed: makeOptedinSelector(ownProps.product)(state),
|
|
133
|
-
frequency:
|
|
134
|
-
productDefaultFrequency:
|
|
136
|
+
frequency: makeProductFrequencyOptedInSelector(ownProps.product)(state),
|
|
137
|
+
productDefaultFrequency: makeProductSpecificDefaultFrequencySelector((ownProps.product || {}).id)(state),
|
|
135
138
|
prepaidShipmentsOptedIn: makeProductPrepaidShipmentsOptedInSelector(ownProps.product)(state),
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
+
defaultFrequency:
|
|
140
|
+
makeProductDefaultFrequencySelector(ownProps.product?.id)(state) || getFallbackValue(ownProps, 'defaultFrequency'),
|
|
141
|
+
frequencies:
|
|
142
|
+
makeProductFrequencyOptionsSelector(ownProps.product?.id)(state) || getFallbackValue(ownProps, 'frequencies'),
|
|
143
|
+
...templatesSelector(state, ownProps),
|
|
144
|
+
productFrequencies: makeProductFrequenciesSelector(ownProps.product)(state)
|
|
139
145
|
});
|
|
140
146
|
|
|
141
147
|
export const ConnectedOptinStatus = connect(mapStateToProps)(OptinStatus);
|
package/src/components/Price.js
CHANGED
|
@@ -3,7 +3,7 @@ import { connect } from '../core/connect';
|
|
|
3
3
|
|
|
4
4
|
import { withProduct } from '../core/resolveProperties';
|
|
5
5
|
import { TemplateElement } from '../core/base';
|
|
6
|
-
import {
|
|
6
|
+
import { makeProductDefaultFrequencySelector, makeProductFrequencyOptedInSelector } from '../core/selectors';
|
|
7
7
|
import { safeProductId } from '../core/utils';
|
|
8
8
|
|
|
9
9
|
export class Price extends withProduct(TemplateElement) {
|
|
@@ -81,8 +81,8 @@ export class Price extends withProduct(TemplateElement) {
|
|
|
81
81
|
}
|
|
82
82
|
const mapStateToProps = (state, ownProps) => ({
|
|
83
83
|
productPlans: state.productPlans,
|
|
84
|
-
configDefaultFrequency:
|
|
85
|
-
frequency:
|
|
84
|
+
configDefaultFrequency: makeProductDefaultFrequencySelector(ownProps.product?.id)(state),
|
|
85
|
+
frequency: makeProductFrequencyOptedInSelector(ownProps.product)(state)
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
export default connect(mapStateToProps)(Price);
|
|
@@ -65,8 +65,12 @@ export class SelectFrequency extends withChildOptions(FrequencyStatus) {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// this runs for shopify selling plans translated to freq
|
|
68
|
-
if (
|
|
69
|
-
|
|
68
|
+
if (
|
|
69
|
+
this.productFrequencies?.frequencies?.length &&
|
|
70
|
+
result &&
|
|
71
|
+
this.productFrequencies?.frequenciesEveryPeriod?.length
|
|
72
|
+
) {
|
|
73
|
+
return frequencyToSellingPlan(result, this.productFrequencies);
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
return result;
|
|
@@ -90,10 +94,11 @@ export class SelectFrequency extends withChildOptions(FrequencyStatus) {
|
|
|
90
94
|
if (this.frequencies?.length) {
|
|
91
95
|
options = this.frequencies.map((value, ix) => {
|
|
92
96
|
let text;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
const { frequenciesEveryPeriod, frequenciesText } = this.productFrequencies;
|
|
98
|
+
if (frequenciesEveryPeriod && ix in frequenciesEveryPeriod) {
|
|
99
|
+
text = frequencyText(frequenciesEveryPeriod[ix], defaultFrequency);
|
|
100
|
+
} else if (frequenciesText && ix in frequenciesText) {
|
|
101
|
+
text = frequenciesText[ix];
|
|
97
102
|
} else {
|
|
98
103
|
text = frequencyText(value, this.defaultFrequency);
|
|
99
104
|
}
|
|
@@ -194,50 +194,54 @@ export class TestWizard extends LitElement {
|
|
|
194
194
|
const offer = document.querySelectorAll('og-offer')[ix];
|
|
195
195
|
const productId = offer.product.id;
|
|
196
196
|
offer.store.dispatch(
|
|
197
|
-
actions.receiveOffer(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
197
|
+
actions.receiveOffer(
|
|
198
|
+
{
|
|
199
|
+
in_stock: { [productId]: inStock },
|
|
200
|
+
eligibility_groups: { [productId]: groups },
|
|
201
|
+
result: 'success',
|
|
202
|
+
autoship: { [productId]: autoship },
|
|
203
|
+
module_view: { regular: '58a01e9aacbe40389b5c7325d79091bb' },
|
|
204
|
+
modifiers: {},
|
|
205
|
+
incentives_display: {
|
|
206
|
+
'47c01e9aacbe40389b5c7325d79091aa': {
|
|
207
|
+
field: 'sub_total',
|
|
208
|
+
object: 'order',
|
|
209
|
+
type: 'Discount Percent',
|
|
210
|
+
value: 5
|
|
211
|
+
},
|
|
212
|
+
e6534b9d877f41e586c37b7d8abc3a58: {
|
|
213
|
+
field: 'total_price',
|
|
214
|
+
object: 'item',
|
|
215
|
+
type: 'Discount Percent',
|
|
216
|
+
value: 5
|
|
217
|
+
},
|
|
218
|
+
f35e842710b24929922db4a529eecd40: {
|
|
219
|
+
field: 'total_price',
|
|
220
|
+
object: 'item',
|
|
221
|
+
type: 'Discount Percent',
|
|
222
|
+
value: 10
|
|
223
|
+
},
|
|
224
|
+
'5be321d7c17f4e18a757212b9a20bfcc': {
|
|
225
|
+
field: 'total_price',
|
|
226
|
+
object: 'item',
|
|
227
|
+
type: 'Discount Percent',
|
|
228
|
+
value: 1
|
|
229
|
+
}
|
|
210
230
|
},
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
type: 'Discount Percent',
|
|
221
|
-
value: 10
|
|
222
|
-
},
|
|
223
|
-
'5be321d7c17f4e18a757212b9a20bfcc': {
|
|
224
|
-
field: 'total_price',
|
|
225
|
-
object: 'item',
|
|
226
|
-
type: 'Discount Percent',
|
|
227
|
-
value: 1
|
|
231
|
+
incentives: {
|
|
232
|
+
[productId]: {
|
|
233
|
+
initial: ['5be321d7c17f4e18a757212b9a20bfcc'],
|
|
234
|
+
ongoing: [
|
|
235
|
+
'e6534b9d877f41e586c37b7d8abc3a58',
|
|
236
|
+
'47c01e9aacbe40389b5c7325d79091aa',
|
|
237
|
+
'f35e842710b24929922db4a529eecd40'
|
|
238
|
+
]
|
|
239
|
+
}
|
|
228
240
|
}
|
|
229
241
|
},
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
ongoing: [
|
|
234
|
-
'e6534b9d877f41e586c37b7d8abc3a58',
|
|
235
|
-
'47c01e9aacbe40389b5c7325d79091aa',
|
|
236
|
-
'f35e842710b24929922db4a529eecd40'
|
|
237
|
-
]
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
})
|
|
242
|
+
{},
|
|
243
|
+
productId
|
|
244
|
+
)
|
|
241
245
|
);
|
|
242
246
|
this.runTests();
|
|
243
247
|
};
|
|
@@ -2,7 +2,12 @@ import { html } from 'lit-element';
|
|
|
2
2
|
import { concludeUpsell, createIu } from '../core/actions';
|
|
3
3
|
import { connect } from '../core/connect';
|
|
4
4
|
import { auth, defaultFrequency } from '../core/props';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
makeOptedinSelector,
|
|
7
|
+
makeProductFrequencyOptedInSelector,
|
|
8
|
+
getFallbackValue,
|
|
9
|
+
makeProductDefaultFrequencySelector
|
|
10
|
+
} from '../core/selectors';
|
|
6
11
|
import { withProduct } from '../core/resolveProperties';
|
|
7
12
|
import { TemplateElement } from '../core/base';
|
|
8
13
|
|
|
@@ -102,8 +107,9 @@ export const mapStateToProps = (state, ownProps) => ({
|
|
|
102
107
|
auth: state.auth,
|
|
103
108
|
offerId: state.offerId,
|
|
104
109
|
subscribed: makeOptedinSelector(ownProps.product)(state),
|
|
105
|
-
frequency:
|
|
106
|
-
|
|
110
|
+
frequency: makeProductFrequencyOptedInSelector(ownProps.product)(state),
|
|
111
|
+
defaultFrequency:
|
|
112
|
+
makeProductDefaultFrequencySelector(ownProps.product?.id)(state) || getFallbackValue(ownProps, 'defaultFrequency'),
|
|
107
113
|
nextUpcomingOrder: state.previewUpsellOffer ? { public_id: 'preview-order-id' } : state.nextUpcomingOrder,
|
|
108
114
|
isPreview: state.previewUpsellOffer
|
|
109
115
|
});
|
|
@@ -369,22 +369,3 @@ describe('multi-currency', () => {
|
|
|
369
369
|
assertOfferShown(element);
|
|
370
370
|
});
|
|
371
371
|
});
|
|
372
|
-
|
|
373
|
-
describe('product specific frequencies', () => {
|
|
374
|
-
it('should hide the offer when on cart', async () => {
|
|
375
|
-
const element = await getOfferElement({
|
|
376
|
-
hasProductSpecificFrequencies: true
|
|
377
|
-
});
|
|
378
|
-
element.isCart = true;
|
|
379
|
-
await element.updateComplete;
|
|
380
|
-
|
|
381
|
-
assertOfferHidden(element);
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
it('should show the offer when not on cart', async () => {
|
|
385
|
-
const element = await getOfferElement({
|
|
386
|
-
hasProductSpecificFrequencies: true
|
|
387
|
-
});
|
|
388
|
-
assertOfferShown(element);
|
|
389
|
-
});
|
|
390
|
-
});
|
|
@@ -29,10 +29,23 @@ describe('OptinStatus', () => {
|
|
|
29
29
|
describe('mapStateToProps', () => {
|
|
30
30
|
it('should pick defaultFrequency from config', () => {
|
|
31
31
|
expect(
|
|
32
|
-
mapStateToProps(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
mapStateToProps(
|
|
33
|
+
{
|
|
34
|
+
config: {
|
|
35
|
+
productFrequencies: {
|
|
36
|
+
123: {
|
|
37
|
+
defaultFrequency: 'foo from config'
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
locale: { defaultFrequency: 'foo from locale' }
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
product: {
|
|
45
|
+
id: '123'
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
)
|
|
36
49
|
).toEqual(jasmine.objectContaining({ defaultFrequency: 'foo from config' }));
|
|
37
50
|
});
|
|
38
51
|
|
|
@@ -19,7 +19,8 @@ import {
|
|
|
19
19
|
receiveCreateOneTime,
|
|
20
20
|
createIu,
|
|
21
21
|
requestConvertOneTimeToSubscription,
|
|
22
|
-
receiveConvertOneTime
|
|
22
|
+
receiveConvertOneTime,
|
|
23
|
+
productChangePrepaidShipments
|
|
23
24
|
} from '../actions';
|
|
24
25
|
import * as constants from '../constants';
|
|
25
26
|
import { api } from '../api';
|
|
@@ -246,6 +247,51 @@ describe('redux actions', function () {
|
|
|
246
247
|
expect(dispatch.calls.argsFor(1)[0]).toEqual(unauthorized(new Error('some reason')));
|
|
247
248
|
});
|
|
248
249
|
});
|
|
250
|
+
|
|
251
|
+
describe('actions.productChangePrepaidShipments', () => {
|
|
252
|
+
function changePrepaidShipments(prepaidShipments) {
|
|
253
|
+
const getState = jasmine.createSpy('getState').and.returnValue({
|
|
254
|
+
config: {
|
|
255
|
+
prepaidSellingPlans: {
|
|
256
|
+
'yum prepaid id': [
|
|
257
|
+
{ numberShipments: 3, sellingPlan: 'yum prepaid selling plan id 1' },
|
|
258
|
+
{
|
|
259
|
+
numberShipments: 4,
|
|
260
|
+
sellingPlan: 'yum prepaid selling plan id 2'
|
|
261
|
+
}
|
|
262
|
+
]
|
|
263
|
+
},
|
|
264
|
+
productFrequencies: {
|
|
265
|
+
'yum prepaid id': {
|
|
266
|
+
frequencies: ['yum selling plan id 1']
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
const dispatch = jasmine.createSpy('dispatch');
|
|
272
|
+
productChangePrepaidShipments(
|
|
273
|
+
{
|
|
274
|
+
id: 'yum prepaid id'
|
|
275
|
+
},
|
|
276
|
+
prepaidShipments,
|
|
277
|
+
{}
|
|
278
|
+
)(dispatch, getState);
|
|
279
|
+
|
|
280
|
+
return {
|
|
281
|
+
dispatchedFrequency: dispatch.calls.argsFor(0)[0]?.payload.frequency
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
it('sets frequency to the corresponding selling plan', () => {
|
|
286
|
+
const { dispatchedFrequency } = changePrepaidShipments(4);
|
|
287
|
+
expect(dispatchedFrequency).toEqual('yum prepaid selling plan id 2');
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('sets frequency to the first frequency when prepaidShipments is null', () => {
|
|
291
|
+
const { dispatchedFrequency } = changePrepaidShipments(null);
|
|
292
|
+
expect(dispatchedFrequency).toEqual('yum selling plan id 1');
|
|
293
|
+
});
|
|
294
|
+
});
|
|
249
295
|
});
|
|
250
296
|
|
|
251
297
|
describe('actions.iu', () => {
|
|
@@ -10,84 +10,7 @@ class MockElement extends TemplateElement {
|
|
|
10
10
|
|
|
11
11
|
customElements.define('og-test-element', MockElement);
|
|
12
12
|
describe('TemplateElement', () => {
|
|
13
|
-
describe('getOption', () => {
|
|
14
|
-
it('should get option from attribute', () => {
|
|
15
|
-
const el = new MockElement();
|
|
16
|
-
el.setAttribute('foo', 'bar');
|
|
17
|
-
expect(el.getOption('foo')).toEqual('bar');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should return undefined given element does not have attribute', () => {
|
|
21
|
-
const el = new MockElement();
|
|
22
|
-
el.setAttribute('yum', 'egg');
|
|
23
|
-
expect(el.getOption('clam')).toBeUndefined();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should return boolean given element has attribute with true string', () => {
|
|
27
|
-
[
|
|
28
|
-
['one', 'true'],
|
|
29
|
-
['two', 'True']
|
|
30
|
-
].forEach(([attrName, attrValue]) => {
|
|
31
|
-
const el = new MockElement();
|
|
32
|
-
el.setAttribute(attrName, attrValue);
|
|
33
|
-
expect(el.getOption(attrName)).toBe(true);
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('should return boolean given element has attribute with false string', () => {
|
|
38
|
-
[
|
|
39
|
-
['three', 'false'],
|
|
40
|
-
['four', 'False']
|
|
41
|
-
].forEach(([attrName, attrValue]) => {
|
|
42
|
-
const el = new MockElement();
|
|
43
|
-
el.setAttribute(attrName, attrValue);
|
|
44
|
-
expect(el.getOption(attrName)).toBe(false);
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('should get option from attribute in kebabCase', () => {
|
|
49
|
-
const el = new MockElement();
|
|
50
|
-
el.setAttribute('foo-bar', 'bar');
|
|
51
|
-
expect(el.getOption('fooBar')).toEqual('bar');
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('should get option from config', () => {
|
|
55
|
-
const el = new MockElement();
|
|
56
|
-
el.config = { fooBar: 'bar' };
|
|
57
|
-
expect(el.getOption('fooBar')).toEqual('bar');
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('should get option from template.config', () => {
|
|
61
|
-
const el = new MockElement();
|
|
62
|
-
el.template = { config: { fooBar: 'bar' } };
|
|
63
|
-
expect(el.getOption('fooBar')).toEqual('bar');
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('should template.config take precedence over config', () => {
|
|
67
|
-
const el = new MockElement();
|
|
68
|
-
el.config = { fooBar: 'baz' };
|
|
69
|
-
el.template = { config: { fooBar: 'bar' } };
|
|
70
|
-
expect(el.getOption('fooBar')).toEqual('bar');
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('should attribute take precedence over template.config', () => {
|
|
74
|
-
const el = new MockElement();
|
|
75
|
-
el.setAttribute('foo-bar', 'foo');
|
|
76
|
-
el.config = { fooBar: 'baz' };
|
|
77
|
-
el.template = { config: { fooBar: 'bar' } };
|
|
78
|
-
expect(el.getOption('fooBar')).toEqual('foo');
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
13
|
describe('applyTemplate', () => {
|
|
83
|
-
it('should attribute take precedence over template.config', () => {
|
|
84
|
-
const el = new MockElement();
|
|
85
|
-
el.setAttribute('foo-bar', 'foo');
|
|
86
|
-
el.config = { fooBar: 'baz' };
|
|
87
|
-
el.template = { config: { fooBar: 'bar' } };
|
|
88
|
-
expect(el.getOption('fooBar')).toEqual('foo');
|
|
89
|
-
});
|
|
90
|
-
|
|
91
14
|
it('should only set innerHTML if change from prev', () => {
|
|
92
15
|
const el = new MockElement();
|
|
93
16
|
/* eslint no-underscore-dangle: ["error", { "allow": ["_templateMarkup"] }] */
|
|
@@ -4,6 +4,7 @@ import { environment, merchantId, offer, sessionId } from '../reducer';
|
|
|
4
4
|
import { requestOffer } from '../actions';
|
|
5
5
|
import { createStore, combineReducers, applyMiddleware } from 'redux';
|
|
6
6
|
import { FETCH_RESPONSE_ERROR } from '../constants';
|
|
7
|
+
import thunk from 'redux-thunk';
|
|
7
8
|
|
|
8
9
|
const mockOfferResponse = (productId, inStock = true, autoship = true, defaultFrequency) => {
|
|
9
10
|
return Promise.resolve({
|
|
@@ -44,7 +45,7 @@ describe('offerRequest', () => {
|
|
|
44
45
|
sessionId: 'x.y.z',
|
|
45
46
|
lastError: null
|
|
46
47
|
},
|
|
47
|
-
applyMiddleware(offerRequestMiddleware)
|
|
48
|
+
applyMiddleware(offerRequestMiddleware, thunk)
|
|
48
49
|
);
|
|
49
50
|
});
|
|
50
51
|
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
makeOptedinSelector,
|
|
4
4
|
isSameProduct,
|
|
5
5
|
templatesSelector,
|
|
6
|
-
|
|
6
|
+
makeProductSpecificDefaultFrequencySelector,
|
|
7
7
|
makeProductPrepaidShipmentOptionsSelector
|
|
8
8
|
} from '../selectors';
|
|
9
9
|
import { stringifyFrequency } from '../api';
|
|
@@ -61,25 +61,25 @@ describe('templatesSelector', () => {
|
|
|
61
61
|
});
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
describe('
|
|
64
|
+
describe('makeProductSpecificDefaultFrequencySelector', () => {
|
|
65
65
|
it('should return memoized function', () => {
|
|
66
|
-
const firsCall =
|
|
66
|
+
const firsCall = makeProductSpecificDefaultFrequencySelector(123);
|
|
67
67
|
expect(firsCall).toEqual(jasmine.any(Function));
|
|
68
|
-
expect(firsCall).toBe(
|
|
68
|
+
expect(firsCall).toBe(makeProductSpecificDefaultFrequencySelector(123));
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
it('should return null by default', () => {
|
|
72
|
-
const selectProductDefaultFrequency =
|
|
72
|
+
const selectProductDefaultFrequency = makeProductSpecificDefaultFrequencySelector(123);
|
|
73
73
|
expect(selectProductDefaultFrequency({})).toEqual(null);
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
it('should select the product default frequency if there is one', () => {
|
|
77
|
-
const selectProductDefaultFrequency =
|
|
77
|
+
const selectProductDefaultFrequency = makeProductSpecificDefaultFrequencySelector(123);
|
|
78
78
|
expect(selectProductDefaultFrequency({ defaultFrequencies: { 123: '2_w' } })).toEqual('2_w');
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
it('should select the product default frequency if there is one (object frequency)', () => {
|
|
82
|
-
const selectProductDefaultFrequency =
|
|
82
|
+
const selectProductDefaultFrequency = makeProductSpecificDefaultFrequencySelector(123);
|
|
83
83
|
const frequency = { every: '2', period: 'w' };
|
|
84
84
|
expect(selectProductDefaultFrequency({ defaultFrequencies: { 123: frequency } })).toEqual(
|
|
85
85
|
stringifyFrequency(frequency)
|