@transferwise/components 0.0.0-experimental-2aa3886 → 0.0.0-experimental-e783ca8
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/i18n/en.json +2 -0
- package/build/i18n/en.json.js +2 -0
- package/build/i18n/en.json.js.map +1 -1
- package/build/i18n/en.json.mjs +2 -0
- package/build/i18n/en.json.mjs.map +1 -1
- package/build/phoneNumberInput/PhoneNumberInput.js +36 -2
- package/build/phoneNumberInput/PhoneNumberInput.js.map +1 -1
- package/build/phoneNumberInput/PhoneNumberInput.messages.js +6 -0
- package/build/phoneNumberInput/PhoneNumberInput.messages.js.map +1 -1
- package/build/phoneNumberInput/PhoneNumberInput.messages.mjs +6 -0
- package/build/phoneNumberInput/PhoneNumberInput.messages.mjs.map +1 -1
- package/build/phoneNumberInput/PhoneNumberInput.mjs +36 -2
- package/build/phoneNumberInput/PhoneNumberInput.mjs.map +1 -1
- package/build/types/phoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
- package/build/types/phoneNumberInput/PhoneNumberInput.messages.d.ts +8 -0
- package/build/types/phoneNumberInput/PhoneNumberInput.messages.d.ts.map +1 -1
- package/build/types/test-utils/index.d.ts +4 -0
- package/build/types/test-utils/index.d.ts.map +1 -1
- package/build/types/uploadInput/UploadInput.d.ts.map +1 -1
- package/build/types/uploadInput/uploadItem/UploadItem.d.ts +1 -1
- package/build/types/uploadInput/uploadItem/UploadItem.d.ts.map +1 -1
- package/build/uploadInput/UploadInput.js +6 -55
- package/build/uploadInput/UploadInput.js.map +1 -1
- package/build/uploadInput/UploadInput.mjs +6 -55
- package/build/uploadInput/UploadInput.mjs.map +1 -1
- package/build/uploadInput/uploadItem/UploadItem.js +6 -12
- package/build/uploadInput/uploadItem/UploadItem.js.map +1 -1
- package/build/uploadInput/uploadItem/UploadItem.mjs +6 -12
- package/build/uploadInput/uploadItem/UploadItem.mjs.map +1 -1
- package/package.json +3 -6
- package/src/i18n/en.json +2 -0
- package/src/phoneNumberInput/PhoneNumberInput.messages.ts +8 -0
- package/src/phoneNumberInput/PhoneNumberInput.spec.tsx +77 -43
- package/src/phoneNumberInput/PhoneNumberInput.tsx +34 -2
- package/src/test-utils/jest.setup.ts +0 -4
- package/src/typeahead/Typeahead.spec.tsx +182 -0
- package/src/typeahead/typeaheadInput/TypeaheadInput.spec.tsx +103 -0
- package/src/typeahead/util/highlight.spec.tsx +43 -0
- package/src/uploadInput/UploadInput.tsx +8 -81
- package/src/uploadInput/uploadItem/UploadItem.tsx +6 -11
- package/src/typeahead/Typeahead.rtl.spec.tsx +0 -54
- package/src/typeahead/Typeahead.spec.js +0 -404
- package/src/typeahead/typeaheadInput/TypeaheadInput.spec.js +0 -74
- package/src/typeahead/typeaheadOption/TypeaheadOption.spec.js +0 -75
- package/src/typeahead/util/highlight.spec.js +0 -34
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { render, fireEvent, screen } from '../../test-utils';
|
|
2
|
+
import TypeaheadInput, { TypeaheadInputProps } from './TypeaheadInput';
|
|
3
|
+
import { TypeaheadOption } from '../Typeahead';
|
|
4
|
+
|
|
5
|
+
const defaultProps: TypeaheadInputProps<number> = {
|
|
6
|
+
id: 'test-id',
|
|
7
|
+
name: 'test-name',
|
|
8
|
+
typeaheadId: 'test-id',
|
|
9
|
+
value: '',
|
|
10
|
+
selected: [],
|
|
11
|
+
onChange: jest.fn(),
|
|
12
|
+
onKeyDown: jest.fn(),
|
|
13
|
+
onFocus: jest.fn(),
|
|
14
|
+
onPaste: jest.fn(),
|
|
15
|
+
autoComplete: 'off',
|
|
16
|
+
placeholder: 'Search...',
|
|
17
|
+
renderChip: jest.fn(),
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
describe('TypeaheadInput', () => {
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
jest.clearAllMocks();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('renders input with placeholder', () => {
|
|
26
|
+
render(<TypeaheadInput {...defaultProps} />);
|
|
27
|
+
expect(screen.getByPlaceholderText('Search...')).toBeInTheDocument();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('renders with given value', () => {
|
|
31
|
+
render(<TypeaheadInput {...defaultProps} value="hello" />);
|
|
32
|
+
expect(screen.getByDisplayValue('hello')).toBeInTheDocument();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('calls onChange when input value changes', () => {
|
|
36
|
+
const onChange = jest.fn();
|
|
37
|
+
render(<TypeaheadInput {...defaultProps} onChange={onChange} />);
|
|
38
|
+
const input = screen.getByPlaceholderText('Search...');
|
|
39
|
+
fireEvent.change(input, { target: { value: 'test' } });
|
|
40
|
+
expect(onChange).toHaveBeenCalled();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('calls onFocus when input is focused', () => {
|
|
44
|
+
const onFocus = jest.fn();
|
|
45
|
+
render(<TypeaheadInput {...defaultProps} onFocus={onFocus} />);
|
|
46
|
+
const input = screen.getByPlaceholderText('Search...');
|
|
47
|
+
fireEvent.focus(input);
|
|
48
|
+
expect(onFocus).toHaveBeenCalled();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('calls onPaste when input is pasted into', () => {
|
|
52
|
+
const onPaste = jest.fn();
|
|
53
|
+
render(<TypeaheadInput {...defaultProps} onPaste={onPaste} />);
|
|
54
|
+
const input = screen.getByPlaceholderText('Search...');
|
|
55
|
+
fireEvent.paste(input, { clipboardData: { getData: () => 'pasted' } });
|
|
56
|
+
expect(onPaste).toHaveBeenCalled();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('calls onKeyDown when key is pressed', () => {
|
|
60
|
+
const onKeyDown = jest.fn();
|
|
61
|
+
render(<TypeaheadInput {...defaultProps} onKeyDown={onKeyDown} />);
|
|
62
|
+
const input = screen.getByPlaceholderText('Search...');
|
|
63
|
+
fireEvent.keyDown(input, { key: 'ArrowDown', code: 'ArrowDown' });
|
|
64
|
+
expect(onKeyDown).toHaveBeenCalled();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('renders chips when multiple is true and selected has items', () => {
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
69
|
+
const renderChip = jest.fn((chip, idx) => <span key={idx}>{chip.label}</span>);
|
|
70
|
+
const selected = [
|
|
71
|
+
{ label: 'Chip 1', value: 1 },
|
|
72
|
+
{ label: 'Chip 2', value: 2 },
|
|
73
|
+
];
|
|
74
|
+
render(
|
|
75
|
+
<TypeaheadInput {...defaultProps} multiple selected={selected} renderChip={renderChip} />,
|
|
76
|
+
);
|
|
77
|
+
expect(screen.getByText('Chip 1')).toBeInTheDocument();
|
|
78
|
+
expect(screen.getByText('Chip 2')).toBeInTheDocument();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('does not show placeholder if multiple is true and selected has items', () => {
|
|
82
|
+
const selected: TypeaheadOption<number>[] = [{ label: 'Chip', value: 1 }];
|
|
83
|
+
render(<TypeaheadInput<number> {...defaultProps} multiple selected={selected} />);
|
|
84
|
+
expect(screen.queryByPlaceholderText('Search...')).not.toBeInTheDocument();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('applies input width style when multiple and selected has items', () => {
|
|
88
|
+
const selected = [{ label: 'Chip', value: 1 }];
|
|
89
|
+
const { container } = render(
|
|
90
|
+
<TypeaheadInput {...defaultProps} multiple selected={selected} value="test" />,
|
|
91
|
+
);
|
|
92
|
+
const input = container.querySelector('input');
|
|
93
|
+
expect(input?.style.width).not.toBe('');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('sets aria attributes correctly', () => {
|
|
97
|
+
render(<TypeaheadInput {...defaultProps} dropdownOpen ariaActivedescendant="option-1" />);
|
|
98
|
+
const input = screen.getByRole('combobox');
|
|
99
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
100
|
+
expect(input).toHaveAttribute('aria-haspopup', 'listbox');
|
|
101
|
+
expect(input).toHaveAttribute('aria-activedescendant', expect.stringContaining('option-1'));
|
|
102
|
+
});
|
|
103
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { render, screen } from '../../test-utils';
|
|
2
|
+
import Highlight from './highlight';
|
|
3
|
+
|
|
4
|
+
describe('Highlight', () => {
|
|
5
|
+
it('renders value with highlighted query (case-insensitive)', () => {
|
|
6
|
+
render(<Highlight value="Hello World" query="world" />);
|
|
7
|
+
expect(screen.getByText('World')).toBeInTheDocument();
|
|
8
|
+
expect(screen.getByText('World').tagName).toBe('STRONG');
|
|
9
|
+
expect(screen.getByText('Hello', { exact: false })).toBeInTheDocument();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('renders value with highlighted query (case-sensitive in output)', () => {
|
|
13
|
+
render(<Highlight value="Hello World" query="HELLO" />);
|
|
14
|
+
expect(screen.getByText('Hello').tagName).toBe('STRONG');
|
|
15
|
+
expect(screen.getByText('World', { exact: false })).toBeInTheDocument();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('renders value without highlight if query not found', () => {
|
|
19
|
+
render(<Highlight value="Hello World" query="foo" />);
|
|
20
|
+
expect(screen.getByText('Hello World')).toBeInTheDocument();
|
|
21
|
+
expect(screen.queryByRole('strong')).not.toBeInTheDocument();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('renders value as is if query is empty', () => {
|
|
25
|
+
render(<Highlight value="Hello World" query="" />);
|
|
26
|
+
expect(screen.getByText('Hello World')).toBeInTheDocument();
|
|
27
|
+
expect(screen.queryByRole('strong')).not.toBeInTheDocument();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('renders value as is if value is empty', () => {
|
|
31
|
+
render(<Highlight value="" query="test" />);
|
|
32
|
+
expect(screen.queryByText(/./)).not.toBeInTheDocument();
|
|
33
|
+
expect(screen.queryByRole('strong')).not.toBeInTheDocument();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('wraps content in span if className is provided', () => {
|
|
37
|
+
const { container } = render(
|
|
38
|
+
<Highlight value="Hello World" query="world" className="highlighted" />,
|
|
39
|
+
);
|
|
40
|
+
expect(container.querySelector('span.highlighted')).toBeInTheDocument();
|
|
41
|
+
expect(container.querySelector('strong')).toBeInTheDocument();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -161,7 +161,6 @@ const UploadInput = ({
|
|
|
161
161
|
}: UploadInputProps) => {
|
|
162
162
|
const inputAttributes = useInputAttributes({ nonLabelable: true });
|
|
163
163
|
const [markedFileForDelete, setMarkedFileForDelete] = useState<UploadedFile | null>(null);
|
|
164
|
-
const [lastAttemptedDeleteId, setLastAttemptedDeleteId] = useState<string | number | null>(null);
|
|
165
164
|
const [mounted, setMounted] = useState(false);
|
|
166
165
|
const { formatMessage } = useIntl();
|
|
167
166
|
const uploadInputRef = useRef<HTMLInputElement | null>(null);
|
|
@@ -322,13 +321,7 @@ const UploadInput = ({
|
|
|
322
321
|
}
|
|
323
322
|
}, [onFilesChange, uploadedFiles]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
324
323
|
|
|
325
|
-
|
|
326
|
-
| HTMLDivElement
|
|
327
|
-
| UploadItemRef
|
|
328
|
-
| { ref: HTMLDivElement | UploadItemRef; target: 'button' | 'link' }
|
|
329
|
-
| null;
|
|
330
|
-
|
|
331
|
-
const [nextFocusable, setNextFocusable] = useState<NextFocusable>(
|
|
324
|
+
const [nextFocusable, setNextFocusable] = useState<HTMLDivElement | UploadItemRef | null>(
|
|
332
325
|
uploadInputRef.current,
|
|
333
326
|
);
|
|
334
327
|
|
|
@@ -338,15 +331,7 @@ const UploadInput = ({
|
|
|
338
331
|
});
|
|
339
332
|
|
|
340
333
|
const filesCount = fileRefs.length;
|
|
341
|
-
let next:
|
|
342
|
-
let focusTarget: 'button' | 'link' = 'button';
|
|
343
|
-
|
|
344
|
-
// If there will be no files left after deletion, focus the upload button
|
|
345
|
-
if (filesCount === 1) {
|
|
346
|
-
next = uploadInputRef.current;
|
|
347
|
-
setNextFocusable(next);
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
334
|
+
let next: HTMLDivElement | UploadItemRef | null = uploadInputRef.current;
|
|
350
335
|
|
|
351
336
|
if (filesCount > 1) {
|
|
352
337
|
const currentFileIndex = fileRefs.findIndex((file) => file?.id === fileId);
|
|
@@ -359,68 +344,15 @@ const UploadInput = ({
|
|
|
359
344
|
} else {
|
|
360
345
|
next = fileRefs[currentFileIndex + 1];
|
|
361
346
|
}
|
|
362
|
-
|
|
363
|
-
// If next is an UploadItemRef, check if it has a URL (succeeded)
|
|
364
|
-
if (next && 'status' in next) {
|
|
365
|
-
// Find the file object for this ref
|
|
366
|
-
const fileObj = uploadedFiles.find(f => f.id === next?.id);
|
|
367
|
-
if (
|
|
368
|
-
fileObj &&
|
|
369
|
-
(fileObj.status === Status.SUCCEEDED || fileObj.status === Status.DONE) &&
|
|
370
|
-
fileObj.url
|
|
371
|
-
) {
|
|
372
|
-
focusTarget = 'link';
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
setNextFocusable(() => {
|
|
376
|
-
if (next && typeof (next as UploadItemRef).focus === 'function') {
|
|
377
|
-
return { ref: next, target: focusTarget };
|
|
378
|
-
}
|
|
379
|
-
return next;
|
|
380
|
-
});
|
|
381
347
|
}
|
|
348
|
+
setNextFocusable(next);
|
|
382
349
|
};
|
|
383
350
|
|
|
384
351
|
const handleRefocus = () => {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
}
|
|
390
|
-
if (focusTarget) {
|
|
391
|
-
// If there are no files left, focus the upload button
|
|
392
|
-
if (
|
|
393
|
-
uploadedFiles.length === 0 &&
|
|
394
|
-
uploadInputRef.current &&
|
|
395
|
-
typeof uploadInputRef.current.focus === 'function'
|
|
396
|
-
) {
|
|
397
|
-
setTimeout(() => {
|
|
398
|
-
uploadInputRef.current!.focus();
|
|
399
|
-
}, 0);
|
|
400
|
-
} else if (
|
|
401
|
-
typeof focusTarget === 'object' &&
|
|
402
|
-
'ref' in focusTarget &&
|
|
403
|
-
focusTarget.ref &&
|
|
404
|
-
typeof focusTarget.ref.focus === 'function'
|
|
405
|
-
) {
|
|
406
|
-
setTimeout(() => {
|
|
407
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
408
|
-
if (
|
|
409
|
-
focusTarget.ref &&
|
|
410
|
-
typeof (focusTarget.ref as UploadItemRef).focus === 'function'
|
|
411
|
-
) {
|
|
412
|
-
// @ts-expect-error: focus may not exist on all possible ref types, but is safe here
|
|
413
|
-
(focusTarget.ref as UploadItemRef).focus(focusTarget.target);
|
|
414
|
-
}
|
|
415
|
-
}, 0);
|
|
416
|
-
} else if (
|
|
417
|
-
focusTarget &&
|
|
418
|
-
typeof (focusTarget as UploadItemRef).focus === 'function'
|
|
419
|
-
) {
|
|
420
|
-
setTimeout(() => {
|
|
421
|
-
(focusTarget as UploadItemRef).focus();
|
|
422
|
-
}, 0);
|
|
423
|
-
}
|
|
352
|
+
if (nextFocusable && 'focus' in nextFocusable && typeof nextFocusable.focus === 'function') {
|
|
353
|
+
setTimeout(() => {
|
|
354
|
+
nextFocusable.focus();
|
|
355
|
+
}, 0);
|
|
424
356
|
}
|
|
425
357
|
};
|
|
426
358
|
|
|
@@ -459,14 +391,10 @@ const UploadInput = ({
|
|
|
459
391
|
onDelete={
|
|
460
392
|
file.status === Status.FAILED
|
|
461
393
|
? async () => {
|
|
462
|
-
setLastAttemptedDeleteId(file.id);
|
|
463
394
|
await removeFile(file);
|
|
464
395
|
handleRefocus();
|
|
465
396
|
}
|
|
466
|
-
: () =>
|
|
467
|
-
setLastAttemptedDeleteId(file.id);
|
|
468
|
-
setMarkedFileForDelete(file);
|
|
469
|
-
}
|
|
397
|
+
: () => setMarkedFileForDelete(file)
|
|
470
398
|
}
|
|
471
399
|
onDownload={onDownload}
|
|
472
400
|
onFocus={() => handleFocus(file.id)}
|
|
@@ -523,7 +451,6 @@ const UploadInput = ({
|
|
|
523
451
|
void removeFile(markedFileForDelete);
|
|
524
452
|
}
|
|
525
453
|
setMarkedFileForDelete(null);
|
|
526
|
-
setLastAttemptedDeleteId(null);
|
|
527
454
|
}}
|
|
528
455
|
>
|
|
529
456
|
{deleteConfirm?.confirmText || formatMessage(MESSAGES.deleteModalConfirmButtonText)}
|
|
@@ -19,7 +19,7 @@ export type UploadItemProps = React.JSX.IntrinsicAttributes & {
|
|
|
19
19
|
singleFileUpload: boolean;
|
|
20
20
|
canDelete: boolean;
|
|
21
21
|
onDelete: () => void;
|
|
22
|
-
onFocus: (
|
|
22
|
+
onFocus: () => void;
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Callback to be called when the file link is clicked.
|
|
@@ -63,15 +63,11 @@ const UploadItem = forwardRef<UploadItemRef, UploadItemProps>(
|
|
|
63
63
|
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
64
64
|
|
|
65
65
|
useImperativeHandle<UploadItemRef, UploadItemRef>(ref, () => ({
|
|
66
|
-
focus: (
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
} else
|
|
70
|
-
|
|
71
|
-
} else if (buttonRef.current) {
|
|
72
|
-
buttonRef.current.focus();
|
|
73
|
-
} else if (linkRef.current) {
|
|
74
|
-
linkRef.current.focus();
|
|
66
|
+
focus: (): void => {
|
|
67
|
+
if (url) {
|
|
68
|
+
linkRef.current?.focus();
|
|
69
|
+
} else {
|
|
70
|
+
buttonRef.current?.focus();
|
|
75
71
|
}
|
|
76
72
|
},
|
|
77
73
|
id: file.id,
|
|
@@ -203,7 +199,6 @@ const UploadItem = forwardRef<UploadItemRef, UploadItemProps>(
|
|
|
203
199
|
tabIndex={0}
|
|
204
200
|
data-testid={`${file.id}-${TEST_IDS.action}`}
|
|
205
201
|
onClick={() => onDelete()}
|
|
206
|
-
// @ts-expect-error: handleFocus is not a standard FocusEventHandler, but required for parent logic
|
|
207
202
|
onFocus={handleFocus}
|
|
208
203
|
>
|
|
209
204
|
<Bin size={16} />
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { Field } from '../field/Field';
|
|
2
|
-
import { mockMatchMedia, render, screen } from '../test-utils';
|
|
3
|
-
import Typeahead from './Typeahead';
|
|
4
|
-
import { createIntl, createIntlCache } from 'react-intl';
|
|
5
|
-
import messages from '../i18n';
|
|
6
|
-
import { DEFAULT_LANG, DEFAULT_LOCALE } from '../common';
|
|
7
|
-
|
|
8
|
-
mockMatchMedia();
|
|
9
|
-
|
|
10
|
-
const cache = createIntlCache();
|
|
11
|
-
const intl = createIntl({ locale: DEFAULT_LOCALE, messages: messages[DEFAULT_LANG] }, cache);
|
|
12
|
-
|
|
13
|
-
describe('Typeahead', () => {
|
|
14
|
-
it('supports `Field` for labeling', () => {
|
|
15
|
-
render(
|
|
16
|
-
<Field id="test" label="Tags">
|
|
17
|
-
<Typeahead
|
|
18
|
-
id="test"
|
|
19
|
-
name="test"
|
|
20
|
-
options={[{ label: 'Test' }]}
|
|
21
|
-
intl={intl}
|
|
22
|
-
onChange={() => {}}
|
|
23
|
-
/>
|
|
24
|
-
</Field>,
|
|
25
|
-
);
|
|
26
|
-
expect(screen.getAllByRole('group')[0]).toHaveAccessibleName(/^Tags/);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
describe('when no options are provided', () => {
|
|
30
|
-
it('does not render a dropdown when no options and no footer are provided', () => {
|
|
31
|
-
render(
|
|
32
|
-
<Field id="test" label="Tags">
|
|
33
|
-
<Typeahead id="test" name="test" options={[]} intl={intl} onChange={() => {}} />
|
|
34
|
-
</Field>,
|
|
35
|
-
);
|
|
36
|
-
expect(screen.queryByRole('menu')).not.toBeInTheDocument();
|
|
37
|
-
});
|
|
38
|
-
it('does render a dropdown when only a footer is provided', () => {
|
|
39
|
-
render(
|
|
40
|
-
<Field id="test" label="Tags">
|
|
41
|
-
<Typeahead
|
|
42
|
-
id="test"
|
|
43
|
-
name="test"
|
|
44
|
-
options={[]}
|
|
45
|
-
intl={intl}
|
|
46
|
-
footer={<p>hello</p>}
|
|
47
|
-
onChange={() => {}}
|
|
48
|
-
/>
|
|
49
|
-
</Field>,
|
|
50
|
-
);
|
|
51
|
-
expect(screen.getByRole('menu')).toBeInTheDocument();
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
});
|