@financial-times/n-conversion-forms 32.3.2 → 32.5.0

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,6 +1,6 @@
1
1
  {
2
2
  "branch": "",
3
3
  "repo": "n-conversion-forms",
4
- "version": "dbf4d85ef93c98eced9c5d9293344ff7542f492d",
5
- "tag": "v32.3.2"
4
+ "version": "816f6435c7f2a3dc27071dea2eece968a969f98a",
5
+ "tag": "v32.5.0"
6
6
  }
@@ -10,6 +10,7 @@ export function AcceptTermsSubscription({
10
10
  isPrintProduct = false,
11
11
  isSingleTerm = false,
12
12
  is7DayPassExperiment = false,
13
+ isTermedSubscriptionTermType = false,
13
14
  isTransition = false,
14
15
  transitionType = null,
15
16
  isDeferredBilling = false,
@@ -88,6 +89,52 @@ export function AcceptTermsSubscription({
88
89
  );
89
90
  }
90
91
 
92
+ if (isTermedSubscriptionTermType) {
93
+ return (
94
+ <div {...divProps}>
95
+ <ul className="o-typography-list ncf__accept-terms-list">
96
+ <li>
97
+ <span className="terms-transition terms-transition--immediate">
98
+ I give consent for the chosen payment method to be charged automatically.
99
+ </span>
100
+ </li>
101
+ <li>
102
+ <span className="terms-transition terms-transition--immediate">
103
+ By placing your order subject to the Terms & Conditions (save for section 2) referred to
104
+ below, you are waiving your statutory right to cancel our contract within 14 days of
105
+ payment. Your payment is a one-time payment collected at the time of checkout, and
106
+ unsubscribing or cancelling at any point (whether before or after the 14-day period)
107
+ will not entitle you to a refund.
108
+ </span>
109
+ </li>
110
+ <li>
111
+ <span className="terms-transition">
112
+ Please see here for the complete{' '}
113
+ <a
114
+ className="ncf__link--external"
115
+ href="http://help.ft.com/help/legal-privacy/terms-conditions/"
116
+ target="_blank"
117
+ rel="noopener noreferrer"
118
+ >
119
+ Terms &amp; Conditions
120
+ </a>
121
+ .
122
+ </span>
123
+ </li>
124
+ </ul>
125
+ <label className={labelClassName} htmlFor="termsAcceptance">
126
+ <input {...inputProps} />
127
+ <span className="o-forms-input__label">
128
+ I agree to the above terms &amp; conditions.
129
+ </span>
130
+ <p className="o-forms-input__error">
131
+ Please accept our terms &amp; conditions
132
+ </p>
133
+ </label>
134
+ </div>
135
+ );
136
+ }
137
+
91
138
  const transitionTerms = isTransition && (
92
139
  <>
93
140
  {!isSingleTerm && (
@@ -261,6 +308,7 @@ AcceptTermsSubscription.propTypes = {
261
308
  isPrintProduct: PropTypes.bool,
262
309
  isSingleTerm: PropTypes.bool,
263
310
  is7DayPassExperiment: PropTypes.bool,
311
+ isTermedSubscriptionTermType: PropTypes.bool,
264
312
  isTransition: PropTypes.bool,
265
313
  transitionType: PropTypes.string,
266
314
  isDeferredBilling: PropTypes.bool,
@@ -70,6 +70,28 @@ describe('AcceptTermsSubscription', () => {
70
70
  expect(transitionTerms.exists()).toBe(true);
71
71
  });
72
72
 
73
+ it('renders the transition terms when isTermedSubscriptionTermType prop is true', () => {
74
+ const props = {
75
+ isTermedSubscriptionTermType: true,
76
+ };
77
+
78
+ const component = mount(<AcceptTermsSubscription {...props} />);
79
+
80
+ const transitionTerms1 = component.find('.terms-transition').at(0);
81
+ const transitionTerms2 = component.find('.terms-transition').at(1);
82
+ const transitionTerms3 = component.find('.terms-transition').at(2);
83
+
84
+ expect(transitionTerms1.text()).toEqual(
85
+ 'I give consent for the chosen payment method to be charged automatically.'
86
+ );
87
+ expect(transitionTerms2.text()).toEqual(
88
+ 'By placing your order subject to the Terms & Conditions (save for section 2) referred to below, you are waiving your statutory right to cancel our contract within 14 days of payment. Your payment is a one-time payment collected at the time of checkout, and unsubscribing or cancelling at any point (whether before or after the 14-day period) will not entitle you to a refund.'
89
+ );
90
+ expect(transitionTerms3.text()).toEqual(
91
+ 'Please see here for the complete Terms & Conditions.'
92
+ );
93
+ });
94
+
73
95
  it('does not render the transition terms when transitionType prop is null', () => {
74
96
  const props = {
75
97
  transitionType: null,
@@ -30,6 +30,14 @@ IsSingleTerm.args = {
30
30
  isSingleTerm: true,
31
31
  };
32
32
 
33
+ export const TermedSubscriptionTermType = (args) => (
34
+ <AcceptTermsSubscription {...args} />
35
+ );
36
+
37
+ TermedSubscriptionTermType.args = {
38
+ isTermedSubscriptionTermType: true,
39
+ };
40
+
33
41
  export const IsTransition = (args) => <AcceptTermsSubscription {...args} />;
34
42
 
35
43
  IsTransition.args = {
@@ -16,12 +16,13 @@ export function PaymentTerm({
16
16
  optionsInARow = false,
17
17
  billingCountry = '',
18
18
  is7DayPassExperiment = false,
19
+ isTermedSubscriptionTermType = false,
19
20
  }) {
20
21
  /**
21
22
  * Compute monthly price for given term name
22
23
  * @param {number} amount price in number format
23
24
  * @param {string} currency country id of the currency
24
- * @param {string} period PxY (yearly) or PxM (montly) where x is the amount of years/months
25
+ * @param {string} period (expressed in IS0 8601 duration format): e.g. PxY (yearly) or PxM (montly) where x is the amount of years/months
25
26
  * @returns {string}
26
27
  */
27
28
  const getMontlyPriceFromPeriod = (amount, currency, period) => {
@@ -33,13 +34,23 @@ export function PaymentTerm({
33
34
  /**
34
35
  * returns period converted to time if found
35
36
  * otherwise returns empty string to avoid show information not mapped
36
- * @param {string} period PxY (yearly) or PxM (montly) where x is the amount of years/months
37
+ * @param {string} period (expressed in IS0 8601 duration format): PxY (yearly), PxM (montly), PxW (weekly), of PxD (daily), where x is the amount of years/months/weeks/days
37
38
  * @returns {string}
38
39
  */
39
40
  const getTimeFromPeriod = (period) => {
40
- const freq =
41
- period.substring(period.length - 1) === 'Y' ? 'years' : 'months';
41
+ const periodUnitCodeToWordMap = {
42
+ Y: 'years',
43
+ M: 'months',
44
+ W: 'weeks',
45
+ D: 'days',
46
+ };
47
+
48
+ const periodUnitCode = period.substring(period.length - 1);
49
+
50
+ const freq = periodUnitCodeToWordMap[periodUnitCode] || '';
51
+
42
52
  const amount = period.substring(1, period.length - 1);
53
+
43
54
  return period ? `${amount} ${freq}` : '';
44
55
  };
45
56
 
@@ -177,6 +188,7 @@ export function PaymentTerm({
177
188
  </span>
178
189
  ),
179
190
  renewsText: (renewalPeriod) =>
191
+ !isTermedSubscriptionTermType &&
180
192
  Boolean(renewalPeriod) && (
181
193
  <p className="ncf__payment-term__renews-text">
182
194
  Renews every {renewalPeriod} unless cancelled
@@ -371,7 +383,7 @@ export function PaymentTerm({
371
383
 
372
384
  {showLegal && (
373
385
  <div className="ncf__payment-term__legal">
374
- {isFixedTermOffer ? (
386
+ {isTermedSubscriptionTermType || isFixedTermOffer ? (
375
387
  <p>
376
388
  Find out more about our cancellation policy in our{' '}
377
389
  <a
@@ -443,6 +455,7 @@ PaymentTerm.propTypes = {
443
455
  })
444
456
  ),
445
457
  isFixedTermOffer: PropTypes.bool,
458
+ isTermedSubscriptionTermType: PropTypes.bool,
446
459
  offerDisplayName: PropTypes.string,
447
460
  showLegal: PropTypes.bool,
448
461
  largePrice: PropTypes.bool,
@@ -184,6 +184,62 @@ describe('PaymentTerm', () => {
184
184
  });
185
185
  });
186
186
 
187
+ describe('given isTermedSubscriptionTermType is true', () => {
188
+ describe('options include duration expressed in weeks', () => {
189
+ const options = [
190
+ {
191
+ price: '£19.00',
192
+ amount: '19.00',
193
+ value: 'P8W',
194
+ },
195
+ ];
196
+ const wrapper = shallow(
197
+ <PaymentTerm options={options} isTermedSubscriptionTermType={true} />
198
+ );
199
+
200
+ it('renders subscription term as title', () => {
201
+ expect(wrapper.find('.ncf__payment-term__title').text()).toMatch(
202
+ '8 weeks'
203
+ );
204
+ });
205
+
206
+ it('renders description text that reflects that the termed subscription requires a single payment that expresses the per duration cost for shorter durations', () => {
207
+ expect(
208
+ wrapper.find('.ncf__payment-term__description').text()
209
+ ).toContain(
210
+ 'Single £19.00 paymentThat’s equivalent to GBP9.50 per month'
211
+ );
212
+ });
213
+ });
214
+
215
+ describe('options include duration expressed in days', () => {
216
+ const options = [
217
+ {
218
+ price: '£30.00',
219
+ amount: '30.00',
220
+ value: 'P90D',
221
+ },
222
+ ];
223
+ const wrapper = shallow(
224
+ <PaymentTerm options={options} isTermedSubscriptionTermType={true} />
225
+ );
226
+
227
+ it('renders subscription term as title', () => {
228
+ expect(wrapper.find('.ncf__payment-term__title').text()).toMatch(
229
+ '90 days'
230
+ );
231
+ });
232
+
233
+ it('renders description text that reflects that the termed subscription requires a single payment that expresses the per duration cost for shorter durations', () => {
234
+ expect(
235
+ wrapper.find('.ncf__payment-term__description').text()
236
+ ).toContain(
237
+ 'Single £30.00 paymentThat’s equivalent to GBP10.00 per month'
238
+ );
239
+ });
240
+ });
241
+ });
242
+
187
243
  describe('getDisplayName', () => {
188
244
  const baseOptions = {
189
245
  name: 'monthly',
@@ -129,6 +129,25 @@ SevenDayPassExperimentOffer.args = {
129
129
  offerDisplayName: '7-day pass',
130
130
  };
131
131
 
132
+ export const TermedSubscriptionTermType = (args) => (
133
+ <div className="ncf">
134
+ <Fieldset>
135
+ <PaymentTerm {...args} />
136
+ </Fieldset>
137
+ </div>
138
+ );
139
+ TermedSubscriptionTermType.args = {
140
+ options: [
141
+ {
142
+ name: '8 weeks',
143
+ price: '£19.00',
144
+ amount: '19.00',
145
+ value: 'P8W',
146
+ },
147
+ ],
148
+ isTermedSubscriptionTermType: true,
149
+ };
150
+
132
151
  export const RenewOffers = (args) => (
133
152
  <div className="ncf">
134
153
  <Fieldset>
@@ -26,6 +26,8 @@ function AcceptTermsSubscription(_ref) {
26
26
  isSingleTerm = _ref$isSingleTerm === void 0 ? false : _ref$isSingleTerm,
27
27
  _ref$is7DayPassExperi = _ref.is7DayPassExperiment,
28
28
  is7DayPassExperiment = _ref$is7DayPassExperi === void 0 ? false : _ref$is7DayPassExperi,
29
+ _ref$isTermedSubscrip = _ref.isTermedSubscriptionTermType,
30
+ isTermedSubscriptionTermType = _ref$isTermedSubscrip === void 0 ? false : _ref$isTermedSubscrip,
29
31
  _ref$isTransition = _ref.isTransition,
30
32
  isTransition = _ref$isTransition === void 0 ? false : _ref$isTransition,
31
33
  _ref$transitionType = _ref.transitionType,
@@ -74,6 +76,29 @@ function AcceptTermsSubscription(_ref) {
74
76
  className: "o-forms-input__error"
75
77
  }, "Please accept our terms & conditions")));
76
78
  }
79
+ if (isTermedSubscriptionTermType) {
80
+ return /*#__PURE__*/_react["default"].createElement("div", divProps, /*#__PURE__*/_react["default"].createElement("ul", {
81
+ className: "o-typography-list ncf__accept-terms-list"
82
+ }, /*#__PURE__*/_react["default"].createElement("li", null, /*#__PURE__*/_react["default"].createElement("span", {
83
+ className: "terms-transition terms-transition--immediate"
84
+ }, "I give consent for the chosen payment method to be charged automatically.")), /*#__PURE__*/_react["default"].createElement("li", null, /*#__PURE__*/_react["default"].createElement("span", {
85
+ className: "terms-transition terms-transition--immediate"
86
+ }, "By placing your order subject to the Terms & Conditions (save for section 2) referred to below, you are waiving your statutory right to cancel our contract within 14 days of payment. Your payment is a one-time payment collected at the time of checkout, and unsubscribing or cancelling at any point (whether before or after the 14-day period) will not entitle you to a refund.")), /*#__PURE__*/_react["default"].createElement("li", null, /*#__PURE__*/_react["default"].createElement("span", {
87
+ className: "terms-transition"
88
+ }, "Please see here for the complete", ' ', /*#__PURE__*/_react["default"].createElement("a", {
89
+ className: "ncf__link--external",
90
+ href: "http://help.ft.com/help/legal-privacy/terms-conditions/",
91
+ target: "_blank",
92
+ rel: "noopener noreferrer"
93
+ }, "Terms & Conditions"), "."))), /*#__PURE__*/_react["default"].createElement("label", {
94
+ className: labelClassName,
95
+ htmlFor: "termsAcceptance"
96
+ }, /*#__PURE__*/_react["default"].createElement("input", inputProps), /*#__PURE__*/_react["default"].createElement("span", {
97
+ className: "o-forms-input__label"
98
+ }, "I agree to the above terms & conditions."), /*#__PURE__*/_react["default"].createElement("p", {
99
+ className: "o-forms-input__error"
100
+ }, "Please accept our terms & conditions")));
101
+ }
77
102
  var transitionTerms = isTransition && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, !isSingleTerm && /*#__PURE__*/_react["default"].createElement("li", null, /*#__PURE__*/_react["default"].createElement("span", {
78
103
  className: "terms-transition"
79
104
  }, "I give consent for my chosen payment method to be charged automatically at the end of each subscription term until I cancel it by contacting", ' ', /*#__PURE__*/_react["default"].createElement("a", {
@@ -144,6 +169,7 @@ AcceptTermsSubscription.propTypes = {
144
169
  isPrintProduct: _propTypes["default"].bool,
145
170
  isSingleTerm: _propTypes["default"].bool,
146
171
  is7DayPassExperiment: _propTypes["default"].bool,
172
+ isTermedSubscriptionTermType: _propTypes["default"].bool,
147
173
  isTransition: _propTypes["default"].bool,
148
174
  transitionType: _propTypes["default"].string,
149
175
  isDeferredBilling: _propTypes["default"].bool
@@ -35,12 +35,14 @@ function PaymentTerm(_ref) {
35
35
  _ref$billingCountry = _ref.billingCountry,
36
36
  billingCountry = _ref$billingCountry === void 0 ? '' : _ref$billingCountry,
37
37
  _ref$is7DayPassExperi = _ref.is7DayPassExperiment,
38
- is7DayPassExperiment = _ref$is7DayPassExperi === void 0 ? false : _ref$is7DayPassExperi;
38
+ is7DayPassExperiment = _ref$is7DayPassExperi === void 0 ? false : _ref$is7DayPassExperi,
39
+ _ref$isTermedSubscrip = _ref.isTermedSubscriptionTermType,
40
+ isTermedSubscriptionTermType = _ref$isTermedSubscrip === void 0 ? false : _ref$isTermedSubscrip;
39
41
  /**
40
42
  * Compute monthly price for given term name
41
43
  * @param {number} amount price in number format
42
44
  * @param {string} currency country id of the currency
43
- * @param {string} period PxY (yearly) or PxM (montly) where x is the amount of years/months
45
+ * @param {string} period (expressed in IS0 8601 duration format): e.g. PxY (yearly) or PxM (montly) where x is the amount of years/months
44
46
  * @returns {string}
45
47
  */
46
48
  var getMontlyPriceFromPeriod = function getMontlyPriceFromPeriod(amount, currency, period) {
@@ -55,11 +57,18 @@ function PaymentTerm(_ref) {
55
57
  /**
56
58
  * returns period converted to time if found
57
59
  * otherwise returns empty string to avoid show information not mapped
58
- * @param {string} period PxY (yearly) or PxM (montly) where x is the amount of years/months
60
+ * @param {string} period (expressed in IS0 8601 duration format): PxY (yearly), PxM (montly), PxW (weekly), of PxD (daily), where x is the amount of years/months/weeks/days
59
61
  * @returns {string}
60
62
  */
61
63
  var getTimeFromPeriod = function getTimeFromPeriod(period) {
62
- var freq = period.substring(period.length - 1) === 'Y' ? 'years' : 'months';
64
+ var periodUnitCodeToWordMap = {
65
+ Y: 'years',
66
+ M: 'months',
67
+ W: 'weeks',
68
+ D: 'days'
69
+ };
70
+ var periodUnitCode = period.substring(period.length - 1);
71
+ var freq = periodUnitCodeToWordMap[periodUnitCode] || '';
63
72
  var amount = period.substring(1, period.length - 1);
64
73
  return period ? "".concat(amount, " ").concat(freq) : '';
65
74
  };
@@ -171,7 +180,7 @@ function PaymentTerm(_ref) {
171
180
  }, _monthlyPrice), ' ', "per month");
172
181
  },
173
182
  renewsText: function renewsText(renewalPeriod) {
174
- return Boolean(renewalPeriod) && /*#__PURE__*/_react["default"].createElement("p", {
183
+ return !isTermedSubscriptionTermType && Boolean(renewalPeriod) && /*#__PURE__*/_react["default"].createElement("p", {
175
184
  className: "ncf__payment-term__renews-text"
176
185
  }, "Renews every ", renewalPeriod, " unless cancelled");
177
186
  }
@@ -276,7 +285,7 @@ function PaymentTerm(_ref) {
276
285
  return createPaymentTerm(option);
277
286
  })), showLegal && /*#__PURE__*/_react["default"].createElement("div", {
278
287
  className: "ncf__payment-term__legal"
279
- }, isFixedTermOffer ? /*#__PURE__*/_react["default"].createElement("p", null, "Find out more about our cancellation policy in our", ' ', /*#__PURE__*/_react["default"].createElement("a", {
288
+ }, isTermedSubscriptionTermType || isFixedTermOffer ? /*#__PURE__*/_react["default"].createElement("p", null, "Find out more about our cancellation policy in our", ' ', /*#__PURE__*/_react["default"].createElement("a", {
280
289
  className: "ncf__link--external",
281
290
  href: "https://help.ft.com/legal-privacy/terms-and-conditions/",
282
291
  title: "FT Legal Terms and Conditions help page",
@@ -316,6 +325,7 @@ PaymentTerm.propTypes = {
316
325
  fulfilmentOption: _propTypes["default"].string
317
326
  })),
318
327
  isFixedTermOffer: _propTypes["default"].bool,
328
+ isTermedSubscriptionTermType: _propTypes["default"].bool,
319
329
  offerDisplayName: _propTypes["default"].string,
320
330
  showLegal: _propTypes["default"].bool,
321
331
  largePrice: _propTypes["default"].bool,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/n-conversion-forms",
3
- "version": "32.3.2",
3
+ "version": "32.5.0",
4
4
  "description": "Containing jsx components and styles for forms included on Accounts and Acqusition apps (next-signup, next-profile, next-retention, etc).",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {