@shopgate/pwa-common 7.32.0-beta.2 → 7.32.0-beta.20

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 (64) hide show
  1. package/components/Button/index.js +6 -0
  2. package/components/Image/Image.d.ts +78 -0
  3. package/components/Image/Image.d.ts.map +1 -0
  4. package/components/Image/Image.js +123 -91
  5. package/components/Image/ImageInner.d.ts +45 -0
  6. package/components/Image/ImageInner.d.ts.map +1 -0
  7. package/components/Image/ImageInner.js +23 -29
  8. package/components/Image/index.d.ts +3 -0
  9. package/components/Image/index.d.ts.map +1 -0
  10. package/components/Swiper/index.js +17 -2
  11. package/constants/Configuration.js +7 -0
  12. package/helpers/mocks/mockRenderOptions.js +21 -0
  13. package/package.json +3 -3
  14. package/providers/toast/index.js +54 -40
  15. package/subscriptions/error.js +50 -27
  16. package/subscriptions/helpers/pipeline.js +68 -0
  17. package/subscriptions/router.js +2 -2
  18. package/action-creators/app/spec.js +0 -96
  19. package/action-creators/client/spec.js +0 -44
  20. package/action-creators/menu/spec.js +0 -37
  21. package/action-creators/modal/spec.js +0 -26
  22. package/action-creators/page/spec.js +0 -38
  23. package/action-creators/url/spec.js +0 -45
  24. package/action-creators/user/spec.js +0 -186
  25. package/components/Backdrop/spec.js +0 -24
  26. package/components/Button/spec.js +0 -42
  27. package/components/Checkbox/spec.js +0 -111
  28. package/components/CountdownTimer/spec.js +0 -141
  29. package/components/Drawer/spec.js +0 -79
  30. package/components/Ellipsis/spec.js +0 -15
  31. package/components/EmbeddedMedia/spec.js +0 -61
  32. package/components/Grid/components/Item/spec.js +0 -24
  33. package/components/Grid/spec.js +0 -24
  34. package/components/HtmlSanitizer/spec.js +0 -229
  35. package/components/I18n/components/FormatDate/spec.js +0 -54
  36. package/components/I18n/components/FormatNumber/spec.js +0 -51
  37. package/components/I18n/components/FormatPrice/spec.js +0 -54
  38. package/components/I18n/components/FormatTime/spec.js +0 -51
  39. package/components/I18n/components/I18nProvider/spec.js +0 -40
  40. package/components/I18n/components/Placeholder/spec.js +0 -37
  41. package/components/I18n/components/Translate/spec.js +0 -33
  42. package/components/InfiniteContainer/spec.js +0 -204
  43. package/components/Input/spec.js +0 -123
  44. package/components/Link/spec.js +0 -60
  45. package/components/List/spec.js +0 -26
  46. package/components/ModalContainer/spec.js +0 -115
  47. package/components/Select/spec.js +0 -122
  48. package/components/SelectBox/spec.js +0 -68
  49. package/components/Swiper/components/SwiperItem/spec.js +0 -26
  50. package/components/Widgets/components/Widget/spec.js +0 -75
  51. package/components/Widgets/components/WidgetGrid/spec.js +0 -53
  52. package/components/Widgets/spec.js +0 -234
  53. package/helpers/data/spec.js +0 -194
  54. package/helpers/date/spec.js +0 -92
  55. package/helpers/style/spec.js +0 -108
  56. package/helpers/validation/spec.js +0 -10
  57. package/styles/reset/form.js +0 -58
  58. package/styles/reset/index.js +0 -8
  59. package/styles/reset/media.js +0 -26
  60. package/styles/reset/root.js +0 -37
  61. package/styles/reset/table.js +0 -14
  62. package/styles/reset/typography.js +0 -30
  63. package/tsconfig.build.json +0 -16
  64. package/tsconfig.json +0 -3
