@shopgate/pwa-common 7.30.0-alpha.7 → 7.30.0-alpha.8

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 (306) hide show
  1. package/App.js +48 -6
  2. package/action-creators/app/index.js +75 -12
  3. package/action-creators/app/spec.js +96 -1
  4. package/action-creators/client/index.js +27 -5
  5. package/action-creators/client/spec.js +44 -1
  6. package/action-creators/error/index.js +15 -3
  7. package/action-creators/index.js +9 -1
  8. package/action-creators/menu/index.js +23 -4
  9. package/action-creators/menu/spec.js +37 -1
  10. package/action-creators/modal/index.js +15 -3
  11. package/action-creators/modal/spec.js +26 -1
  12. package/action-creators/page/index.js +24 -4
  13. package/action-creators/page/spec.js +38 -1
  14. package/action-creators/router/index.js +48 -7
  15. package/action-creators/url/index.js +24 -4
  16. package/action-creators/url/spec.js +45 -1
  17. package/action-creators/user/index.js +90 -13
  18. package/action-creators/user/spec.js +186 -2
  19. package/actions/app/handleDeepLink.js +11 -2
  20. package/actions/app/handleLink.js +62 -6
  21. package/actions/app/handlePushNotification.js +32 -4
  22. package/actions/app/handleUniversalLink.js +11 -2
  23. package/actions/app/registerLinkEvents.js +24 -3
  24. package/actions/client/fetchClientInformation.js +26 -2
  25. package/actions/menu/fetchMenu.js +23 -2
  26. package/actions/modal/closeModal.js +18 -2
  27. package/actions/modal/promiseMap.js +3 -1
  28. package/actions/modal/showModal.js +54 -8
  29. package/actions/page/fetchPageConfig.js +69 -2
  30. package/actions/page/getPageConfig.js +6 -2
  31. package/actions/page/index.js +1 -1
  32. package/actions/router/historyPop.js +12 -2
  33. package/actions/router/historyPopToRoute.js +27 -2
  34. package/actions/router/historyPush.js +12 -2
  35. package/actions/router/historyRedirect.js +21 -2
  36. package/actions/router/historyReplace.js +20 -3
  37. package/actions/router/historyReset.js +11 -2
  38. package/actions/router/historyResetTo.js +12 -2
  39. package/actions/router/index.js +17 -1
  40. package/actions/router/routeDidPop.js +11 -2
  41. package/actions/router/routeDidPush.js +13 -2
  42. package/actions/router/routeDidReplace.js +11 -2
  43. package/actions/router/routeDidReset.js +11 -2
  44. package/actions/router/routeDidUpdate.js +10 -2
  45. package/actions/router/routeWillPop.js +11 -2
  46. package/actions/router/routeWillPush.js +13 -2
  47. package/actions/router/routeWillReplace.js +11 -2
  48. package/actions/router/routeWillReset.js +11 -2
  49. package/actions/router/windowOpenOverride.js +10 -2
  50. package/actions/user/fetchRegisterUrl.js +36 -2
  51. package/actions/user/fetchUser.js +29 -3
  52. package/actions/user/getUser.js +6 -2
  53. package/actions/user/index.js +1 -1
  54. package/actions/user/login.js +76 -9
  55. package/actions/user/logout.js +30 -2
  56. package/collections/AuthRoutes.js +73 -14
  57. package/collections/Configuration.js +54 -7
  58. package/collections/EmbeddedMedia.js +84 -11
  59. package/collections/PersistedReducers.js +41 -6
  60. package/collections/Redirects.js +103 -17
  61. package/collections/index.js +5 -1
  62. package/collections/media-providers/MediaProvider.js +151 -26
  63. package/collections/media-providers/Vimeo.js +113 -19
  64. package/collections/media-providers/YouTube.js +74 -14
  65. package/collections/media-providers/index.js +3 -1
  66. package/collections/media-providers/style.js +52 -2
  67. package/components/Backdrop/index.js +95 -6
  68. package/components/Backdrop/spec.js +23 -1
  69. package/components/Backdrop/style.js +11 -2
  70. package/components/Button/index.js +47 -5
  71. package/components/Button/spec.js +36 -1
  72. package/components/Button/style.js +6 -1
  73. package/components/Checkbox/index.js +126 -32
  74. package/components/Checkbox/spec.js +94 -3
  75. package/components/Consume/helpers/buildParams.js +13 -2
  76. package/components/Consume/index.js +14 -2
  77. package/components/CountdownTimer/index.js +115 -17
  78. package/components/CountdownTimer/spec.js +126 -12
  79. package/components/Drawer/index.js +131 -16
  80. package/components/Drawer/spec.js +76 -1
  81. package/components/Drawer/style.js +37 -1
  82. package/components/Dropdown/index.js +65 -6
  83. package/components/Dropdown/style.js +4 -1
  84. package/components/Dropdown/transitions.js +34 -1
  85. package/components/Ellipsis/index.js +16 -2
  86. package/components/Ellipsis/spec.js +13 -1
  87. package/components/EmbeddedMedia/index.js +56 -6
  88. package/components/EmbeddedMedia/spec.js +52 -3
  89. package/components/ErrorBoundary/connector.js +9 -2
  90. package/components/ErrorBoundary/index.js +43 -7
  91. package/components/Grid/components/Item/index.js +40 -4
  92. package/components/Grid/components/Item/spec.js +23 -1
  93. package/components/Grid/components/Item/style.js +17 -3
  94. package/components/Grid/index.js +36 -4
  95. package/components/Grid/spec.js +23 -1
  96. package/components/Grid/style.js +11 -2
  97. package/components/HtmlSanitizer/connector.js +24 -3
  98. package/components/HtmlSanitizer/index.js +104 -12
  99. package/components/HtmlSanitizer/spec.js +207 -6
  100. package/components/I18n/components/FormatDate/index.js +26 -2
  101. package/components/I18n/components/FormatDate/spec.js +46 -1
  102. package/components/I18n/components/FormatNumber/index.js +34 -2
  103. package/components/I18n/components/FormatNumber/spec.js +41 -2
  104. package/components/I18n/components/FormatPrice/index.js +32 -2
  105. package/components/I18n/components/FormatPrice/spec.js +46 -1
  106. package/components/I18n/components/FormatTime/index.js +26 -2
  107. package/components/I18n/components/FormatTime/spec.js +43 -2
  108. package/components/I18n/components/I18nProvider/index.js +52 -9
  109. package/components/I18n/components/I18nProvider/spec.js +39 -1
  110. package/components/I18n/components/Placeholder/index.js +8 -2
  111. package/components/I18n/components/Placeholder/spec.js +30 -1
  112. package/components/I18n/components/Translate/index.js +68 -7
  113. package/components/I18n/components/Translate/spec.js +30 -1
  114. package/components/I18n/index.js +16 -1
  115. package/components/Icon/index.js +25 -2
  116. package/components/Icon/style.js +6 -1
  117. package/components/Image/Image.js +176 -19
  118. package/components/Image/ImageInner.js +48 -2
  119. package/components/Image/index.js +1 -1
  120. package/components/Image/style.js +29 -2
  121. package/components/InfiniteContainer/index.js +381 -49
  122. package/components/InfiniteContainer/spec.js +199 -10
  123. package/components/Input/components/DateInput.js +262 -6
  124. package/components/Input/components/MultiLineInput.js +98 -12
  125. package/components/Input/components/SimpleInput.js +207 -31
  126. package/components/Input/index.js +32 -3
  127. package/components/Input/spec.js +122 -1
  128. package/components/KeyboardConsumer/index.js +48 -7
  129. package/components/Link/connector.js +7 -1
  130. package/components/Link/index.js +96 -11
  131. package/components/Link/spec.js +56 -1
  132. package/components/Link/style.js +10 -1
  133. package/components/List/components/Item/index.js +35 -3
  134. package/components/List/components/Item/style.js +16 -1
  135. package/components/List/index.js +20 -2
  136. package/components/List/spec.js +31 -1
  137. package/components/Loading/index.js +6 -2
  138. package/components/Modal/index.js +38 -3
  139. package/components/Modal/style.js +36 -1
  140. package/components/ModalContainer/connector.js +17 -3
  141. package/components/ModalContainer/index.js +36 -3
  142. package/components/ModalContainer/spec.js +105 -5
  143. package/components/Picker/components/Button/index.js +34 -2
  144. package/components/Picker/components/Button/style.js +19 -1
  145. package/components/Picker/components/List/index.js +33 -2
  146. package/components/Picker/components/List/style.js +17 -1
  147. package/components/Picker/components/Modal/index.js +60 -7
  148. package/components/Picker/components/Modal/style.js +78 -1
  149. package/components/Picker/index.js +167 -21
  150. package/components/Picker/spec.js +83 -2
  151. package/components/Portal/index.js +130 -19
  152. package/components/ProductCharacteristics/connector.js +33 -4
  153. package/components/ProductCharacteristics/context.js +2 -1
  154. package/components/ProductCharacteristics/helpers/index.js +135 -21
  155. package/components/ProductCharacteristics/index.js +266 -31
  156. package/components/RangeSlider/components/Handle/index.js +25 -2
  157. package/components/RangeSlider/components/Handle/style.js +14 -1
  158. package/components/RangeSlider/helper.js +43 -8
  159. package/components/RangeSlider/index.js +228 -38
  160. package/components/RangeSlider/style.js +14 -1
  161. package/components/Route/RouteNotFound.js +46 -3
  162. package/components/Route/index.js +78 -10
  163. package/components/Router/connector.js +9 -2
  164. package/components/Router/index.js +237 -31
  165. package/components/ScannerContainer/connector.js +9 -2
  166. package/components/ScannerContainer/index.js +42 -6
  167. package/components/Select/components/Item/index.js +20 -4
  168. package/components/Select/components/Item/style.js +4 -1
  169. package/components/Select/index.js +149 -28
  170. package/components/Select/spec.js +86 -2
  171. package/components/Select/style.js +17 -1
  172. package/components/SelectBox/components/Item/index.js +47 -5
  173. package/components/SelectBox/components/Item/style.js +7 -1
  174. package/components/SelectBox/index.js +173 -17
  175. package/components/SelectBox/spec.js +59 -3
  176. package/components/SelectBox/style.js +18 -1
  177. package/components/Slider/index.js +6 -2
  178. package/components/SurroundPortals/index.js +26 -2
  179. package/components/Swiper/components/SwiperItem/index.js +28 -4
  180. package/components/Swiper/components/SwiperItem/spec.js +17 -1
  181. package/components/Swiper/components/SwiperItem/styles.js +5 -1
  182. package/components/Swiper/index.js +210 -18
  183. package/components/Swiper/styles.js +75 -7
  184. package/components/Toaster/index.js +10 -2
  185. package/components/Transition/index.js +89 -13
  186. package/components/Widgets/components/Widget/index.js +52 -4
  187. package/components/Widgets/components/Widget/spec.js +68 -3
  188. package/components/Widgets/components/Widget/style.js +21 -3
  189. package/components/Widgets/components/WidgetGrid/index.js +52 -7
  190. package/components/Widgets/components/WidgetGrid/spec.js +46 -2
  191. package/components/Widgets/components/WidgetGrid/style.js +8 -1
  192. package/components/Widgets/helpers/shouldShowWidget.js +44 -7
  193. package/components/Widgets/index.js +127 -15
  194. package/components/Widgets/spec.js +213 -6
  195. package/components/index.js +9 -1
  196. package/constants/ActionTypes.js +97 -19
  197. package/constants/Configuration.js +12 -2
  198. package/constants/Device.js +29 -2
  199. package/constants/DisplayOptions.js +8 -1
  200. package/constants/MenuIDs.js +2 -1
  201. package/constants/ModalTypes.js +1 -1
  202. package/constants/PageIDs.js +1 -1
  203. package/constants/Pipelines.js +7 -1
  204. package/constants/Portals.js +136 -3
  205. package/constants/Registration.js +3 -1
  206. package/constants/RoutePaths.js +13 -2
  207. package/constants/Tracking.js +3 -1
  208. package/constants/client.js +6 -1
  209. package/constants/ui.js +2 -1
  210. package/constants/user.js +6 -2
  211. package/context/index.js +33 -3
  212. package/helpers/config/index.js +139 -21
  213. package/helpers/config/mock.js +200 -8
  214. package/helpers/config/theme.js +50 -4
  215. package/helpers/data/index.js +204 -29
  216. package/helpers/data/spec.js +187 -7
  217. package/helpers/date/index.js +58 -6
  218. package/helpers/date/spec.js +92 -1
  219. package/helpers/dom/index.js +48 -11
  220. package/helpers/environment/index.js +14 -2
  221. package/helpers/html/decodeHTML.js +7 -1
  222. package/helpers/html/handleDOM.js +172 -21
  223. package/helpers/html/parseHTML.js +67 -12
  224. package/helpers/i18n/getDateFormatter.js +23 -4
  225. package/helpers/i18n/getNumberFormatter.js +32 -4
  226. package/helpers/i18n/getPriceFormatter.js +38 -4
  227. package/helpers/i18n/getTimeFormatter.js +23 -4
  228. package/helpers/i18n/getTranslator.js +62 -8
  229. package/helpers/i18n/index.js +5 -1
  230. package/helpers/i18n/mergeTranslations.js +36 -9
  231. package/helpers/i18n/messageCache.js +3 -1
  232. package/helpers/legacy/index.js +47 -9
  233. package/helpers/modal/withShowModal.js +13 -2
  234. package/helpers/portals/portalCollection.js +28 -6
  235. package/helpers/portals/routePortals.js +12 -1
  236. package/helpers/redux/compareObjects.js +7 -2
  237. package/helpers/redux/generateResultHash.js +36 -3
  238. package/helpers/redux/generateSortedHash.js +7 -2
  239. package/helpers/redux/hasExpired.js +10 -2
  240. package/helpers/redux/index.js +7 -1
  241. package/helpers/redux/mutable.js +143 -24
  242. package/helpers/redux/shouldFetchData.js +46 -10
  243. package/helpers/redux/shouldFetchFilters.js +17 -4
  244. package/helpers/router/index.js +49 -5
  245. package/helpers/style/index.js +43 -4
  246. package/helpers/style/spec.js +108 -2
  247. package/helpers/tracking/index.js +52 -9
  248. package/helpers/validation/index.js +39 -12
  249. package/helpers/validation/spec.js +10 -1
  250. package/package.json +3 -3
  251. package/providers/index.js +4 -1
  252. package/providers/loading/context.js +2 -1
  253. package/providers/loading/index.js +137 -22
  254. package/providers/toast/context.js +2 -1
  255. package/providers/toast/index.js +105 -11
  256. package/reducers/client/connectivity.js +22 -2
  257. package/reducers/client/index.js +7 -1
  258. package/reducers/client/info.js +27 -2
  259. package/reducers/index.js +23 -4
  260. package/reducers/menu/index.js +5 -1
  261. package/reducers/menu/menusById.js +41 -2
  262. package/reducers/modal/index.js +14 -2
  263. package/reducers/page/index.js +68 -5
  264. package/reducers/router/index.js +48 -2
  265. package/reducers/url/index.js +42 -3
  266. package/reducers/user/data.js +27 -2
  267. package/reducers/user/index.js +7 -1
  268. package/reducers/user/login.js +65 -2
  269. package/selectors/client.js +138 -21
  270. package/selectors/history.js +49 -11
  271. package/selectors/menu.js +34 -6
  272. package/selectors/modal.js +15 -4
  273. package/selectors/page.js +25 -4
  274. package/selectors/router.js +154 -30
  275. package/selectors/url.js +25 -4
  276. package/selectors/user.js +90 -13
  277. package/store/index.js +60 -6
  278. package/store/middelwares/logger.js +7 -1
  279. package/store/middelwares/streams.js +19 -2
  280. package/streams/app.js +60 -8
  281. package/streams/client.js +8 -2
  282. package/streams/error.js +14 -3
  283. package/streams/index.js +6 -1
  284. package/streams/interval.js +6 -2
  285. package/streams/main.js +27 -2
  286. package/streams/router.js +45 -8
  287. package/streams/user.js +89 -15
  288. package/streams/view.js +97 -25
  289. package/styles/reset/form.js +57 -5
  290. package/styles/reset/index.js +6 -1
  291. package/styles/reset/media.js +22 -1
  292. package/styles/reset/root.js +33 -1
  293. package/styles/reset/table.js +10 -1
  294. package/styles/reset/typography.js +26 -1
  295. package/subscriptions/app.js +148 -17
  296. package/subscriptions/error.js +292 -13
  297. package/subscriptions/helpers/buildRegisterUrl.js +25 -6
  298. package/subscriptions/helpers/clearUpInAppBrowser.js +14 -3
  299. package/subscriptions/helpers/handleLinks.js +267 -25
  300. package/subscriptions/helpers/pipeline.js +12 -1
  301. package/subscriptions/history.js +34 -6
  302. package/subscriptions/index.js +25 -4
  303. package/subscriptions/menu.js +22 -5
  304. package/subscriptions/mock.js +39 -7
  305. package/subscriptions/router.js +336 -23
  306. package/subscriptions/user.js +93 -3
