@financial-times/n-conversion-forms 26.0.0 → 27.0.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.
Files changed (111) hide show
  1. package/.circleci/config.yml +4 -4
  2. package/.eslintignore +1 -0
  3. package/.github/workflows/gh-pages-deploy.yml +1 -0
  4. package/.storybook/main.js +0 -1
  5. package/__mocks__/@financial-times/o-expander.js +9 -0
  6. package/__mocks__/@financial-times/o-forms-input.js +11 -0
  7. package/__mocks__/@financial-times/o-forms.js +40 -0
  8. package/build-state/npm-shrinkwrap.json +294 -6334
  9. package/components/__snapshots__/b2c-partnership-confirmation.spec.js.snap +1 -1
  10. package/components/__snapshots__/confirmation.spec.js.snap +0 -3
  11. package/components/__snapshots__/debug.spec.js.snap +25 -13
  12. package/components/__snapshots__/delivery-postcode.spec.js.snap +1 -1
  13. package/components/__snapshots__/payment-term.spec.js.snap +1 -1
  14. package/components/__snapshots__/payment-type.spec.js.snap +19 -0
  15. package/components/__snapshots__/registration-confirmation.spec.js.snap +230 -74
  16. package/components/accept-terms.jsx +57 -36
  17. package/components/accept-terms.stories.js +28 -1
  18. package/components/b2c-partnership-confirmation.jsx +1 -1
  19. package/components/confirmation.jsx +15 -8
  20. package/components/confirmation.spec.js +1 -1
  21. package/components/debug.jsx +19 -12
  22. package/components/debug.stories.js +13 -0
  23. package/components/delivery-address.jsx +21 -58
  24. package/components/delivery-address.stories.js +7 -0
  25. package/components/delivery-city.jsx +4 -2
  26. package/components/delivery-city.stories.js +9 -0
  27. package/components/delivery-option.jsx +5 -3
  28. package/components/delivery-option.stories.js +7 -1
  29. package/components/delivery-postcode.jsx +32 -13
  30. package/components/delivery-postcode.stories.js +2 -1
  31. package/components/delivery-security-instructions.spec.js +3 -3
  32. package/components/graduation-date.spec.js +8 -8
  33. package/components/index.jsx +1 -1
  34. package/components/message.jsx +1 -1
  35. package/components/payment-term.jsx +152 -25
  36. package/components/payment-term.spec.js +46 -4
  37. package/components/payment-term.stories.js +69 -14
  38. package/components/payment-type.jsx +3 -1
  39. package/components/position.jsx +6 -3
  40. package/components/position.spec.js +15 -5
  41. package/components/registration-confirmation.jsx +111 -32
  42. package/components/responsibility.jsx +6 -3
  43. package/components/responsibility.spec.js +15 -5
  44. package/components/text-input.jsx +73 -0
  45. package/components/text-input.spec.js +118 -0
  46. package/components/text-input.stories.js +31 -0
  47. package/dist/accept-terms.js +15 -7
  48. package/dist/b2c-partnership-confirmation.js +1 -1
  49. package/dist/confirmation.js +11 -2
  50. package/dist/debug.js +6 -6
  51. package/dist/delivery-address.js +19 -32
  52. package/dist/delivery-city.js +4 -2
  53. package/dist/delivery-option.js +5 -2
  54. package/dist/delivery-postcode.js +31 -12
  55. package/dist/index.js +9 -9
  56. package/dist/message.js +1 -1
  57. package/dist/payment-term.js +117 -11
  58. package/dist/payment-type.js +5 -2
  59. package/dist/position.js +6 -2
  60. package/dist/registration-confirmation.js +87 -29
  61. package/dist/responsibility.js +6 -2
  62. package/dist/text-input.js +84 -0
  63. package/helpers/constants.js +7 -0
  64. package/helpers/deliveryAddressMap.js +167 -0
  65. package/helpers/index.js +7 -0
  66. package/helpers/index.spec.js +11 -0
  67. package/helpers/ncf-common-data.spec.js +34 -0
  68. package/helpers/ncf-countries.spec.js +136 -0
  69. package/helpers/supportedCountries.js +76 -0
  70. package/helpers/supportedPostcodeExamples.js +57 -0
  71. package/helpers/supportedPostcodeValidators.js +53 -0
  72. package/helpers/utilities.js +14 -0
  73. package/jest.config.js +8 -1
  74. package/main.scss +461 -0
  75. package/package.json +6 -3
  76. package/styles/confirmation.scss +122 -0
  77. package/styles/payment-term.scss +3 -0
  78. package/utils/app-banner.spec.js +68 -0
  79. package/utils/apple-pay.spec.js +177 -0
  80. package/utils/billing-country.spec.js +87 -0
  81. package/utils/billing-postcode.spec.js +138 -0
  82. package/utils/company-name.spec.js +3 -7
  83. package/utils/country.spec.js +87 -0
  84. package/utils/delivery-address-type.spec.js +24 -11
  85. package/utils/delivery-option-messages.js +15 -0
  86. package/utils/delivery-option-messages.spec.js +3 -3
  87. package/utils/delivery-option.spec.js +100 -15
  88. package/utils/delivery-postcode.spec.js +138 -0
  89. package/utils/delivery-start-date.spec.js +177 -0
  90. package/utils/email.spec.js +210 -0
  91. package/utils/event-notifier.spec.js +116 -0
  92. package/utils/form-element.spec.js +71 -0
  93. package/utils/loader.spec.js +161 -0
  94. package/utils/password.spec.js +65 -0
  95. package/utils/payment-term.js +25 -1
  96. package/utils/payment-term.spec.js +198 -0
  97. package/utils/payment-type.js +1 -1
  98. package/utils/payment-type.spec.js +136 -0
  99. package/utils/postcode.spec.js +122 -0
  100. package/utils/salesforce.spec.js +30 -0
  101. package/utils/submit.spec.js +81 -0
  102. package/utils/tracking.spec.js +174 -0
  103. package/utils/validation.js +2 -2
  104. package/utils/validation.spec.js +234 -0
  105. package/utils/zuora.spec.js +249 -0
  106. package/components/__snapshots__/b2c-partnership-payment-term.spec.js.snap +0 -193
  107. package/components/b2c-partnership-payment-term.jsx +0 -126
  108. package/components/b2c-partnership-payment-term.spec.js +0 -52
  109. package/components/b2c-partnership-payment-term.stories.js +0 -44
  110. package/dist/b2c-partnership-payment-term.js +0 -91
  111. package/styles/b2c-partnership-payment-term.scss +0 -20
