@financial-times/n-conversion-forms 46.0.1 → 47.0.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.
@@ -1,390 +1,748 @@
1
- import { PaymentTerm } from './index';
2
- import { expectToRenderCorrectly } from '../test-jest/helpers/expect-to-render-correctly';
3
1
  import React from 'react';
4
2
  import Enzyme, { shallow } from 'enzyme';
5
3
  import Adapter from 'enzyme-adapter-react-16';
6
4
 
5
+ import { PaymentTerm } from './index';
6
+ import { expectToRenderCorrectly } from '../test-jest/helpers/expect-to-render-correctly';
7
+
7
8
  expect.extend(expectToRenderCorrectly);
8
9
  Enzyme.configure({ adapter: new Adapter() });
9
10
 
10
- describe('PaymentTerm', () => {
11
- it('render with defaults', () => {
12
- const props = {};
11
+ const mockGetMonthlyEquivalentIf90DaysOrLonger = jest.fn();
13
12
 
14
- expect(PaymentTerm).toRenderCorrectly(props);
15
- });
13
+ jest.mock('@financial-times/n-pricing', () => {
14
+ const actual = jest.requireActual('@financial-times/n-pricing');
16
15
 
17
- it('render with isPrintOrBundle', () => {
18
- const props = {
19
- isPrintOrBundle: true,
20
- };
21
-
22
- expect(PaymentTerm).toRenderCorrectly(props);
23
- });
24
-
25
- ['annual', 'quarterly', 'monthly'].forEach((type) => {
26
- describe(`${type} option`, () => {
27
- it('render option', () => {
28
- const props = {
29
- options: [
30
- {
31
- name: type,
32
- value: type,
33
- price: '£20.00',
34
- },
35
- ],
36
- };
16
+ return {
17
+ ...actual,
18
+ Price: jest.fn().mockImplementation(() => ({
19
+ getMonthlyEquivalentIf90DaysOrLonger:
20
+ mockGetMonthlyEquivalentIf90DaysOrLonger,
21
+ })),
22
+ };
23
+ });
37
24
 
38
- expect(PaymentTerm).toRenderCorrectly(props);
39
- });
25
+ const buildOption = (overrides = {}) => ({
26
+ name: 'monthly',
27
+ price: '£20.00',
28
+ value: 'P1M',
29
+ amount: '20.00',
30
+ symbol: '£',
31
+ isTrial: false,
32
+ selected: false,
33
+ subscriptionAutoRenewTerm: true,
34
+ ...overrides,
35
+ });
40
36
 
41
- it('render option with discount', () => {
42
- const props = {
43
- options: [
44
- {
45
- name: type,
46
- value: type,
47
- price: '£20.00',
48
- discount: '25% off',
49
- },
50
- ],
51
- };
37
+ describe('PaymentTerm', () => {
38
+ beforeEach(() => {
39
+ mockGetMonthlyEquivalentIf90DaysOrLonger.mockReset();
40
+ });
52
41
 
53
- expect(PaymentTerm).toRenderCorrectly(props);
54
- });
42
+ describe('default props are used', () => {
43
+ it('renders correctly', () => {
44
+ const props = {};
55
45
 
56
- it('render option with isTrial', () => {
57
- const props = {
58
- options: [
59
- {
60
- name: type,
61
- value: type,
62
- price: '£20.00',
63
- isTrial: true,
64
- },
65
- ],
66
- };
46
+ expect(PaymentTerm).toRenderCorrectly(props);
47
+ });
48
+ });
67
49
 
68
- expect(PaymentTerm).toRenderCorrectly(props);
50
+ describe('payment term input props', () => {
51
+ describe('option.isTrial is false', () => {
52
+ it('renders option.trialAmount as data-base-amount', () => {
53
+ const options = [
54
+ {
55
+ name: 'monthly',
56
+ price: '$5.00',
57
+ value: 'monthly',
58
+ monthlyPrice: '$5.00',
59
+ isTrial: false,
60
+ amount: 100,
61
+ trialAmount: 1,
62
+ },
63
+ ];
64
+ const wrapper = shallow(<PaymentTerm options={options} />);
65
+ expect(wrapper.find('input').prop('data-base-amount')).toBe(100);
69
66
  });
67
+ });
70
68
 
71
- it('render option with selected', () => {
72
- const props = {
73
- options: [
74
- {
75
- name: type,
76
- value: type,
77
- price: '£20.00',
78
- selected: true,
79
- },
80
- ],
81
- };
82
-
83
- expect(PaymentTerm).toRenderCorrectly(props);
69
+ describe('option.isTrial is true', () => {
70
+ it('renders option.trialAmount as data-base-amount', () => {
71
+ const options = [
72
+ {
73
+ name: 'monthly',
74
+ price: '$5.00',
75
+ value: 'monthly',
76
+ monthlyPrice: '$5.00',
77
+ isTrial: true,
78
+ amount: 100,
79
+ trialAmount: 1,
80
+ },
81
+ ];
82
+ const wrapper = shallow(<PaymentTerm options={options} />);
83
+ expect(wrapper.find('input').prop('data-base-amount')).toBe(1);
84
84
  });
85
+ });
85
86
 
86
- it('render option with trial', () => {
87
- const props = {
88
- options: [
89
- {
90
- name: type,
91
- value: type,
92
- price: '£20.00',
93
- isTrial: true,
94
- trialDuration: '6 weeks',
95
- trialPrice: '£1.00',
96
- },
97
- ],
98
- };
87
+ describe('option.selected is true', () => {
88
+ it('renders the option as selected', () => {
89
+ const options = [
90
+ buildOption({
91
+ selected: true,
92
+ }),
93
+ ];
94
+ const wrapper = shallow(<PaymentTerm options={options} />);
99
95
 
100
- expect(PaymentTerm).toRenderCorrectly(props);
96
+ expect(wrapper.find('input')).toHaveLength(1);
97
+ expect(wrapper.find('input').prop('defaultChecked')).toBe(true);
98
+ expect(wrapper.find('input').prop('id')).toBe('P1M');
99
+ expect(wrapper.find('label').prop('htmlFor')).toBe('P1M');
101
100
  });
101
+ });
102
102
 
103
- it('render option with monthlyPrice', () => {
104
- const props = {
105
- options: [
106
- {
107
- name: type,
108
- value: type,
109
- price: '£20.00',
110
- monthlyPrice: '£1.67',
111
- },
112
- ],
113
- };
103
+ describe('option.selected is false', () => {
104
+ it('does not render the option as selected', () => {
105
+ const options = [
106
+ buildOption({
107
+ selected: false,
108
+ }),
109
+ ];
110
+ const wrapper = shallow(<PaymentTerm options={options} />);
114
111
 
115
- expect(PaymentTerm).toRenderCorrectly(props);
112
+ expect(wrapper.find('input')).toHaveLength(1);
113
+ expect(wrapper.find('input').prop('defaultChecked')).toBeUndefined();
114
+ expect(wrapper.find('input').prop('id')).toBe('P1M');
115
+ expect(wrapper.find('label').prop('htmlFor')).toBe('P1M');
116
116
  });
117
117
  });
118
118
  });
119
119
 
120
- describe('isAutoRenewingSubscriptionTermType is true; isNonRenewingSubscriptionTermType is false', () => {
121
- describe('pre-defined option name (i.e. frequency)', () => {
122
- const ANNUAL_FREQUENCY = 'annual';
123
- const QUARTERLY_FREQUENCY = 'quarterly';
124
- const MONTHLY_FREQUENCY = 'monthly';
125
-
126
- [ANNUAL_FREQUENCY, QUARTERLY_FREQUENCY, MONTHLY_FREQUENCY].forEach(
127
- (frequency) => {
128
- const FREQUENCY_TO_RENEWAL_TEXT_MAP = {
129
- [ANNUAL_FREQUENCY]: 'Renews annually unless cancelled',
130
- [QUARTERLY_FREQUENCY]: 'Renews quarterly unless cancelled',
131
- [MONTHLY_FREQUENCY]: 'Renews monthly unless cancelled',
132
- };
133
-
134
- describe(`${frequency} option`, () => {
135
- const options = [
136
- {
137
- name: frequency,
138
- value: frequency,
139
- price: '£20.00',
140
- },
141
- ];
120
+ describe('payment term option discount', () => {
121
+ describe('option.discount is true', () => {
122
+ describe('option.bestOffer is true', () => {
123
+ it('displays "Best offer"', () => {
124
+ const options = [
125
+ buildOption({
126
+ discount: '25%',
127
+ bestOffer: true,
128
+ }),
129
+ ];
130
+ const wrapper = shallow(<PaymentTerm options={options} />);
131
+
132
+ expect(wrapper.find('.ncf__payment-term__discount')).toHaveLength(1);
133
+ expect(wrapper.find('.ncf__payment-term__discount').text()).toBe(
134
+ 'Best offer'
135
+ );
136
+ });
137
+ });
142
138
 
143
- it(`renders '${FREQUENCY_TO_RENEWAL_TEXT_MAP[frequency]}' when true`, () => {
144
- const wrapper = shallow(
145
- <PaymentTerm
146
- options={options}
147
- isAutoRenewingSubscriptionTermType={true}
148
- isNonRenewingSubscriptionTermType={false}
149
- />
150
- );
151
- expect(
152
- wrapper.find('.ncf__payment-term__renews-text').exists()
153
- ).toBe(true);
154
- expect(
155
- wrapper.find('.ncf__payment-term__renews-text').text()
156
- ).toBe(FREQUENCY_TO_RENEWAL_TEXT_MAP[frequency]);
157
- });
158
- });
159
- }
160
- );
139
+ describe('option.bestOffer is false', () => {
140
+ it('displays, e.g. "Save 25% off RRP" where the percentage is defined by the offer.discount value', () => {
141
+ const options = [
142
+ buildOption({
143
+ discount: '25%',
144
+ bestOffer: false,
145
+ }),
146
+ ];
147
+ const wrapper = shallow(<PaymentTerm options={options} />);
148
+
149
+ expect(wrapper.find('.ncf__payment-term__discount')).toHaveLength(1);
150
+ expect(wrapper.find('.ncf__payment-term__discount').text()).toBe(
151
+ 'Save 25% off RRP'
152
+ );
153
+ });
154
+ });
161
155
  });
162
156
 
163
- describe('custom option with period provided', () => {
164
- const options = [
165
- {
166
- price: '£50.00',
167
- amount: '50.00',
168
- currency: 'GBP',
169
- value: 'P6M',
170
- },
171
- ];
172
-
173
- it('renders renewal text for custom terms that specify a period', () => {
174
- const wrapper = shallow(
175
- <PaymentTerm
176
- options={options}
177
- isAutoRenewingSubscriptionTermType={true}
178
- isNonRenewingSubscriptionTermType={false}
179
- />
180
- );
181
- expect(wrapper.find('.ncf__payment-term__renews-text').text()).toBe(
182
- 'Renews every 6 months unless cancelled'
157
+ describe('option.discount is false', () => {
158
+ it('does not display any discount-related text', () => {
159
+ const options = [
160
+ buildOption({
161
+ discount: '',
162
+ }),
163
+ ];
164
+ const wrapper = shallow(<PaymentTerm options={options} />);
165
+
166
+ expect(wrapper.find('.ncf__payment-term__discount').exists()).toBe(
167
+ false
183
168
  );
169
+ expect(wrapper.text()).not.toContain('Best offer');
170
+ expect(wrapper.text()).not.toContain('off RRP');
184
171
  });
185
172
  });
186
173
  });
187
174
 
188
- describe('isAutoRenewingSubscriptionTermType is false; isNonRenewingSubscriptionTermType is true', () => {
189
- describe('options include duration expressed in weeks', () => {
190
- const options = [
191
- {
192
- price: '£19.00',
193
- amount: '19.00',
194
- value: 'P8W',
195
- },
196
- ];
197
- const wrapper = shallow(
198
- <PaymentTerm
199
- options={options}
200
- isAutoRenewingSubscriptionTermType={false}
201
- isNonRenewingSubscriptionTermType={true}
202
- />
203
- );
204
-
205
- it('renders subscription term as title', () => {
175
+ describe('payment term option display name', () => {
176
+ describe('option.isTrial is true (and isPrintOrBundle and isDigitalEdition are both false)', () => {
177
+ it('prefixes the payment term option display name with "Trial: "', () => {
178
+ const options = [
179
+ buildOption({
180
+ name: 'annual',
181
+ value: 'P1Y',
182
+ isTrial: true,
183
+ trialDuration: '4 weeks',
184
+ trialPrice: '£1.00',
185
+ }),
186
+ ];
187
+ const wrapper = shallow(<PaymentTerm options={options} />);
188
+
206
189
  expect(wrapper.find('.ncf__payment-term__title').text()).toMatch(
207
- '8 weeks'
190
+ /^Trial: /
208
191
  );
209
192
  });
210
193
 
211
- it('renders description text that reflects that the non-renewing subscription requires a single payment that expresses the per duration cost for shorter durations', () => {
212
- expect(
213
- wrapper.find('.ncf__payment-term__description').text()
214
- ).toContain(
215
- 'Single £19.00 paymentThat’s equivalent to GBP9.50 per month'
216
- );
194
+ describe('custom option.displayName is provided', () => {
195
+ it('uses the custom option.displayName as the term display name', () => {
196
+ const options = [
197
+ buildOption({
198
+ name: 'annual',
199
+ value: 'P1Y',
200
+ isTrial: true,
201
+ displayName: 'Standard Digital Plus',
202
+ trialDuration: '4 weeks',
203
+ trialPrice: '£1.00',
204
+ }),
205
+ ];
206
+ const wrapper = shallow(<PaymentTerm options={options} />);
207
+
208
+ expect(wrapper.find('.ncf__payment-term__title').text()).toContain(
209
+ 'Trial: Standard Digital Plus - Annual'
210
+ );
211
+ });
212
+ });
213
+
214
+ describe('custom option.displayName is not provided', () => {
215
+ it('defaults to "Premium Digital"', () => {
216
+ const options = [
217
+ buildOption({
218
+ name: 'annual',
219
+ value: 'P1Y',
220
+ isTrial: true,
221
+ trialDuration: '4 weeks',
222
+ trialPrice: '£1.00',
223
+ }),
224
+ ];
225
+ const wrapper = shallow(<PaymentTerm options={options} />);
226
+
227
+ expect(wrapper.find('.ncf__payment-term__title').text()).toContain(
228
+ 'Trial: Premium Digital - Annual'
229
+ );
230
+ });
217
231
  });
218
232
  });
219
233
 
220
- describe('options include duration expressed in days', () => {
221
- const options = [
222
- {
223
- price: '£30.00',
224
- amount: '30.00',
225
- value: 'P90D',
226
- },
227
- ];
228
- const wrapper = shallow(
229
- <PaymentTerm
230
- options={options}
231
- isAutoRenewingSubscriptionTermType={false}
232
- isNonRenewingSubscriptionTermType={true}
233
- />
234
- );
235
-
236
- it('renders subscription term as title', () => {
237
- expect(wrapper.find('.ncf__payment-term__title').text()).toMatch(
238
- '90 days'
234
+ describe('option.isTrial is false', () => {
235
+ it('does not prefix the payment term option display name with "Trial: "', () => {
236
+ const options = [
237
+ buildOption({
238
+ name: 'annual',
239
+ value: 'P1Y',
240
+ isTrial: false,
241
+ }),
242
+ ];
243
+ const wrapper = shallow(<PaymentTerm options={options} />);
244
+
245
+ expect(wrapper.find('.ncf__payment-term__title').text()).not.toContain(
246
+ 'Trial: '
239
247
  );
240
248
  });
249
+ });
241
250
 
242
- it('renders description text that reflects that the non-renewing subscription requires a single payment that expresses the per duration cost for shorter durations', () => {
243
- expect(
244
- wrapper.find('.ncf__payment-term__description').text()
245
- ).toContain(
246
- 'Single £30.00 paymentThat’s equivalent to GBP10.00 per month'
251
+ describe('option.subscriptionAutoRenewTerm is true, i.e. auto-renewing subscription, and option.name is present', () => {
252
+ it('expresses the term period by using the capitalised option.name value', () => {
253
+ const options = [
254
+ buildOption({
255
+ name: 'annual',
256
+ subscriptionAutoRenewTerm: true,
257
+ }),
258
+ ];
259
+ const wrapper = shallow(<PaymentTerm options={options} />);
260
+
261
+ expect(wrapper.find('.ncf__payment-term__title').text()).toContain(
262
+ 'Annual'
247
263
  );
248
264
  });
249
265
  });
250
266
 
251
- describe('renewal text', () => {
252
- const options = [
253
- {
254
- price: '£19.00',
255
- amount: '19.00',
256
- value: 'P8W',
257
- },
258
- ];
267
+ describe('option.subscriptionAutoRenewTerm is false, i.e. non-renewing (single-term) subscription', () => {
268
+ describe('option.value is a valid period', () => {
269
+ it('expresses the term period as a human-readable duration derived from the option.value value', () => {
270
+ const options = [
271
+ buildOption({
272
+ displayName: 'Standard Digital',
273
+ isTrial: true,
274
+ subscriptionAutoRenewTerm: false,
275
+ value: 'P8W',
276
+ price: '£19.00',
277
+ amount: '19.00',
278
+ trialDuration: '4 weeks',
279
+ trialPrice: '£1.00',
280
+ }),
281
+ ];
282
+ const wrapper = shallow(
283
+ <PaymentTerm
284
+ options={options}
285
+ isAutoRenewingSubscriptionTermType={false}
286
+ isNonRenewingSubscriptionTermType={true}
287
+ />
288
+ );
289
+
290
+ expect(wrapper.find('.ncf__payment-term__title').text()).toContain(
291
+ 'Trial: Standard Digital - 8 weeks'
292
+ );
293
+ });
294
+ });
259
295
 
260
- it('does not render renewal text for custom terms', () => {
261
- const wrapper = shallow(
262
- <PaymentTerm
263
- options={options}
264
- isAutoRenewingSubscriptionTermType={false}
265
- isNonRenewingSubscriptionTermType={true}
266
- />
267
- );
268
- expect(wrapper.find('.ncf__payment-term__renews-text').exists()).toBe(
269
- false
270
- );
296
+ describe('option.value is a not valid period', () => {
297
+ it('uses the option.title value', () => {
298
+ const options = [
299
+ buildOption({
300
+ displayName: 'Standard Digital',
301
+ isTrial: true,
302
+ subscriptionAutoRenewTerm: false,
303
+ value: 'custom-term',
304
+ title: '12 Month Subscription',
305
+ price: '£100.00',
306
+ trialDuration: '4 weeks',
307
+ trialPrice: '£1.00',
308
+ }),
309
+ ];
310
+ const wrapper = shallow(
311
+ <PaymentTerm
312
+ options={options}
313
+ isAutoRenewingSubscriptionTermType={false}
314
+ isNonRenewingSubscriptionTermType={true}
315
+ />
316
+ );
317
+
318
+ expect(wrapper.find('.ncf__payment-term__title').text()).toContain(
319
+ 'Trial: Standard Digital - 12 Month Subscription'
320
+ );
321
+ });
271
322
  });
272
323
  });
273
324
  });
274
325
 
275
- describe('getDisplayName', () => {
276
- const baseOptions = {
277
- name: 'monthly',
278
- value: 'monthly',
279
- price: '£20.00',
280
- monthlyPrice: '£1.67',
281
- };
282
- describe('non-trial terms', () => {
283
- const options = [
284
- {
285
- ...baseOptions,
286
- isTrial: false,
287
- },
288
- ];
289
- it('renders with time period only if trial.option == false', () => {
326
+ describe('payment term option description', () => {
327
+ describe('option.isTrial is true', () => {
328
+ it('displays the trial duration', () => {
329
+ const options = [
330
+ buildOption({
331
+ isTrial: true,
332
+ displayName: 'Standard Digital',
333
+ trialDuration: '6 weeks',
334
+ trialPrice: '£1.00',
335
+ price: '£20.00',
336
+ value: 'P1M',
337
+ }),
338
+ ];
290
339
  const wrapper = shallow(<PaymentTerm options={options} />);
291
- expect(wrapper.find('.ncf__payment-term__label').text()).toMatch(
292
- /^Monthly .*$/
293
- );
340
+
341
+ expect(
342
+ wrapper.find('.ncf__payment-term__description').text()
343
+ ).toContain('6 weeks');
294
344
  });
295
- });
296
- describe('getDisplayName', () => {
297
- const trialOptions = {
298
- ...baseOptions,
299
- isTrial: true,
300
- };
301
- it('defaults to `Premium digital`', () => {
302
- const options = [trialOptions];
345
+
346
+ it('displays the trial price', () => {
347
+ const options = [
348
+ buildOption({
349
+ isTrial: true,
350
+ displayName: 'Standard Digital',
351
+ trialDuration: '6 weeks',
352
+ trialPrice: '£1.00',
353
+ price: '£20.00',
354
+ value: 'P1M',
355
+ }),
356
+ ];
303
357
  const wrapper = shallow(<PaymentTerm options={options} />);
304
- expect(wrapper.find('.ncf__payment-term__label').text()).toMatch(
305
- /^Trial: Premium Digital - Monthly .*$/
358
+
359
+ expect(wrapper.find('.ncf__payment-term__trial-price').text()).toBe(
360
+ '£1.00'
306
361
  );
307
362
  });
308
- it('renders using displayName if available', () => {
363
+
364
+ it('displays the trial price explanatory text', () => {
309
365
  const options = [
310
- {
311
- ...trialOptions,
312
- displayName: 'someDisplayName',
313
- },
366
+ buildOption({
367
+ isTrial: true,
368
+ displayName: 'Standard Digital',
369
+ trialDuration: '6 weeks',
370
+ trialPrice: '£1.00',
371
+ price: '£20.00',
372
+ value: 'P1M',
373
+ }),
314
374
  ];
315
375
  const wrapper = shallow(<PaymentTerm options={options} />);
316
- expect(wrapper.find('.ncf__payment-term__label').text()).toMatch(
317
- /^Trial: someDisplayName - Monthly .*/
376
+
377
+ expect(
378
+ wrapper.find('.ncf__payment-term__description').text()
379
+ ).toContain(
380
+ 'Unless you cancel during your trial you will be billed £20.00 per month after the trial period.'
318
381
  );
319
382
  });
320
383
  });
321
- });
322
384
 
323
- describe('[data-base-amount]', () => {
324
- it('renders option.amount as data-base-amount if isTrial is false', () => {
325
- const options = [
326
- {
327
- name: 'monthly',
328
- price: '$5.00',
329
- value: 'monthly',
330
- monthlyPrice: '$5.00',
331
- isTrial: false,
332
- amount: 100,
333
- trialAmount: 1,
334
- },
335
- ];
336
- const wrapper = shallow(<PaymentTerm options={options} />);
337
- expect(wrapper.find('input').prop('data-base-amount')).toBe(100);
338
- });
385
+ describe('option.isTrial is false', () => {
386
+ describe('option.value is a valid period', () => {
387
+ describe('option.subscriptionAutoRenewTerm is false, i.e. non-renewing (single-term) subscription', () => {
388
+ it('expresses price as a single payment', () => {
389
+ const options = [
390
+ buildOption({
391
+ isTrial: false,
392
+ subscriptionAutoRenewTerm: false,
393
+ value: 'P8W',
394
+ price: '£19.00',
395
+ amount: '19.00',
396
+ }),
397
+ ];
398
+ const wrapper = shallow(
399
+ <PaymentTerm
400
+ options={options}
401
+ isAutoRenewingSubscriptionTermType={false}
402
+ isNonRenewingSubscriptionTermType={true}
403
+ />
404
+ );
405
+
406
+ expect(
407
+ wrapper.find('.ncf__payment-term__description').text()
408
+ ).toContain('Single £19.00 payment');
409
+ });
410
+
411
+ it('does not describe a renewal period', () => {
412
+ const options = [
413
+ buildOption({
414
+ isTrial: false,
415
+ subscriptionAutoRenewTerm: false,
416
+ value: 'P8W',
417
+ price: '£19.00',
418
+ amount: '19.00',
419
+ }),
420
+ ];
421
+ const wrapper = shallow(
422
+ <PaymentTerm
423
+ options={options}
424
+ isAutoRenewingSubscriptionTermType={false}
425
+ isNonRenewingSubscriptionTermType={true}
426
+ />
427
+ );
428
+
429
+ expect(
430
+ wrapper.find('.ncf__payment-term__renews-text').exists()
431
+ ).toBe(false);
432
+ });
433
+ });
434
+
435
+ describe('option.subscriptionAutoRenewTerm is true, i.e. auto-renewing subscription', () => {
436
+ describe('offer term is 52 weeks or longer', () => {
437
+ it('expresses price as a single payment', () => {
438
+ const options = [
439
+ buildOption({
440
+ name: 'annual',
441
+ value: 'P1Y',
442
+ price: '£120.00',
443
+ amount: '120.00',
444
+ subscriptionAutoRenewTerm: true,
445
+ }),
446
+ ];
447
+ const wrapper = shallow(<PaymentTerm options={options} />);
448
+
449
+ expect(
450
+ wrapper.find('.ncf__payment-term__description').text()
451
+ ).toContain('Single £120.00 payment');
452
+ });
453
+ });
339
454
 
340
- it('renders option.trialAmount as data-base-amount if isTrial is true', () => {
341
- const options = [
342
- {
343
- name: 'monthly',
344
- price: '$5.00',
345
- value: 'monthly',
346
- monthlyPrice: '$5.00',
347
- isTrial: true,
348
- amount: 100,
349
- trialAmount: 1,
350
- },
351
- ];
352
- const wrapper = shallow(<PaymentTerm options={options} />);
353
- expect(wrapper.find('input').prop('data-base-amount')).toBe(1);
455
+ describe('offer term is shorter than 52 weeks', () => {
456
+ it('expresses price as a recurring payment', () => {
457
+ const options = [
458
+ buildOption({
459
+ name: 'quarterly',
460
+ value: 'P3M',
461
+ price: '£30.00',
462
+ amount: '30.00',
463
+ subscriptionAutoRenewTerm: true,
464
+ }),
465
+ ];
466
+ const wrapper = shallow(<PaymentTerm options={options} />);
467
+
468
+ expect(
469
+ wrapper.find('.ncf__payment-term__description').text()
470
+ ).toContain('£30.00 per 3 months');
471
+ });
472
+ });
473
+
474
+ it('describes the renewal period', () => {
475
+ const options = [
476
+ buildOption({
477
+ name: 'quarterly',
478
+ value: 'P3M',
479
+ price: '£30.00',
480
+ amount: '30.00',
481
+ subscriptionAutoRenewTerm: true,
482
+ }),
483
+ ];
484
+ const wrapper = shallow(<PaymentTerm options={options} />);
485
+
486
+ expect(
487
+ wrapper.find('.ncf__payment-term__renews-text')
488
+ ).toHaveLength(1);
489
+ expect(wrapper.find('.ncf__payment-term__renews-text').text()).toBe(
490
+ 'Renews every 3 months unless cancelled'
491
+ );
492
+ });
493
+ });
494
+
495
+ describe('offer term is 90 days or longer', () => {
496
+ describe('option.monthlyPrice is provided', () => {
497
+ describe('option.monthlyPrice value is "0"', () => {
498
+ it('displays the equivalent monthly price calculated from the option property values', () => {
499
+ mockGetMonthlyEquivalentIf90DaysOrLonger.mockReturnValue({
500
+ amount: { value: '£10.00' },
501
+ });
502
+ const option = buildOption({
503
+ name: 'annual',
504
+ value: 'P1Y',
505
+ price: '£120.00',
506
+ amount: '120.00',
507
+ symbol: '£',
508
+ monthlyPrice: '0',
509
+ subscriptionAutoRenewTerm: false,
510
+ });
511
+ const wrapper = shallow(
512
+ <PaymentTerm
513
+ options={[option]}
514
+ isAutoRenewingSubscriptionTermType={false}
515
+ isNonRenewingSubscriptionTermType={true}
516
+ />
517
+ );
518
+
519
+ expect(
520
+ wrapper.find('.ncf__payment-term__monthly-price').text()
521
+ ).toBe('£10.00');
522
+ });
523
+ });
524
+
525
+ describe('option.monthlyPrice value can be parsed as a number, e.g. 54.17', () => {
526
+ it('displays the equivalent monthly price constructed from option.symbol and option.monthlyPrice values', () => {
527
+ mockGetMonthlyEquivalentIf90DaysOrLonger.mockReturnValue({
528
+ amount: { value: '£99.99' }, // This value should be ignored in favour of the option.monthlyPrice value
529
+ });
530
+ const option = buildOption({
531
+ name: 'annual',
532
+ value: 'P1Y',
533
+ price: '£650.00',
534
+ amount: '650.00',
535
+ symbol: '£',
536
+ monthlyPrice: '54.17',
537
+ subscriptionAutoRenewTerm: false,
538
+ });
539
+ const wrapper = shallow(
540
+ <PaymentTerm
541
+ options={[option]}
542
+ isAutoRenewingSubscriptionTermType={false}
543
+ isNonRenewingSubscriptionTermType={true}
544
+ />
545
+ );
546
+
547
+ expect(
548
+ wrapper.find('.ncf__payment-term__monthly-price').text()
549
+ ).toBe('£54.17');
550
+ });
551
+ });
552
+
553
+ describe('option.monthlyPrice value cannot be parsed as a number, e.g. "£54.17"', () => {
554
+ it('displays the equivalent monthly price derived directly from the option.monthlyPrice value', () => {
555
+ mockGetMonthlyEquivalentIf90DaysOrLonger.mockReturnValue({
556
+ amount: { value: '£99.99' }, // This value should be ignored in favour of the option.monthlyPrice value
557
+ });
558
+ const option = buildOption({
559
+ name: 'annual',
560
+ value: 'P1Y',
561
+ price: '£650.00',
562
+ amount: '650.00',
563
+ symbol: '£',
564
+ monthlyPrice: '£54.17',
565
+ subscriptionAutoRenewTerm: false,
566
+ });
567
+ const wrapper = shallow(
568
+ <PaymentTerm
569
+ options={[option]}
570
+ isAutoRenewingSubscriptionTermType={false}
571
+ isNonRenewingSubscriptionTermType={true}
572
+ />
573
+ );
574
+
575
+ expect(
576
+ wrapper.find('.ncf__payment-term__monthly-price').text()
577
+ ).toBe('£54.17');
578
+ });
579
+ });
580
+ });
581
+
582
+ describe('option.monthlyPrice is not provided', () => {
583
+ it('displays the equivalent monthly price calculated from the option property values', () => {
584
+ mockGetMonthlyEquivalentIf90DaysOrLonger.mockReturnValue({
585
+ amount: { value: '£10.00' },
586
+ });
587
+ const option = buildOption({
588
+ name: 'annual',
589
+ value: 'P1Y',
590
+ price: '£120.00',
591
+ amount: '120.00',
592
+ symbol: '£',
593
+ subscriptionAutoRenewTerm: false,
594
+ monthlyPrice: undefined,
595
+ });
596
+ const wrapper = shallow(
597
+ <PaymentTerm
598
+ options={[option]}
599
+ isAutoRenewingSubscriptionTermType={false}
600
+ isNonRenewingSubscriptionTermType={true}
601
+ />
602
+ );
603
+
604
+ expect(
605
+ wrapper.find('.ncf__payment-term__monthly-price').text()
606
+ ).toBe('£10.00');
607
+ });
608
+ });
609
+ });
610
+
611
+ describe('offer term is shorter than 90 days', () => {
612
+ it('does not display the equivalent monthly price', () => {
613
+ mockGetMonthlyEquivalentIf90DaysOrLonger.mockReturnValue(undefined);
614
+ const options = [
615
+ buildOption({
616
+ value: 'P8W',
617
+ price: '£19.00',
618
+ amount: '19.00',
619
+ subscriptionAutoRenewTerm: false,
620
+ }),
621
+ ];
622
+ const wrapper = shallow(
623
+ <PaymentTerm
624
+ options={options}
625
+ isAutoRenewingSubscriptionTermType={false}
626
+ isNonRenewingSubscriptionTermType={true}
627
+ />
628
+ );
629
+
630
+ expect(
631
+ wrapper.find('.ncf__payment-term__equivalent-price').exists()
632
+ ).toBe(false);
633
+ expect(wrapper.text()).not.toContain('That’s equivalent to');
634
+ });
635
+ });
636
+ });
637
+
638
+ describe('option.value is not a valid period', () => {
639
+ it('renders a component using option custom properties', () => {
640
+ const options = [
641
+ {
642
+ title: 'Annual',
643
+ subTitle: '(Renews annually unless cancelled)',
644
+ price: '€ 270.00',
645
+ value: 270.0,
646
+ isTrial: false,
647
+ discount: '33%',
648
+ bestOffer: true,
649
+ selected: false,
650
+ chargeOnText: 'You will be charged on May 1, 2021',
651
+ },
652
+ ];
653
+ const wrapper = shallow(
654
+ <PaymentTerm
655
+ options={options}
656
+ showLegal={false}
657
+ largePrice={true}
658
+ />
659
+ );
660
+
661
+ expect(wrapper.find('.ncf__payment-term__title').text()).toContain(
662
+ 'Annual'
663
+ );
664
+ expect(wrapper.find('.ncf__payment-term__sub-title').text()).toBe(
665
+ '(Renews annually unless cancelled)'
666
+ );
667
+ expect(wrapper.find('.ncf__payment-term__large-price').text()).toBe(
668
+ '€ 270.00'
669
+ );
670
+ expect(
671
+ wrapper.find('.ncf__payment-term__charge-on-text').text()
672
+ ).toBe('You will be charged on May 1, 2021');
673
+ });
674
+ });
354
675
  });
355
676
  });
356
677
 
357
- describe('When using custom options', () => {
358
- it('renders when not using an option in nameMap but provides a custom props instead', () => {
359
- const props = {
360
- showLegal: false,
361
- largePrice: true,
362
- options: [
363
- {
364
- title: 'Annual',
365
- subTitle: '(Renews annually unless cancelled)',
366
- price: '€ 270.00',
367
- value: 270.0,
368
- isTrial: false,
369
- discount: '33%',
370
- bestOffer: true,
371
- selected: false,
372
- chargeOnText: 'You will be charged on May 1, 2021',
373
- },
374
- {
375
- title: '12 Month Subscription',
376
- price: '€ 300.00',
377
- value: 300.0,
378
- isTrial: false,
379
- discount: '10%',
380
- selected: true,
381
- chargeOnText: 'You will be charged on May 1, 2021',
382
- },
383
- ],
384
- optionsInARow: true,
385
- };
678
+ describe('payment term legal text', () => {
679
+ describe('showLegal is true', () => {
680
+ describe('isAutoRenewingSubscriptionTermType is true; isNonRenewingSubscriptionTermType is false', () => {
681
+ it('displays relevant legal text', () => {
682
+ const wrapper = shallow(
683
+ <PaymentTerm
684
+ options={[buildOption()]}
685
+ showLegal={true}
686
+ isAutoRenewingSubscriptionTermType={true}
687
+ isNonRenewingSubscriptionTermType={false}
688
+ />
689
+ );
690
+
691
+ expect(wrapper.find('.ncf__payment-term__legal').exists()).toBe(true);
692
+ expect(wrapper.find('.ncf__payment-term__legal').text()).toContain(
693
+ 'With all subscription types, we will automatically renew your subscription using the payment method provided unless you cancel before your renewal date.'
694
+ );
695
+ expect(wrapper.find('.ncf__payment-term__legal').text()).toContain(
696
+ 'We will notify you at least 14 days in advance'
697
+ );
698
+ expect(wrapper.find('.ncf__payment-term__legal').text()).toContain(
699
+ 'Terms & Conditions'
700
+ );
701
+ });
702
+ });
386
703
 
387
- expect(PaymentTerm).toRenderCorrectly(props);
704
+ describe('isAutoRenewingSubscriptionTermType is false; isNonRenewingSubscriptionTermType is true', () => {
705
+ it('displays relevant legal text; hides unrelated legal text', () => {
706
+ const wrapper = shallow(
707
+ <PaymentTerm
708
+ options={[buildOption()]}
709
+ showLegal={true}
710
+ isAutoRenewingSubscriptionTermType={false}
711
+ isNonRenewingSubscriptionTermType={true}
712
+ />
713
+ );
714
+
715
+ expect(wrapper.find('.ncf__payment-term__legal').exists()).toBe(true);
716
+ expect(wrapper.find('.ncf__payment-term__legal').text()).toContain(
717
+ 'Find out more about our cancellation policy in our Terms & Conditions.'
718
+ );
719
+ expect(
720
+ wrapper.find('.ncf__payment-term__legal').text()
721
+ ).not.toContain(
722
+ 'With all subscription types, we will automatically renew your subscription'
723
+ );
724
+ expect(
725
+ wrapper.find('.ncf__payment-term__legal').text()
726
+ ).not.toContain('We will notify you at least 14 days in advance');
727
+ });
728
+ });
729
+ });
730
+
731
+ describe('showLegal is false', () => {
732
+ it('hides legal text', () => {
733
+ const wrapper = shallow(
734
+ <PaymentTerm
735
+ options={[buildOption()]}
736
+ showLegal={false}
737
+ isAutoRenewingSubscriptionTermType={true}
738
+ isNonRenewingSubscriptionTermType={false}
739
+ />
740
+ );
741
+
742
+ expect(wrapper.find('.ncf__payment-term__legal').exists()).toBe(false);
743
+ expect(wrapper.text()).not.toContain('Terms & Conditions');
744
+ expect(wrapper.text()).not.toContain('automatically renew');
745
+ });
388
746
  });
389
747
  });
390
748
  });