@transferwise/components 0.0.0-experimental-e3e9aac → 0.0.0-experimental-b795207

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 (70) hide show
  1. package/build/index.js +180 -197
  2. package/build/index.js.map +1 -1
  3. package/build/index.mjs +174 -191
  4. package/build/index.mjs.map +1 -1
  5. package/build/types/accordion/AccordionItem/AccordionItem.d.ts.map +1 -1
  6. package/build/types/common/hooks/useMedia.d.ts.map +1 -1
  7. package/build/types/common/panel/Panel.d.ts.map +1 -1
  8. package/build/types/common/responsivePanel/ResponsivePanel.d.ts.map +1 -1
  9. package/build/types/dimmer/Dimmer.d.ts +1 -11
  10. package/build/types/dimmer/Dimmer.d.ts.map +1 -1
  11. package/build/types/drawer/Drawer.d.ts +4 -4
  12. package/build/types/index.d.ts +3 -2
  13. package/build/types/index.d.ts.map +1 -1
  14. package/build/types/inputs/SelectInput.d.ts.map +1 -1
  15. package/build/types/modal/Modal.d.ts.map +1 -1
  16. package/build/types/processIndicator/ProcessIndicator.d.ts +36 -19
  17. package/build/types/processIndicator/ProcessIndicator.d.ts.map +1 -1
  18. package/build/types/processIndicator/index.d.ts +2 -2
  19. package/build/types/processIndicator/index.d.ts.map +1 -1
  20. package/build/types/promoCard/PromoCard.d.ts.map +1 -1
  21. package/build/types/select/searchBox/SearchBox.d.ts +1 -1
  22. package/build/types/snackbar/Snackbar.d.ts +1 -3
  23. package/build/types/snackbar/Snackbar.d.ts.map +1 -1
  24. package/build/types/test-utils/wait.d.ts +2 -0
  25. package/build/types/test-utils/wait.d.ts.map +1 -0
  26. package/build/types/tooltip/Tooltip.d.ts +1 -1
  27. package/build/types/tooltip/Tooltip.d.ts.map +1 -1
  28. package/build/types/uploadInput/uploadItem/UploadItem.d.ts.map +1 -1
  29. package/build/types/withDisplayFormat/WithDisplayFormat.d.ts.map +1 -1
  30. package/package.json +12 -16
  31. package/src/accordion/AccordionItem/AccordionItem.tsx +2 -4
  32. package/src/avatarWrapper/AvatarWrapper.story.tsx +1 -3
  33. package/src/button/Button.tsx +1 -1
  34. package/src/common/hooks/useConditionalListener/useConditionalListener.spec.js +1 -1
  35. package/src/common/hooks/useHasIntersected/useHasIntersected.spec.js +3 -3
  36. package/src/common/hooks/useMedia.spec.ts +1 -1
  37. package/src/common/hooks/useMedia.ts +1 -2
  38. package/src/common/panel/Panel.tsx +90 -92
  39. package/src/common/responsivePanel/ResponsivePanel.tsx +34 -38
  40. package/src/dateLookup/DateLookup.rtl.spec.tsx +181 -5
  41. package/src/dateLookup/DateLookup.testingLibrary.spec.js +171 -124
  42. package/src/drawer/Drawer.js +3 -3
  43. package/src/field/Field.tsx +3 -3
  44. package/src/index.ts +3 -2
  45. package/src/inputs/SelectInput.story.tsx +3 -2
  46. package/src/inputs/SelectInput.tsx +10 -2
  47. package/src/modal/Modal.tsx +1 -2
  48. package/src/processIndicator/ProcessIndicator.rtl.spec.tsx +45 -0
  49. package/src/processIndicator/ProcessIndicator.tsx +110 -0
  50. package/src/promoCard/PromoCard.tsx +1 -2
  51. package/src/radio/__snapshots__/Radio.rtl.spec.tsx.snap +0 -1
  52. package/src/snackbar/Snackbar.spec.js +112 -0
  53. package/src/snackbar/Snackbar.story.tsx +100 -18
  54. package/src/snackbar/Snackbar.tsx +13 -9
  55. package/src/tabs/Tabs.spec.js +46 -27
  56. package/src/test-utils/index.js +5 -7
  57. package/src/test-utils/jest.setup.js +9 -3
  58. package/src/test-utils/wait.ts +7 -0
  59. package/src/tooltip/Tooltip.tsx +44 -46
  60. package/src/tooltip/__snapshots__/Tooltip.spec.tsx.snap +2 -2
  61. package/src/upload/Upload.spec.js +34 -13
  62. package/src/uploadInput/UploadInput.spec.tsx +21 -23
  63. package/src/uploadInput/uploadItem/UploadItem.tsx +1 -3
  64. package/src/withDisplayFormat/WithDisplayFormat.spec.js +63 -32
  65. package/src/withDisplayFormat/WithDisplayFormat.tsx +4 -6
  66. package/src/dateLookup/DateLookup.keyboardEvents.spec.js +0 -180
  67. package/src/processIndicator/ProcessIndicator.js +0 -117
  68. package/src/processIndicator/ProcessIndicator.spec.js +0 -101
  69. package/src/snackbar/Snackbar.tests.story.tsx +0 -284
  70. /package/src/processIndicator/{index.js → index.ts} +0 -0