@@ -12,43 +12,101 @@ var _react = _interopRequireDefault(require("react"));
12
12
  var _propTypes = _interopRequireDefault(require("prop-types"));
13
13
 
14
14
  var EMAIL_DEFAULT_TEXT = 'your email';
15
+ var SOCIALS = [{
16
+ name: 'instagram',
17
+ link: 'https://www.instagram.com/financialtimes'
18
+ }, {
19
+ name: 'linkedin',
20
+ link: 'https://www.linkedin.com/company/financial-times'
21
+ }, {
22
+ name: 'twitter',
23
+ link: 'https://twitter.com/FT'
24
+ }, {
25
+ name: 'facebook',
26
+ link: 'https://www.facebook.com/financialtimes'
27
+ }];
28
+ var STORES = [{
29
+ name: 'apple',
30
+ link: 'https://apps.apple.com/app/apple-store/id1200842933'
31
+ }, {
32
+ name: 'android',
33
+ link: 'https://play.google.com/store/apps/details?id=com.ft.news'
34
+ }];
15
35
 
16
36
  function RegistrationConfirmation(_ref) {
17
37
  var _ref$email = _ref.email,
18
- email = _ref$email === void 0 ? EMAIL_DEFAULT_TEXT : _ref$email;
38
+ email = _ref$email === void 0 ? EMAIL_DEFAULT_TEXT : _ref$email,
39
+ _ref$returnUrl = _ref.returnUrl,
40
+ returnUrl = _ref$returnUrl === void 0 ? '/' : _ref$returnUrl;
19
41
  return /*#__PURE__*/_react["default"].createElement("div", {
20
- className: "ncf ncf__wrapper"
42
+ className: "ncf"
21
43
  }, /*#__PURE__*/_react["default"].createElement("div", {
22
- className: "ncf__center"
44
+ className: "ncf__center ncf__margin"
23
45
  }, /*#__PURE__*/_react["default"].createElement("div", {
24
46
  className: "ncf__icon ncf__icon--tick ncf__icon--large"
25
- }), /*#__PURE__*/_react["default"].createElement("div", {
26
- className: "ncf__paragraph"
27
- }, /*#__PURE__*/_react["default"].createElement("h1", {
47
+ }), /*#__PURE__*/_react["default"].createElement("h1", {
28
48
  className: "ncf__header ncf__header--confirmation"
29
- }, "Welcome to FT.com"))), /*#__PURE__*/_react["default"].createElement("p", {
30
- className: "ncf__paragraph"
31
- }, "We\u2019ve sent confirmation of your new account to ", email, "."), /*#__PURE__*/_react["default"].createElement("div", {
32
- className: "ncf__headed-paragraph"
33
- }, /*#__PURE__*/_react["default"].createElement("h2", {
34
- className: "ncf__header"
35
- }, "Something not right?"), /*#__PURE__*/_react["default"].createElement("p", {
36
- className: "ncf__paragraph"
37
- }, "Go to your", ' ', /*#__PURE__*/_react["default"].createElement("a", {
38
- className: "ncf__link ncf__link--external",
39
- href: "https://www.ft.com/myaccount/personal-details",
40
- target: "_blank",
41
- rel: "noopener noreferrer",
42
- "data-trackable": "yourAccount"
43
- }, "account settings"), ' ', "to view or edit your account. If you need to get in touch call us on", ' ', /*#__PURE__*/_react["default"].createElement("a", {
44
- href: "tel:+442077556248",
45
- className: "ncf__link ncf__link--external"
46
- }, "+44 (0) 207 755 6248"), ". Or contact us for additional support.")), /*#__PURE__*/_react["default"].createElement("p", {
47
- className: "ncf__center"
48
- }, /*#__PURE__*/_react["default"].createElement("a", {
49
- href: "/products ",
50
- className: "ncf__button ncf__button--submit"
51
- }, "See our subscription packages")));
49
+ }, "Success"), /*#__PURE__*/_react["default"].createElement("p", {
50
+ className: "ncf__confirmation--message"
51
+ }, "We\u2019ve sent confirmation to ", email, ".")), /*#__PURE__*/_react["default"].createElement("div", {
52
+ className: "ncf__divider-horizontal"
53
+ }), /*#__PURE__*/_react["default"].createElement("div", {
54
+ className: "ncf__confirmation--links ncf__margin"
55
+ }, /*#__PURE__*/_react["default"].createElement("div", {
56
+ className: "ncf__confirmation--socials"
57
+ }, /*#__PURE__*/_react["default"].createElement("b", null, "Breaking news alerts, direct to your lock screen"), /*#__PURE__*/_react["default"].createElement("p", {
58
+ className: "ncf__confirmation--mobile"
59
+ }, "Download our apps or follow us on our socials"), /*#__PURE__*/_react["default"].createElement("p", {
60
+ className: "ncf__confirmation--desktop"
61
+ }, "Find us in the app and google play stores or follow us on our socials"), /*#__PURE__*/_react["default"].createElement("div", {
62
+ className: "ncf__confirmation--badges"
63
+ }, /*#__PURE__*/_react["default"].createElement("div", {
64
+ className: "o-social-follow",
65
+ "aria-label": "Follow on social media"
66
+ }, SOCIALS.map(function (_ref2) {
67
+ var name = _ref2.name,
68
+ link = _ref2.link;
69
+ return /*#__PURE__*/_react["default"].createElement("a", {
70
+ key: name,
71
+ href: link,
72
+ className: "o-social-follow-icon o-social-follow-icon--".concat(name),
73
+ target: "_blank",
74
+ rel: "noopener noreferrer",
75
+ "data-trackable": "register-social-".concat(name)
76
+ }, /*#__PURE__*/_react["default"].createElement("span", {
77
+ className: "o-social-follow-icon__label"
78
+ }, "on ", name));
79
+ })), /*#__PURE__*/_react["default"].createElement("div", {
80
+ className: "ncf__confirmation--mobile ncf__confirmation--app-badges",
81
+ "aria-label": "Download the app"
82
+ }, STORES.map(function (_ref3) {
83
+ var name = _ref3.name,
84
+ link = _ref3.link;
85
+ return /*#__PURE__*/_react["default"].createElement("a", {
86
+ key: name,
87
+ href: link,
88
+ className: "ncf-icon ncf-icon--".concat(name),
89
+ target: "_blank",
90
+ rel: "noopener noreferrer",
91
+ "data-trackable": "register-app-".concat(name)
92
+ }, /*#__PURE__*/_react["default"].createElement("span", {
93
+ className: "o-social-follow-icon__label"
94
+ }, "on ", name));
95
+ })))), /*#__PURE__*/_react["default"].createElement("div", {
96
+ className: "ncf__confirmation--alerts"
97
+ }, /*#__PURE__*/_react["default"].createElement("b", null, "Set up email alerts in", /*#__PURE__*/_react["default"].createElement("span", {
98
+ "aria-label": "myFT",
99
+ className: "ncf-icon ncf-icon--myft"
100
+ })), /*#__PURE__*/_react["default"].createElement("p", null, "Choose the content you want to follow by personalising your alerts for the most important topics and additional newsletters"), /*#__PURE__*/_react["default"].createElement("a", {
101
+ href: "/myft",
102
+ className: "margin-top-x4 ncf__button ncf__button--secondary",
103
+ "data-trackable": "register-personalise-my-alerts"
104
+ }, "Personalise my alerts"))), /*#__PURE__*/_react["default"].createElement("a", {
105
+ href: returnUrl,
106
+ target: "_parent",
107
+ className: "ncf__confirmation--finish ncf__button ncf__button--submit",
108
+ "data-trackable": "register-finish"
109
+ }, "Finish"));
52
110
  }