@@ -1,9 +1,41 @@
1
- function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _callSuper(_this,derived,args){function isNativeReflectConstruct(){if(typeof Reflect==="undefined"||!Reflect.construct)return false;if(Reflect.construct.sham)return false;if(typeof Proxy==="function")return true;try{return!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}));}catch(e){return false;}}derived=_getPrototypeOf(derived);return _possibleConstructorReturn(_this,isNativeReflectConstruct()?Reflect.construct(derived,args||[],_getPrototypeOf(_this).constructor):derived.apply(_this,args));}function _possibleConstructorReturn(self,call){if(call&&(_typeof(call)==="object"||typeof call==="function")){return call;}return _assertThisInitialized(self);}function _assertThisInitialized(self){if(self===void 0){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return self;}function _getPrototypeOf(o){_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function _getPrototypeOf(o){return o.__proto__||Object.getPrototypeOf(o);};return _getPrototypeOf(o);}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function");}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,writable:true,configurable:true}});if(superClass)_setPrototypeOf(subClass,superClass);}function _setPrototypeOf(o,p){_setPrototypeOf=Object.setPrototypeOf||function _setPrototypeOf(o,p){o.__proto__=p;return o;};return _setPrototypeOf(o,p);}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}import React,{Component}from'react';import PropTypes from'prop-types';import{objectWithoutProps}from"../../helpers/data";import GridItem from"./components/Item";import styles,{wrap}from"./style";/**
1
+ import React, { Component } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { objectWithoutProps } from "../../helpers/data";
4
+ import GridItem from "./components/Item";
5
+ import styles, { wrap } from "./style";
6
+
7
+ /**
2
8
  * The grid component.
3
- */var Grid=/*#__PURE__*/function(_Component){function Grid(){_classCallCheck(this,Grid);return _callSuper(this,Grid,arguments);}_inherits(Grid,_Component);return _createClass(Grid,[{key:"getProps",value:/**
9
+ */
10
+ class Grid extends Component {
11
+ /**
4
12
  * Composes the props.
5
13
  * @returns {Object} The composed props.
6
- */function getProps(){var className="".concat(this.props.className," ").concat(styles," common__grid");if(this.props.wrap){className+=" ".concat(wrap(this.props.wrap));}var props=_extends({},this.props,{className:className});return objectWithoutProps(props,['wrap','component']);}/**
14
+ */
15
+ getProps() {
16
+ let className = `${this.props.className} ${styles} common__grid`;
17
+ if (this.props.wrap) {
18
+ className += ` ${wrap(this.props.wrap)}`;
19
+ }
20
+ const props = {
21
+ ...this.props,
22
+ className
23
+ };
24
+ return objectWithoutProps(props, ['wrap', 'component']);
25
+ }
26
+
27
+ /**
7
28
  * Renders the component.
8
29
  * @returns {JSX}
9
- */},{key:"render",value:function render(){return React.createElement(this.props.component,this.getProps());}}]);}(Component);_defineProperty(Grid,"Item",GridItem);_defineProperty(Grid,"defaultProps",{className:'',component:'ul',wrap:false});export default Grid;
30
+ */
31
+ render() {
32
+ return /*#__PURE__*/React.createElement(this.props.component, this.getProps());
33
+ }
34
+ }
35
+ Grid.Item = GridItem;
36
+ Grid.defaultProps = {
37
+ className: '',
38
+ component: 'ul',
39
+ wrap: false
40
+ };
41
+ export default Grid;
@@ -1 +1,23 @@
1
- import React from'react';import{shallow}from'enzyme';import Grid from"./index";describe('<Grid />',function(){it('should render without any further props',function(){var wrapper=shallow(React.createElement(Grid,null));expect(wrapper).toMatchSnapshot();});it('should be able to render a custom tag',function(){var wrapper=shallow(React.createElement(Grid,{component:"article"}));expect(wrapper).toMatchSnapshot();expect(wrapper.type()).toEqual('article');});it('should add custom classes on demand',function(){var wrapper=shallow(React.createElement(Grid,{className:"custom-class-name"}));expect(wrapper).toMatchSnapshot();expect(wrapper.hasClass('custom-class-name')).toEqual(true);});});
1
+ import React from 'react';
2
+ import { shallow } from 'enzyme';
3
+ import Grid from "./index";
4
+ describe('<Grid />', () => {
5
+ it('should render without any further props', () => {
6
+ const wrapper = shallow(/*#__PURE__*/React.createElement(Grid, null));
7
+ expect(wrapper).toMatchSnapshot();
8
+ });
9
+ it('should be able to render a custom tag', () => {
10
+ const wrapper = shallow(/*#__PURE__*/React.createElement(Grid, {
11
+ component: "article"
12
+ }));
13
+ expect(wrapper).toMatchSnapshot();
14
+ expect(wrapper.type()).toEqual('article');
15
+ });
16
+ it('should add custom classes on demand', () => {
17
+ const wrapper = shallow(/*#__PURE__*/React.createElement(Grid, {
18
+ className: "custom-class-name"
19
+ }));
20
+ expect(wrapper).toMatchSnapshot();
21
+ expect(wrapper.hasClass('custom-class-name')).toEqual(true);
22
+ });
23
+ });
@@ -1,5 +1,14 @@
1
- import{css}from'glamor';/**
1
+ import { css } from 'glamor';
2
+
3
+ /**
2
4
  * Creates a class name for the flex-wrap property
3
5
  * @param {boolean} [value=false] TRUE for 'wrap', FALSE for 'nowrap'
4
6
  * @return {string} The class name
5
- */export var wrap=function wrap(){var value=arguments.length>0&&arguments[0]!==undefined?arguments[0]:false;return css({flexWrap:value?'wrap':'nowrap'}).toString();};export default css({display:'flex',minWidth:'100%'}).toString();
7
+ */
8
+ export const wrap = (value = false) => css({
9
+ flexWrap: value ? 'wrap' : 'nowrap'
10
+ }).toString();
11
+ export default css({
12
+ display: 'flex',
13
+ minWidth: '100%'
14
+ }).toString();
@@ -1,9 +1,30 @@
1
- function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}import{connect}from'react-redux';import{getAreComfortCookiesAccepted,getAreStatisticsCookiesAccepted}from'@shopgate/engage/tracking/selectors';import{historyPush}from"../../actions/router";/**
1
+ import { connect } from 'react-redux';
2
+ import { getAreComfortCookiesAccepted, getAreStatisticsCookiesAccepted } from '@shopgate/engage/tracking/selectors';
3
+ import { historyPush } from "../../actions/router";
4
+
5
+ /**
2
6
  * Maps the current application state to the component props.
3
7
  * @param {Object} state The current application state.
4
8
  * @return {Object} The populated component props.
5
- */var mapStateToProps=function mapStateToProps(state){return{comfortCookiesAccepted:getAreComfortCookiesAccepted(state),statisticsCookiesAccepted:getAreStatisticsCookiesAccepted(state)};};/**
9
+ */
10
+ const mapStateToProps = state => ({
11
+ comfortCookiesAccepted: getAreComfortCookiesAccepted(state),
12
+ statisticsCookiesAccepted: getAreStatisticsCookiesAccepted(state)
13
+ });
14
+
15
+ /**
6
16
  * Connects the dispatch function to a callable function in the props.
7
17
  * @param {Function} dispatch The redux dispatch function.
8
18
  * @return {Object} The extended component props.
9
- */var mapDispatchToProps=function mapDispatchToProps(dispatch){return{navigate:function navigate(pathname,target){return dispatch(historyPush(_extends({pathname:pathname},target&&{state:{target:target}})));}};};export default connect(mapStateToProps,mapDispatchToProps);
19
+ */
20
+ const mapDispatchToProps = dispatch => ({
21
+ navigate: (pathname, target) => dispatch(historyPush({
22
+ pathname,
23
+ ...(target && {
24
+ state: {
25
+ target
26
+ }
27
+ })
28
+ }))
29
+ });
30
+ export default connect(mapStateToProps, mapDispatchToProps);
@@ -1,22 +1,114 @@
1
- function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _callSuper(_this,derived,args){function isNativeReflectConstruct(){if(typeof Reflect==="undefined"||!Reflect.construct)return false;if(Reflect.construct.sham)return false;if(typeof Proxy==="function")return true;try{return!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}));}catch(e){return false;}}derived=_getPrototypeOf(derived);return _possibleConstructorReturn(_this,isNativeReflectConstruct()?Reflect.construct(derived,args||[],_getPrototypeOf(_this).constructor):derived.apply(_this,args));}function _possibleConstructorReturn(self,call){if(call&&(_typeof(call)==="object"||typeof call==="function")){return call;}return _assertThisInitialized(self);}function _assertThisInitialized(self){if(self===void 0){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return self;}function _getPrototypeOf(o){_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function _getPrototypeOf(o){return o.__proto__||Object.getPrototypeOf(o);};return _getPrototypeOf(o);}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function");}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,writable:true,configurable:true}});if(superClass)_setPrototypeOf(subClass,superClass);}function _setPrototypeOf(o,p){_setPrototypeOf=Object.setPrototypeOf||function _setPrototypeOf(o,p){o.__proto__=p;return o;};return _setPrototypeOf(o,p);}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}import React,{Component}from'react';import PropTypes from'prop-types';import classNames from'classnames';import{embeddedMedia}from'@shopgate/pwa-common/collections';import EmbeddedMedia from"../EmbeddedMedia";import parseHTML from"../../helpers/html/parseHTML";import connect from"./connector";/**
1
+ import React, { Component } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import classNames from 'classnames';
4
+ import { embeddedMedia } from '@shopgate/pwa-common/collections';
5
+ import EmbeddedMedia from "../EmbeddedMedia";
6
+ import parseHTML from "../../helpers/html/parseHTML";
7
+ import connect from "./connector";
8
+
9
+ /**
2
10
  * HtmlSanitizer component.
3
- */var HtmlSanitizer=/*#__PURE__*/function(_Component){/**
11
+ */
12
+ class HtmlSanitizer extends Component {
13
+ /**
4
14
  * @param {Object} props The component props.
5
- */function HtmlSanitizer(props){var _this2;_classCallCheck(this,HtmlSanitizer);_this2=_callSuper(this,HtmlSanitizer,[props]);/**
6
- * If the user tapped a link element, prevent the default behavior.
7
- * @param {Object} event The touchstart event.
8
- */_defineProperty(_this2,"handleTap",function(event){var linkTag=event.target.closest('a');if(linkTag){var _linkTag$attributes3=linkTag.attributes,_linkTag$attributes4=_linkTag$attributes3===void 0?{}:_linkTag$attributes3,_linkTag$attributes2$7=_linkTag$attributes4.href,_linkTag$attributes2$8=_linkTag$attributes2$7===void 0?{}:_linkTag$attributes2$7,_linkTag$attributes2$9=_linkTag$attributes2$8.value,href=_linkTag$attributes2$9===void 0?'':_linkTag$attributes2$9,_linkTag$attributes2$10=_linkTag$attributes4.target,_linkTag$attributes2$11=_linkTag$attributes2$10===void 0?{}:_linkTag$attributes2$10,_linkTag$attributes2$12=_linkTag$attributes2$11.value,target=_linkTag$attributes2$12===void 0?'':_linkTag$attributes2$12;if(href){event.preventDefault();if(_this2.props.settings.handleClick){_this2.props.settings.handleClick(href,target);}else{_this2.props.navigate(href,target);}}}});_this2.htmlContainer=React.createRef();return _this2;}/**
15
+ */
16
+ constructor(props) {
17
+ super(props);
18
+ /**
19
+ * If the user tapped a link element, prevent the default behavior.
20
+ * @param {Object} event The touchstart event.
21
+ */
22
+ this.handleTap = event => {
23
+ const linkTag = event.target.closest('a');
24
+ if (linkTag) {
25
+ const {
26
+ attributes: {
27
+ href: {
28
+ value: href = ''
29
+ } = {},
30
+ target: {
31
+ value: target = ''
32
+ } = {}
33
+ } = {}
34
+ } = linkTag;
35
+ if (href) {
36
+ event.preventDefault();
37
+ if (this.props.settings.handleClick) {
38
+ this.props.settings.handleClick(href, target);
39
+ } else {
40
+ this.props.navigate(href, target);
41
+ }
42
+ }
43
+ }
44
+ };
45
+ this.htmlContainer = /*#__PURE__*/React.createRef();
46
+ }
47
+
48
+ /**
9
49
  * Registers the event handler for when the user taps inside the html content.
10
- */_inherits(HtmlSanitizer,_Component);return _createClass(HtmlSanitizer,[{key:"componentDidMount",value:function componentDidMount(){this.htmlContainer.current.addEventListener('click',this.handleTap,true);embeddedMedia.add(this.htmlContainer.current);}/**
50
+ */
51
+ componentDidMount() {
52
+ this.htmlContainer.current.addEventListener('click', this.handleTap, true);
53
+ embeddedMedia.add(this.htmlContainer.current);
54
+ }
55
+
56
+ /**
11
57
  * Only update if the HTML changed.
12
58
  * @param {Object} nextProps The next props for the component.
13
59
  * @return {boolean}
14
- */},{key:"shouldComponentUpdate",value:function shouldComponentUpdate(nextProps){return nextProps.children!==this.props.children||nextProps.comfortCookiesAccepted!==this.props.comfortCookiesAccepted||nextProps.statisticsCookiesAccepted!==this.props.statisticsCookiesAccepted;}/**
60
+ */
61
+ shouldComponentUpdate(nextProps) {
62
+ return nextProps.children !== this.props.children || nextProps.comfortCookiesAccepted !== this.props.comfortCookiesAccepted || nextProps.statisticsCookiesAccepted !== this.props.statisticsCookiesAccepted;
63
+ }
64
+
65
+ /**
15
66
  * Updates embedded media within the html container.
16
- */},{key:"componentDidUpdate",value:function componentDidUpdate(){embeddedMedia.add(this.htmlContainer.current);}/**
67
+ */
68
+ componentDidUpdate() {
69
+ embeddedMedia.add(this.htmlContainer.current);
70
+ }
71
+
72
+ /**
17
73
  * Removes the event handler.
18
- */},{key:"componentWillUnmount",value:function componentWillUnmount(){this.htmlContainer.current.removeEventListener('click',this.handleTap,true);embeddedMedia.remove(this.htmlContainer.current);}},{key:"render",value:/**
74
+ */
75
+ componentWillUnmount() {
76
+ this.htmlContainer.current.removeEventListener('click', this.handleTap, true);
77
+ embeddedMedia.remove(this.htmlContainer.current);
78
+ }
79
+ /**
19
80
  * Renders the component.
20
81
  * @returns {JSX}
21
- */function render(){var cookieConsentSettings={comfortCookiesAccepted:this.props.comfortCookiesAccepted,statisticsCookiesAccepted:this.props.statisticsCookiesAccepted};var innerHTML={__html:parseHTML(this.props.children,this.props.decode,this.props.settings,this.props.processStyles,cookieConsentSettings)};var Wrapper=this.props.wrapper;return React.createElement(Wrapper,{cookieConsentSettings:cookieConsentSettings},React.createElement("div",{// eslint-disable-next-line react/no-danger
22
- dangerouslySetInnerHTML:innerHTML,ref:this.htmlContainer,className:classNames(this.props.className,'common__html-sanitizer')}));}}]);}(Component);_defineProperty(HtmlSanitizer,"defaultProps",{children:'',className:'',decode:false,processStyles:false,settings:{},wrapper:EmbeddedMedia,comfortCookiesAccepted:false,statisticsCookiesAccepted:false});export default connect(HtmlSanitizer);
82
+ */
83
+ render() {
84
+ const cookieConsentSettings = {
85
+ comfortCookiesAccepted: this.props.comfortCookiesAccepted,
86
+ statisticsCookiesAccepted: this.props.statisticsCookiesAccepted
87
+ };
88
+ const innerHTML = {
89
+ __html: parseHTML(this.props.children, this.props.decode, this.props.settings, this.props.processStyles, cookieConsentSettings)
90
+ };
91
+ const {
92
+ wrapper: Wrapper
93
+ } = this.props;
94
+ return /*#__PURE__*/React.createElement(Wrapper, {
95
+ cookieConsentSettings: cookieConsentSettings
96
+ }, /*#__PURE__*/React.createElement("div", {
97
+ // eslint-disable-next-line react/no-danger
98
+ dangerouslySetInnerHTML: innerHTML,
99
+ ref: this.htmlContainer,
100
+ className: classNames(this.props.className, 'common__html-sanitizer')
101
+ }));
102
+ }
103
+ }
104
+ HtmlSanitizer.defaultProps = {
105
+ children: '',
106
+ className: '',
107
+ decode: false,
108
+ processStyles: false,
109
+ settings: {},
110
+ wrapper: EmbeddedMedia,
111
+ comfortCookiesAccepted: false,
112
+ statisticsCookiesAccepted: false
113
+ };
114
+ export default connect(HtmlSanitizer);
@@ -1,18 +1,219 @@
1
- function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}import React from'react';import{mount}from'enzyme';import{JSDOM}from'jsdom';import{embeddedMedia}from'@shopgate/pwa-common/collections';import HtmlSanitizer from"./index";jest.mock("../EmbeddedMedia",function(){return function(_ref){var children=_ref.children;return children;};});jest.mock("./connector",function(){return function(Cmp){return Cmp;};});/**
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import React from 'react';
3
+ import { mount } from 'enzyme';
4
+ import { JSDOM } from 'jsdom';
5
+ import { embeddedMedia } from '@shopgate/pwa-common/collections';
6
+ import HtmlSanitizer from "./index";
7
+ jest.mock("../EmbeddedMedia", () => ({
8
+ children
9
+ }) => children);
10
+ jest.mock("./connector", () => Cmp => Cmp);
11
+
12
+ /**
2
13
  * @param {string} html HTML markup.
3
14
  * @param {Object} props Component props.
4
15
  * @returns {JSX}
5
- */var createWrapper=function createWrapper(html){var props=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};return mount(React.createElement(HtmlSanitizer,_extends({navigate:function navigate(){}},props),html));};describe('<HtmlSanitizer />',function(){var embeddedMediaAddSpy;var embeddedMediaRemoveSpy;var embeddedMediaHandleCookieConsentSpy;beforeEach(function(){jest.clearAllMocks();embeddedMediaAddSpy=jest.spyOn(embeddedMedia,'add');embeddedMediaRemoveSpy=jest.spyOn(embeddedMedia,'remove');embeddedMediaHandleCookieConsentSpy=jest.spyOn(embeddedMedia,'handleCookieConsent');});it('should render the HtmlSanitizer',function(){/**
16
+ */
17
+ const createWrapper = (html, props = {}) => mount(/*#__PURE__*/React.createElement(HtmlSanitizer, _extends({
18
+ navigate: () => {}
19
+ }, props), html));
20
+ describe('<HtmlSanitizer />', () => {
21
+ let embeddedMediaAddSpy;
22
+ let embeddedMediaRemoveSpy;
23
+ let embeddedMediaHandleCookieConsentSpy;
24
+ beforeEach(() => {
25
+ jest.clearAllMocks();
26
+ embeddedMediaAddSpy = jest.spyOn(embeddedMedia, 'add');
27
+ embeddedMediaRemoveSpy = jest.spyOn(embeddedMedia, 'remove');
28
+ embeddedMediaHandleCookieConsentSpy = jest.spyOn(embeddedMedia, 'handleCookieConsent');
29
+ });
30
+ it('should render the HtmlSanitizer', () => {
31
+ /**
6
32
  * The value for html is the HTML-escaped equivalent of the following:
7
33
  * <h1>Hello World!</h1>
8
34
  * @type {string}
9
- */var html='&lt;h1&gt;Hello World!&lt;/h1&gt;';var wrapper=createWrapper(html,{decode:true});// Test result of dangerouslySetInnerHTML.
10
- expect(wrapper.html()).toEqual('<div class="common__html-sanitizer"><h1>Hello World!</h1></div>');expect(wrapper.render()).toMatchSnapshot();});it('should add and remove handlers for embedded media',function(){var wrapper=createWrapper('<div></div>',{decode:true});var ref=wrapper.instance().htmlContainer.current;expect(embeddedMediaAddSpy).toHaveBeenCalledTimes(1);expect(embeddedMediaAddSpy).toHaveBeenCalledWith(ref);expect(embeddedMediaRemoveSpy).toHaveBeenCalledTimes(0);wrapper.setProps({children:'<span></span>'});expect(embeddedMediaAddSpy).toHaveBeenCalledTimes(2);expect(embeddedMediaAddSpy).toHaveBeenCalledWith(ref);expect(embeddedMediaRemoveSpy).toHaveBeenCalledTimes(0);wrapper.unmount();expect(embeddedMediaAddSpy).toHaveBeenCalledTimes(2);expect(embeddedMediaRemoveSpy).toHaveBeenCalledTimes(1);expect(embeddedMediaRemoveSpy).toHaveBeenCalledWith(ref);});it('strips out images with relative paths',function(){var html="\n <div>\n <style>a { color: red }</style>\n <a href=\"foo\">\n <img src=\"bar.jpg\" />\n </a>\n </div>\n ";var wrapper=createWrapper(html);expect(wrapper.html()).not.toContain('<img');expect(wrapper.html()).toContain('<style>');expect(wrapper.render()).toMatchSnapshot();});it('should move style blocks out of the content',function(){var html="\n <div>\n <style>a { color: red }</style>\n <a href=\"foo\">\n <img src=\"bar.jpg\" />\n </a>\n </div>\n ";var wrapper=createWrapper(html,{processStyles:true});expect(wrapper.html()).not.toContain('<style>');});it('does not strip out images with absolute paths',function(){var html="\n <div>\n <a href=\"foo\">\n <img src=\"http://google.de/bar.jpg\" />\n </a>\n </div>\n ";var wrapper=createWrapper(html);expect(wrapper.html()).toContain('<img');expect(wrapper.render()).toMatchSnapshot();});it('strips out the script tags',function(){/**
35
+ */
36
+ const html = '&lt;h1&gt;Hello World!&lt;/h1&gt;';
37
+ const wrapper = createWrapper(html, {
38
+ decode: true
39
+ });
40
+
41
+ // Test result of dangerouslySetInnerHTML.
42
+ expect(wrapper.html()).toEqual('<div class="common__html-sanitizer"><h1>Hello World!</h1></div>');
43
+ expect(wrapper.render()).toMatchSnapshot();
44
+ });
45
+ it('should add and remove handlers for embedded media', () => {
46
+ const wrapper = createWrapper('<div></div>', {
47
+ decode: true
48
+ });
49
+ const ref = wrapper.instance().htmlContainer.current;
50
+ expect(embeddedMediaAddSpy).toHaveBeenCalledTimes(1);
51
+ expect(embeddedMediaAddSpy).toHaveBeenCalledWith(ref);
52
+ expect(embeddedMediaRemoveSpy).toHaveBeenCalledTimes(0);
53
+ wrapper.setProps({
54
+ children: '<span></span>'
55
+ });
56
+ expect(embeddedMediaAddSpy).toHaveBeenCalledTimes(2);
57
+ expect(embeddedMediaAddSpy).toHaveBeenCalledWith(ref);
58
+ expect(embeddedMediaRemoveSpy).toHaveBeenCalledTimes(0);
59
+ wrapper.unmount();
60
+ expect(embeddedMediaAddSpy).toHaveBeenCalledTimes(2);
61
+ expect(embeddedMediaRemoveSpy).toHaveBeenCalledTimes(1);
62
+ expect(embeddedMediaRemoveSpy).toHaveBeenCalledWith(ref);
63
+ });
64
+ it('strips out images with relative paths', () => {
65
+ const html = `
66
+ <div>
67
+ <style>a { color: red }</style>
68
+ <a href="foo">
69
+ <img src="bar.jpg" />
70
+ </a>
71
+ </div>
72
+ `;
73
+ const wrapper = createWrapper(html);
74
+ expect(wrapper.html()).not.toContain('<img');
75
+ expect(wrapper.html()).toContain('<style>');
76
+ expect(wrapper.render()).toMatchSnapshot();
77
+ });
78
+ it('should move style blocks out of the content', () => {
79
+ const html = `
80
+ <div>
81
+ <style>a { color: red }</style>
82
+ <a href="foo">
83
+ <img src="bar.jpg" />
84
+ </a>
85
+ </div>
86
+ `;
87
+ const wrapper = createWrapper(html, {
88
+ processStyles: true
89
+ });
90
+ expect(wrapper.html()).not.toContain('<style>');
91
+ });
92
+ it('does not strip out images with absolute paths', () => {
93
+ const html = `
94
+ <div>
95
+ <a href="foo">
96
+ <img src="http://google.de/bar.jpg" />
97
+ </a>
98
+ </div>
99
+ `;
100
+ const wrapper = createWrapper(html);
101
+ expect(wrapper.html()).toContain('<img');
102
+ expect(wrapper.render()).toMatchSnapshot();
103
+ });
104
+ it('strips out the script tags', () => {
105
+ /**
11
106
  * The value for html is the HTML-escaped equivalent of the following:
12
107
  * <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
13
108
  * <script type="text/javascript">var x = 42;</script>
14
109
  * <p>Foo Bar</p>
15
110
  * <script>var y = 23;</script>
16
111
  * @type {string}
17
- */var html='&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js&quot;&gt;&lt;/script&gt; &lt;script type=&quot;text/javascript&quot;&gt;var x = 42;&lt;/script&gt; &lt;p&gt;Foo Bar&lt;/p&gt; &lt;script&gt;var y = 23;&lt;/script&gt;';var wrapper=createWrapper(html,{decode:true});// Test result of dangerouslySetInnerHTML.
18
- expect(wrapper.html()).toEqual('<div class="common__html-sanitizer"> <p>Foo Bar</p> </div>');expect(wrapper).toMatchSnapshot();});describe('Link handling',function(){var mockedHandleClick=jest.fn();beforeEach(function(){mockedHandleClick.mockClear();});it('follows a link from a plain <a>',function(){var doc=new JSDOM('<!doctype html><html><body><div>/<div></body></html>').window.document;var html='&lt;a id=&quot;link&quot; href=&quot;#follow-me-and-everything-is-alright&quot;&gt;Plain Link&lt;/a&gt;';var wrapper=mount(React.createElement(HtmlSanitizer,{decode:true,settings:{handleClick:mockedHandleClick},navigate:function navigate(){}},html),{attachTo:doc.getElementsByTagName('div')[0]});var aTag=doc.getElementsByTagName('a')[0];aTag.closest=function(){return aTag;};var event={target:aTag,preventDefault:function preventDefault(){}};wrapper.instance().handleTap(event);expect(mockedHandleClick).toHaveBeenCalledTimes(1);expect(mockedHandleClick).toHaveBeenCalledWith('#follow-me-and-everything-is-alright','');});it('follows a link from a <a> with other HTML inside',function(){var doc=new JSDOM('<!doctype html><html><body><div>/<div></body></html>').window.document;var html='&lt;a id=&quot;link&quot; target=&quot;_blank&quot; href=&quot;#I-ll-be-the-one-to-tuck-you-in-at-night&quot;&gt;&lt;span&gt;Span Link&lt;/span&gt;&lt;/a&gt;';var wrapper=mount(React.createElement(HtmlSanitizer,{decode:true,settings:{handleClick:mockedHandleClick},navigate:function navigate(){}},html),{attachTo:doc.getElementsByTagName('div')[0]});var aTag=doc.getElementsByTagName('a')[0];var spanTag=doc.getElementsByTagName('span')[0];spanTag.closest=function(){return aTag;};var event={target:spanTag,preventDefault:function preventDefault(){}};wrapper.instance().handleTap(event);expect(mockedHandleClick).toHaveBeenCalledTimes(1);expect(mockedHandleClick).toHaveBeenCalledWith('#I-ll-be-the-one-to-tuck-you-in-at-night','_blank');});});describe('Cookie consent handling',function(){it('should invoke handleCookieConsent method of embedded media with default cookie consent settings',function(){createWrapper('<div></div>',{decode:true});expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledTimes(1);expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledWith(expect.any(Document),{comfortCookiesAccepted:false,statisticsCookiesAccepted:false});});it('should invoke handleCookieConsent method of embedded media with accepted comfort cookies',function(){createWrapper('<div></div>',{decode:true,comfortCookiesAccepted:true});expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledTimes(1);expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledWith(expect.any(Document),{comfortCookiesAccepted:true,statisticsCookiesAccepted:false});});it('should invoke handleCookieConsent method of embedded media with accepted statistics cookies',function(){createWrapper('<div></div>',{decode:true,statisticsCookiesAccepted:true});expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledTimes(1);expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledWith(expect.any(Document),{comfortCookiesAccepted:false,statisticsCookiesAccepted:true});});it('should invoke handleCookieConsent method of embedded media with all cookies accepted',function(){createWrapper('<div></div>',{decode:true,comfortCookiesAccepted:true,statisticsCookiesAccepted:true});expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledTimes(1);expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledWith(expect.any(Document),{comfortCookiesAccepted:true,statisticsCookiesAccepted:true});});});});
112
+ */
113
+ const html = '&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js&quot;&gt;&lt;/script&gt; &lt;script type=&quot;text/javascript&quot;&gt;var x = 42;&lt;/script&gt; &lt;p&gt;Foo Bar&lt;/p&gt; &lt;script&gt;var y = 23;&lt;/script&gt;';
114
+ const wrapper = createWrapper(html, {
115
+ decode: true
116
+ });
117
+
118
+ // Test result of dangerouslySetInnerHTML.
119
+ expect(wrapper.html()).toEqual('<div class="common__html-sanitizer"> <p>Foo Bar</p> </div>');
120
+ expect(wrapper).toMatchSnapshot();
121
+ });
122
+ describe('Link handling', () => {
123
+ const mockedHandleClick = jest.fn();
124
+ beforeEach(() => {
125
+ mockedHandleClick.mockClear();
126
+ });
127
+ it('follows a link from a plain <a>', () => {
128
+ const doc = new JSDOM('<!doctype html><html><body><div>/<div></body></html>').window.document;
129
+ const html = '&lt;a id=&quot;link&quot; href=&quot;#follow-me-and-everything-is-alright&quot;&gt;Plain Link&lt;/a&gt;';
130
+ const wrapper = mount(/*#__PURE__*/React.createElement(HtmlSanitizer, {
131
+ decode: true,
132
+ settings: {
133
+ handleClick: mockedHandleClick
134
+ },
135
+ navigate: () => {}
136
+ }, html), {
137
+ attachTo: doc.getElementsByTagName('div')[0]
138
+ });
139
+ const aTag = doc.getElementsByTagName('a')[0];
140
+ aTag.closest = () => aTag;
141
+ const event = {
142
+ target: aTag,
143
+ preventDefault: () => {}
144
+ };
145
+ wrapper.instance().handleTap(event);
146
+ expect(mockedHandleClick).toHaveBeenCalledTimes(1);
147
+ expect(mockedHandleClick).toHaveBeenCalledWith('#follow-me-and-everything-is-alright', '');
148
+ });
149
+ it('follows a link from a <a> with other HTML inside', () => {
150
+ const doc = new JSDOM('<!doctype html><html><body><div>/<div></body></html>').window.document;
151
+ const html = '&lt;a id=&quot;link&quot; target=&quot;_blank&quot; href=&quot;#I-ll-be-the-one-to-tuck-you-in-at-night&quot;&gt;&lt;span&gt;Span Link&lt;/span&gt;&lt;/a&gt;';
152
+ const wrapper = mount(/*#__PURE__*/React.createElement(HtmlSanitizer, {
153
+ decode: true,
154
+ settings: {
155
+ handleClick: mockedHandleClick
156
+ },
157
+ navigate: () => {}
158
+ }, html), {
159
+ attachTo: doc.getElementsByTagName('div')[0]
160
+ });
161
+ const aTag = doc.getElementsByTagName('a')[0];
162
+ const spanTag = doc.getElementsByTagName('span')[0];
163
+ spanTag.closest = () => aTag;
164
+ const event = {
165
+ target: spanTag,
166
+ preventDefault: () => {}
167
+ };
168
+ wrapper.instance().handleTap(event);
169
+ expect(mockedHandleClick).toHaveBeenCalledTimes(1);
170
+ expect(mockedHandleClick).toHaveBeenCalledWith('#I-ll-be-the-one-to-tuck-you-in-at-night', '_blank');
171
+ });
172
+ });
173
+ describe('Cookie consent handling', () => {
174
+ it('should invoke handleCookieConsent method of embedded media with default cookie consent settings', () => {
175
+ createWrapper('<div></div>', {
176
+ decode: true
177
+ });
178
+ expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledTimes(1);
179
+ expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledWith(expect.any(Document), {
180
+ comfortCookiesAccepted: false,
181
+ statisticsCookiesAccepted: false
182
+ });
183
+ });
184
+ it('should invoke handleCookieConsent method of embedded media with accepted comfort cookies', () => {
185
+ createWrapper('<div></div>', {
186
+ decode: true,
187
+ comfortCookiesAccepted: true
188
+ });
189
+ expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledTimes(1);
190
+ expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledWith(expect.any(Document), {
191
+ comfortCookiesAccepted: true,
192
+ statisticsCookiesAccepted: false
193
+ });
194
+ });
195
+ it('should invoke handleCookieConsent method of embedded media with accepted statistics cookies', () => {
196
+ createWrapper('<div></div>', {
197
+ decode: true,
198
+ statisticsCookiesAccepted: true
199
+ });
200
+ expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledTimes(1);
201
+ expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledWith(expect.any(Document), {
202
+ comfortCookiesAccepted: false,
203
+ statisticsCookiesAccepted: true
204
+ });
205
+ });
206
+ it('should invoke handleCookieConsent method of embedded media with all cookies accepted', () => {
207
+ createWrapper('<div></div>', {
208
+ decode: true,
209
+ comfortCookiesAccepted: true,
210
+ statisticsCookiesAccepted: true
211
+ });
212
+ expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledTimes(1);
213
+ expect(embeddedMediaHandleCookieConsentSpy).toHaveBeenCalledWith(expect.any(Document), {
214
+ comfortCookiesAccepted: true,
215
+ statisticsCookiesAccepted: true
216
+ });
217
+ });
218
+ });
219
+ });
@@ -1,5 +1,29 @@
1
- import React,{Fragment,memo}from'react';import PropTypes from'prop-types';import{i18n}from'@shopgate/engage/core/helpers/i18n';/**
1
+ import React, { Fragment, memo } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { i18n } from '@shopgate/engage/core/helpers/i18n';
4
+
5
+ /**
2
6
  * Formats a date.
3
7
  * @param {Object} props The component props.
4
8
  * @returns {JSX}
5
- */var FormatDate=function FormatDate(_ref){var timestamp=_ref.timestamp,format=_ref.format;return React.createElement(Fragment,null,FormatDate.format({timestamp:timestamp,format:format}));};FormatDate.format=function(_ref2){var timestamp=_ref2.timestamp,format=_ref2.format;if(!i18n.ready){return timestamp;}return i18n.date(timestamp,format);};FormatDate.defaultProps={format:'medium'};export default memo(FormatDate);
9
+ */
10
+ const FormatDate = ({
11
+ timestamp,
12
+ format
13
+ }) => /*#__PURE__*/React.createElement(Fragment, null, FormatDate.format({
14
+ timestamp,
15
+ format
16
+ }));
17
+ FormatDate.format = ({
18
+ timestamp,
19
+ format
20
+ }) => {
21
+ if (!i18n.ready) {
22
+ return timestamp;
23
+ }
24
+ return i18n.date(timestamp, format);
25
+ };
26
+ FormatDate.defaultProps = {
27
+ format: 'medium'
28
+ };
29
+ export default /*#__PURE__*/memo(FormatDate);
@@ -1 +1,46 @@
1
- import React from'react';import{mount}from'enzyme';import{i18n}from'@shopgate/engage/core';import I18n from"../../index";jest.unmock('@shopgate/engage/core/helpers/i18n');describe('<FormatDate />',function(){var locales={greeting:'Hello {date}'};var lang='en-US';var timestamp=123456789000;var formattedDate='Nov 29, 1973';var format='medium';i18n.init({locales:locales,lang:lang});describe('Given the component was mounted to the DOM',function(){var renderedElement;it('should match snapshot',function(){renderedElement=mount(React.createElement(I18n.Provider,null,React.createElement("div",null,React.createElement("span",{className:"only-date"},React.createElement(I18n.Date,{timestamp:timestamp,format:format})),React.createElement("span",{className:"text-with-date"},React.createElement(I18n.Text,{string:"greeting"},React.createElement(I18n.Date,{forKey:"date",timestamp:timestamp,format:format}))))));expect(renderedElement).toMatchSnapshot();});it('should render formatted date',function(){var text=renderedElement.find('.only-date').text();expect(text).toBe(formattedDate);});it('should render within translated text',function(){var text=renderedElement.find('.text-with-date').text();expect(text).toBe("Hello ".concat(formattedDate));});});});
1
+ import React from 'react';
2
+ import { mount } from 'enzyme';
3
+ import { i18n } from '@shopgate/engage/core';
4
+ import I18n from "../../index";
5
+ jest.unmock('@shopgate/engage/core/helpers/i18n');
6
+ describe('<FormatDate />', () => {
7
+ const locales = {
8
+ greeting: 'Hello {date}'
9
+ };
10
+ const lang = 'en-US';
11
+ const timestamp = 123456789000;
12
+ const formattedDate = 'Nov 29, 1973';
13
+ const format = 'medium';
14
+ i18n.init({
15
+ locales,
16
+ lang
17
+ });
18
+ describe('Given the component was mounted to the DOM', () => {
19
+ let renderedElement;
20
+ it('should match snapshot', () => {
21
+ renderedElement = mount(/*#__PURE__*/React.createElement(I18n.Provider, null, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("span", {
22
+ className: "only-date"
23
+ }, /*#__PURE__*/React.createElement(I18n.Date, {
24
+ timestamp: timestamp,
25
+ format: format
26
+ })), /*#__PURE__*/React.createElement("span", {
27
+ className: "text-with-date"
28
+ }, /*#__PURE__*/React.createElement(I18n.Text, {
29
+ string: "greeting"
30
+ }, /*#__PURE__*/React.createElement(I18n.Date, {
31
+ forKey: "date",
32
+ timestamp: timestamp,
33
+ format: format
34
+ }))))));
35
+ expect(renderedElement).toMatchSnapshot();
36
+ });
37
+ it('should render formatted date', () => {
38
+ const text = renderedElement.find('.only-date').text();
39
+ expect(text).toBe(formattedDate);
40
+ });
41
+ it('should render within translated text', () => {
42
+ const text = renderedElement.find('.text-with-date').text();
43
+ expect(text).toBe(`Hello ${formattedDate}`);
44
+ });
45
+ });
46
+ });
@@ -1,5 +1,37 @@
1
- import React,{memo}from'react';import PropTypes from'prop-types';import{i18n}from'@shopgate/engage/core/helpers/i18n';/**
1
+ import React, { memo } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { i18n } from '@shopgate/engage/core/helpers/i18n';
4
+ /**
2
5
  * Formats a number.
3
6
  * @param {Object} props The component props.
4
7
  * @returns {JSX}
5
- */var FormatNumber=function FormatNumber(_ref){var className=_ref.className,number=_ref.number,fractions=_ref.fractions;if(!className){FormatNumber.format({number:number,fractions:fractions});}return React.createElement("span",{className:className},FormatNumber.format({number:number,fractions:fractions}));};FormatNumber.format=function(props){if(!i18n.ready){return props.number;}return i18n.number(props.number,props.fractions);};FormatNumber.defaultProps={className:null,fractions:0};export default memo(FormatNumber);
8
+ */
9
+ const FormatNumber = ({
10
+ className,
11
+ number,
12
+ fractions
13
+ }) => {
14
+ if (!className) {
15
+ FormatNumber.format({
16
+ number,
17
+ fractions
18
+ });
19
+ }
20
+ return /*#__PURE__*/React.createElement("span", {
21
+ className: className
22
+ }, FormatNumber.format({
23
+ number,
24
+ fractions
25
+ }));
26
+ };
27
+ FormatNumber.format = props => {
28
+ if (!i18n.ready) {
29
+ return props.number;
30
+ }
31
+ return i18n.number(props.number, props.fractions);
32
+ };
33
+ FormatNumber.defaultProps = {
34
+ className: null,
35
+ fractions: 0
36
+ };
37
+ export default /*#__PURE__*/memo(FormatNumber);