@magento/pagebuilder 7.1.0 → 7.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/lib/ContentTypes/Banner/__tests__/__snapshots__/banner.shimmer.spec.js.snap +0 -1
  2. package/lib/ContentTypes/Banner/__tests__/__snapshots__/banner.spec.js.snap +0 -1
  3. package/lib/ContentTypes/Banner/banner.js +23 -4
  4. package/lib/ContentTypes/Banner/banner.shimmer.js +13 -2
  5. package/lib/ContentTypes/Banner/configAggregator.js +4 -2
  6. package/lib/ContentTypes/Column/column.js +13 -2
  7. package/lib/ContentTypes/Column/configAggregator.js +3 -1
  8. package/lib/ContentTypes/DynamicBlock/__tests__/__snapshots__/dynamicBlock.ce.spec.js.snap +3 -0
  9. package/lib/ContentTypes/DynamicBlock/__tests__/__snapshots__/dynamicBlock.ee.spec.js.snap +93 -0
  10. package/lib/ContentTypes/DynamicBlock/__tests__/__snapshots__/dynamicBlock.shimmer.spec.js.snap +39 -0
  11. package/lib/ContentTypes/DynamicBlock/__tests__/configAggregator.spec.js +49 -0
  12. package/lib/ContentTypes/DynamicBlock/__tests__/dynamicBlock.ce.spec.js +17 -0
  13. package/lib/ContentTypes/DynamicBlock/__tests__/dynamicBlock.ee.spec.js +70 -0
  14. package/lib/ContentTypes/DynamicBlock/__tests__/dynamicBlock.shimmer.spec.js +20 -0
  15. package/lib/ContentTypes/DynamicBlock/configAggregator.js +25 -0
  16. package/lib/ContentTypes/DynamicBlock/dynamicBlock.ce.js +5 -0
  17. package/lib/ContentTypes/DynamicBlock/dynamicBlock.ee.js +134 -0
  18. package/lib/ContentTypes/DynamicBlock/dynamicBlock.module.css +8 -0
  19. package/lib/ContentTypes/DynamicBlock/dynamicBlock.shimmer.js +134 -0
  20. package/lib/ContentTypes/DynamicBlock/dynamicBlock.shimmer.module.css +26 -0
  21. package/lib/ContentTypes/DynamicBlock/index.js +2 -0
  22. package/lib/ContentTypes/Image/__tests__/__snapshots__/image.shimmer.spec.js.snap +139 -0
  23. package/lib/ContentTypes/Image/__tests__/configAggregator.spec.js +28 -10
  24. package/lib/ContentTypes/Image/__tests__/image.shimmer.spec.js +122 -0
  25. package/lib/ContentTypes/Image/__tests__/image.spec.js +5 -5
  26. package/lib/ContentTypes/Image/configAggregator.js +51 -18
  27. package/lib/ContentTypes/Image/image.js +25 -9
  28. package/lib/ContentTypes/Image/image.module.css +2 -0
  29. package/lib/ContentTypes/Image/image.shimmer.js +191 -0
  30. package/lib/ContentTypes/Image/image.shimmer.module.css +5 -0
  31. package/lib/ContentTypes/Image/index.js +1 -0
  32. package/lib/ContentTypes/Row/__tests__/configAggregator.spec.js +18 -0
  33. package/lib/ContentTypes/Row/__tests__/row.spec.js +2 -1
  34. package/lib/ContentTypes/Row/configAggregator.js +13 -3
  35. package/lib/ContentTypes/Row/row.js +26 -3
  36. package/lib/ContentTypes/Slider/configAggregator.js +3 -2
  37. package/lib/ContentTypes/Slider/slider.js +21 -2
  38. package/lib/ContentTypes/Slider/slider.shimmer.js +13 -2
  39. package/lib/ContentTypes/TabItem/configAggregator.js +4 -2
  40. package/lib/ContentTypes/TabItem/tabItem.js +13 -2
  41. package/lib/ContentTypes/Tabs/configAggregator.js +4 -2
  42. package/lib/ContentTypes/Tabs/tabs.js +19 -2
  43. package/lib/__tests__/parseStorageHtml.spec.js +35 -0
  44. package/lib/__tests__/utils.spec.js +21 -1
  45. package/lib/config.js +10 -2
  46. package/lib/parseStorageHtml.js +32 -0
  47. package/lib/utils.js +46 -0
  48. package/package.json +7 -7