@@ -1,68 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { mount } from 'enzyme';
4
- import SelectBox from "./index";
5
-
6
- /**
7
- * Mock Icon component.
8
- * @returns {JSX}
9
- */
10
- import { jsx as _jsx } from "react/jsx-runtime";
11
- const MockIconComponent = () => /*#__PURE__*/_jsx("span", {
12
- id: "icon"
13
- });
14
-
15
- /**
16
- * Mock Item component.
17
- * @param {Object} props The components props.
18
- * @param {JSX} props.children The components children.
19
- * @returns {JSX}
20
- */
21
- const MockItemComponent = ({
22
- children
23
- }) => /*#__PURE__*/_jsx("div", {
24
- children: children
25
- });
26
- describe('<SelectBox>', () => {
27
- const dummyItems = [{
28
- label: 'My item #1',
29
- value: 'item_1'
30
- }, {
31
- label: 'My item #2',
32
- value: 'item_2'
33
- }, {
34
- label: 'My item #3',
35
- value: 'item_3'
36
- }];
37
- it('should render the selectbox with given mock components', () => {
38
- const wrapper = mount(/*#__PURE__*/_jsx(SelectBox, {
39
- icon: MockIconComponent,
40
- item: MockItemComponent,
41
- items: dummyItems
42
- }));
43
- expect(wrapper).toMatchSnapshot();
44
- expect(wrapper.find(MockIconComponent).length).toEqual(1);
45
- expect(wrapper.find(MockItemComponent).length).toEqual(3);
46
- });
47
- it('should render with a default text', () => {
48
- const wrapper = mount(/*#__PURE__*/_jsx(SelectBox, {
49
- icon: MockIconComponent,
50
- item: MockItemComponent,
51
- items: dummyItems,
52
- defaultText: "Foo"
53
- }));
54
- expect(wrapper).toMatchSnapshot();
55
- expect(wrapper.find('span').at(0).text()).toEqual('Foo');
56
- });
57
- it('should render with a preselected selection', () => {
58
- const wrapper = mount(/*#__PURE__*/_jsx(SelectBox, {
59
- icon: MockIconComponent,
60
- item: MockItemComponent,
61
- items: dummyItems,
62
- defaultText: "Foo",
63
- initialValue: "item_2"
64
- }));
65
- expect(wrapper).toMatchSnapshot();
66
- expect(wrapper.find('span').at(0).text()).toEqual('My item #2');
67
- });
68
- });
@@ -1,26 +0,0 @@
1
- import React from 'react';
2
- import { shallow } from 'enzyme';
3
- import { CLASS_PREFIX } from '@shopgate/engage/styles/tss';
4
- import SwiperItem from '.';
5
- import { jsx as _jsx } from "react/jsx-runtime";
6
- jest.mock('react', () => ({
7
- ...jest.requireActual('react'),
8
- useLayoutEffect: jest.requireActual('react').useEffect
9
- }));
10
- describe('<SwiperItem />', () => {
11
- it('should not render without children', () => {
12
- const wrapper = shallow(/*#__PURE__*/_jsx(SwiperItem, {
13
- children: /*#__PURE__*/_jsx("div", {})
14
- }));
15
- expect(wrapper).toMatchSnapshot();
16
- expect(wrapper.html()).toMatch(new RegExp(`^<div class="swiper-slide ${CLASS_PREFIX}-[^"]+" data-test-id="Slider"><div></div></div>$`));
17
- });
18
- it('should add custom className', () => {
19
- const wrapper = shallow(/*#__PURE__*/_jsx(SwiperItem, {
20
- className: "test",
21
- children: /*#__PURE__*/_jsx("div", {})
22
- }));
23
- expect(wrapper).toMatchSnapshot();
24
- expect(wrapper.html()).toMatch(new RegExp(`^<div class="swiper-slide ${CLASS_PREFIX}-[^"]+ test" data-test-id="Slider"><div></div></div>$`));
25
- });
26
- });
@@ -1,75 +0,0 @@
1
- import React from 'react';
2
- import { mount } from 'enzyme';
3
- import Grid from "../../../Grid";
4
- import Widget from "./index";
5
- import { jsx as _jsx } from "react/jsx-runtime";
6
- jest.mock('react', () => {
7
- const actual = jest.requireActual('react');
8
- return {
9
- ...actual,
10
- memo: c => c,
11
- Suspense: function Suspense({
12
- children
13
- }) {
14
- return children;
15
- }
16
- };
17
- });
18
-
19
- /**
20
- * A dummy component.
21
- * @returns {JSX}
22
- */
23
- const MyComponent = () => /*#__PURE__*/_jsx("div", {});
24
- const widgets = {
25
- '@shopgate/commerce-widgets/image': MyComponent
26
- };
27
- describe('<Widget />', () => {
28
- it('should render an image widget', () => {
29
- const config = {
30
- type: '@shopgate/commerce-widgets/image',
31
- col: 1,
32
- row: 1,
33
- width: 12,
34
- height: 6
35
- };
36
- const wrapper = mount(/*#__PURE__*/_jsx(Widget, {
37
- config: config,
38
- component: widgets[config.type]
39
- }));
40
- expect(wrapper).toMatchSnapshot();
41
- expect(wrapper.find(Grid.Item).exists()).toBe(true);
42
- });
43
- it('should render an image widget with offset', () => {
44
- const config = {
45
- type: '@shopgate/commerce-widgets/image',
46
- col: 1,
47
- row: 1,
48
- width: 6,
49
- height: 6
50
- };
51
- const wrapper = mount(/*#__PURE__*/_jsx(Widget, {
52
- config: config,
53
- component: widgets[config.type],
54
- cellSize: 100
55
- }));
56
- expect(wrapper).toMatchSnapshot();
57
- expect(wrapper.find(Grid.Item).exists()).toBe(true);
58
- });
59
- it('should not render when the `type` prop is invalid', () => {
60
- const config = {
61
- type: 'some_widget',
62
- // Invalid
63
- col: 1,
64
- row: 1,
65
- width: 12,
66
- height: 6
67
- };
68
- const wrapper = mount(/*#__PURE__*/_jsx(Widget, {
69
- config: config,
70
- component: widgets[config.type]
71
- }));
72
- expect(wrapper).toMatchSnapshot();
73
- expect(wrapper.find(Grid.Item).exists()).toBe(false);
74
- });
75
- });
@@ -1,53 +0,0 @@
1
- import React from 'react';
2
- import { mount } from 'enzyme';
3
- import WidgetGrid from "./index";
4
- import { jsx as _jsx } from "react/jsx-runtime";
5
- jest.mock('react', () => {
6
- const actual = jest.requireActual('react');
7
- return {
8
- ...actual,
9
- memo: c => c,
10
- Suspense: function Suspense({
11
- children
12
- }) {
13
- return children;
14
- }
15
- };
16
- });
17
-
18
- /**
19
- * A mock Image component.
20
- * @returns {JSX}
21
- */
22
- const Image = () => /*#__PURE__*/_jsx("div", {});
23
- const components = {
24
- '@shopgate/commerce-widgets/image': Image
25
- };
26
- describe('<WidgetGrid />', () => {
27
- it('should render with a config', () => {
28
- const config = [{
29
- col: 0,
30
- row: 0,
31
- width: 12,
32
- height: 3,
33
- settings: {
34
- id: 83535,
35
- image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg'
36
- },
37
- type: '@shopgate/commerce-widgets/image'
38
- }];
39
- const wrapper = mount(/*#__PURE__*/_jsx(WidgetGrid, {
40
- config: config,
41
- components: components
42
- }));
43
- expect(wrapper).toMatchSnapshot();
44
- expect(wrapper.find(Image).length).toEqual(1);
45
- });
46
- it('should not render without a `config` prop', () => {
47
- const wrapper = mount(/*#__PURE__*/_jsx(WidgetGrid, {
48
- components: components
49
- }));
50
- expect(wrapper).toMatchSnapshot();
51
- expect(wrapper.find(Image).length).toEqual(0);
52
- });
53
- });
@@ -1,234 +0,0 @@
1
- import React from 'react';
2
- import { mount } from 'enzyme';
3
- import { ThemeResourcesProvider } from '@shopgate/engage/core/providers';
4
- import Widgets from "./index";
5
- import { jsx as _jsx } from "react/jsx-runtime";
6
- jest.useFakeTimers();
7
- jest.mock('@shopgate/pwa-common/context', () => ({
8
- ThemeContext: {
9
- Provider: ({
10
- children
11
- }) => children
12
- }
13
- }));
14
-
15
- /**
16
- * A mock Image component.
17
- * @returns {JSX}
18
- */
19
- const Image = () => /*#__PURE__*/_jsx("img", {
20
- alt: ""
21
- });
22
- /* eslint-disable react/prop-types */
23
- /**
24
- * A mock WidgetGrid component.
25
- * @param {Array} children Array of children.
26
- * @returns {JSX}
27
- */
28
- const WidgetGrid = ({
29
- children
30
- }) => /*#__PURE__*/_jsx("div", {
31
- className: "widget-grid",
32
- children: children
33
- });
34
- /* eslint-enable react/prop-types */
35
-
36
- const components = {
37
- v1: {
38
- '@shopgate/commerce-widgets/image': Image,
39
- '@shopgate/commerce-widgets/widget-grid': WidgetGrid
40
- }
41
- };
42
-
43
- /**
44
- * @param {Object[]} widgets Widgets to be rendered.
45
- * @returns {JSX.Element}
46
- */
47
- const createWrapper = widgets => mount(/*#__PURE__*/_jsx(ThemeResourcesProvider, {
48
- widgets: components,
49
- components: {},
50
- children: /*#__PURE__*/_jsx(Widgets, {
51
- widgets: widgets
52
- })
53
- }));
54
- describe('<Widgets />', () => {
55
- it('should render a grid if height is defined', () => {
56
- const widgets = [{
57
- col: 0,
58
- row: 0,
59
- width: 12,
60
- height: 3,
61
- settings: {
62
- id: 83535,
63
- image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg'
64
- },
65
- type: '@shopgate/commerce-widgets/image'
66
- }];
67
- const wrapper = createWrapper(widgets);
68
- expect(wrapper.find('WidgetGrid').exists()).toBe(true);
69
- });
70
- it('should not wrap a widget which is not a grid and has no height', () => {
71
- const widgets = [{
72
- col: 0,
73
- row: 0,
74
- width: 12,
75
- settings: {
76
- id: 83535,
77
- image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg'
78
- },
79
- type: '@shopgate/commerce-widgets/image'
80
- }];
81
- const wrapper = createWrapper(widgets);
82
- expect(wrapper).toMatchSnapshot();
83
- expect(wrapper.find('WidgetGrid').exists()).toBe(false);
84
- });
85
- it('should render a grid if the widget is of type grid', () => {
86
- const widgets = [{
87
- type: '@shopgate/commerce-widgets/widget-grid',
88
- settings: {
89
- widgets: [{
90
- col: 0,
91
- row: 0,
92
- width: 12,
93
- height: 5,
94
- settings: {
95
- id: '84961',
96
- alt: '',
97
- image: 'https://data.shopgate.com/shop_widget_images/23836/aedc545959f55e3f73851eca0ed40a75.min.jpeg',
98
- link: '/category/'
99
- },
100
- type: '@shopgate/commerce-widgets/image'
101
- }]
102
- }
103
- }];
104
- const wrapper = createWrapper(widgets);
105
- expect(wrapper).toMatchSnapshot();
106
- expect(wrapper.find('WidgetGrid').exists()).toBe(true);
107
- });
108
- it('should render only one widget when the second one is not published and third one is invalid', () => {
109
- const widgets = [{
110
- col: 0,
111
- row: 0,
112
- width: 12,
113
- settings: {
114
- id: 835351,
115
- image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg'
116
- },
117
- type: '@shopgate/commerce-widgets/image'
118
- }, {
119
- col: 0,
120
- row: 0,
121
- width: 12,
122
- settings: {
123
- id: 835352,
124
- image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg'
125
- },
126
- type: '@shopgate/commerce-widgets/imagefoo'
127
- }, {
128
- col: 0,
129
- row: 0,
130
- width: 12,
131
- settings: {
132
- published: false,
133
- id: 835353,
134
- image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg'
135
- },
136
- type: '@shopgate/commerce-widgets/image'
137
- }];
138
- const wrapper = createWrapper(widgets);
139
- expect(wrapper).toMatchSnapshot();
140
- expect(wrapper.find('img').length).toBe(1);
141
- });
142
- it('should schedule a re-render when widget is scheduled', () => {
143
- // Use a fixed point in time so "next full hour" is deterministic.
144
- // Pick a time that's not exactly on the hour.
145
- const base = new Date('2023-01-01T10:37:00.000Z');
146
- jest.setSystemTime(base);
147
- const minutesToNextFullHour = 60 - base.getMinutes(); // 23
148
- const msToNextFullHour = minutesToNextFullHour * 60000; // 23 * 60_000
149
-
150
- const scheduledFromMs = Date.now() + msToNextFullHour - 1;
151
- const scheduledToMs = Date.now() + minutesToNextFullHour + 1000;
152
- const widgets = [{
153
- col: 0,
154
- row: 0,
155
- width: 12,
156
- settings: {
157
- id: 835351,
158
- image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg',
159
- published: true,
160
- plan: true,
161
- planDate: {
162
- valid_from: new Date(scheduledFromMs).toISOString(),
163
- valid_to: new Date(scheduledToMs).toISOString()
164
- }
165
- },
166
- type: '@shopgate/commerce-widgets/image'
167
- }];
168
- const wrapper = createWrapper(widgets);
169
- const instance = wrapper.find('Widgets').instance();
170
- const clearSpy = jest.spyOn(global, 'clearTimeout');
171
- instance.forceUpdate = jest.fn();
172
-
173
- // Before the schedule hits, the image should not render yet.
174
- expect(wrapper.find(Image).exists()).toBe(false);
175
-
176
- // 1) Advance to the next full hour -> first forced update.
177
- jest.advanceTimersByTime(msToNextFullHour);
178
- expect(instance.forceUpdate).toHaveBeenCalledTimes(1);
179
-
180
- // 2) The component should schedule the next tick for +60 min.
181
- jest.advanceTimersByTime(60 * 60000);
182
- expect(instance.forceUpdate).toHaveBeenCalledTimes(2);
183
-
184
- // Unmount triggers cleanup of any pending timeouts.
185
- wrapper.unmount();
186
- expect(clearSpy).toHaveBeenCalled();
187
- clearSpy.mockRestore();
188
- });
189
- it('should render only wrapper when widgets array is empty', () => {
190
- const widgets = [];
191
- const wrapper = createWrapper(widgets);
192
- expect(wrapper.find('Image').exists()).toBe(false);
193
- });
194
- it('should render null when no widgets are passed', () => {
195
- const wrapper = createWrapper(undefined);
196
- expect(wrapper.find('Widgets').html()).toBe(null);
197
- });
198
- it('should check settings of child widgets inside widget-grid', () => {
199
- const widgets = [{
200
- height: 2,
201
- id: 'index-5-@shopgate/commerce-widgets/widget-grid',
202
- type: '@shopgate/commerce-widgets/widget-grid',
203
- settings: {
204
- widgets: [{
205
- col: 0,
206
- row: 0,
207
- height: 2,
208
- width: 2,
209
- settings: {
210
- id: 835351,
211
- image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg',
212
- published: true,
213
- plan: false
214
- },
215
- type: '@shopgate/commerce-widgets/image'
216
- }, {
217
- col: 2,
218
- row: 0,
219
- height: 2,
220
- width: 2,
221
- settings: {
222
- id: 835352,
223
- image: 'https://data.shopgate.com/shop_widget_images/23836/92204c0f264ac30d6836994c2fb64eb1.min.jpeg',
224
- published: false,
225
- plan: false
226
- },
227
- type: '@shopgate/commerce-widgets/image'
228
- }]
229
- }
230
- }];
231
- const wrapper = createWrapper(widgets);
232
- expect(wrapper.find('img').length).toBe(1);
233
- });
234
- });
@@ -1,194 +0,0 @@
1
- import { assignObjectDeep } from '.';
2
- import { isObject } from "../validation";
3
- describe('helpers/data', () => {
4
- describe('assignObjectDeep', () => {
5
- it('should merge simple objects correctly', () => {
6
- const modifier = {
7
- b: 0,
8
- c: null,
9
- d: undefined,
10
- g: 1.7,
11
- h: 'g',
12
- i: {
13
- x: 'x'
14
- },
15
- j: ['a', 'b']
16
- };
17
-
18
- // Object to be mutated
19
- const actual = {
20
- a: 0,
21
- b: 1,
22
- c: 'abc',
23
- d: 'def',
24
- e: 'ghi',
25
- f: null,
26
- g: 1.6
27
- };
28
- assignObjectDeep(actual, modifier, false);
29
- expect(actual).toEqual({
30
- a: 0,
31
- b: 0,
32
- c: null,
33
- d: undefined,
34
- e: 'ghi',
35
- f: null,
36
- g: 1.7,
37
- h: 'g',
38
- i: {
39
- x: 'x'
40
- },
41
- j: ['a', 'b']
42
- });
43
- });
44
- it('should merge objects containing sub-objects correctly', () => {
45
- const modifier = {
46
- a: {
47
- x: 2,
48
- y: {
49
- i: 'first mod',
50
- k: 'new entry'
51
- }
52
- },
53
- b: 'c',
54
- c: undefined,
55
- d: {
56
- x: 'x'
57
- },
58
- e: ['a', 'b']
59
- };
60
-
61
- // Object to be mutated
62
- const actual = {
63
- a: {
64
- x: 1,
65
- y: {
66
- i: 'first',
67
- j: 'second'
68
- }
69
- },
70
- b: {
71
- x: 2,
72
- y: {
73
- i: 'first',
74
- j: 'second'
75
- }
76
- }
77
- };
78
- assignObjectDeep(actual, modifier, false);
79
- expect(actual).toEqual({
80
- a: {
81
- x: 2,
82
- y: {
83
- i: 'first mod',
84
- j: 'second',
85
- k: 'new entry'
86
- }
87
- },
88
- b: 'c',
89
- c: undefined,
90
- d: {
91
- x: 'x'
92
- },
93
- e: ['a', 'b']
94
- });
95
- });
96
- it('should merge objects containing arrays correctly', () => {
97
- /**
98
- * This comparator detects unique scalar types and objects containing an id
99
- * within the 'a' prop
100
- *
101
- * @param {string} path path
102
- * @param {*} prev prev
103
- * @param {*} next next
104
- * @returns {boolean}
105
- */
106
- const comparator = (path, prev, next) => {
107
- // Scalar types
108
- if (!isObject(prev) || !isObject(next)) {
109
- return prev === next;
110
- }
111
-
112
- // Object merge only occurring on array object-items within the 'a' prop
113
- if (path.startsWith('$.a.')) {
114
- return prev.id === next.id;
115
- }
116
- return false;
117
- };
118
- const modifier = {
119
- b: [1, 2, 3],
120
- a: [['non-unique1', 'non-unique1'], 'unique element', 2, {
121
- id: 'custom-id-2',
122
- data: {
123
- x: null,
124
- y: {
125
- i: 'first',
126
- j: 'second mod',
127
- k: 'third'
128
- },
129
- z: 'new data entry'
130
- }
131
- }, {
132
- id: 'custom-id-3',
133
- data: {
134
- x: 'a'
135
- }
136
- }]
137
- };
138
-
139
- // Object to be mutated
140
- const actual = {
141
- a: [1, 'unique element', {
142
- id: 'custom-id-1',
143
- data: {
144
- x: 1,
145
- y: {
146
- i: 'first',
147
- j: 'second'
148
- }
149
- }
150
- }, {
151
- id: 'custom-id-2',
152
- data: {
153
- x: 1,
154
- y: {
155
- i: 'first',
156
- j: 'second'
157
- }
158
- }
159
- }, ['non-unique1', 'non-unique1']],
160
- b: [0]
161
- };
162
- assignObjectDeep(actual, modifier, false, comparator, '$');
163
- expect(actual).toEqual({
164
- a: [1, 'unique element', {
165
- id: 'custom-id-1',
166
- data: {
167
- x: 1,
168
- y: {
169
- i: 'first',
170
- j: 'second'
171
- }
172
- }
173
- }, {
174
- id: 'custom-id-2',
175
- data: {
176
- x: null,
177
- y: {
178
- i: 'first',
179
- j: 'second mod',
180
- k: 'third'
181
- },
182
- z: 'new data entry'
183
- }
184
- }, ['non-unique1', 'non-unique1'], ['non-unique1', 'non-unique1'], 2, {
185
- id: 'custom-id-3',
186
- data: {
187
- x: 'a'
188
- }
189
- }],
190
- b: [0, 1, 2, 3]
191
- });
192
- });
193
- });
194
- });