@shopgate/pwa-ui-material 7.32.0-beta.2 → 7.32.0-beta.21
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.
- package/AppBar/components/Title/index.js +8 -6
- package/BaseDialog/components/Buttons/index.js +4 -3
- package/SnackBar/index.js +92 -29
- package/package.json +2 -2
- package/Accordion/components/AccordionContent/spec.js +0 -37
- package/Accordion/spec.js +0 -41
- package/BaseDialog/components/Buttons/spec.js +0 -29
- package/BaseDialog/components/Content/spec.js +0 -18
- package/BaseDialog/components/Title/spec.js +0 -18
- package/BaseDialog/spec.js +0 -44
- package/NavDrawer/components/Divider/spec.js +0 -10
- package/NavDrawer/spec.js +0 -139
- package/tsconfig.build.json +0 -16
- package/tsconfig.json +0 -3
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { Typography } from '@shopgate/engage/components';
|
|
4
4
|
import { makeStyles } from '@shopgate/engage/styles';
|
|
5
|
+
import htmlToText from '@shopgate/pwa-common/helpers/html/htmlToText';
|
|
5
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
7
|
const useStyles = makeStyles()({
|
|
7
8
|
root: {
|
|
@@ -25,7 +26,10 @@ const AppBarTitle = ({
|
|
|
25
26
|
classes,
|
|
26
27
|
cx
|
|
27
28
|
} = useStyles();
|
|
28
|
-
|
|
29
|
+
// Titles can contain HTML entities (e.g. product names). They are decoded to plain text, since
|
|
30
|
+
// titles might originate from untrusted sources like URL parameters and must not render as HTML.
|
|
31
|
+
const text = useMemo(() => htmlToText(title), [title]);
|
|
32
|
+
if (!text) {
|
|
29
33
|
return null;
|
|
30
34
|
}
|
|
31
35
|
return /*#__PURE__*/_jsx(Typography, {
|
|
@@ -36,15 +40,13 @@ const AppBarTitle = ({
|
|
|
36
40
|
role: "heading",
|
|
37
41
|
"aria-labelledby": "titleLabel",
|
|
38
42
|
"aria-level": "1",
|
|
39
|
-
"data-test-id": `title: ${
|
|
43
|
+
"data-test-id": `title: ${text}`,
|
|
40
44
|
tabIndex: -1,
|
|
41
45
|
children: /*#__PURE__*/_jsx("span", {
|
|
42
46
|
role: "presentation",
|
|
43
47
|
onClick: onClick,
|
|
44
48
|
id: "titleLabel",
|
|
45
|
-
|
|
46
|
-
__html: title
|
|
47
|
-
}
|
|
49
|
+
children: text
|
|
48
50
|
})
|
|
49
51
|
});
|
|
50
52
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { memo } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import { I18n
|
|
3
|
+
import { I18n } from '@shopgate/engage/components';
|
|
4
|
+
import { Button } from '@shopgate/engage/components/v2';
|
|
4
5
|
import { makeStyles } from '@shopgate/engage/styles';
|
|
5
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
7
|
const useStyles = makeStyles()(theme => ({
|
|
@@ -27,8 +28,8 @@ const Buttons = ({
|
|
|
27
28
|
disabled = false
|
|
28
29
|
}) => /*#__PURE__*/_jsx(Button, {
|
|
29
30
|
className: classes.button,
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
variant: "text",
|
|
32
|
+
color: "secondary",
|
|
32
33
|
onClick: action,
|
|
33
34
|
disabled: disabled,
|
|
34
35
|
children: /*#__PURE__*/_jsx(I18n.Text, {
|
package/SnackBar/index.js
CHANGED
|
@@ -4,9 +4,17 @@ import { config } from 'react-spring';
|
|
|
4
4
|
import { Spring } from 'react-spring/renderprops.cjs';
|
|
5
5
|
import Ellipsis from '@shopgate/pwa-common/components/Ellipsis';
|
|
6
6
|
import { i18n } from '@shopgate/engage/core/helpers';
|
|
7
|
+
import { useLongPress } from '@shopgate/engage/core/hooks/events';
|
|
8
|
+
import { Button } from '@shopgate/engage/components/v2';
|
|
7
9
|
import { makeStyles } from '@shopgate/engage/styles';
|
|
8
10
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
11
|
const defaultToast = {};
|
|
12
|
+
|
|
13
|
+
// Approximate settle time of the slide-out (config.stiff). The current toast is removed from the
|
|
14
|
+
// queue this long after it starts sliding out, so the exit animation is fully visible before the
|
|
15
|
+
// next toast slides in. Timer-driven removal keeps queue advancement independent of the spring's
|
|
16
|
+
// onRest callback, which fires unreliably during the toast-to-toast handoff.
|
|
17
|
+
const EXIT_ANIMATION_MS = 500;
|
|
10
18
|
const useStyles = makeStyles()(theme => ({
|
|
11
19
|
container: {
|
|
12
20
|
position: 'fixed',
|
|
@@ -48,12 +56,8 @@ const useStyles = makeStyles()(theme => ({
|
|
|
48
56
|
overflow: 'hidden'
|
|
49
57
|
},
|
|
50
58
|
actionButton: {
|
|
51
|
-
color: theme.palette.secondary.main,
|
|
52
|
-
fontWeight: theme.typography.fontWeightMedium,
|
|
53
|
-
height: 36,
|
|
54
|
-
letterSpacing: 'inherit',
|
|
55
59
|
margin: '0 -8px 0 8px',
|
|
56
|
-
|
|
60
|
+
minWidth: 0,
|
|
57
61
|
padding: '0 8px',
|
|
58
62
|
textTransform: 'uppercase'
|
|
59
63
|
}
|
|
@@ -88,48 +92,106 @@ const SnackBar = ({
|
|
|
88
92
|
cx
|
|
89
93
|
} = useStyles();
|
|
90
94
|
const toasts = useMemo(() => toastsProp || [], [toastsProp]);
|
|
95
|
+
const current = toasts.length ? toasts[0] : null;
|
|
96
|
+
const currentId = current ? current.id : null;
|
|
91
97
|
const [visible, setVisible] = useState(true);
|
|
92
|
-
const
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
const autoHideTimer = useRef(null);
|
|
99
|
+
const exitTimer = useRef(null);
|
|
100
|
+
const pressingRef = useRef(false);
|
|
101
|
+
|
|
102
|
+
// Latest values reachable from the stable timer callbacks below without re-creating them.
|
|
103
|
+
const durationRef = useRef();
|
|
104
|
+
durationRef.current = current && current.duration || 2500;
|
|
105
|
+
const removeToastRef = useRef(removeToast);
|
|
106
|
+
removeToastRef.current = removeToast;
|
|
107
|
+
|
|
108
|
+
// Show whenever there is a toast to display; hide when the queue drains. Reacting to the queue
|
|
109
|
+
// length is what slides the next toast in after the current one has been removed.
|
|
97
110
|
useEffect(() => {
|
|
98
111
|
setVisible(toasts.length > 0);
|
|
99
112
|
}, [toasts.length]);
|
|
113
|
+
useEffect(() => () => {
|
|
114
|
+
clearTimeout(autoHideTimer.current);
|
|
115
|
+
clearTimeout(exitTimer.current);
|
|
116
|
+
}, []);
|
|
100
117
|
const snack = useMemo(() => {
|
|
101
|
-
const raw =
|
|
118
|
+
const raw = current || defaultToast;
|
|
102
119
|
return {
|
|
103
120
|
...raw,
|
|
104
121
|
message: i18n.text(raw.message || '', raw.messageParams || {}),
|
|
105
122
|
actionLabel: i18n.text(raw.actionLabel || '')
|
|
106
123
|
};
|
|
107
|
-
}, [
|
|
124
|
+
}, [current]);
|
|
125
|
+
|
|
126
|
+
// Slide the current toast out, then advance the queue once the exit animation has played. The
|
|
127
|
+
// removal is timer-driven (not the spring's onRest), so it fires exactly once for the toast being
|
|
128
|
+
// dismissed and can't be re-triggered by the spring re-settling as the next toast slides in.
|
|
108
129
|
const hide = useCallback(() => {
|
|
109
|
-
clearTimeout(
|
|
130
|
+
clearTimeout(autoHideTimer.current);
|
|
131
|
+
clearTimeout(exitTimer.current);
|
|
110
132
|
setVisible(false);
|
|
133
|
+
exitTimer.current = setTimeout(() => removeToastRef.current(), EXIT_ANIMATION_MS);
|
|
111
134
|
}, []);
|
|
135
|
+
|
|
136
|
+
// (Re)starts the auto-hide countdown. Stable identity (reads the duration via a ref), so the
|
|
137
|
+
// effect below only re-runs when the shown toast actually changes.
|
|
138
|
+
const scheduleAutoHide = useCallback(() => {
|
|
139
|
+
clearTimeout(autoHideTimer.current);
|
|
140
|
+
autoHideTimer.current = setTimeout(hide, durationRef.current);
|
|
141
|
+
}, [hide]);
|
|
142
|
+
|
|
143
|
+
// Start the countdown once per shown toast, keyed on its id — NOT on the spring's onRest. With
|
|
144
|
+
// `force`, onRest fires on every re-render, so scheduling the auto-hide there restarted the
|
|
145
|
+
// countdown on each render and could keep a toast on screen far longer than its duration.
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
if (!currentId) {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
scheduleAutoHide();
|
|
151
|
+
return () => clearTimeout(autoHideTimer.current);
|
|
152
|
+
}, [currentId, scheduleAutoHide]);
|
|
112
153
|
const handleAction = useCallback(() => {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
154
|
+
current?.action?.();
|
|
155
|
+
hide();
|
|
156
|
+
}, [current, hide]);
|
|
157
|
+
const handleLongPress = useCallback(() => {
|
|
158
|
+
pressingRef.current = false;
|
|
159
|
+
if (snack.onLongPress) {
|
|
160
|
+
snack.onLongPress();
|
|
116
161
|
}
|
|
117
162
|
hide();
|
|
118
|
-
}, [
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
163
|
+
}, [snack, hide]);
|
|
164
|
+
|
|
165
|
+
// While a long press is held, freeze the auto-hide countdown so the toast can't disappear
|
|
166
|
+
// mid-press. A press released before the threshold resumes the countdown from the start.
|
|
167
|
+
const handlePressStart = useCallback(() => {
|
|
168
|
+
pressingRef.current = true;
|
|
169
|
+
clearTimeout(autoHideTimer.current);
|
|
170
|
+
}, []);
|
|
171
|
+
const handlePressCancel = useCallback(() => {
|
|
172
|
+
pressingRef.current = false;
|
|
173
|
+
if (currentId) {
|
|
174
|
+
scheduleAutoHide();
|
|
125
175
|
}
|
|
126
|
-
}, [
|
|
176
|
+
}, [currentId, scheduleAutoHide]);
|
|
177
|
+
const longPressHandlers = useLongPress(handleLongPress, {
|
|
178
|
+
threshold: 4000,
|
|
179
|
+
onStart: handlePressStart,
|
|
180
|
+
onCancel: handlePressCancel
|
|
181
|
+
});
|
|
127
182
|
const {
|
|
128
183
|
action = null,
|
|
129
184
|
actionLabel = null,
|
|
130
|
-
message = null
|
|
185
|
+
message = null,
|
|
186
|
+
onLongPress = null
|
|
131
187
|
} = snack;
|
|
132
|
-
|
|
188
|
+
|
|
189
|
+
// A toast is either long-pressable or has a whole-box click action — never both. Attaching both
|
|
190
|
+
// would let a single long press fire onLongPress (at the threshold) and then handleAction (on the
|
|
191
|
+
// release click). Long-press takes precedence.
|
|
192
|
+
const boxProps = onLongPress ? {
|
|
193
|
+
...longPressHandlers
|
|
194
|
+
} : {
|
|
133
195
|
...(action && !actionLabel && {
|
|
134
196
|
onClick: handleAction
|
|
135
197
|
})
|
|
@@ -151,7 +213,6 @@ const SnackBar = ({
|
|
|
151
213
|
config: config.stiff,
|
|
152
214
|
reverse: !visible,
|
|
153
215
|
force: true,
|
|
154
|
-
onRest: handleRest,
|
|
155
216
|
children: springProps =>
|
|
156
217
|
/*#__PURE__*/
|
|
157
218
|
// eslint-disable-next-line max-len
|
|
@@ -172,10 +233,12 @@ const SnackBar = ({
|
|
|
172
233
|
role: "status",
|
|
173
234
|
children: message
|
|
174
235
|
})
|
|
175
|
-
}), action && actionLabel && /*#__PURE__*/_jsx(
|
|
236
|
+
}), action && actionLabel && /*#__PURE__*/_jsx(Button, {
|
|
176
237
|
className: classes.actionButton,
|
|
238
|
+
variant: "text",
|
|
239
|
+
size: "small",
|
|
240
|
+
color: "secondary",
|
|
177
241
|
onClick: handleAction,
|
|
178
|
-
type: "button",
|
|
179
242
|
"aria-hidden": true,
|
|
180
243
|
children: actionLabel
|
|
181
244
|
})]
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopgate/pwa-ui-material",
|
|
3
|
-
"version": "7.32.0-beta.
|
|
3
|
+
"version": "7.32.0-beta.21",
|
|
4
4
|
"description": "Shopgate's material design UI components.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"devDependencies": {
|
|
8
|
-
"@shopgate/pwa-common": "7.32.0-beta.
|
|
8
|
+
"@shopgate/pwa-common": "7.32.0-beta.21",
|
|
9
9
|
"@types/color": "^4.2.0",
|
|
10
10
|
"@types/react-transition-group": "^4.4.12",
|
|
11
11
|
"react": "^17.0.2",
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { mount } from 'enzyme';
|
|
3
|
-
import AccordionContent from "./index";
|
|
4
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
-
jest.mock('react-spring', () => ({
|
|
6
|
-
...jest.requireActual('react-spring'),
|
|
7
|
-
useSpring: jest.fn().mockReturnValue({
|
|
8
|
-
hook: 'useSpring return value'
|
|
9
|
-
})
|
|
10
|
-
}));
|
|
11
|
-
describe('<AccordionContent />', () => {
|
|
12
|
-
it('should render as closed', () => {
|
|
13
|
-
const wrapper = mount(/*#__PURE__*/_jsx(AccordionContent, {
|
|
14
|
-
id: "some-id",
|
|
15
|
-
children: /*#__PURE__*/_jsx("div", {
|
|
16
|
-
id: "test",
|
|
17
|
-
children: "Some Child"
|
|
18
|
-
})
|
|
19
|
-
}));
|
|
20
|
-
expect(wrapper.find('#test').text()).toEqual('Some Child');
|
|
21
|
-
expect(wrapper.find('div').get(0).props['aria-hidden']).toEqual(true);
|
|
22
|
-
expect(wrapper).toMatchSnapshot();
|
|
23
|
-
});
|
|
24
|
-
it('should render as open', () => {
|
|
25
|
-
const wrapper = mount(/*#__PURE__*/_jsx(AccordionContent, {
|
|
26
|
-
open: true,
|
|
27
|
-
id: "some-id",
|
|
28
|
-
children: /*#__PURE__*/_jsx("div", {
|
|
29
|
-
id: "test",
|
|
30
|
-
children: "Some Child"
|
|
31
|
-
})
|
|
32
|
-
}));
|
|
33
|
-
expect(wrapper.find('#test').text()).toEqual('Some Child');
|
|
34
|
-
expect(wrapper.find('div').get(0).props['aria-hidden']).toEqual(false);
|
|
35
|
-
expect(wrapper).toMatchSnapshot();
|
|
36
|
-
});
|
|
37
|
-
});
|
package/Accordion/spec.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { mount } from 'enzyme';
|
|
3
|
-
import Accordion from "./index";
|
|
4
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
-
jest.unmock('@shopgate/pwa-ui-shared');
|
|
6
|
-
jest.mock('@shopgate/engage/components');
|
|
7
|
-
jest.mock('react-spring', () => ({
|
|
8
|
-
...jest.requireActual('react-spring'),
|
|
9
|
-
useSpring: jest.fn().mockReturnValue({
|
|
10
|
-
hook: 'useSpring return value'
|
|
11
|
-
})
|
|
12
|
-
}));
|
|
13
|
-
describe('<Accordion />', () => {
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
jest.clearAllMocks();
|
|
16
|
-
});
|
|
17
|
-
it('should render with renderLabel prop and children', () => {
|
|
18
|
-
const wrapper = mount(/*#__PURE__*/_jsx(Accordion, {
|
|
19
|
-
renderLabel: () => /*#__PURE__*/_jsx("div", {}),
|
|
20
|
-
testId: "Some Thing",
|
|
21
|
-
children: "Some content."
|
|
22
|
-
}));
|
|
23
|
-
expect(wrapper).toMatchSnapshot();
|
|
24
|
-
expect(wrapper.find('AccordionContent').exists()).toBe(true);
|
|
25
|
-
});
|
|
26
|
-
it('should not render without a renderLabel prop', () => {
|
|
27
|
-
const wrapper = mount(/*#__PURE__*/_jsx(Accordion, {
|
|
28
|
-
testId: "Some Thing"
|
|
29
|
-
}));
|
|
30
|
-
expect(wrapper).toMatchSnapshot();
|
|
31
|
-
expect(wrapper.instance()).toEqual(null);
|
|
32
|
-
});
|
|
33
|
-
it('should not render without children', () => {
|
|
34
|
-
const wrapper = mount(/*#__PURE__*/_jsx(Accordion, {
|
|
35
|
-
renderLabel: () => {},
|
|
36
|
-
testId: "Some Thing"
|
|
37
|
-
}));
|
|
38
|
-
expect(wrapper).toMatchSnapshot();
|
|
39
|
-
expect(wrapper.instance()).toEqual(null);
|
|
40
|
-
});
|
|
41
|
-
});
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { shallow } from 'enzyme';
|
|
3
|
-
import Button from '@shopgate/pwa-ui-shared/Button';
|
|
4
|
-
import Buttons from "./index";
|
|
5
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
|
-
const actions = [{
|
|
7
|
-
label: 'action0',
|
|
8
|
-
action: jest.fn()
|
|
9
|
-
}, {
|
|
10
|
-
label: 'action1',
|
|
11
|
-
action: jest.fn()
|
|
12
|
-
}, {
|
|
13
|
-
label: 'action2',
|
|
14
|
-
action: jest.fn()
|
|
15
|
-
}];
|
|
16
|
-
describe('<Buttons />', () => {
|
|
17
|
-
it('should not render if no actions are passed', () => {
|
|
18
|
-
const wrapper = shallow(/*#__PURE__*/_jsx(Buttons, {}));
|
|
19
|
-
expect(wrapper).toMatchSnapshot();
|
|
20
|
-
expect(wrapper.instance()).toEqual(null);
|
|
21
|
-
});
|
|
22
|
-
it('should render buttons', () => {
|
|
23
|
-
const wrapper = shallow(/*#__PURE__*/_jsx(Buttons, {
|
|
24
|
-
actions: actions
|
|
25
|
-
}));
|
|
26
|
-
expect(wrapper).toMatchSnapshot();
|
|
27
|
-
expect(wrapper.find(Button).length).toBe(actions.length);
|
|
28
|
-
});
|
|
29
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { shallow } from 'enzyme';
|
|
3
|
-
import Content from "./index";
|
|
4
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
-
describe('<Content />', () => {
|
|
6
|
-
it('should not render if no content is passed', () => {
|
|
7
|
-
const wrapper = shallow(/*#__PURE__*/_jsx(Content, {}));
|
|
8
|
-
expect(wrapper).toMatchSnapshot();
|
|
9
|
-
expect(wrapper.instance()).toEqual(null);
|
|
10
|
-
});
|
|
11
|
-
it('should render content components', () => {
|
|
12
|
-
const wrapper = shallow(/*#__PURE__*/_jsx(Content, {
|
|
13
|
-
content: "Hello World"
|
|
14
|
-
}));
|
|
15
|
-
expect(wrapper).toMatchSnapshot();
|
|
16
|
-
expect(wrapper.find('[id="basicDialogDesc"]').length).toBe(1);
|
|
17
|
-
});
|
|
18
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { shallow } from 'enzyme';
|
|
3
|
-
import Title from "./index";
|
|
4
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
-
describe('<Title />', () => {
|
|
6
|
-
it('should not render without a title', () => {
|
|
7
|
-
const wrapper = shallow(/*#__PURE__*/_jsx(Title, {}));
|
|
8
|
-
expect(wrapper).toMatchSnapshot();
|
|
9
|
-
expect(wrapper.instance()).toEqual(null);
|
|
10
|
-
});
|
|
11
|
-
it('should render with a title', () => {
|
|
12
|
-
const wrapper = shallow(/*#__PURE__*/_jsx(Title, {
|
|
13
|
-
title: "Some test title"
|
|
14
|
-
}));
|
|
15
|
-
expect(wrapper).toMatchSnapshot();
|
|
16
|
-
expect(wrapper.find('[id="basicDialogTitle"]').length).toBe(1);
|
|
17
|
-
});
|
|
18
|
-
});
|
package/BaseDialog/spec.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { shallow } from 'enzyme';
|
|
3
|
-
import Title from "./components/Title";
|
|
4
|
-
import Content from "./components/Content";
|
|
5
|
-
import Buttons from "./components/Buttons";
|
|
6
|
-
import BasicDialog from "./index";
|
|
7
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
-
const props = {
|
|
9
|
-
title: 'Hello World',
|
|
10
|
-
children: /*#__PURE__*/_jsx("div", {
|
|
11
|
-
children: "Hello World"
|
|
12
|
-
}),
|
|
13
|
-
actions: [{
|
|
14
|
-
label: 'action0',
|
|
15
|
-
action: jest.fn()
|
|
16
|
-
}, {
|
|
17
|
-
label: 'action1',
|
|
18
|
-
action: jest.fn()
|
|
19
|
-
}, {
|
|
20
|
-
label: 'action2',
|
|
21
|
-
action: jest.fn()
|
|
22
|
-
}]
|
|
23
|
-
};
|
|
24
|
-
jest.mock('@shopgate/engage/a11y/components');
|
|
25
|
-
describe('<BasicDialog />', () => {
|
|
26
|
-
it('should render with minimal props', () => {
|
|
27
|
-
const wrapper = shallow(/*#__PURE__*/_jsx(BasicDialog, {
|
|
28
|
-
actions: []
|
|
29
|
-
}));
|
|
30
|
-
expect(wrapper).toMatchSnapshot();
|
|
31
|
-
});
|
|
32
|
-
it('should render as expected', () => {
|
|
33
|
-
const wrapper = shallow(/*#__PURE__*/_jsx(BasicDialog, {
|
|
34
|
-
...props
|
|
35
|
-
}));
|
|
36
|
-
expect(wrapper).toMatchSnapshot();
|
|
37
|
-
expect(wrapper.find(Title).length).toBe(1);
|
|
38
|
-
expect(wrapper.find(Title).props().title).toEqual(props.title);
|
|
39
|
-
expect(wrapper.find(Content).length).toBe(1);
|
|
40
|
-
expect(wrapper.find(Content).props().content).toEqual(props.children);
|
|
41
|
-
expect(wrapper.find(Buttons).length).toBe(1);
|
|
42
|
-
expect(wrapper.find(Buttons).props().actions).toEqual(props.actions);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { mount } from 'enzyme';
|
|
3
|
-
import Divider from "./index";
|
|
4
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
-
describe('<NavDrawerDivider />', () => {
|
|
6
|
-
it('should match the snapshot', () => {
|
|
7
|
-
const wrapper = mount(/*#__PURE__*/_jsx(Divider, {}));
|
|
8
|
-
expect(wrapper).toMatchSnapshot();
|
|
9
|
-
});
|
|
10
|
-
});
|
package/NavDrawer/spec.js
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import "core-js/modules/es.array.reduce.js";
|
|
2
|
-
/* eslint-disable global-require, extra-rules/no-single-line-objects */
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { shallow, mount } from 'enzyme';
|
|
5
|
-
import { act } from 'react-dom/test-utils';
|
|
6
|
-
import Transition from 'react-transition-group/Transition';
|
|
7
|
-
jest.unmock('@shopgate/pwa-core');
|
|
8
|
-
jest.mock('@shopgate/engage/styles', () => ({
|
|
9
|
-
makeStyles: () => function mockUseStylesFactory(defs) {
|
|
10
|
-
return function useStylesMock() {
|
|
11
|
-
const keys = Object.keys(defs);
|
|
12
|
-
const classes = keys.reduce((acc, key) => {
|
|
13
|
-
acc[key] = `mock-class-${key}`;
|
|
14
|
-
return acc;
|
|
15
|
-
}, {});
|
|
16
|
-
const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
17
|
-
return {
|
|
18
|
-
classes,
|
|
19
|
-
cx
|
|
20
|
-
};
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
}));
|
|
24
|
-
jest.mock('@shopgate/engage/components', () => {
|
|
25
|
-
const mockReact = require('react');
|
|
26
|
-
const mockPropTypes = require('prop-types');
|
|
27
|
-
function Backdrop(props) {
|
|
28
|
-
const {
|
|
29
|
-
isVisible,
|
|
30
|
-
onClick
|
|
31
|
-
} = props;
|
|
32
|
-
if (!isVisible) {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
return mockReact.createElement('button', {
|
|
36
|
-
type: 'button',
|
|
37
|
-
'aria-label': 'Close',
|
|
38
|
-
'data-test-id': 'NavDrawerBackdrop',
|
|
39
|
-
onClick
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
Backdrop.propTypes = {
|
|
43
|
-
isVisible: mockPropTypes.bool,
|
|
44
|
-
onClick: mockPropTypes.func
|
|
45
|
-
};
|
|
46
|
-
Backdrop.defaultProps = {
|
|
47
|
-
isVisible: false,
|
|
48
|
-
onClick: undefined
|
|
49
|
-
};
|
|
50
|
-
Backdrop.displayName = 'Backdrop';
|
|
51
|
-
return {
|
|
52
|
-
Backdrop
|
|
53
|
-
};
|
|
54
|
-
});
|
|
55
|
-
jest.mock('@shopgate/engage/a11y/components', () => {
|
|
56
|
-
const mockPropTypes = require('prop-types');
|
|
57
|
-
function ModalStateTracker(props) {
|
|
58
|
-
return props.children;
|
|
59
|
-
}
|
|
60
|
-
ModalStateTracker.propTypes = {
|
|
61
|
-
children: mockPropTypes.node
|
|
62
|
-
};
|
|
63
|
-
ModalStateTracker.defaultProps = {
|
|
64
|
-
children: null
|
|
65
|
-
};
|
|
66
|
-
return {
|
|
67
|
-
ModalStateTracker
|
|
68
|
-
};
|
|
69
|
-
});
|
|
70
|
-
jest.mock("./components/Item", () => {
|
|
71
|
-
const mockReact = require('react');
|
|
72
|
-
const mockPropTypes = require('prop-types');
|
|
73
|
-
const ItemWithRef = mockReact.forwardRef((props, ref) => mockReact.createElement('button', {
|
|
74
|
-
type: 'button',
|
|
75
|
-
ref,
|
|
76
|
-
'data-test-id': 'nav-drawer-item'
|
|
77
|
-
}, props.label));
|
|
78
|
-
ItemWithRef.propTypes = {
|
|
79
|
-
label: mockPropTypes.string
|
|
80
|
-
};
|
|
81
|
-
ItemWithRef.defaultProps = {
|
|
82
|
-
label: ''
|
|
83
|
-
};
|
|
84
|
-
return {
|
|
85
|
-
__esModule: true,
|
|
86
|
-
default: ItemWithRef
|
|
87
|
-
};
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
// eslint-disable-next-line import/first
|
|
91
|
-
import NavDrawer from "./index";
|
|
92
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
93
|
-
describe('NavDrawer', () => {
|
|
94
|
-
it('should match the snapshot', () => {
|
|
95
|
-
const wrapper = shallow(/*#__PURE__*/_jsx(NavDrawer, {
|
|
96
|
-
children: "Content"
|
|
97
|
-
}));
|
|
98
|
-
expect(wrapper).toMatchSnapshot();
|
|
99
|
-
});
|
|
100
|
-
it('should open and close with an event', () => {
|
|
101
|
-
const onOpen = jest.fn();
|
|
102
|
-
const onClose = jest.fn();
|
|
103
|
-
const wrapper = mount(/*#__PURE__*/_jsx(NavDrawer, {
|
|
104
|
-
onOpen: onOpen,
|
|
105
|
-
onClose: onClose,
|
|
106
|
-
children: "Content"
|
|
107
|
-
}));
|
|
108
|
-
act(() => {
|
|
109
|
-
NavDrawer.open();
|
|
110
|
-
});
|
|
111
|
-
wrapper.update();
|
|
112
|
-
expect(wrapper.find(Transition).prop('in')).toEqual(true);
|
|
113
|
-
expect(onOpen).toHaveBeenCalled();
|
|
114
|
-
expect(onClose).not.toHaveBeenCalled();
|
|
115
|
-
act(() => {
|
|
116
|
-
NavDrawer.close();
|
|
117
|
-
});
|
|
118
|
-
wrapper.update();
|
|
119
|
-
expect(wrapper.find(Transition).prop('in')).toEqual(false);
|
|
120
|
-
expect(onClose).toHaveBeenCalled();
|
|
121
|
-
});
|
|
122
|
-
it('should close when Backdrop is clicked', () => {
|
|
123
|
-
const wrapper = mount(/*#__PURE__*/_jsx(NavDrawer, {
|
|
124
|
-
children: "Content"
|
|
125
|
-
}));
|
|
126
|
-
act(() => {
|
|
127
|
-
NavDrawer.open();
|
|
128
|
-
});
|
|
129
|
-
wrapper.update();
|
|
130
|
-
expect(wrapper.find(Transition).prop('in')).toEqual(true);
|
|
131
|
-
const backdrop = wrapper.find('[data-test-id="NavDrawerBackdrop"]');
|
|
132
|
-
act(() => {
|
|
133
|
-
backdrop.simulate('click');
|
|
134
|
-
});
|
|
135
|
-
wrapper.update();
|
|
136
|
-
expect(wrapper.find(Transition).prop('in')).toEqual(false);
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
/* eslint-enable global-require, extra-rules/no-single-line-objects */
|
package/tsconfig.build.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "@shopgate/engage/tsconfig.build.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"outDir": "./dist",
|
|
5
|
-
"rootDir": "."
|
|
6
|
-
},
|
|
7
|
-
"include": ["**/*.ts", "**/*.tsx"],
|
|
8
|
-
"exclude": [
|
|
9
|
-
"dist",
|
|
10
|
-
"node_modules",
|
|
11
|
-
"**/*.spec.*",
|
|
12
|
-
"**/__tests__/**",
|
|
13
|
-
"**/__snapshots__/**",
|
|
14
|
-
"coverage"
|
|
15
|
-
]
|
|
16
|
-
}
|
package/tsconfig.json
DELETED