@@ -0,0 +1,134 @@
1
+ import React from 'react';
2
+ import { arrayOf, bool, oneOf, shape, string } from 'prop-types';
3
+
4
+ import { useStyle } from '@magento/venia-ui/lib/classify';
5
+ import CmsDynamicBlockGroup, {
6
+ DISPLAY_MODE_FIXED_TYPE,
7
+ DISPLAY_MODE_SALES_RULE_TYPE,
8
+ DISPLAY_MODE_CATALOG_RULE_TYPE
9
+ } from '@magento/venia-ui/lib/components/CmsDynamicBlock';
10
+ import defaultClasses from './dynamicBlock.module.css';
11
+
12
+ /**
13
+ * Page Builder Dynamic Block component.
14
+ *
15
+ * This component is part of the Page Builder / PWA integration. It can be consumed without Page Builder.
16
+ *
17
+ * @typedef DynamicBlock
18
+ * @kind functional component
19
+ *
20
+ * @param {props} props React component props
21
+ *
22
+ * @returns {React.Element} A React component that displays a Dynamic Block.
23
+ */
24
+ const DynamicBlock = props => {
25
+ const classes = useStyle(defaultClasses, props.classes);
26
+ const {
27
+ displayInline,
28
+ displayMode,
29
+ uids = '',
30
+ textAlign,
31
+ border,
32
+ borderColor,
33
+ borderWidth,
34
+ borderRadius,
35
+ marginTop,
36
+ marginRight,
37
+ marginBottom,
38
+ marginLeft,
39
+ minHeight,
40
+ paddingTop,
41
+ paddingRight,
42
+ paddingBottom,
43
+ paddingLeft,
44
+ cssClasses = []
45
+ } = props;
46
+
47
+ const dynamicStyles = {
48
+ textAlign,
49
+ border,
50
+ borderColor,
51
+ borderWidth,
52
+ borderRadius,
53
+ marginTop,
54
+ marginRight,
55
+ marginBottom,
56
+ marginLeft,
57
+ minHeight,
58
+ paddingTop,
59
+ paddingRight,
60
+ paddingBottom,
61
+ paddingLeft
62
+ };
63
+
64
+ const RootTag = displayInline ? 'span' : 'div';
65
+
66
+ // If no uids are found, do not render
67
+ if (!uids || (uids && uids.length === 0)) {
68
+ return null;
69
+ }
70
+
71
+ return (
72
+ <RootTag
73
+ style={dynamicStyles}
74
+ className={[classes.root, ...cssClasses].join(' ')}
75
+ aria-live="polite"
76
+ aria-busy="false"
77
+ >
78
+ <CmsDynamicBlockGroup displayMode={displayMode} uids={uids} />
79
+ </RootTag>
80
+ );
81
+ };
82
+
83
+ /**
84
+ * Props for {@link DynamicBlock}
85
+ *
86
+ * @typedef props
87
+ *
88
+ * @property {Object} classes An object containing the class names for the component
89
+ * @property {String} classes.root CSS class for the component root element
90
+ * @property {Boolean} displayInline Select display inline or display block
91
+ * @property {String} displayMode Display mode of the dynamic block
92
+ * @property {String} uids ID of the dynamic block
93
+ * @property {String} textAlign Alignment of the component within the parent container
94
+ * @property {String} border CSS border property
95
+ * @property {String} borderColor CSS border color property
96
+ * @property {String} borderWidth CSS border width property
97
+ * @property {String} borderRadius CSS border radius property
98
+ * @property {String} marginTop CSS margin top property
99
+ * @property {String} marginRight CSS margin right property
100
+ * @property {String} marginBottom CSS margin bottom property
101
+ * @property {String} marginLeft CSS margin left property
102
+ * @property {String} paddingTop CSS padding top property
103
+ * @property {String} paddingRight CSS padding right property
104
+ * @property {String} paddingBottom CSS padding bottom property
105
+ * @property {String} paddingLeft CSS padding left property
106
+ * @property {Array} cssClasses List of CSS classes to be applied to the component
107
+ */
108
+ DynamicBlock.propTypes = {
109
+ classes: shape({
110
+ root: string
111
+ }),
112
+ displayInline: bool,
113
+ displayMode: oneOf([
114
+ DISPLAY_MODE_FIXED_TYPE,
115
+ DISPLAY_MODE_SALES_RULE_TYPE,
116
+ DISPLAY_MODE_CATALOG_RULE_TYPE
117
+ ]),
118
+ uids: string,
119
+ textAlign: string,
120
+ border: string,
121
+ borderColor: string,
122
+ borderWidth: string,
123
+ borderRadius: string,
124
+ marginTop: string,
125
+ marginRight: string,
126
+ marginBottom: string,
127
+ marginLeft: string,
128
+ paddingTop: string,
129
+ paddingRight: string,
130
+ paddingBottom: string,
131
+ cssClasses: arrayOf(string)
132
+ };
133
+
134
+ export default DynamicBlock;
@@ -0,0 +1,8 @@
1
+ .root:empty {
2
+ display: none;
3
+ }
4
+
5
+ .root_inline {
6
+ composes: root;
7
+ display: inline-block;
8
+ }
@@ -0,0 +1,134 @@
1
+ import React from 'react';
2
+ import { arrayOf, shape, string, object } from 'prop-types';
3
+ import defaultClasses from './dynamicBlock.shimmer.module.css';
4
+ import { useStyle } from '@magento/venia-ui/lib/classify';
5
+ import Shimmer from '@magento/venia-ui/lib/components/Shimmer';
6
+
7
+ /**
8
+ * Page Builder Dynamic Block Shimmer component.
9
+ *
10
+ * @typedef DynamicBlockShimmer
11
+ * @kind functional component
12
+ *
13
+ * @param {props} props React component props
14
+ *
15
+ * @returns {React.Element} A React component that displays a Dynamic Block Shimmer.
16
+ */
17
+ const DynamicBlockShimmer = props => {
18
+ const classes = useStyle(defaultClasses, props.classes);
19
+ const {
20
+ border,
21
+ borderWidth,
22
+ marginTop,
23
+ marginRight,
24
+ marginBottom,
25
+ marginLeft,
26
+ minHeight,
27
+ paddingTop,
28
+ paddingRight,
29
+ paddingBottom,
30
+ paddingLeft,
31
+ cssClasses = []
32
+ } = props;
33
+
34
+ const rootStyles = {
35
+ marginTop,
36
+ marginRight,
37
+ marginBottom,
38
+ marginLeft,
39
+ minHeight
40
+ };
41
+
42
+ const wrapperStyles = {
43
+ border,
44
+ borderWidth,
45
+ paddingTop,
46
+ paddingRight,
47
+ paddingBottom,
48
+ paddingLeft
49
+ };
50
+
51
+ // Only render shimmer if min-height specified
52
+ return minHeight ? (
53
+ <div
54
+ className={classes.parent}
55
+ style={rootStyles}
56
+ aria-live="polite"
57
+ aria-busy="true"
58
+ >
59
+ <Shimmer
60
+ classes={{
61
+ root_rectangle: [
62
+ classes.root,
63
+ classes.shimmerRoot,
64
+ ...cssClasses
65
+ ].join(' ')
66
+ }}
67
+ >
68
+ <div className={classes.wrapper} style={wrapperStyles}>
69
+ <div className={classes.overlay}>
70
+ <div className={classes.content} />
71
+ </div>
72
+ </div>
73
+ </Shimmer>
74
+ </div>
75
+ ) : null;
76
+ };
77
+
78
+ /**
79
+ * Props for {@link DynamicBlockShimmer}
80
+ *
81
+ * @typedef props
82
+ *
83
+ * @property {Object} classes An object containing the class names for the dynamic block
84
+ * @property {String} classes.root CSS class for the dynamic block root element
85
+ * @property {String} classes.shimmerRoot CSS class for the dynamic block
86
+ * shimmer root_rectangle element
87
+ * @property {String} classes.wrapper CSS class for the dynamic block wrapper element
88
+ * @property {String} classes.overlay CSS class for the dynamic block overlay element
89
+ * @property {String} classes.content CSS class for the dynamic block content element
90
+ * @property {String} minHeight CSS minimum height property
91
+ * @property {String} border CSS border property
92
+ * @property {String} borderWidth CSS border width property
93
+ * @property {String} marginTop CSS margin top property
94
+ * @property {String} marginRight CSS margin right property
95
+ * @property {String} marginBottom CSS margin bottom property
96
+ * @property {String} marginLeft CSS margin left property
97
+ * @property {Array} mediaQueries List of media query rules to be applied to the component
98
+ * @property {String} paddingTop CSS padding top property
99
+ * @property {String} paddingRight CSS padding right property
100
+ * @property {String} paddingBottom CSS padding bottom property
101
+ * @property {String} paddingLeft CSS padding left property
102
+ * @property {Array} cssClasses List of CSS classes to be applied to
103
+ * the component
104
+ */
105
+ DynamicBlockShimmer.propTypes = {
106
+ classes: shape({
107
+ root: string,
108
+ shimmerRoot: string,
109
+ parent: string,
110
+ wrapper: string,
111
+ overlay: string,
112
+ content: string
113
+ }),
114
+ minHeight: string,
115
+ border: string,
116
+ borderWidth: string,
117
+ marginTop: string,
118
+ marginRight: string,
119
+ marginBottom: string,
120
+ marginLeft: string,
121
+ mediaQueries: arrayOf(
122
+ shape({
123
+ media: string,
124
+ style: object
125
+ })
126
+ ),
127
+ paddingTop: string,
128
+ paddingRight: string,
129
+ paddingBottom: string,
130
+ paddingLeft: string,
131
+ cssClasses: arrayOf(string)
132
+ };
133
+
134
+ export default DynamicBlockShimmer;
@@ -0,0 +1,26 @@
1
+ .parent {
2
+ display: flex;
3
+ }
4
+
5
+ /* Only show one shimmer when multiple dynamic blocks */
6
+ .parent + .parent {
7
+ display: none;
8
+ }
9
+
10
+ .shimmerRoot {
11
+ composes: root_rectangle from '~@magento/venia-ui/lib/components/Shimmer/shimmer.module.css';
12
+ composes: root from './dynamicBlock.module.css';
13
+ flex: 1;
14
+ }
15
+
16
+ .wrapper {
17
+ composes: wrapper from './dynamicBlock.module.css';
18
+ }
19
+
20
+ .overlay {
21
+ composes: overlay from './dynamicBlock.module.css';
22
+ }
23
+
24
+ .content {
25
+ composes: content from './dynamicBlock.module.css';
26
+ }
@@ -0,0 +1,2 @@
1
+ export { default } from './dynamicBlock';
2
+ export { default as DynamicBlockShimmer } from './dynamicBlock.shimmer';
@@ -0,0 +1,139 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`renders ImageShimmer correctly render empty ImageShimmer component 1`] = `null`;
4
+
5
+ exports[`renders ImageShimmer correctly renders a ImageShimmer using desktop image dimension 1`] = `
6
+ <figure
7
+ style={
8
+ Object {
9
+ "marginBottom": undefined,
10
+ "marginLeft": undefined,
11
+ "marginRight": undefined,
12
+ "marginTop": undefined,
13
+ "paddingBottom": undefined,
14
+ "paddingLeft": undefined,
15
+ "paddingRight": undefined,
16
+ "paddingTop": undefined,
17
+ "textAlign": undefined,
18
+ }
19
+ }
20
+ >
21
+ <div
22
+ aria-busy="true"
23
+ aria-live="polite"
24
+ className="root_rectangle"
25
+ style={
26
+ Object {
27
+ "border": undefined,
28
+ "borderColor": undefined,
29
+ "borderRadius": undefined,
30
+ "borderWidth": undefined,
31
+ "height": "300px",
32
+ "width": "400px",
33
+ }
34
+ }
35
+ />
36
+ </figure>
37
+ `;
38
+
39
+ exports[`renders ImageShimmer correctly renders a ImageShimmer using desktop image dimension on mobile device when no mobile image 1`] = `
40
+ <figure
41
+ style={
42
+ Object {
43
+ "marginBottom": undefined,
44
+ "marginLeft": undefined,
45
+ "marginRight": undefined,
46
+ "marginTop": undefined,
47
+ "paddingBottom": undefined,
48
+ "paddingLeft": undefined,
49
+ "paddingRight": undefined,
50
+ "paddingTop": undefined,
51
+ "textAlign": undefined,
52
+ }
53
+ }
54
+ >
55
+ <div
56
+ aria-busy="true"
57
+ aria-live="polite"
58
+ className="root_rectangle"
59
+ style={
60
+ Object {
61
+ "border": undefined,
62
+ "borderColor": undefined,
63
+ "borderRadius": undefined,
64
+ "borderWidth": undefined,
65
+ "height": "300px",
66
+ "width": "400px",
67
+ }
68
+ }
69
+ />
70
+ </figure>
71
+ `;
72
+
73
+ exports[`renders ImageShimmer correctly renders a ImageShimmer using mobile image dimension 1`] = `
74
+ <figure
75
+ style={
76
+ Object {
77
+ "marginBottom": undefined,
78
+ "marginLeft": undefined,
79
+ "marginRight": undefined,
80
+ "marginTop": undefined,
81
+ "paddingBottom": undefined,
82
+ "paddingLeft": undefined,
83
+ "paddingRight": undefined,
84
+ "paddingTop": undefined,
85
+ "textAlign": undefined,
86
+ }
87
+ }
88
+ >
89
+ <div
90
+ aria-busy="true"
91
+ aria-live="polite"
92
+ className="root_rectangle"
93
+ style={
94
+ Object {
95
+ "border": undefined,
96
+ "borderColor": undefined,
97
+ "borderRadius": undefined,
98
+ "borderWidth": undefined,
99
+ "height": "250px",
100
+ "width": "125px",
101
+ }
102
+ }
103
+ />
104
+ </figure>
105
+ `;
106
+
107
+ exports[`renders ImageShimmer correctly renders a ImageShimmer using mobile image dimension even without desktop image 1`] = `
108
+ <figure
109
+ style={
110
+ Object {
111
+ "marginBottom": undefined,
112
+ "marginLeft": undefined,
113
+ "marginRight": undefined,
114
+ "marginTop": undefined,
115
+ "paddingBottom": undefined,
116
+ "paddingLeft": undefined,
117
+ "paddingRight": undefined,
118
+ "paddingTop": undefined,
119
+ "textAlign": undefined,
120
+ }
121
+ }
122
+ >
123
+ <div
124
+ aria-busy="true"
125
+ aria-live="polite"
126
+ className="root_rectangle"
127
+ style={
128
+ Object {
129
+ "border": undefined,
130
+ "borderColor": undefined,
131
+ "borderRadius": undefined,
132
+ "borderWidth": undefined,
133
+ "height": "250px",
134
+ "width": "125px",
135
+ }
136
+ }
137
+ />
138
+ </figure>
139
+ `;
@@ -2,15 +2,21 @@ import configAggregator from '../configAggregator';
2
2
 
