@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.
- package/.toolkitstate/ci.json +3 -3
- package/.toolkitstate/install.json +1 -1
- package/components/__snapshots__/payment-term.spec.js.snap +1 -1031
- package/components/delivery-option.stories.js +2 -2
- package/components/payment-term.jsx +249 -208
- package/components/payment-term.spec.js +675 -317
- package/components/payment-term.stories.js +135 -24
- package/dist/payment-term.jsx +198 -145
- package/helpers/duration-helpers.js +90 -0
- package/helpers/duration-helpers.spec.js +142 -0
- package/helpers/index.js +3 -0
- package/helpers/index.spec.js +8 -0
- package/package.json +2 -2
- package/styles/payment-term.scss +5 -5
- package/styles/payment-type.scss +0 -4
|
@@ -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
|
-
|
|
11
|
-
it('render with defaults', () => {
|
|
12
|
-
const props = {};
|
|
11
|
+
const mockGetMonthlyEquivalentIf90DaysOrLonger = jest.fn();
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
jest.mock('@financial-times/n-pricing', () => {
|
|
14
|
+
const actual = jest.requireActual('@financial-times/n-pricing');
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
54
|
-
|
|
42
|
+
describe('default props are used', () => {
|
|
43
|
+
it('renders correctly', () => {
|
|
44
|
+
const props = {};
|
|
55
45
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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(
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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(
|
|
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('
|
|
121
|
-
describe('
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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('
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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('
|
|
189
|
-
describe('
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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
|
-
|
|
190
|
+
/^Trial: /
|
|
208
191
|
);
|
|
209
192
|
});
|
|
210
193
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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('
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
<PaymentTerm
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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('
|
|
252
|
-
|
|
253
|
-
{
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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('
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
-
|
|
292
|
-
|
|
293
|
-
|
|
340
|
+
|
|
341
|
+
expect(
|
|
342
|
+
wrapper.find('.ncf__payment-term__description').text()
|
|
343
|
+
).toContain('6 weeks');
|
|
294
344
|
});
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
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
|
-
|
|
305
|
-
|
|
358
|
+
|
|
359
|
+
expect(wrapper.find('.ncf__payment-term__trial-price').text()).toBe(
|
|
360
|
+
'£1.00'
|
|
306
361
|
);
|
|
307
362
|
});
|
|
308
|
-
|
|
363
|
+
|
|
364
|
+
it('displays the trial price explanatory text', () => {
|
|
309
365
|
const options = [
|
|
310
|
-
{
|
|
311
|
-
|
|
312
|
-
displayName: '
|
|
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
|
-
|
|
317
|
-
|
|
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
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
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('
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
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
|
-
|
|
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
|
});
|