@@ -6,14 +6,14 @@ exports[`Tooltip Component renders an empty list when no items are passed 1`] =
6
6
  class="tw-tooltip-container"
7
7
  >
8
8
  <span
9
- aria-describedby="radix-0-tooltip"
9
+ aria-describedby=":r0:-tooltip"
10
10
  >
11
11
  Hover me
12
12
  </span>
13
13
  <div
14
14
  aria-hidden="true"
15
15
  class="np-tooltip np-panel"
16
- id="radix-0-tooltip"
16
+ id=":r0:-tooltip"
17
17
  role="tooltip"
18
18
  style="position: absolute; left: 0px; top: 0px;"
19
19
  >
@@ -1,4 +1,5 @@
1
1
  import { shallow, mount } from 'enzyme';
2
+ import { act } from 'react';
2
3
 
3
4
  import { ANIMATION_DURATION_IN_MS } from '../processIndicator';
4
5
 
@@ -6,7 +7,6 @@ import { CompleteStep, UploadImageStep, MediaUploadStep, ProcessingStep } from '
6
7
 
7
8
  import Upload from '.';
8
9
 
9
- jest.useFakeTimers();
10
10
  jest.mock('./utils/postData', () => ({
11
11
  postData: async () => 'ServerResponse',
12
12
  }));
@@ -15,12 +15,12 @@ jest.mock('./utils/asyncFileRead');
15
15
  const { asyncFileRead } = require('./utils/asyncFileRead');
16
16
 
17
17
  const defaultLocale = 'en-GB';