3
3
  test('image config aggregator retrieves image data without anchor', () => {
4
4
  const node = document.createElement('div');
5
- node.innerHTML = `<figure data-content-type="image" data-appearance="full-width" data-element="main" style="margin: 0px; padding: 0px; border-style: none;"><img class="pagebuilder-mobile-hidden" src="desktop-image.png" alt="Test Alt Text" title="Test Title Text" data-element="desktop_image" style="border-style: none; border-width: 1px; border-radius: 0px; max-width: 100%; height: auto;"><img class="pagebuilder-mobile-only" src="mobile-image.png" alt="Test Alt Text" title="Test Title Text" data-element="mobile_image" style="border-style: none; border-width: 1px; border-radius: 0px; max-width: 100%; height: auto;"></figure>`;
5
+ node.innerHTML = `<figure data-content-type="image" data-appearance="full-width" data-element="main" style="margin: 0px; padding: 0px; border-style: none;"><img class="pagebuilder-mobile-hidden" src="desktop-image.png" alt="Test Alt Text" title="Test Title Text" data-element="desktop_image" style="border-style: none; border-width: 1px; border-radius: 0px; max-width: 100%; height: auto;" data-image-dimensions="{&quot;height&quot;:300,&quot;width&quot;:460,&quot;ratio&quot;:0.65}"><img class="pagebuilder-mobile-only" src="mobile-image.png" alt="Test Alt Text" title="Test Title Text" data-element="mobile_image" style="border-style: none; border-width: 1px; border-radius: 0px; max-width: 100%; height: auto;" data-image-dimensions="{&quot;height&quot;:200,&quot;width&quot;:100,&quot;ratio&quot;:0.5}"></figure>`;
6
6
  expect(
7
7
  configAggregator(node.childNodes[0], {
8
8
  appearance: 'full-width'
9
9
  })
10
10
  ).toEqual(
11
11
  expect.objectContaining({
12
- desktopImage: 'desktop-image.png',
13
- mobileImage: 'mobile-image.png',
12
+ desktopImage: {
13
+ dimensions: { height: 300, ratio: 0.65, width: 460 },
14
+ src: 'desktop-image.png'
15
+ },
16
+ mobileImage: {
17
+ dimensions: { height: 200, ratio: 0.5, width: 100 },
18
+ src: 'mobile-image.png'
19
+ },
14
20
  altText: 'Test Alt Text',
15
21
  title: 'Test Title Text'
16
22
  })
@@ -19,15 +25,21 @@ test('image config aggregator retrieves image data without anchor', () => {
19
25
 
20
26
  test('image config aggregator retrieves image data with anchor', () => {
21
27
  const node = document.createElement('div');
22
- node.innerHTML = `<figure class="another-class-image" data-content-type="image" data-appearance="full-width" data-element="main" style="text-align: center; margin: 1px 2px 3px 4px; padding: 5px 6px 7px 8px; border-style: none;"><a href="/test-link" target="" data-link-type="page" title="Title Text" data-element="link"><img class="pagebuilder-mobile-hidden" src="desktop-image.png" alt="Alt Text" title="Title Text" data-element="desktop_image" style="border-style: solid; border-color: rgb(255, 0, 0); border-width: 5px; border-radius: 10px; max-width: 100%; height: auto;"><img class="pagebuilder-mobile-only" src="mobile-image.png" alt="Alt Text" title="Title Text" data-element="mobile_image" style="border-style: solid; border-color: rgb(255, 0, 0); border-width: 5px; border-radius: 10px; max-width: 100%; height: auto;"></a><figcaption data-element="caption">Test Caption</figcaption></figure>`;
28
+ node.innerHTML = `<figure class="another-class-image" data-content-type="image" data-appearance="full-width" data-element="main" style="text-align: center; margin: 1px 2px 3px 4px; padding: 5px 6px 7px 8px; border-style: none;"><a href="/test-link" target="" data-link-type="page" title="Title Text" data-element="link"><img class="pagebuilder-mobile-hidden" src="desktop-image.png" alt="Alt Text" title="Title Text" data-element="desktop_image" style="border-style: solid; border-color: rgb(255, 0, 0); border-width: 5px; border-radius: 10px; max-width: 100%; height: auto;" data-image-dimensions="{&quot;height&quot;:300,&quot;width&quot;:460,&quot;ratio&quot;:0.65}"><img class="pagebuilder-mobile-only" src="mobile-image.png" alt="Alt Text" title="Title Text" data-element="mobile_image" style="border-style: solid; border-color: rgb(255, 0, 0); border-width: 5px; border-radius: 10px; max-width: 100%; height: auto;" data-image-dimensions="{&quot;height&quot;:200,&quot;width&quot;:100,&quot;ratio&quot;:0.5}"></a><figcaption data-element="caption">Test Caption</figcaption></figure>`;
23
29
  expect(
24
30
  configAggregator(node.childNodes[0], {
25
31
  appearance: 'full-width'
26
32
  })
27
33
  ).toEqual(
28
34
  expect.objectContaining({
29
- desktopImage: 'desktop-image.png',
30
- mobileImage: 'mobile-image.png',
35
+ desktopImage: {
36
+ dimensions: { height: 300, ratio: 0.65, width: 460 },
37
+ src: 'desktop-image.png'
38
+ },
39
+ mobileImage: {
40
+ dimensions: { height: 200, ratio: 0.5, width: 100 },
41
+ src: 'mobile-image.png'
42
+ },
31
43
  altText: 'Alt Text',
32
44
  title: 'Title Text',
33
45
  link: '/test-link',
@@ -38,27 +50,33 @@ test('image config aggregator retrieves image data with anchor', () => {
38
50
 
39
51
  test('image config aggregator sets proper mobileImage when desktopImage equals mobilImage', () => {
40
52
  const node = document.createElement('div');
41
- node.innerHTML = `<figure class="another-class-image" data-content-type="image" data-appearance="full-width" data-element="main" style="text-align: center; margin: 1px 2px 3px 4px; padding: 5px 6px 7px 8px; border-style: none;"><a href="/test-link" target="" data-link-type="page" title="Title Text" data-element="link"><img class="pagebuilder-mobile-hidden" src="same-image.png" alt="Alt Text" title="Title Text" data-element="desktop_image" style="border-style: solid; border-color: rgb(255, 0, 0); border-width: 5px; border-radius: 10px; max-width: 100%; height: auto;"><img class="pagebuilder-mobile-only" src="same-image.png" alt="Alt Text" title="Title Text" data-element="mobile_image" style="border-style: solid; border-color: rgb(255, 0, 0); border-width: 5px; border-radius: 10px; max-width: 100%; height: auto;"></a><figcaption data-element="caption">Test Caption</figcaption></figure>`;
53
+ node.innerHTML = `<figure class="another-class-image" data-content-type="image" data-appearance="full-width" data-element="main" style="text-align: center; margin: 1px 2px 3px 4px; padding: 5px 6px 7px 8px; border-style: none;"><a href="/test-link" target="" data-link-type="page" title="Title Text" data-element="link"><img class="pagebuilder-mobile-hidden" src="same-image.png" alt="Alt Text" title="Title Text" data-element="desktop_image" style="border-style: solid; border-color: rgb(255, 0, 0); border-width: 5px; border-radius: 10px; max-width: 100%; height: auto;" data-image-dimensions="{&quot;height&quot;:300,&quot;width&quot;:460,&quot;ratio&quot;:0.65}"><img class="pagebuilder-mobile-only" src="same-image.png" alt="Alt Text" title="Title Text" data-element="mobile_image" style="border-style: solid; border-color: rgb(255, 0, 0); border-width: 5px; border-radius: 10px; max-width: 100%; height: auto;" data-image-dimensions="{&quot;height&quot;:300,&quot;width&quot;:460,&quot;ratio&quot;:0.65}"></a><figcaption data-element="caption">Test Caption</figcaption></figure>`;
42
54
 
43
55
  const config = configAggregator(node.childNodes[0]);
44
56
 
45
57
  expect(config).toEqual(
46
58
  expect.objectContaining({
47
- desktopImage: 'same-image.png',
59
+ desktopImage: {
60
+ dimensions: { height: 300, ratio: 0.65, width: 460 },
61
+ src: 'same-image.png'
62
+ },
48
63
  mobileImage: null
49
64
  })
50
65
  );
51
66
  });
52
67
  test('image config aggregator sets proper mobileImage only', () => {
53
68
  const node = document.createElement('div');
54
- node.innerHTML = `<figure data-content-type="image" data-appearance="full-width" data-element="main" style="margin: 0px; padding: 0px; border-style: none;"><img class="pagebuilder-mobile-only" src="mobile-image.png" alt="Test Alt Text" title="Test Title Text" data-element="mobile_image" style="border-style: none; border-width: 1px; border-radius: 0px; max-width: 100%; height: auto;"></figure>`;
69
+ node.innerHTML = `<figure data-content-type="image" data-appearance="full-width" data-element="main" style="margin: 0px; padding: 0px; border-style: none;"><img class="pagebuilder-mobile-only" src="mobile-image.png" alt="Test Alt Text" title="Test Title Text" data-element="mobile_image" style="border-style: none; border-width: 1px; border-radius: 0px; max-width: 100%; height: auto;" data-image-dimensions="{&quot;height&quot;:200,&quot;width&quot;:100,&quot;ratio&quot;:0.5}"></figure>`;
55
70
 
56
71
  const config = configAggregator(node.childNodes[0]);
57
72
 
58
73
  expect(config).toEqual(
59
74
  expect.objectContaining({
60
75
  desktopImage: null,
61
- mobileImage: 'mobile-image.png'
76
+ mobileImage: {
77
+ dimensions: { height: 200, ratio: 0.5, width: 100 },
78
+ src: 'mobile-image.png'
79
+ }
62
80
  })
63
81
  );
64
82
  });
@@ -0,0 +1,122 @@
1
+ import React from 'react';
2
+ import { createTestInstance } from '@magento/peregrine';
3
+ import ImageShimmer from '../image.shimmer';
4
+
5
+ jest.mock('@magento/venia-ui/lib/classify');
6
+
7
+ describe('renders ImageShimmer correctly', () => {
8
+ test('render empty ImageShimmer component', () => {
9
+ const component = createTestInstance(<ImageShimmer />);
10
+
11
+ expect(component.toJSON()).toMatchSnapshot();
12
+ });
13
+
14
+ test('renders a ImageShimmer using mobile image dimension', () => {
15
+ Object.defineProperty(window, 'matchMedia', {
16
+ value: jest.fn().mockImplementation(() => ({
17
+ matches: true
18
+ }))
19
+ });
20
+
21
+ const props = {
22
+ desktopImage: {
23
+ url: '/desktop-image.jpg',
24
+ dimensions: {
25
+ height: 300,
26
+ width: 400,
27
+ ratio: 0.75
28
+ }
29
+ },
30
+ mobileImage: {
31
+ url: '/mobile-image.png',
32
+ dimensions: {
33
+ height: 250,
34
+ width: 125,
35
+ ratio: 2
36
+ }
37
+ }
38
+ };
39
+
40
+ const component = createTestInstance(<ImageShimmer {...props} />);
41
+
42
+ expect(component.toJSON()).toMatchSnapshot();
43
+ });
44
+
45
+ test('renders a ImageShimmer using mobile image dimension even without desktop image', () => {
46
+ Object.defineProperty(window, 'matchMedia', {
47
+ value: jest.fn().mockImplementation(() => ({
48
+ matches: true
49
+ }))
50
+ });
51
+
52
+ const props = {
53
+ mobileImage: {
54
+ url: '/mobile-image.png',
55
+ dimensions: {
56
+ height: 250,
57
+ width: 125,
58
+ ratio: 2
59
+ }
60
+ }
61
+ };
62
+
63
+ const component = createTestInstance(<ImageShimmer {...props} />);
64
+
65
+ expect(component.toJSON()).toMatchSnapshot();
66
+ });
67
+
68
+ test('renders a ImageShimmer using desktop image dimension on mobile device when no mobile image', () => {
69
+ Object.defineProperty(window, 'matchMedia', {
70
+ value: jest.fn().mockImplementation(() => ({
71
+ matches: true
72
+ }))
73
+ });
74
+
75
+ const props = {
76
+ desktopImage: {
77
+ url: '/desktop-image.jpg',
78
+ dimensions: {
79
+ height: 300,
80
+ width: 400,
81
+ ratio: 0.75
82
+ }
83
+ },
84
+ mobileImage: null
85
+ };
86
+
87
+ const component = createTestInstance(<ImageShimmer {...props} />);
88
+
89
+ expect(component.toJSON()).toMatchSnapshot();
90
+ });
91
+
92
+ test('renders a ImageShimmer using desktop image dimension', () => {
93
+ Object.defineProperty(window, 'matchMedia', {
94
+ value: jest.fn().mockImplementation(() => ({
95
+ matches: false
96
+ }))
97
+ });
98
+
99
+ const props = {
100
+ desktopImage: {
101
+ url: '/desktop-image.jpg',
102
+ dimensions: {
103
+ height: 300,
104
+ width: 400,
105
+ ratio: 0.75
106
+ }
107
+ },
108
+ mobileImage: {
109
+ url: '/mobile-image.png',
110
+ dimensions: {
111
+ height: 250,
112
+ width: 125,
113
+ ratio: 2
114
+ }
115
+ }
116
+ };
117
+
118
+ const component = createTestInstance(<ImageShimmer {...props} />);
119
+
120
+ expect(component.toJSON()).toMatchSnapshot();
121
+ });
122
+ });