@ordergroove/offers 2.33.0 → 2.33.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ordergroove/offers",
3
- "version": "2.33.0",
3
+ "version": "2.33.2",
4
4
  "description": "offer state component",
5
5
  "author": "Eugenio Lattanzio <eugenio63@gmail.com>",
6
6
  "homepage": "https://github.com/ordergroove/plush-toys#readme",
@@ -47,5 +47,5 @@
47
47
  "devDependencies": {
48
48
  "@ordergroove/offers-templates": "^0.8.0"
49
49
  },
50
- "gitHead": "79b0589a027dd38497e5b6db11397e1dfd94d639"
50
+ "gitHead": "771e0978a0b4025ce0a250e35a976e22cd1f09b2"
51
51
  }
@@ -16,9 +16,16 @@ export class When extends withProduct(LitElement) {
16
16
  }
17
17
 
18
18
  render() {
19
- const result =
20
- this.test &&
21
- expression.parse(removeWhitespace(this.test), key => descriptors[key] && descriptors[key](this.state, this));
19
+ if (!this.test) {
20
+ return html``;
21
+ }
22
+
23
+ let test = removeWhitespace(this.test);
24
+ // the parser returns incorrect result if you use an expression with &!, e.g. test1&!test2
25
+ // it succeeds if you wrap !test2 in parentheses, e.g. test1&(!test2)
26
+ // so we'll wrap all "not" expressions in parentheses
27
+ test = test.replace(/(![a-zA-Z]+)/g, '($1)');
28
+ const result = expression.parse(test, key => descriptors[key] && descriptors[key](this.state, this));
22
29
 
23
30
  if (result) {
24
31
  return html`
@@ -12,38 +12,62 @@ class When extends WhenBase {
12
12
  }
13
13
  customElements.define('og-when-test', When);
14
14
 
15
+ const PRODUCT_ID = 'prodA';
16
+
17
+ function stateToString(state) {
18
+ return Object.keys(state)
19
+ .map(key => `${key}=${state[key][PRODUCT_ID]}`)
20
+ .join(' and ');
21
+ }
22
+
23
+ async function testWhen(expression, productState, expected) {
24
+ const element = new When();
25
+ element.product = { id: PRODUCT_ID };
26
+ element.test = expression;
27
+ element.state = Object.keys(productState).reduce((acc, key) => {
28
+ acc[key] = { [PRODUCT_ID]: productState[key] };
29
+ return acc;
30
+ }, {});
31
+ await appendToBody(element).then(() => {
32
+ const slot = querySelector(element, 'slot');
33
+ const expectedMessage = `expected ${expression} to be ${expected} when ${stateToString(element.state)}`;
34
+ if (expected) {
35
+ expect(slot).toBeTruthy(expectedMessage);
36
+ } else {
37
+ expect(slot).toBeFalsy(expectedMessage);
38
+ }
39
+ });
40
+ }
41
+
15
42
  describe('Conditional', () => {
16
43
  it('should not render child given test result is false', async () => {
17
- const element = new When();
18
- element.product = { id: 'prodA' };
19
- element.test = 'inStock';
20
- element.state = {
21
- inStock: {
22
- prodA: false
23
- },
24
- autoshipEligible: {
25
- prodA: false
26
- }
27
- };
28
- await appendToBody(element);
29
-
30
- expect(querySelector(element, 'slot')).toBeFalsy();
44
+ await testWhen('inStock', { inStock: false, autoshipEligible: false }, false);
31
45
  });
32
46
 
33
47
  it('should render child given test result is true', async () => {
34
- const element = new When();
35
- element.product = { id: 'prodA' };
36
- element.test = 'inStock';
37
- element.state = {
38
- inStock: {
39
- prodA: true
40
- },
41
- autoshipEligible: {
42
- prodA: true
43
- }
44
- };
45
- await appendToBody(element);
46
-
47
- expect(querySelector(element, 'slot')).toBeTruthy();
48
+ await testWhen('inStock', { inStock: true, autoshipEligible: false }, true);
49
+ });
50
+
51
+ it('should handle compound expressions', async () => {
52
+ await testWhen('inStock&!eligible', { inStock: false, autoshipEligible: false }, false);
53
+ await testWhen('inStock&(!eligible)', { inStock: false, autoshipEligible: false }, false);
54
+ await testWhen('inStock|!eligible', { inStock: false, autoshipEligible: false }, true);
55
+ await testWhen('inStock|eligible', { inStock: false, autoshipEligible: true }, true);
56
+ await testWhen('!inStock&!eligible', { inStock: false, autoshipEligible: false }, true);
57
+ await testWhen(
58
+ 'inStock&eligible&autoshipByDefault',
59
+ { inStock: false, autoshipEligible: true, autoshipbyDefault: true },
60
+ false
61
+ );
62
+ await testWhen(
63
+ 'inStock&eligible&autoshipByDefault',
64
+ { inStock: true, autoshipEligible: true, autoshipbyDefault: true },
65
+ false
66
+ );
67
+ await testWhen(
68
+ 'inStock&(!eligible|autoshipByDefault)',
69
+ { inStock: true, autoshipEligible: true, autoshipByDefault: true },
70
+ true
71
+ );
48
72
  });
49
73
  });
@@ -104,6 +104,68 @@ describe('autoshipEligible', () => {
104
104
 
105
105
  expect(actual).toEqual({ 'yum existing key': 'yum existing value' });
106
106
  });
107
+
108
+ it('should return false if there are only prepaid selling_plans', () => {
109
+ const actual = autoshipEligible(
110
+ {},
111
+ {
112
+ type: constants.SETUP_PRODUCT,
113
+ payload: {
114
+ product: {
115
+ id: 'yum product id',
116
+ selling_plan_allocations: [],
117
+ variants: [
118
+ {
119
+ id: 'single-non-prepaid',
120
+ selling_plan_allocations: [{ selling_plan_id: 1 }]
121
+ },
122
+ {
123
+ id: 'prepaid-and-non-prepaid',
124
+ selling_plan_allocations: [{ selling_plan_id: 1 }, { selling_plan_id: 2 }]
125
+ },
126
+ {
127
+ id: 'single-prepaid',
128
+ selling_plan_allocations: [{ selling_plan_id: 2 }]
129
+ },
130
+ {
131
+ id: 'multiple-prepaid',
132
+ selling_plan_allocations: [{ selling_plan_id: 2 }, { selling_plan_id: 3 }]
133
+ }
134
+ ],
135
+ selling_plan_groups: [
136
+ {
137
+ name: 'Subscribe and Save',
138
+ selling_plans: [
139
+ {
140
+ id: 1
141
+ }
142
+ ]
143
+ },
144
+ {
145
+ name: 'Prepaid-yum variant id',
146
+ selling_plans: [
147
+ {
148
+ id: 2
149
+ },
150
+ {
151
+ id: 3
152
+ }
153
+ ]
154
+ }
155
+ ]
156
+ }
157
+ }
158
+ }
159
+ );
160
+
161
+ expect(actual).toEqual({
162
+ 'yum product id': false,
163
+ 'single-non-prepaid': true,
164
+ 'prepaid-and-non-prepaid': true,
165
+ 'single-prepaid': false,
166
+ 'multiple-prepaid': false
167
+ });
168
+ });
107
169
  });
108
170
 
109
171
  describe('config', () => {
@@ -145,6 +145,28 @@ const reduceProductCartLine = (acc, cur) => {
145
145
  return { ...acc, [cur.key]: acc[productId] || null };
146
146
  };
147
147
 
148
+ const isPrepaidSellingPlanGroup = sellingPlanGroup => sellingPlanGroup.name.toUpperCase().includes('PREPAID');
149
+
150
+ const filterNonPrepaidSellingPlans = (sellingPlanAllocations, sellingPlanGroups) => {
151
+ if (!sellingPlanAllocations || sellingPlanAllocations.length === 0) {
152
+ return [];
153
+ }
154
+ if (!sellingPlanGroups || sellingPlanGroups.length === 0) {
155
+ return sellingPlanAllocations;
156
+ }
157
+
158
+ const nonPrepaidSellingPlansIds = sellingPlanGroups.reduce((allIds, group) => {
159
+ if (!isPrepaidSellingPlanGroup(group)) {
160
+ allIds.push(...group.selling_plans.map(sellingPlan => sellingPlan.id));
161
+ }
162
+ return allIds;
163
+ }, []);
164
+
165
+ return sellingPlanAllocations.filter(sellingPlanAllocation =>
166
+ nonPrepaidSellingPlansIds.includes(sellingPlanAllocation.selling_plan_id)
167
+ );
168
+ };
169
+
148
170
  export const autoshipEligible = (state = {}, action) => {
149
171
  if (constants.RECEIVE_PRODUCT_PLANS === action.type) {
150
172
  return Object.entries(action.payload).reduce(productTrue, state);
@@ -157,13 +179,17 @@ export const autoshipEligible = (state = {}, action) => {
157
179
  const {
158
180
  payload: { product }
159
181
  } = action;
160
- return [product, ...(product?.variants || [])]?.reduce(
161
- (acc, cur) => ({
162
- ...overrideLineKey(acc, cur.id, cur.selling_plan_allocations?.length > 0),
163
- [cur.id]: cur.selling_plan_allocations?.length > 0
164
- }),
165
- state
166
- );
182
+ return [product, ...(product?.variants || [])]?.reduce((acc, cur) => {
183
+ const selling_plans_without_prepaid = filterNonPrepaidSellingPlans(
184
+ cur?.selling_plan_allocations,
185
+ product?.selling_plan_groups
186
+ );
187
+
188
+ return {
189
+ ...overrideLineKey(acc, cur.id, selling_plans_without_prepaid?.length > 0),
190
+ [cur.id]: selling_plans_without_prepaid?.length > 0
191
+ };
192
+ }, state);
167
193
  }
168
194
  return state;
169
195
  };