53
111
 
54
112
  RegistrationConfirmation.propTypes = {
@@ -15,7 +15,8 @@ var _classnames = _interopRequireDefault(require("classnames"));
15
15
 
16
16
  var _nCommonStaticData = require("n-common-static-data");
17
17
 
18
- var defaultOptions = _nCommonStaticData.demographics.responsibilities.responsibilities;
18
+ var B2CResponsibilities = _nCommonStaticData.demographics.responsibilities.responsibilities;
19
+ var B2BResponsibilities = _nCommonStaticData.b2b.demographics.responsibilities.responsibilities;
19
20
 
20
21
  function Responsibility(_ref) {
21
22
  var value = _ref.value,
@@ -31,8 +32,10 @@ function Responsibility(_ref) {
31
32
  selectId = _ref$selectId === void 0 ? 'responsibility' : _ref$selectId,
32
33
  _ref$selectName = _ref.selectName,
33
34
  selectName = _ref$selectName === void 0 ? 'responsibility' : _ref$selectName,
35
+ _ref$isB2B = _ref.isB2B,
36
+ isB2B = _ref$isB2B === void 0 ? false : _ref$isB2B,
34
37
  _ref$options = _ref.options,
35
- options = _ref$options === void 0 ? defaultOptions : _ref$options,
38
+ options = _ref$options === void 0 ? isB2B ? B2BResponsibilities : B2CResponsibilities : _ref$options,
36
39
  _ref$fieldLabel = _ref.fieldLabel,
37
40
  fieldLabel = _ref$fieldLabel === void 0 ? 'Which best describes your job responsibility?' : _ref$fieldLabel;
38
41
  var inputWrapperClassName = (0, _classnames["default"])(['o-forms-input', 'o-forms-input--select', {
@@ -81,6 +84,7 @@ Responsibility.propTypes = {
81
84
  fieldId: _propTypes["default"].string,
82
85
  selectId: _propTypes["default"].string,
83
86
  selectName: _propTypes["default"].string,
87
+ isB2B: _propTypes["default"].bool,
84
88
  options: _propTypes["default"].arrayOf(_propTypes["default"].shape({
85
89
  code: _propTypes["default"].string,
86
90
  description: _propTypes["default"].string
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.TextInput = TextInput;
9
+
10
+ var _react = _interopRequireDefault(require("react"));
11
+
12
+ var _propTypes = _interopRequireDefault(require("prop-types"));
13
+
14
+ var _classnames = _interopRequireDefault(require("classnames"));
15
+
16
+ function TextInput(_ref) {
17
+ var dataTrackable = _ref.dataTrackable,
18
+ _ref$errorText = _ref.errorText,
19
+ errorText = _ref$errorText === void 0 ? 'Please enter a value' : _ref$errorText,
20
+ fieldId = _ref.fieldId,
21
+ _ref$hasError = _ref.hasError,
22
+ hasError = _ref$hasError === void 0 ? false : _ref$hasError,
23
+ inputId = _ref.inputId,
24
+ inputName = _ref.inputName,
25
+ _ref$isDisabled = _ref.isDisabled,
26
+ isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
27
+ _ref$isRequired = _ref.isRequired,
28
+ isRequired = _ref$isRequired === void 0 ? false : _ref$isRequired,
29
+ _ref$label = _ref.label,
30
+ label = _ref$label === void 0 ? '' : _ref$label,
31
+ _ref$placeHolder = _ref.placeHolder,
32
+ placeHolder = _ref$placeHolder === void 0 ? '' : _ref$placeHolder,
33
+ _ref$value = _ref.value,
34
+ value = _ref$value === void 0 ? '' : _ref$value,
35
+ description = _ref.description;
36
+ // Use inputId if inputName is not explicitly passed.
37
+ inputName = inputName || inputId;
38
+ var inputWrapperClassNames = (0, _classnames["default"])(['o-forms-input', 'o-forms-input--text', {
39
+ 'o-forms-input--invalid': hasError
40
+ }, {
41
+ 'o-forms-field--optional': !isRequired
42
+ }]);
43
+ return /*#__PURE__*/_react["default"].createElement("label", {
44
+ id: fieldId,
45
+ className: "o-forms-field ncf__validation-error",
46
+ "data-validate": "required",
47
+ htmlFor: inputId
48
+ }, /*#__PURE__*/_react["default"].createElement("span", {
49
+ className: "o-forms-title"
50
+ }, /*#__PURE__*/_react["default"].createElement("span", {
51
+ className: "o-forms-title__main"
52
+ }, label), description ? /*#__PURE__*/_react["default"].createElement("span", {
53
+ className: "o-forms-title__prompt"
54
+ }, description) : null), /*#__PURE__*/_react["default"].createElement("span", {
55
+ className: inputWrapperClassNames
56
+ }, /*#__PURE__*/_react["default"].createElement("input", {
57
+ type: "text",
58
+ id: inputId,
59
+ name: inputName,
60
+ placeholder: placeHolder,
61
+ "data-trackable": dataTrackable,
62
+ "aria-required": isRequired,
63
+ required: isRequired,
64
+ disabled: isDisabled,
65
+ defaultValue: value
66
+ }), /*#__PURE__*/_react["default"].createElement("span", {
67
+ className: "o-forms-input__error"
68
+ }, errorText)));
69
+ }
70
+
71
+ TextInput.propTypes = {
72
+ dataTrackable: _propTypes["default"].string,
73
+ errorText: _propTypes["default"].string,
74
+ fieldId: _propTypes["default"].string,
75
+ hasError: _propTypes["default"].bool,
76
+ inputId: _propTypes["default"].string,
77
+ inputName: _propTypes["default"].string,
78
+ isDisabled: _propTypes["default"].bool,
79
+ isRequired: _propTypes["default"].bool,
80
+ label: _propTypes["default"].string,
81
+ placeHolder: _propTypes["default"].string,
82
+ value: _propTypes["default"].string,
83
+ description: _propTypes["default"].string
84
+ };
@@ -0,0 +1,7 @@
1
+ const printRegions = {
2
+ cemeaV1: 'CEMEA_V1',
3
+ cemeaV2: 'CEMEA_V2',
4
+ apac: 'APAC'
5
+ };
6
+
7
+ module.exports = { printRegions };
@@ -0,0 +1,167 @@
1
+ const React = require('react');
2
+
3
+ const addressTemplateGenerator = (addressLine1, addressLine2, addressLine3) => (<>
4
+ {' '}
5
+ {addressLine1}
6
+ {addressLine2}
7
+ {addressLine3}{' '}
8
+ </>);
9
+
10
+ const deliveryAddressMap = {
11
+ 'home': {
12
+ addressLine1Placeholder: {
13
+ GBR: 'e.g. 10 Elm Street',
14
+ USA: 'e.g. 10 Elm St.',
15
+ CAN: 'e.g. 36 Poirier Blvd.',
16
+ CEMEA_V1: 'Street and House Number',
17
+ CEMEA_V2: 'House Number and Street',
18
+ APAC: 'Street name',
19
+ ARE: 'PO Box 12345'
20
+ },
21
+ addressLine2Placeholder: {
22
+ CEMEA_V1: 'Apt No./Floor/Building',
23
+ CEMEA_V2: 'Apt No./Floor/Building',
24
+ APAC: 'House/Apartment/Building name',
25
+ },
26
+ addressLine3Placeholder: {
27
+ USA: 'e.g Apt 2C / FL 10 / STE 50',
28
+ CAN: 'e.g Apt 2C / FL 10 / STE 50',
29
+ CEMEA_V1: ' ',
30
+ CEMEA_V2: ' ',
31
+ APAC: 'District/County/Province/Ward',
32
+ },
33
+ addressLine1Title:{
34
+ 'ARE': 'PO Box',
35
+ },
36
+ addressLine3Title: {
37
+ GBR: 'Address line 3',
38
+ USA: 'APT/FL/STE',
39
+ CAN: 'APT/FL/STE',
40
+ CEMEA_V1: 'Address line 3',
41
+ CEMEA_V2: 'Address line 3',
42
+ },
43
+ addressLine3Prompt: {
44
+ USA: 'Max. 6 characters. Please enter “Apartment 2C” as “Apt 2C”, “Floor 10 as FL 10”',
45
+ CAN: 'Max. 6 characters. Please enter “Apartment 2C” as “Apt 2C”, “Floor 10 as FL 10”',
46
+ },
47
+ template: (addressLine1, addressLine2, addressLine3, region) => {
48
+ const addressLines = {
49
+ GBR: addressTemplateGenerator(addressLine1, addressLine2, addressLine3),
50
+ USA: addressTemplateGenerator(addressLine1, addressLine3, addressLine2),
51
+ CAN: addressTemplateGenerator(addressLine1, addressLine3, addressLine2),
52
+
53
+ CEMEA_V1: addressTemplateGenerator(addressLine1, addressLine2, addressLine3),
54
+ CEMEA_V2: addressTemplateGenerator(addressLine1, addressLine2, addressLine3),
55
+ APAC: addressTemplateGenerator(addressLine1, addressLine2, addressLine3),
56
+ ARE:(
57
+ <>
58
+ {' '}
59
+ {addressLine1}{' '}
60
+ </>
61
+ )
62
+ };
63
+ return addressLines[region];
64
+ }
65
+ },
66
+ 'company': {
67
+ addressLine1Placeholder: {
68
+ GBR: 'e.g. 10 Elm Street',
69
+ USA: 'e.g. 10 Elm St.',
70
+ CAN: 'e.g. 36 Poirier Blvd.',
71
+ CEMEA_V1: 'Street and House Number',
72
+ CEMEA_V2: 'House Number and Street',
73
+ APAC: 'Street name',
74
+ ARE: 'PO Box 12345'
75
+ },
76
+ addressLine2Placeholder: {
77
+ CEMEA_V1: 'Apt No./Floor/Building/Department',
78
+ CEMEA_V2: 'Apt No./Floor/Building/Department',
79
+ APAC: 'House/Apartment/Building name',
80
+ },
81
+ addressLine3Placeholder: {
82
+ USA: 'e.g Apt 2C / FL 10 / STE 50',
83
+ CAN: 'e.g Apt 2C / FL 10 / STE 50',
84
+ CEMEA_V1: 'Department name/job title',
85
+ CEMEA_V2: 'Department name/job title',
86
+ APAC: 'District/County/Province/Ward',
87
+ },
88
+ addressLine3Title: {
89
+ GBR: 'Address line 3',
90
+ USA: 'APT/FL/STE',
91
+ CAN: 'APT/FL/STE',
92
+ CEMEA_V1: 'Address line 3',
93
+ CEMEA_V3: 'Address line 3',
94
+ },
95
+ addressLine3Prompt: {
96
+ USA: 'Max. 6 characters. Please enter “Apartment 2C” as “Apt 2C”, “Floor 10 as FL 10”',
97
+ CAN: 'Max. 6 characters. Please enter “Apartment 2C” as “Apt 2C”, “Floor 10 as FL 10”',
98
+ },
99
+ addressLine1Title:{
100
+ 'ARE': 'PO Box',
101
+ },
102
+ template: (addressLine1, addressLine2, addressLine3, region) => {
103
+ const addressLines = {
104
+ GBR: addressTemplateGenerator(addressLine1, addressLine2, addressLine3),
105
+ USA: addressTemplateGenerator(addressLine1, addressLine3, addressLine2),
106
+ CAN: addressTemplateGenerator(addressLine1, addressLine3, addressLine2),
107
+
108
+ CEMEA_V1: addressTemplateGenerator(addressLine1, addressLine2, addressLine3),
109
+ CEMEA_V2: addressTemplateGenerator(addressLine1, addressLine2, addressLine3),
110
+ APAC: addressTemplateGenerator(addressLine1, addressLine2, addressLine3),
111
+ ARE:(
112
+ <>
113
+ {' '}
114
+ {addressLine1}{' '}
115
+ </>
116
+ )
117
+ };
118
+ return addressLines[region];
119
+ }
120
+ },
121
+ 'pobox': {
122
+ addressLine1Placeholder: {
123
+ GBR: 'e.g. 10 Elm Street',
124
+ USA: 'e.g. 10 Elm St.',
125
+ CAN: 'e.g. 36 Poirier Blvd.',
126
+ CEMEA_V1: 'P.O. Box',
127
+ CEMEA_V2: 'P.O. Box',
128
+ },
129
+ addressLine2Placeholder: {
130
+ },
131
+ addressLine3Placeholder: {
132
+ },
133
+ addressLine1Title:{},
134
+ addressLine3Title: {
135
+ GBR: 'Address line 3',
136
+ USA: 'APT/FL/STE',
137
+ CAN: 'APT/FL/STE',
138
+ },
139
+ addressLine3Prompt: {
140
+ USA: 'Max. 6 characters. Please enter “Apartment 2C” as “Apt 2C”, “Floor 10 as FL 10”',
141
+ CAN: 'Max. 6 characters. Please enter “Apartment 2C” as “Apt 2C”, “Floor 10 as FL 10”',
142
+ },
143
+ template: (addressLine1, addressLine2, addressLine3, region) => {
144
+ const addressLines = {
145
+ GBR: addressTemplateGenerator(addressLine1, addressLine2, addressLine3),
146
+ USA: addressTemplateGenerator(addressLine1, addressLine3, addressLine2),
147
+ CAN: addressTemplateGenerator(addressLine1, addressLine3, addressLine2),
148
+
149
+ CEMEA_V1: (
150
+ <>
151
+ {' '}
152
+ {addressLine1}{' '}
153
+ </>
154
+ ),
155
+ CEMEA_V2:(
156
+ <>
157
+ {' '}
158
+ {addressLine1}{' '}
159
+ </>
160
+ )
161
+ };
162
+ return addressLines[region];
163
+ }
164
+ },
165
+ };
166
+
167
+ module.exports = deliveryAddressMap;
package/helpers/index.js CHANGED
@@ -1,4 +1,11 @@
1
1
  module.exports = {
2
2
  'ncf-countries': require('./ncf-countries'),
3
3
  'ncf-common-data': require('./ncf-common-data'),
4
+ 'cemeaV1ISO': require('./supportedCountries').cemeaV1ISO,
5
+ 'cemeaV2ISO': require('./supportedCountries').cemeaV2ISO,
6
+ 'apacISO': require('./supportedCountries').apacISO,
7
+ 'countriesSupported': require('./supportedCountries').countriesSupported,
8
+ 'countriesSupportedISO': require('./supportedCountries').countriesSupportedISO,
9
+ 'supportedPostcodeValidators': require('./supportedPostcodeValidators').supportedPostcodeValidators,
10
+ 'allSupportedPostcodeExamples': require('./supportedPostcodeExamples').allSupportedPostcodeExamples,
4
11
  };
@@ -0,0 +1,11 @@
1
+ const helpers = require('.');
2
+
3
+ describe('helpers', () => {
4
+ it('exports a "ncf-common-data" helper', () => {
5
+ expect(helpers).toHaveProperty('ncf-common-data');
6
+ });
7
+
8
+ it('exports a "ncf-countries" helper', () => {
9
+ expect(helpers).toHaveProperty('ncf-countries');
10
+ });
11
+ });
@@ -0,0 +1,34 @@
1
+ const mockCommonModule = {
2
+ example: 'example',
3
+ another: 'sample',
4
+ nested: {
5
+ property: 'no-problem',
6
+ },
7
+ };
8
+ jest.mock('n-common-static-data', () => mockCommonModule);
9
+ const helper = require('./ncf-common-data');
10
+
11
+ describe('ncf-common-data', () => {
12
+ let stub;
13
+
14
+ beforeEach(() => {
15
+ stub = jest.fn();
16
+ });
17
+
18
+ it('imports and exports the properties as defined', () => {
19
+ const hash = { import: 'example', export: 'whatever' };
20
+ helper({ hash, fn: stub });
21
+ const context = stub.mock.calls[0][0];
22
+ expect(context).toHaveProperty(hash.export, mockCommonModule[hash.import]);
23
+ });
24
+
25
+ it('can import nested properties', () => {
26
+ const hash = { import: 'nested.property', export: 'whatever' };
27
+ helper({ hash, fn: stub });
28
+ const context = stub.mock.calls[0][0];
29
+ expect(context).toHaveProperty(
30
+ hash.export,
31
+ mockCommonModule.nested.property
32
+ );
33
+ });
34
+ });
@@ -0,0 +1,136 @@
1
+ let mockCountries = generateCountryArray(100, { includeAllFrequent: true });
2
+ jest.mock('n-common-static-data', () => {
3
+ return {
4
+ billingCountries: { countries: mockCountries },
5
+ };
6
+ });
7
+ jest.mock('n-common-static-data');
8
+ const helper = require('./ncf-countries');
9
+
10
+ describe('ncf-countries', () => {
11
+ let stub;
12
+
13
+ beforeEach(() => {
14
+ stub = jest.fn();
15
+ });
16
+
17
+ afterEach(() => {
18
+ jest.clearAllMocks();
19
+ });
20
+
21
+ describe('filter', () => {
22
+ it('does not filter if not present', () => {
23
+ helper({ hash: {}, fn: stub });
24
+ const context = stub.mock.calls[0][0];
25
+
26
+ expect(context.countries[1].countries).toEqual(mockCountries);
27
+ });
28
+
29
+ it('does not filter if not an array', () => {
30
+ helper({ hash: { filterList: 'C-1' }, fn: stub });
31
+ const context = stub.mock.calls[0][0];
32
+
33
+ expect(context.countries[1].countries).toEqual(mockCountries);
34
+ });
35
+
36
+ it('filters and return only countries in array', () => {
37
+ helper({ hash: { filterList: ['C-1'] }, fn: stub });
38
+ const context = stub.mock.calls[0][0];
39
+
40
+ expect(context.countries).toEqual([{ code: 'C-1' }]);
41
+ });
42
+ });
43
+
44
+ describe('select', () => {
45
+ it('does not mark any countries selected if no value passed', () => {
46
+ helper({ hash: {}, fn: stub });
47
+ const context = stub.mock.calls[0][0];
48
+
49
+ expect(
50
+ context.countries.find((country) => country.selected)
51
+ ).not.toBeDefined();
52
+ });
53
+
54
+ it('does not mark any countries selected if incorrect value passed', () => {
55
+ helper({ hash: { value: 'Test' }, fn: stub });
56
+ const context = stub.mock.calls[0][0];
57
+
58
+ expect(
59
+ context.countries.find((country) => country.selected)
60
+ ).not.toBeDefined();
61
+ });
62
+
63
+ it('marks a country as selected if value matches code', () => {
64
+ const value = 'C-2';
65
+ helper({ hash: { value }, fn: stub });
66
+ const context = stub.mock.calls[0][0];
67
+
68
+ expect(
69
+ context.countries[1].countries.find((country) => country.code === value)
70
+ ).toBeDefined();
71
+ });
72
+ });
73
+
74
+ describe('group', () => {
75
+ it('does not group if frequently used countries under limit', () => {
76
+ helper({ hash: { filterList: ['CAN', 'FRA', 'JPN', 'USA'] }, fn: stub });
77
+ const context = stub.mock.calls[0][0];
78
+
79
+ expect(context.countries[0]).not.toHaveProperty('label');
80
+ });
81
+
82
+ it('groups countries over limits', () => {
83
+ helper({ hash: {}, fn: stub });
84
+ const context = stub.mock.calls[0][0];
85
+
86
+ expect(context.countries[0]).toHaveProperty('label');
87
+ });
88
+
89
+ it('sorts the group of frequently used countries', () => {
90
+ helper({ hash: {}, fn: stub });
91
+ const context = stub.mock.calls[0][0];
92
+ const correctOrder = ['GBR', 'USA', 'JPN', 'FRA', 'CAN'];
93
+ const frequentlyUsed = context.countries[0].countries;
94
+
95
+ frequentlyUsed.forEach((item, index) => {
96
+ expect(correctOrder[index]).toEqual(item.code);
97
+ });
98
+ });
99
+
100
+ it('selects only one country if it exists in two places', () => {
101
+ const value = 'GBR';
102
+ helper({ hash: { value }, fn: stub });
103
+ const context = stub.mock.calls[0][0];
104
+ const frequentlyUsed = context.countries[0].countries;
105
+ const alphabetical = context.countries[1].countries;
106
+
107
+ expect(frequentlyUsed.find((item) => item.code === value)).toEqual(
108
+ expect.objectContaining({
109
+ selected: true,
110
+ })
111
+ );
112
+ expect(alphabetical.find((item) => item.code === value)).toEqual(
113
+ expect.objectContaining({
114
+ selected: false,
115
+ })
116
+ );
117
+ });
118
+ });
119
+ });
120
+
121
+ function generateCountryArray (length, { includeAllFrequent = true } = {}) {
122
+ return Array.from(Array(length), (item, index) => ({
123
+ code: `C-${index}`,
124
+ })).concat(
125
+ // prettier-ignore
126
+ includeAllFrequent
127
+ ? [
128
+ { code: 'JPN' },
129
+ { code: 'FRA' },
130
+ { code: 'USA' },
131
+ { code: 'CAN' },
132
+ { code: 'GBR' },
133
+ ]
134
+ : []
135
+ );
136
+ }