18
- const formatMessage = (id) => `${id}`;
18
+ const formatMessage = (id) => String(id);
19
19
  jest.mock('react-intl', () => ({
20
20
  injectIntl: (Component) =>
21
21
  function (props) {
22
22
  return (
23
- <Component {...props} intl={{ locale: defaultLocale, formatMessage: (id) => `${id}` }} />
23
+ <Component {...props} intl={{ locale: defaultLocale, formatMessage: (id) => String(id) }} />
24
24
  );
25
25
  },
26
26
  useIntl: () => ({ formatMessage }),
@@ -87,11 +87,14 @@ const COMPLETED_STEP_PROPS = {
87
87
  describe('Upload', () => {
88
88
  let component;
89
89
  beforeEach(() => {
90
+ jest.useFakeTimers();
90
91
  component = shallow(<Upload {...props} />).dive();
91
92
  asyncFileRead.mockImplementation(async () => 'a value');
92
93
  });
93
94
 
94
- afterEach(() => {
95
+ afterEach(async () => {
96
+ await jest.runOnlyPendingTimersAsync();
97
+ jest.useRealTimers();
95
98
  jest.clearAllMocks();
96
99
  jest.clearAllTimers();
97
100
  });
@@ -213,6 +216,14 @@ describe('Upload', () => {
213
216
  });
214
217
 
215
218
  describe('when file is processed', () => {
219
+ const waitForUpload = async () => {
220
+ for (let i = 0; i < 4; i += 1) {
221
+ await act(async () => {
222
+ await jest.runOnlyPendingTimersAsync();
223
+ });
224
+ }
225
+ };
226
+
216
227
  it('step changes from UploadImageStep to CompleteStep', async () => {
217
228
  component = mount(<Upload {...props} />);
218
229
  const upload = component.children();
@@ -220,8 +231,10 @@ describe('Upload', () => {
220
231
  expect(upload.find(ProcessingStep)).toHaveLength(0);
221
232
  expect(upload.find(CompleteStep)).toHaveLength(0);
222
233
 
223
- await upload.instance().fileDropped(TEST_FILE);
224
- jest.advanceTimersByTime(props.animationDelay + ANIMATION_DELAY);
234
+ await act(async () => {
235
+ await upload.instance().fileDropped(TEST_FILE);
236
+ });
237
+ await waitForUpload();
225
238
  component.update();
226
239
 
227
240
  expect(component.find(UploadImageStep)).toHaveLength(0);
@@ -236,8 +249,10 @@ describe('Upload', () => {
236
249
  throw 'An error';
237
250
  });
238
251
 
239
- await upload.instance().fileDropped(TEST_FILE);
240
- jest.advanceTimersByTime(props.animationDelay + ANIMATION_DELAY);
252
+ await act(async () => {
253
+ await upload.instance().fileDropped(TEST_FILE);
254
+ });
255
+ await waitForUpload();
241
256
  component.update();
242
257
 
243
258
  expect(component.find(CompleteStep).props()).toStrictEqual({
@@ -252,8 +267,10 @@ describe('Upload', () => {
252
267
  it('onSuccess is called with response when httpOptions are provided', async () => {
253
268
  component = mount(<Upload {...props} httpOptions={{ url: 'a-url' }} />).children();
254
269
 
255
- await component.instance().fileDropped(TEST_FILE);
256
- jest.advanceTimersByTime(props.animationDelay + ANIMATION_DELAY);
270
+ await act(async () => {
271
+ await component.instance().fileDropped(TEST_FILE);
272
+ });
273
+ await waitForUpload();
257
274
 
258
275
  expect(props.onSuccess).toHaveBeenCalledWith('ServerResponse', TEST_FILE.name);
259
276
  });
@@ -261,11 +278,15 @@ describe('Upload', () => {
261
278
  it('wont process new file while current process is in progress', async () => {
262
279
  component = mount(<Upload {...props} httpOptions={{ url: 'a-url' }} />).children();
263
280
 
264
- await component.instance().fileDropped(TEST_FILE);
265
- const result = await component.instance().fileDropped(TEST_FILE);
266
- jest.advanceTimersByTime(props.animationDelay + ANIMATION_DELAY);
281
+ await act(async () => {
282
+ await component.instance().fileDropped(TEST_FILE);
283
+ });
284
+ const result = await act(async () => component.instance().fileDropped(TEST_FILE));
267
285
 
268
286
  expect(result).toBe(false);
287
+
288
+ await waitForUpload();
289
+
269
290
  expect(props.onSuccess).toHaveBeenCalledTimes(1);
270
291
  });
271
292
  });
@@ -7,8 +7,7 @@ import { mockMatchMedia, render, screen, waitFor, waitForElementToBeRemoved } fr
7
7
  import UploadInput, { UploadInputProps } from './UploadInput';
8
8
  import { TEST_IDS as UPLOAD_BUTTON_TEST_IDS } from './uploadButton/UploadButton';
9
9
  import { TEST_IDS as UPLOAD_ITEM_TEST_IDS } from './uploadItem/UploadItem';
10
-
11
- const spiedDateObject = jest.spyOn(global, 'Date');
10
+ import { act } from 'react';
12
11
 
13
12
  mockMatchMedia();
14
13
 
@@ -42,43 +41,35 @@ describe('UploadInput', () => {
42
41
  render(<UploadInput {...customProps} />);
43
42
 
44
43
  beforeEach(() => {
45
- (spiedDateObject as jest.Mock).mockImplementation(() => ({
46
- getTime: jest.fn().mockReturnValue(Math.random()),
47
- }));
44
+ jest.useFakeTimers();
48
45
  });
49
46
 
50
- afterAll(() => {
51
- (spiedDateObject as jest.Mock).mockRestore();
47
+ afterEach(async () => {
48
+ await jest.runOnlyPendingTimersAsync();
49
+ jest.useRealTimers();
52
50
  });
53
51
 
54
52
  describe('single file upload', () => {
55
53
  it('should trigger onUploadFiles & onFilesChange with a single FormData entry containing `file` field', async () => {
56
- const mockTimeStampValue1 = '11111111';
57
- const mockTimeStampValue2 = '22222222';
58
- (spiedDateObject as jest.Mock).mockImplementation(() => ({
59
- getTime: jest
60
- .fn()
61
- .mockReturnValueOnce(mockTimeStampValue1)
62
- .mockReturnValueOnce(mockTimeStampValue2),
63
- }));
54
+ const date = Date.now();
55
+ jest.setSystemTime(date);
64
56
 
65
57
  const onFilesChange = jest.fn();
66
58
  renderComponent({ ...props, onFilesChange });
67
59
 
68
60
  const input = screen.getByTestId(UPLOAD_BUTTON_TEST_IDS.uploadInput);
69
61
  userEvent.upload(input, [pngFile, jpgFile]);
70
-
71
- await waitFor(() => {
72
- expect(props.onUploadFile).toHaveBeenCalledTimes(1);
62
+ await act(async () => {
63
+ await jest.runOnlyPendingTimersAsync();
73
64
  });
74
65
 
66
+ expect(props.onUploadFile).toHaveBeenCalledTimes(1);
75
67
  expect(onFilesChange).toHaveBeenCalledTimes(2);
76
68
  expect(onFilesChange).toHaveBeenNthCalledWith(1, [
77
69
  {
78
70
  filename: 'foo.png',
79
- id: `foo.png_3_${mockTimeStampValue1}`,
71
+ id: `foo.png_3_${date}`,
80
72
  status: 'pending',
81
- url: undefined,
82
73
  },
83
74
  ]);
84
75
 
@@ -150,6 +141,10 @@ describe('UploadInput', () => {
150
141
 
151
142
  const fileToDelete = screen.getAllByTestId(UPLOAD_ITEM_TEST_IDS.uploadItem)[0];
152
143
  within(fileToDelete).getByLabelText('Remove file', { exact: false }).click();
144
+ await act(async () => {
145
+ await jest.runOnlyPendingTimersAsync();
146
+ });
147
+
153
148
  screen.getByText('Remove').click();
154
149
 
155
150
  await waitForElementToBeRemoved(fileToDelete);
@@ -179,7 +174,7 @@ describe('UploadInput', () => {
179
174
  ]);
180
175
  });
181
176
 
182
- it('should delete file with failed state without modal confirmation', () => {
177
+ it('should delete file with failed state without modal confirmation', async () => {
183
178
  const files = [
184
179
  {
185
180
  id: 1,
@@ -197,6 +192,9 @@ describe('UploadInput', () => {
197
192
 
198
193
  const fileToDelete = screen.getAllByTestId(UPLOAD_ITEM_TEST_IDS.uploadItem)[0];
199
194
  within(fileToDelete).getByLabelText('Remove file', { exact: false }).click();
195
+ await act(async () => {
196
+ await jest.runOnlyPendingTimersAsync();
197
+ });
200
198
 
201
199
  expect(fileToDelete).not.toBeInTheDocument();
202
200
 
@@ -240,7 +238,7 @@ describe('UploadInput', () => {
240
238
  onUploadFile: mockOnUploadFileFn,
241
239
  });
242
240
 
243
- mockOnUploadFileFn.mockImplementation((formData: FormData) => {
241
+ mockOnUploadFileFn.mockImplementation(async (formData: FormData) => {
244
242
  const file = formData.get('file');
245
243
  return Promise.resolve({ file, id: Math.random() });
246
244
  });
@@ -268,7 +266,7 @@ describe('UploadInput', () => {
268
266
  onUploadFile: mockOnUploadFileFn,
269
267
  });
270
268
 
271
- mockOnUploadFileFn.mockImplementation((formData: FormData) => {
269
+ mockOnUploadFileFn.mockImplementation(async (formData: FormData) => {
272
270
  const file = formData.get('file');
273
271
  return Promise.resolve({ file, id: Math.random() });
274
272
  });
@@ -83,9 +83,7 @@ const UploadItem = ({
83
83
  };
84
84
 
85
85
  const getErrorMessage = () =>
86
- (typeof error === 'object' && error.message) ||
87
- error ||
88
- formatMessage(MESSAGES.uploadingFailed);
86
+ typeof error === 'object' ? error.message : error || formatMessage(MESSAGES.uploadingFailed);
89
87
 
90
88
  const getDescription = () => {
91
89
  if (error || status === Status.FAILED) {
@@ -1,4 +1,5 @@
1
1
  import { mount } from 'enzyme/build';
2
+ import { act } from 'react';
2
3
 
3
4
  import { HistoryNavigator } from '../common';
4
5
  import { fakeKeyDownEventForKey } from '../common/fakeEvents';
@@ -6,8 +7,6 @@ import { Input } from '../inputs/Input';
6
7
 
7
8
  import WithDisplayFormat from '.';
8
9
 
9
- jest.useFakeTimers();
10
-
11
10
  const REDO_EVENT = { ctrlKey: true, charCode: 'z', shiftKey: true, which: 90 };
12
11
  const UNDO_EVENT = { ctrlKey: true, charCode: 'z', which: 90 };
13
12
 
@@ -36,11 +35,13 @@ describe('InputWithTextFormat', () => {
36
35
  };
37
36
 
38
37
  beforeEach(() => {
38
+ jest.useFakeTimers();
39
39
  component = mountComponent(props);
40
40
  });
41
41
 
42
- afterEach(() => {
43
- jest.clearAllTimers();
42
+ afterEach(async () => {
43
+ await jest.runOnlyPendingTimersAsync();
44
+ jest.useRealTimers();
44
45
  });
45
46
 
46
47
  TESTS.forEach((test) => {
@@ -64,10 +65,12 @@ describe('InputWithTextFormat', () => {
64
65
  });
65
66
 
66
67
  describe('when Undo/Redo is preformed', () => {
67
- it(`goes back/forward in input value's history`, () => {
68
+ it(`goes back/forward in input value's history`, async () => {
68
69
  component.setProps({ displayPattern: '***' });
69
- component.setState({
70
- historyNavigator: new HistoryNavigator(['@', '@@', '@@@']),
70
+ await act(async () => {
71
+ component.setState({
72
+ historyNavigator: new HistoryNavigator(['@', '@@', '@@@']),
73
+ });
71
74
  });
72
75
 
73
76
  componentInput().simulate('keyDown', UNDO_EVENT);
@@ -136,8 +139,10 @@ describe('InputWithTextFormat', () => {
136
139
  expect(componentInput().props().value).toBe('12-3');
137
140
  });
138
141
 
139
- it(`performs an extra delete if next char is a separator`, () => {
140
- component.setState({ selectionStart: 3, selectionEnd: 3 });
142
+ it(`performs an extra delete if next char is a separator`, async () => {
143
+ await act(async () => {
144
+ component.setState({ selectionStart: 3, selectionEnd: 3 });
145
+ });
141
146
 
142
147
  componentInput().simulate('change', { target: { value: '123' } });
143
148
  expect(componentInput().props().value).toBe('13');
@@ -152,27 +157,41 @@ describe('InputWithTextFormat', () => {
152
157
  });
153
158
  });
154
159
 
155
- it(`when entered a char`, () => {
156
- component.setState({ selectionStart: 4, selectionEnd: 4 });
160
+ it(`when entered a char`, async () => {
161
+ await act(async () => {
162
+ component.setState({ selectionStart: 4, selectionEnd: 4 });
163
+ });
157
164
  componentInput().simulate('change', { target: { value: '13-4@' } });
158
- jest.runAllTimers();
165
+ await act(async () => {
166
+ await jest.runOnlyPendingTimersAsync();
167
+ });
159
168
  expect(component.state().selectionStart).toBe(5);
160
169
  });
161
170
 
162
- it(`when entered a char before a symbol`, () => {
163
- component.setState({ selectionStart: 2, selectionEnd: 2 });
171
+ it(`when entered a char before a symbol`, async () => {
172
+ await act(async () => {
173
+ component.setState({ selectionStart: 2, selectionEnd: 2 });
174
+ });
164
175
  componentInput().simulate('change', { target: { value: '13-@' } });
165
- jest.runAllTimers();
176
+ await act(async () => {
177
+ await jest.runOnlyPendingTimersAsync();
178
+ });
166
179
  expect(component.state().selectionStart).toBe(4);
167
180
  });
168
181
  //
169
- it(`when deleted a char before the symbol`, () => {
170
- component.setState({
171
- triggerEvent: { ...triggerEventA, key: 'Backspace' },
182
+ it(`when deleted a char before the symbol`, async () => {
183
+ await act(async () => {
184
+ component.setState({
185
+ triggerEvent: { ...triggerEventA, key: 'Backspace' },
186
+ });
187
+ });
188
+ await act(async () => {
189
+ component.setState({ selectionStart: 3, selectionEnd: 3 });
172
190
  });
173
- component.setState({ selectionStart: 3, selectionEnd: 3 });
174
191
  componentInput().simulate('change', { target: { value: '13-45-6' } });
175
- jest.runAllTimers();
192
+ await act(async () => {
193
+ await jest.runOnlyPendingTimersAsync();
194
+ });
176
195
  expect(component.state().selectionStart).toBe(1);
177
196
  });
178
197
 
@@ -187,26 +206,38 @@ describe('InputWithTextFormat', () => {
187
206
  expect(component.state().selectionStart).toBe(2);
188
207
  });
189
208
 
190
- it(`when pasted selection is entered after a symbol`, () => {
191
- component.setState({
192
- triggerType: 'Paste',
193
- pastedLength: 2,
209
+ it(`when pasted selection is entered after a symbol`, async () => {
210
+ await act(async () => {
211
+ component.setState({
212
+ triggerType: 'Paste',
213
+ pastedLength: 2,
214
+ });
194
215
  });
195
216
 
196
- component.setState({ selectionStart: 2, selectionEnd: 2 });
217
+ await act(async () => {
218
+ component.setState({ selectionStart: 2, selectionEnd: 2 });
219
+ });
197
220
  componentInput().simulate('change', { target: { value: '13-@@' } });
198
- jest.runAllTimers();
221
+ await act(async () => {
222
+ await jest.runOnlyPendingTimersAsync();
223
+ });
199
224
  expect(component.state().selectionStart).toBe(5);
200
225
  });
201
226
 
202
- it(`when pasted selection is entered before a symbol`, () => {
203
- component.setState({
204
- triggerType: 'Paste',
205
- pastedLength: 2,
227
+ it(`when pasted selection is entered before a symbol`, async () => {
228
+ await act(async () => {
229
+ component.setState({
230
+ triggerType: 'Paste',
231
+ pastedLength: 2,
232
+ });
233
+ });
234
+ await act(async () => {
235
+ component.setState({ selectionStart: 1, selectionEnd: 1 });
206
236
  });
207
- component.setState({ selectionStart: 1, selectionEnd: 1 });
208
237
  componentInput().simulate('change', { target: { value: '1@-@' } });
209
- jest.runAllTimers();
238
+ await act(async () => {
239
+ await jest.runOnlyPendingTimersAsync();
240
+ });
210
241
  expect(component.state().selectionStart).toBe(4);
211
242
  });
212
243
 
@@ -137,10 +137,9 @@ class WithDisplayFormat<T extends TextElementProps> extends Component<
137
137
  return 'Backspace';
138
138
  }
139
139
  return triggerEvent.key;
140
- } else {
141
- // triggerEvent can be null only in case of "autofilling" (via password manager extension or browser build-in one) events
142
- return 'Paste';
143
140
  }
141
+ // triggerEvent can be null only in case of "autofilling" (via password manager extension or browser build-in one) events
142
+ return 'Paste';
144
143
  };
145
144
 
146
145
  resetEvent = () => {
@@ -273,6 +272,7 @@ class WithDisplayFormat<T extends TextElementProps> extends Component<
273
272
  handleCursorPositioning = (action: string) => {
274
273
  const { displayPattern } = this.props;
275
274
  const { triggerEvent, selectionStart, selectionEnd, pastedLength } = this.state;
275
+ const target = triggerEvent?.currentTarget;
276
276
 
277
277
  const cursorPosition = getCursorPositionAfterKeystroke(
278
278
  action,
@@ -283,9 +283,7 @@ class WithDisplayFormat<T extends TextElementProps> extends Component<
283
283
  );
284
284
 
285
285
  setTimeout(() => {
286
- if (triggerEvent) {
287
- (triggerEvent.target as HTMLTextElement).setSelectionRange(cursorPosition, cursorPosition);
288
- }
286
+ target?.setSelectionRange(cursorPosition, cursorPosition);
289
287
  this.setState({ selectionStart: cursorPosition, selectionEnd: cursorPosition });
290
288
  }, 0);
291
289
  };
@@ -1,180 +0,0 @@
1
- /* eslint-disable jest/expect-expect */
2
- import { mount } from 'enzyme';
3
-
4
- import { fakeKeyDownEventForKey } from '../common/fakeEvents';
5
- import { mockMatchMedia } from '../test-utils';
6
-
7
- import { DateLookupWithoutInputAttributes as DateLookup } from './DateLookup';
8
-
9
- mockMatchMedia();
10
-
11
- const defaultLocale = 'en-GB';
12
- const formatMessage = (id) => String(id);
13
- jest.mock('react-intl', () => ({
14
- injectIntl: (Component) =>
15
- function (props) {
16
- return <Component {...props} intl={{ locale: defaultLocale, formatMessage }} />;
17
- },
18
- useIntl: () => ({ locale: defaultLocale, formatMessage }),
19
- defineMessages: (translations) => translations,
20
- }));
21
-
22
- describe('DateLookup (keyboard events)', () => {
23
- const date = new Date(2018, 11, 27);
24
- let component;
25
- let props;
26
-
27
- beforeEach(() => {
28
- props = { value: date, onChange: jest.fn() };
29
- component = mount(<DateLookup {...props} />);
30
- });
31
-
32
- it('can be opened by LEFT arrow', () => {
33
- pressKey('ArrowLeft');
34
- expect(component.instance().state.open).toBe(true);
35
- });
36
-
37
- it('can be opened by UP arrow', () => {
38
- pressKey('ArrowUp');
39
- expect(component.instance().state.open).toBe(true);
40
- });
41
-
42
- it('can be opened by RIGHT arrow', () => {
43
- pressKey('ArrowRight');
44
- expect(component.instance().state.open).toBe(true);
45
- });
46
-
47
- it('can be opened by DOWN arrow', () => {
48
- pressKey('ArrowDown');
49
- expect(component.instance().state.open).toBe(true);
50
- });
51
-
52
- it('can be closed by pressing ESCAPE', () => {
53
- component.setState({ open: true });
54
- pressKey('Escape');
55
- expect(component.instance().state.open).toBe(false);
56
- });
57
-
58
- describe('when open and in day mode', () => {
59
- beforeEach(() => {
60
- component.setState({ open: true, mode: 'day' });
61
- });
62
-
63
- it('moves 1 day back by pressing LEFT', () => {
64
- pressKey('ArrowLeft');
65
- onChangeCalledWith(new Date(2018, 11, 26));
66
- });
67
-
68
- it('moves 7 days back by pressing UP', () => {
69
- pressKey('ArrowUp');
70
- onChangeCalledWith(new Date(2018, 11, 20));
71
- });
72
-
73
- it('moves 1 day forward by pressing RIGHT', () => {
74
- pressKey('ArrowRight');
75
- onChangeCalledWith(new Date(2018, 11, 28));
76
- });
77
-
78
- it('moves 7 day forward by pressing DOWN', () => {
79
- pressKey('ArrowDown');
80
- onChangeCalledWith(new Date(2019, 0, 3));
81
- });
82
-
83
- it('resets to original date when escape key is pressed', () => {
84
- pressKey('ArrowLeft');
85
- pressKey('Escape');
86
- onChangeCalledWith(date);
87
- });
88
-
89
- it('resets to original date when clicking outside modal', () => {
90
- pressKey('ArrowLeft');
91
- component.find('.dimmer').simulate('click');
92
- onChangeCalledWith(date);
93
- });
94
- });
95
-
96
- describe('when open and in month mode', () => {
97
- beforeEach(() => {
98
- component.setState({ open: true, mode: 'month' });
99
- });
100
-
101
- it('moves 1 month back by pressing LEFT', () => {
102
- pressKey('ArrowLeft');
103
- onChangeCalledWith(new Date(2018, 10, 27));
104
- });
105
-
106
- it('moves 4 months back by pressing UP', () => {
107
- pressKey('ArrowUp');
108
- onChangeCalledWith(new Date(2018, 7, 27));
109
- });
110
-
111
- it('moves 1 month forward by pressing RIGHT', () => {
112
- pressKey('ArrowRight');
113
- onChangeCalledWith(new Date(2019, 0, 27));
114
- });
115
-
116
- it('moves 4 months forward by pressing DOWN', () => {
117
- pressKey('ArrowDown');
118
- onChangeCalledWith(new Date(2019, 3, 27));
119
- });
120
- });
121
-
122
- describe('when open and in year mode', () => {
123
- beforeEach(() => {
124
- component.setState({ open: true, mode: 'year' });
125
- });
126
-
127
- it('moves 1 year back by pressing LEFT', () => {
128
- pressKey('ArrowLeft');
129
- onChangeCalledWith(new Date(2017, 11, 27));
130
- });
131
-
132
- it('moves 4 years back by pressing UP', () => {
133
- pressKey('ArrowUp');
134
- onChangeCalledWith(new Date(2014, 11, 27));
135
- });
136
-
137
- it('moves 1 year forward by pressing RIGHT', () => {
138
- pressKey('ArrowRight');
139
- onChangeCalledWith(new Date(2019, 11, 27));
140
- });
141
-
142
- it('moves 4 year forward by pressing DOWN', () => {
143
- pressKey('ArrowDown');
144
- onChangeCalledWith(new Date(2022, 11, 27));
145
- });
146
- });
147
-
148
- describe('when min and max provided', () => {
149
- beforeEach(() => {
150
- component.setState({
151
- open: true,
152
- mode: 'day',
153
- min: new Date(2018, 11, 26),
154
- max: new Date(2018, 11, 28),
155
- });
156
- });
157
-
158
- it('makes sure that date is >= min', () => {
159
- pressKey('ArrowLeft');
160
- onChangeCalledWith(new Date(2018, 11, 26));
161
- pressKey('ArrowLeft');
162
- onChangeCalledWith(new Date(2018, 11, 26));
163
- });
164
-
165
- it('makes sure that date is <= max', () => {
166
- pressKey('ArrowRight');
167
- onChangeCalledWith(new Date(2018, 11, 28));
168
- pressKey('ArrowRight');
169
- onChangeCalledWith(new Date(2018, 11, 28));
170
- });
171
- });
172
-
173
- const pressKey = (key) => {
174
- component.simulate('keyDown', fakeKeyDownEventForKey(key));
175
- };
176
-
177
- const onChangeCalledWith = (d) => {
178
- expect(props.onChange).toHaveBeenLastCalledWith(d);
179
- };
180
- });