@transferwise/components 46.34.0 → 46.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.js +170 -192
- package/build/index.js.map +1 -1
- package/build/index.mjs +164 -186
- package/build/index.mjs.map +1 -1
- package/build/types/accordion/AccordionItem/AccordionItem.d.ts.map +1 -1
- package/build/types/common/hooks/useMedia.d.ts.map +1 -1
- package/build/types/common/panel/Panel.d.ts.map +1 -1
- package/build/types/common/responsivePanel/ResponsivePanel.d.ts.map +1 -1
- package/build/types/dimmer/Dimmer.d.ts +1 -11
- package/build/types/dimmer/Dimmer.d.ts.map +1 -1
- package/build/types/drawer/Drawer.d.ts +4 -4
- package/build/types/index.d.ts +3 -2
- package/build/types/index.d.ts.map +1 -1
- package/build/types/inputs/SelectInput.d.ts.map +1 -1
- package/build/types/modal/Modal.d.ts.map +1 -1
- package/build/types/processIndicator/ProcessIndicator.d.ts +36 -19
- package/build/types/processIndicator/ProcessIndicator.d.ts.map +1 -1
- package/build/types/processIndicator/index.d.ts +2 -2
- package/build/types/processIndicator/index.d.ts.map +1 -1
- package/build/types/promoCard/PromoCard.d.ts.map +1 -1
- package/build/types/select/searchBox/SearchBox.d.ts +1 -1
- package/build/types/snackbar/Snackbar.d.ts +0 -1
- package/build/types/snackbar/Snackbar.d.ts.map +1 -1
- package/build/types/test-utils/wait.d.ts +2 -0
- package/build/types/test-utils/wait.d.ts.map +1 -0
- package/build/types/tooltip/Tooltip.d.ts +1 -1
- package/build/types/tooltip/Tooltip.d.ts.map +1 -1
- package/build/types/uploadInput/uploadItem/UploadItem.d.ts.map +1 -1
- package/build/types/withDisplayFormat/WithDisplayFormat.d.ts.map +1 -1
- package/package.json +11 -15
- package/src/accordion/AccordionItem/AccordionItem.tsx +2 -4
- package/src/avatarWrapper/AvatarWrapper.story.tsx +1 -3
- package/src/button/Button.tsx +1 -1
- package/src/common/hooks/useConditionalListener/useConditionalListener.spec.js +1 -1
- package/src/common/hooks/useHasIntersected/useHasIntersected.spec.js +3 -3
- package/src/common/hooks/useMedia.spec.ts +1 -1
- package/src/common/hooks/useMedia.ts +1 -2
- package/src/common/panel/Panel.tsx +90 -92
- package/src/common/responsivePanel/ResponsivePanel.tsx +34 -38
- package/src/dateLookup/DateLookup.rtl.spec.tsx +181 -5
- package/src/dateLookup/DateLookup.testingLibrary.spec.js +171 -124
- package/src/drawer/Drawer.js +3 -3
- package/src/field/Field.tsx +3 -3
- package/src/index.ts +3 -2
- package/src/inputs/SelectInput.story.tsx +3 -2
- package/src/inputs/SelectInput.tsx +10 -2
- package/src/modal/Modal.tsx +1 -2
- package/src/processIndicator/ProcessIndicator.rtl.spec.tsx +45 -0
- package/src/processIndicator/ProcessIndicator.tsx +110 -0
- package/src/promoCard/PromoCard.tsx +1 -2
- package/src/radio/__snapshots__/Radio.rtl.spec.tsx.snap +0 -1
- package/src/snackbar/Snackbar.spec.js +8 -2
- package/src/snackbar/Snackbar.story.tsx +3 -1
- package/src/snackbar/Snackbar.tsx +1 -1
- package/src/tabs/Tabs.spec.js +46 -27
- package/src/test-utils/index.js +5 -7
- package/src/test-utils/jest.setup.js +9 -3
- package/src/test-utils/wait.ts +7 -0
- package/src/tooltip/Tooltip.tsx +44 -46
- package/src/tooltip/__snapshots__/Tooltip.spec.tsx.snap +2 -2
- package/src/upload/Upload.spec.js +34 -13
- package/src/uploadInput/UploadInput.spec.tsx +21 -23
- package/src/uploadInput/uploadItem/UploadItem.tsx +1 -3
- package/src/withDisplayFormat/WithDisplayFormat.spec.js +63 -32
- package/src/withDisplayFormat/WithDisplayFormat.tsx +4 -6
- package/src/dateLookup/DateLookup.keyboardEvents.spec.js +0 -180
- package/src/processIndicator/ProcessIndicator.js +0 -117
- package/src/processIndicator/ProcessIndicator.spec.js +0 -101
- /package/src/processIndicator/{index.js → index.ts} +0 -0
|
@@ -38,109 +38,107 @@ export type PanelProps = PropsWithChildren<{
|
|
|
38
38
|
}> &
|
|
39
39
|
HTMLAttributes<HTMLDivElement>;
|
|
40
40
|
|
|
41
|
-
const Panel = forwardRef<HTMLDivElement, PanelProps>(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
|
|
41
|
+
const Panel = forwardRef<HTMLDivElement, PanelProps>(function Panel(
|
|
42
|
+
{
|
|
43
|
+
arrow = false,
|
|
44
|
+
flip = true,
|
|
45
|
+
altAxis = false,
|
|
46
|
+
children,
|
|
47
|
+
open = false,
|
|
48
|
+
onClose,
|
|
49
|
+
position = Position.BOTTOM,
|
|
50
|
+
anchorRef,
|
|
51
|
+
anchorWidth = false,
|
|
52
|
+
...rest
|
|
53
|
+
}: PanelProps,
|
|
54
|
+
reference,
|
|
55
|
+
) {
|
|
56
|
+
const [arrowElement, setArrowElement] = useState<HTMLDivElement | null>(null);
|
|
57
|
+
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
const modifiers = [];
|
|
61
60
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
61
|
+
if (altAxis) {
|
|
62
|
+
modifiers.push({
|
|
63
|
+
// https://popper.js.org/docs/v2/modifiers/prevent-overflow
|
|
64
|
+
name: 'preventOverflow',
|
|
65
|
+
options: {
|
|
66
|
+
altAxis: true,
|
|
67
|
+
tether: false,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
options: {
|
|
79
|
-
padding: 8, // 8px from the edges of the popper
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
});
|
|
83
|
-
// This lets you displace a popper element from its reference element.
|
|
84
|
-
modifiers.push({ name: 'offset', options: { offset: POPOVER_OFFSET } });
|
|
85
|
-
}
|
|
86
|
-
if (flip && fallbackPlacements[position]) {
|
|
87
|
-
modifiers.push({
|
|
88
|
-
name: 'flip',
|
|
72
|
+
if (arrow) {
|
|
73
|
+
modifiers.push({
|
|
74
|
+
name: 'arrow',
|
|
75
|
+
options: {
|
|
76
|
+
element: arrowElement,
|
|
89
77
|
options: {
|
|
90
|
-
|
|
78
|
+
padding: 8, // 8px from the edges of the popper
|
|
91
79
|
},
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const { styles, attributes, forceUpdate } = usePopper(anchorRef.current, popperElement, {
|
|
96
|
-
placement: position,
|
|
97
|
-
modifiers,
|
|
80
|
+
},
|
|
98
81
|
});
|
|
82
|
+
// This lets you displace a popper element from its reference element.
|
|
83
|
+
modifiers.push({ name: 'offset', options: { offset: POPOVER_OFFSET } });
|
|
84
|
+
}
|
|
85
|
+
if (flip && fallbackPlacements[position]) {
|
|
86
|
+
modifiers.push({
|
|
87
|
+
name: 'flip',
|
|
88
|
+
options: {
|
|
89
|
+
fallbackPlacements: fallbackPlacements[position],
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const { styles, attributes, forceUpdate } = usePopper(anchorRef.current, popperElement, {
|
|
95
|
+
placement: position,
|
|
96
|
+
modifiers,
|
|
97
|
+
});
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
// If the trigger is not visible when the position is calculated, it will be incorrect. Because this can happen repeatedly (on resize for example),
|
|
100
|
+
// it is most simple just to always position before opening
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
if (open && forceUpdate) {
|
|
103
|
+
forceUpdate();
|
|
104
|
+
}
|
|
105
|
+
}, [open]);
|
|
107
106
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
const contentStyle: CSSProperties = {
|
|
108
|
+
...(anchorWidth ? { width: anchorRef.current?.clientWidth } : undefined),
|
|
109
|
+
};
|
|
111
110
|
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
return (
|
|
112
|
+
<Dimmer open={open} transparent fadeContentOnEnter fadeContentOnExit onClose={onClose}>
|
|
113
|
+
<div
|
|
114
|
+
{...rest}
|
|
115
|
+
ref={setPopperElement}
|
|
116
|
+
role="dialog"
|
|
117
|
+
// eslint-disable-next-line react/forbid-dom-props
|
|
118
|
+
style={{ ...styles.popper }}
|
|
119
|
+
{...attributes.popper}
|
|
120
|
+
className={classnames('np-panel', { 'np-panel--open': open }, rest.className)}
|
|
121
|
+
>
|
|
114
122
|
<div
|
|
115
|
-
{
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
style={{ ...styles.popper }}
|
|
120
|
-
{...attributes.popper}
|
|
121
|
-
className={classnames('np-panel', { 'np-panel--open': open }, rest['className'])}
|
|
123
|
+
ref={reference}
|
|
124
|
+
/* eslint-disable-next-line react/forbid-dom-props */
|
|
125
|
+
style={contentStyle}
|
|
126
|
+
className={classnames('np-panel__content')}
|
|
122
127
|
>
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
ref={setArrowElement}
|
|
134
|
-
className={classnames('np-panel__arrow')}
|
|
135
|
-
// eslint-disable-next-line react/forbid-dom-props
|
|
136
|
-
style={styles.arrow}
|
|
137
|
-
/>
|
|
138
|
-
)}
|
|
139
|
-
</div>
|
|
128
|
+
{children}
|
|
129
|
+
{/* Arrow has to stay inside content to get the same animations as the "dialog" and to get hidden when panel is closed. */}
|
|
130
|
+
{arrow && (
|
|
131
|
+
<div
|
|
132
|
+
ref={setArrowElement}
|
|
133
|
+
className={classnames('np-panel__arrow')}
|
|
134
|
+
// eslint-disable-next-line react/forbid-dom-props
|
|
135
|
+
style={styles.arrow}
|
|
136
|
+
/>
|
|
137
|
+
)}
|
|
140
138
|
</div>
|
|
141
|
-
</
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
);
|
|
139
|
+
</div>
|
|
140
|
+
</Dimmer>
|
|
141
|
+
);
|
|
142
|
+
});
|
|
145
143
|
|
|
146
144
|
export default Panel;
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { useTheme } from '@wise/components-theming';
|
|
2
|
-
import classNames from 'classnames';
|
|
3
1
|
import { forwardRef } from 'react';
|
|
4
2
|
|
|
5
3
|
import { Position } from '..';
|
|
@@ -8,44 +6,42 @@ import { useLayout } from '../hooks';
|
|
|
8
6
|
import Panel from '../panel';
|
|
9
7
|
import { PanelProps } from '../panel/Panel';
|
|
10
8
|
|
|
11
|
-
const ResponsivePanel = forwardRef<HTMLDivElement, PanelProps>(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (isMobile) {
|
|
27
|
-
return (
|
|
28
|
-
<BottomSheet key="bottomSheet" open={open} className={className} onClose={onClose}>
|
|
29
|
-
{children}
|
|
30
|
-
</BottomSheet>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
9
|
+
const ResponsivePanel = forwardRef<HTMLDivElement, PanelProps>(function ResponsivePanel(
|
|
10
|
+
{
|
|
11
|
+
anchorRef,
|
|
12
|
+
arrow = false,
|
|
13
|
+
flip = true,
|
|
14
|
+
children,
|
|
15
|
+
className = undefined,
|
|
16
|
+
onClose,
|
|
17
|
+
open = false,
|
|
18
|
+
position = Position.BOTTOM,
|
|
19
|
+
}: PanelProps,
|
|
20
|
+
reference,
|
|
21
|
+
) {
|
|
22
|
+
const { isMobile } = useLayout();
|
|
23
|
+
if (isMobile) {
|
|
33
24
|
return (
|
|
34
|
-
<
|
|
35
|
-
key="panel"
|
|
36
|
-
ref={reference}
|
|
37
|
-
flip={flip}
|
|
38
|
-
arrow={arrow}
|
|
39
|
-
open={open}
|
|
40
|
-
position={position}
|
|
41
|
-
anchorRef={anchorRef}
|
|
42
|
-
className={className}
|
|
43
|
-
onClose={onClose}
|
|
44
|
-
>
|
|
25
|
+
<BottomSheet key="bottomSheet" open={open} className={className} onClose={onClose}>
|
|
45
26
|
{children}
|
|
46
|
-
</
|
|
27
|
+
</BottomSheet>
|
|
47
28
|
);
|
|
48
|
-
}
|
|
49
|
-
|
|
29
|
+
}
|
|
30
|
+
return (
|
|
31
|
+
<Panel
|
|
32
|
+
key="panel"
|
|
33
|
+
ref={reference}
|
|
34
|
+
flip={flip}
|
|
35
|
+
arrow={arrow}
|
|
36
|
+
open={open}
|
|
37
|
+
position={position}
|
|
38
|
+
anchorRef={anchorRef}
|
|
39
|
+
className={className}
|
|
40
|
+
onClose={onClose}
|
|
41
|
+
>
|
|
42
|
+
{children}
|
|
43
|
+
</Panel>
|
|
44
|
+
);
|
|
45
|
+
});
|
|
50
46
|
|
|
51
47
|
export default ResponsivePanel;
|
|
@@ -1,20 +1,196 @@
|
|
|
1
1
|
import { Field } from '../field/Field';
|
|
2
|
-
import { mockMatchMedia, mockResizeObserver, render, screen } from '../test-utils';
|
|
3
|
-
import DateLookup from './DateLookup';
|
|
2
|
+
import { mockMatchMedia, mockResizeObserver, render, screen, userEvent } from '../test-utils';
|
|
3
|
+
import DateLookup, { DateLookupProps } from './DateLookup';
|
|
4
|
+
|
|
5
|
+
import { act } from 'react';
|
|
4
6
|
|
|
5
7
|
mockMatchMedia();
|
|
6
8
|
mockResizeObserver();
|
|
7
9
|
|
|
8
|
-
const
|
|
10
|
+
const initialValue = new Date(2000, 0, 1);
|
|
9
11
|
|
|
10
12
|
describe('DateLookup', () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
jest.useFakeTimers();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterEach(async () => {
|
|
18
|
+
await jest.runOnlyPendingTimersAsync();
|
|
19
|
+
jest.useRealTimers();
|
|
20
|
+
});
|
|
21
|
+
|
|
11
22
|
it('supports `Field` for labeling', () => {
|
|
12
23
|
render(
|
|
13
24
|
<Field label="Date of birth">
|
|
14
|
-
<DateLookup value={
|
|
25
|
+
<DateLookup value={initialValue} onChange={() => {}} />
|
|
15
26
|
</Field>,
|
|
16
27
|
);
|
|
17
28
|
// TODO: Replace with `.toHaveAttribute('aria-haspopup')`
|
|
18
|
-
expect(screen.getByLabelText('Date of birth')).toHaveTextContent(
|
|
29
|
+
expect(screen.getByLabelText('Date of birth')).toHaveTextContent(
|
|
30
|
+
initialValue.getFullYear().toString(),
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it.each([' ', '{Enter}', '{ArrowDown}', '{ArrowUp}', '{ArrowRight}', '{ArrowLeft}'])(
|
|
35
|
+
"opens with '%s' and closes with '{Escape}'",
|
|
36
|
+
async (text) => {
|
|
37
|
+
render(<DateLookup value={initialValue} onChange={() => {}} />);
|
|
38
|
+
|
|
39
|
+
userEvent.tab();
|
|
40
|
+
userEvent.keyboard(text);
|
|
41
|
+
|
|
42
|
+
expect(screen.getByRole('button', { name: /next/iu })).toBeInTheDocument();
|
|
43
|
+
|
|
44
|
+
userEvent.keyboard('{Escape}');
|
|
45
|
+
await act(async () => {
|
|
46
|
+
await jest.runOnlyPendingTimersAsync();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
expect(screen.queryByRole('button', { name: /next/iu })).not.toBeInTheDocument();
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const setupAndOpenWithMouse = async (props: Partial<DateLookupProps> = {}) => {
|
|
54
|
+
const view = render(<DateLookup value={initialValue} onChange={() => {}} {...props} />);
|
|
55
|
+
|
|
56
|
+
userEvent.click(screen.getByRole('button'));
|
|
57
|
+
await act(async () => {
|
|
58
|
+
await jest.runOnlyPendingTimersAsync();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return view;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
it('opens and closes with mouse', async () => {
|
|
65
|
+
await setupAndOpenWithMouse();
|
|
66
|
+
|
|
67
|
+
expect(screen.getByRole('button', { name: /next/iu })).toBeInTheDocument();
|
|
68
|
+
|
|
69
|
+
const dimmerElement = screen.getByRole('dialog').parentElement?.parentElement;
|
|
70
|
+
if (dimmerElement != null) {
|
|
71
|
+
userEvent.click(dimmerElement);
|
|
72
|
+
}
|
|
73
|
+
await act(async () => {
|
|
74
|
+
await jest.runOnlyPendingTimersAsync();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
expect(screen.queryByRole('button', { name: /next/iu })).not.toBeInTheDocument();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe('in day view', () => {
|
|
81
|
+
it.each([
|
|
82
|
+
['{ArrowLeft}', -1],
|
|
83
|
+
['{ArrowRight}', +1],
|
|
84
|
+
['{ArrowUp}', -7],
|
|
85
|
+
['{ArrowDown}', +7],
|
|
86
|
+
])("handles '%s' to step %d day(s)", async (text, step) => {
|
|
87
|
+
const handleChange = jest.fn();
|
|
88
|
+
await setupAndOpenWithMouse({ onChange: handleChange });
|
|
89
|
+
|
|
90
|
+
expect(handleChange).not.toHaveBeenCalled();
|
|
91
|
+
|
|
92
|
+
userEvent.keyboard(text);
|
|
93
|
+
|
|
94
|
+
const value = new Date(initialValue);
|
|
95
|
+
value.setDate(initialValue.getDate() + step);
|
|
96
|
+
expect(handleChange).toHaveBeenCalledWith(value);
|
|
97
|
+
|
|
98
|
+
userEvent.keyboard('{Escape}');
|
|
99
|
+
await act(async () => {
|
|
100
|
+
await jest.runOnlyPendingTimersAsync();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
expect(handleChange).toHaveBeenCalledWith(initialValue);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('in year view', () => {
|
|
108
|
+
it.each([
|
|
109
|
+
['{ArrowLeft}', -1],
|
|
110
|
+
['{ArrowRight}', +1],
|
|
111
|
+
['{ArrowUp}', -4],
|
|
112
|
+
['{ArrowDown}', +4],
|
|
113
|
+
])("handles '%s' to step %d year(s)", async (text, step) => {
|
|
114
|
+
const handleChange = jest.fn();
|
|
115
|
+
await setupAndOpenWithMouse({ onChange: handleChange });
|
|
116
|
+
|
|
117
|
+
userEvent.click(screen.getByRole('button', { name: /year view/iu }));
|
|
118
|
+
await act(async () => {
|
|
119
|
+
await jest.runOnlyPendingTimersAsync();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
expect(handleChange).not.toHaveBeenCalled();
|
|
123
|
+
|
|
124
|
+
userEvent.keyboard(text);
|
|
125
|
+
|
|
126
|
+
const value = new Date(initialValue);
|
|
127
|
+
value.setFullYear(initialValue.getFullYear() + step);
|
|
128
|
+
expect(handleChange).toHaveBeenCalledWith(value);
|
|
129
|
+
|
|
130
|
+
userEvent.keyboard('{Escape}');
|
|
131
|
+
await act(async () => {
|
|
132
|
+
await jest.runOnlyPendingTimersAsync();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
expect(handleChange).toHaveBeenCalledWith(initialValue);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe('in month view', () => {
|
|
140
|
+
it.each([
|
|
141
|
+
['{ArrowLeft}', -1],
|
|
142
|
+
['{ArrowRight}', +1],
|
|
143
|
+
['{ArrowUp}', -4],
|
|
144
|
+
['{ArrowDown}', +4],
|
|
145
|
+
])("handles '%s' to step %d month(s)", async (text, step) => {
|
|
146
|
+
const handleChange = jest.fn();
|
|
147
|
+
await setupAndOpenWithMouse({ onChange: handleChange });
|
|
148
|
+
|
|
149
|
+
userEvent.click(screen.getByRole('button', { name: /year view/iu }));
|
|
150
|
+
await act(async () => {
|
|
151
|
+
await jest.runOnlyPendingTimersAsync();
|
|
152
|
+
});
|
|
153
|
+
userEvent.keyboard(' ');
|
|
154
|
+
await act(async () => {
|
|
155
|
+
await jest.runOnlyPendingTimersAsync();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
expect(handleChange).not.toHaveBeenCalled();
|
|
159
|
+
|
|
160
|
+
userEvent.keyboard(text);
|
|
161
|
+
|
|
162
|
+
const value = new Date(initialValue);
|
|
163
|
+
value.setMonth(initialValue.getMonth() + step);
|
|
164
|
+
expect(handleChange).toHaveBeenCalledWith(value);
|
|
165
|
+
|
|
166
|
+
userEvent.keyboard('{Escape}');
|
|
167
|
+
await act(async () => {
|
|
168
|
+
await jest.runOnlyPendingTimersAsync();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
expect(handleChange).toHaveBeenCalledWith(initialValue);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('limits min value', async () => {
|
|
176
|
+
const min = new Date(initialValue);
|
|
177
|
+
min.setDate(min.getDate() - 1);
|
|
178
|
+
const handleChange = jest.fn();
|
|
179
|
+
await setupAndOpenWithMouse({ min, onChange: handleChange });
|
|
180
|
+
|
|
181
|
+
userEvent.keyboard('{ArrowLeft}{ArrowLeft}');
|
|
182
|
+
|
|
183
|
+
expect(handleChange).toHaveBeenCalledWith(min);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('limits max value', async () => {
|
|
187
|
+
const max = new Date(initialValue);
|
|
188
|
+
max.setDate(max.getDate() + 1);
|
|
189
|
+
const handleChange = jest.fn();
|
|
190
|
+
await setupAndOpenWithMouse({ max, onChange: handleChange });
|
|
191
|
+
|
|
192
|
+
userEvent.keyboard('{ArrowRight}{ArrowRight}');
|
|
193
|
+
|
|
194
|
+
expect(handleChange).toHaveBeenCalledWith(max);
|
|
19
195
|
});
|
|
20
196
|
});
|