@leafygreen-ui/combobox 7.1.0 → 8.0.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/CHANGELOG.md +51 -0
- package/dist/Combobox/Combobox.d.ts +1 -1
- package/dist/Combobox/Combobox.d.ts.map +1 -1
- package/dist/Combobox/Combobox.types.d.ts +8 -0
- package/dist/Combobox/Combobox.types.d.ts.map +1 -1
- package/dist/Combobox/utils/isValueCurrentSelection.d.ts +7 -0
- package/dist/Combobox/utils/isValueCurrentSelection.d.ts.map +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/Combobox.types.d.ts +6 -1
- package/dist/types/Combobox.types.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/doesSelectionExist.d.ts +3 -0
- package/dist/utils/doesSelectionExist.d.ts.map +1 -0
- package/package.json +8 -7
- package/src/Combobox/Combobox.spec.tsx +198 -66
- package/src/Combobox/Combobox.tsx +75 -58
- package/src/Combobox/Combobox.types.ts +10 -0
- package/src/Combobox/utils/isValueCurrentSelection.ts +14 -0
- package/src/Combobox.story.tsx +1 -0
- package/src/types/Combobox.types.ts +7 -1
- package/src/types/index.ts +1 -0
- package/src/utils/doesSelectionExist.ts +16 -0
- package/stories.js +1 -1
- package/tsconfig.json +3 -0
- package/tsdoc.json +22 -2
|
@@ -59,12 +59,17 @@ export declare type SearchState = (typeof SearchState)[keyof typeof SearchState]
|
|
|
59
59
|
* Type varies depending on the value of `multiselect`
|
|
60
60
|
*/
|
|
61
61
|
export declare type SelectValueType<M extends boolean> = M extends true ? Array<string> : string | null;
|
|
62
|
+
/** Represents an element that was added or removed from the multiselect value array */
|
|
63
|
+
export interface DiffObject {
|
|
64
|
+
diffType: 'insert' | 'delete';
|
|
65
|
+
value: string | Array<string>;
|
|
66
|
+
}
|
|
62
67
|
/**
|
|
63
68
|
* Callback event fired when the value changes
|
|
64
69
|
*
|
|
65
70
|
* Type varies depending on the value of `multiselect`
|
|
66
71
|
*/
|
|
67
|
-
export declare type onChangeType<M extends boolean> = M extends true ? (value: SelectValueType<true
|
|
72
|
+
export declare type onChangeType<M extends boolean> = M extends true ? (value: SelectValueType<true>, diff?: DiffObject) => void : (value: SelectValueType<false>) => void;
|
|
68
73
|
/**
|
|
69
74
|
* Returns the correct empty state for multiselect / single select
|
|
70
75
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Combobox.types.d.ts","sourceRoot":"","sources":["../../src/types/Combobox.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;CAQlB,CAAC;AACX,oBAAY,eAAe,GACzB,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;CAKf,CAAC;AACX,oBAAY,YAAY,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAE5E;;GAEG;AACH,eAAO,MAAM,QAAQ;IACnB;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;CAEK,CAAC;AACX,oBAAY,QAAQ,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,OAAO,QAAQ,CAAC,CAAC;AAEhE,sCAAsC;AACtC,eAAO,MAAM,KAAK;;;CAGR,CAAC;AACX,oBAAY,KAAK,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC;AAEvD,uCAAuC;AACvC,eAAO,MAAM,WAAW;;;;CAId,CAAC;AACX,oBAAY,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEzE;;;;;GAKG;AACH,oBAAY,eAAe,CAAC,CAAC,SAAS,OAAO,IAAI,CAAC,SAAS,IAAI,GAC3D,KAAK,CAAC,MAAM,CAAC,GACb,MAAM,GAAG,IAAI,CAAC;AAElB;;;;GAIG;AAEH,oBAAY,YAAY,CAAC,CAAC,SAAS,OAAO,IAAI,CAAC,SAAS,IAAI,GACxD,CAAC,KAAK,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"Combobox.types.d.ts","sourceRoot":"","sources":["../../src/types/Combobox.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;CAQlB,CAAC;AACX,oBAAY,eAAe,GACzB,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;CAKf,CAAC;AACX,oBAAY,YAAY,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAE5E;;GAEG;AACH,eAAO,MAAM,QAAQ;IACnB;;OAEG;;IAEH;;OAEG;;IAEH;;OAEG;;CAEK,CAAC;AACX,oBAAY,QAAQ,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,OAAO,QAAQ,CAAC,CAAC;AAEhE,sCAAsC;AACtC,eAAO,MAAM,KAAK;;;CAGR,CAAC;AACX,oBAAY,KAAK,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC;AAEvD,uCAAuC;AACvC,eAAO,MAAM,WAAW;;;;CAId,CAAC;AACX,oBAAY,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEzE;;;;;GAKG;AACH,oBAAY,eAAe,CAAC,CAAC,SAAS,OAAO,IAAI,CAAC,SAAS,IAAI,GAC3D,KAAK,CAAC,MAAM,CAAC,GACb,MAAM,GAAG,IAAI,CAAC;AAElB,uFAAuF;AACvF,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC9B,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED;;;;GAIG;AAEH,oBAAY,YAAY,CAAC,CAAC,SAAS,OAAO,IAAI,CAAC,SAAS,IAAI,GACxD,CAAC,KAAK,EAAE,eAAe,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,UAAU,KAAK,IAAI,GACzD,CAAC,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AAE5C;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,OAAO,EAChD,WAAW,EAAE,CAAC,GACb,eAAe,CAAC,CAAC,CAAC,CAMpB"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { ComboboxElement, ComboboxSize, getNullSelection, onChangeType, Overflow, SearchState, SelectValueType, State, } from './Combobox.types';
|
|
1
|
+
export { ComboboxElement, ComboboxSize, DiffObject, getNullSelection, onChangeType, Overflow, SearchState, SelectValueType, State, } from './Combobox.types';
|
|
2
2
|
export { TruncationLocation } from '@leafygreen-ui/chip';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,eAAe,EACf,KAAK,GACN,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,eAAe,EACf,KAAK,GACN,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doesSelectionExist.d.ts","sourceRoot":"","sources":["../../src/utils/doesSelectionExist.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,eAAO,MAAM,kBAAkB,4EAE5B,OAMF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafygreen-ui/combobox",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "leafyGreen UI Kit Combobox",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -22,19 +22,19 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@leafygreen-ui/checkbox": "^12.0
|
|
25
|
+
"@leafygreen-ui/checkbox": "^12.1.0",
|
|
26
26
|
"@leafygreen-ui/chip": "^1.0.0",
|
|
27
27
|
"@leafygreen-ui/emotion": "^4.0.7",
|
|
28
|
-
"@leafygreen-ui/hooks": "^8.
|
|
28
|
+
"@leafygreen-ui/hooks": "^8.1.1",
|
|
29
29
|
"@leafygreen-ui/icon": "^11.23.0",
|
|
30
30
|
"@leafygreen-ui/icon-button": "^15.0.19",
|
|
31
31
|
"@leafygreen-ui/inline-definition": "^6.0.13",
|
|
32
32
|
"@leafygreen-ui/input-option": "^1.0.13",
|
|
33
|
-
"@leafygreen-ui/lib": "^13.
|
|
33
|
+
"@leafygreen-ui/lib": "^13.2.1",
|
|
34
34
|
"@leafygreen-ui/palette": "^4.0.7",
|
|
35
35
|
"@leafygreen-ui/popover": "^11.1.1",
|
|
36
|
-
"@leafygreen-ui/tokens": "^2.
|
|
37
|
-
"@leafygreen-ui/typography": "^18.
|
|
36
|
+
"@leafygreen-ui/tokens": "^2.3.0",
|
|
37
|
+
"@leafygreen-ui/typography": "^18.2.0",
|
|
38
38
|
"chalk": "^4.1.2",
|
|
39
39
|
"lodash": "^4.17.21",
|
|
40
40
|
"polished": "^4.2.2"
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"@leafygreen-ui/leafygreen-provider": "^3.1.10"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@leafygreen-ui/button": "^21.0.
|
|
46
|
+
"@leafygreen-ui/button": "^21.0.12",
|
|
47
|
+
"@leafygreen-ui/testing-lib": "^0.4.0"
|
|
47
48
|
},
|
|
48
49
|
"homepage": "https://github.com/mongodb/leafygreen-ui/tree/main/packages/combobox",
|
|
49
50
|
"repository": {
|
|
@@ -16,6 +16,7 @@ import isUndefined from 'lodash/isUndefined';
|
|
|
16
16
|
|
|
17
17
|
import Button from '@leafygreen-ui/button';
|
|
18
18
|
import { keyMap } from '@leafygreen-ui/lib';
|
|
19
|
+
import { eventContainingTargetValue } from '@leafygreen-ui/testing-lib';
|
|
19
20
|
|
|
20
21
|
import { OptionObject } from '../ComboboxOption/ComboboxOption.types';
|
|
21
22
|
import {
|
|
@@ -134,6 +135,13 @@ describe('packages/combobox', () => {
|
|
|
134
135
|
});
|
|
135
136
|
expect(clearButtonEl).not.toBeInTheDocument();
|
|
136
137
|
});
|
|
138
|
+
|
|
139
|
+
test('`inputValue` prop is rendered in the textbox', () => {
|
|
140
|
+
const { inputEl } = renderCombobox(select, {
|
|
141
|
+
inputValue: 'abc',
|
|
142
|
+
});
|
|
143
|
+
expect(inputEl).toHaveValue('abc');
|
|
144
|
+
});
|
|
137
145
|
});
|
|
138
146
|
|
|
139
147
|
/**
|
|
@@ -420,7 +428,7 @@ describe('packages/combobox', () => {
|
|
|
420
428
|
/**
|
|
421
429
|
* Input element
|
|
422
430
|
*/
|
|
423
|
-
describe('Input interaction', () => {
|
|
431
|
+
describe('Typing (Input interaction)', () => {
|
|
424
432
|
test('Typing any character updates the input', () => {
|
|
425
433
|
const { inputEl } = renderCombobox(select);
|
|
426
434
|
userEvent.type(inputEl, 'zy');
|
|
@@ -434,70 +442,103 @@ describe('packages/combobox', () => {
|
|
|
434
442
|
expect(inputEl).toHaveValue(displayName);
|
|
435
443
|
expect(inputEl.scrollWidth).toBeGreaterThanOrEqual(inputEl.clientWidth);
|
|
436
444
|
});
|
|
437
|
-
});
|
|
438
445
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
test('Typing any character updates the input', () => {
|
|
445
|
-
const value = select === 'multiple' ? [] : '';
|
|
446
|
-
const { inputEl } = renderCombobox(select, {
|
|
447
|
-
value,
|
|
448
|
-
});
|
|
449
|
-
expect(inputEl).toHaveValue('');
|
|
450
|
-
userEvent.type(inputEl, 'z');
|
|
451
|
-
expect(inputEl).toHaveValue('z');
|
|
446
|
+
test('Typing does not fire onChange callback', () => {
|
|
447
|
+
const onChange = jest.fn();
|
|
448
|
+
const { inputEl } = renderCombobox(select, { onChange });
|
|
449
|
+
userEvent.type(inputEl, 'Apple');
|
|
450
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
452
451
|
});
|
|
453
452
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
const { inputEl
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
rerenderCombobox({ value });
|
|
462
|
-
expect(inputEl).toHaveValue('Banana');
|
|
453
|
+
test('Typing fires onInputChange callback', () => {
|
|
454
|
+
const onInputChange = jest.fn();
|
|
455
|
+
const { inputEl } = renderCombobox(select, { onInputChange });
|
|
456
|
+
userEvent.type(inputEl, 'abc');
|
|
457
|
+
expect(onInputChange).toHaveBeenCalledWith(
|
|
458
|
+
eventContainingTargetValue('abc'),
|
|
459
|
+
);
|
|
463
460
|
});
|
|
464
461
|
|
|
465
|
-
|
|
466
|
-
const
|
|
467
|
-
const { inputEl } = renderCombobox(select, {
|
|
468
|
-
|
|
462
|
+
test('Blurring the input after typing a valid value fires onChange', async () => {
|
|
463
|
+
const onChange = jest.fn();
|
|
464
|
+
const { inputEl, openMenu } = renderCombobox(select, { onChange });
|
|
465
|
+
const { menuContainerEl } = openMenu();
|
|
466
|
+
userEvent.type(inputEl, 'Apple');
|
|
467
|
+
userEvent.tab();
|
|
468
|
+
await waitForElementToBeRemoved(menuContainerEl);
|
|
469
|
+
if (select === 'multiple') {
|
|
470
|
+
expect(onChange).toHaveBeenCalledWith(['apple'], expect.anything());
|
|
471
|
+
} else {
|
|
472
|
+
expect(onChange).toHaveBeenCalledWith('apple');
|
|
473
|
+
}
|
|
469
474
|
});
|
|
470
475
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
476
|
+
/**
|
|
477
|
+
* Controlled
|
|
478
|
+
* (i.e. `value` prop is set)
|
|
479
|
+
*/
|
|
480
|
+
describe('When value is controlled', () => {
|
|
481
|
+
test('Typing any character updates the input', () => {
|
|
482
|
+
const value = select === 'multiple' ? [] : '';
|
|
483
|
+
const { inputEl } = renderCombobox(select, {
|
|
475
484
|
value,
|
|
476
485
|
});
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
486
|
+
expect(inputEl).toHaveValue('');
|
|
487
|
+
userEvent.type(inputEl, 'z');
|
|
488
|
+
expect(inputEl).toHaveValue('z');
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
testSingleSelect('Text input renders with value update', () => {
|
|
492
|
+
let value = 'apple';
|
|
493
|
+
const { inputEl, rerenderCombobox } = renderCombobox(select, {
|
|
494
|
+
value,
|
|
495
|
+
});
|
|
496
|
+
expect(inputEl).toHaveValue('Apple');
|
|
497
|
+
value = 'banana';
|
|
482
498
|
rerenderCombobox({ value });
|
|
499
|
+
expect(inputEl).toHaveValue('Banana');
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
testSingleSelect(
|
|
503
|
+
'Invalid option passed as value is not selected',
|
|
504
|
+
() => {
|
|
505
|
+
const value = 'jellybean';
|
|
506
|
+
const { inputEl } = renderCombobox(select, { value });
|
|
507
|
+
expect(inputEl).toHaveValue('');
|
|
508
|
+
},
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
testMultiSelect('Updating `value` updates the chips', () => {
|
|
512
|
+
let value = ['apple', 'banana'];
|
|
513
|
+
const { queryChipsByName, queryAllChips, rerenderCombobox } =
|
|
514
|
+
renderCombobox(select, {
|
|
515
|
+
value,
|
|
516
|
+
});
|
|
483
517
|
waitFor(() => {
|
|
484
|
-
const allChips = queryChipsByName(['
|
|
518
|
+
const allChips = queryChipsByName(['Apple', 'Banana']);
|
|
485
519
|
allChips?.forEach(chip => expect(chip).toBeInTheDocument());
|
|
486
520
|
expect(queryAllChips()).toHaveLength(2);
|
|
521
|
+
value = ['banana', 'carrot'];
|
|
522
|
+
rerenderCombobox({ value });
|
|
523
|
+
waitFor(() => {
|
|
524
|
+
const allChips = queryChipsByName(['Carrot', 'Banana']);
|
|
525
|
+
allChips?.forEach(chip => expect(chip).toBeInTheDocument());
|
|
526
|
+
expect(queryAllChips()).toHaveLength(2);
|
|
527
|
+
});
|
|
487
528
|
});
|
|
488
529
|
});
|
|
489
|
-
});
|
|
490
530
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
531
|
+
testMultiSelect('Invalid options are not selected', () => {
|
|
532
|
+
const value = ['apple', 'jellybean'];
|
|
533
|
+
const { queryChipsByName, queryAllChips } = renderCombobox(select, {
|
|
534
|
+
value,
|
|
535
|
+
});
|
|
536
|
+
waitFor(() => {
|
|
537
|
+
const allChips = queryChipsByName(['Apple']);
|
|
538
|
+
allChips?.forEach(chip => expect(chip).toBeInTheDocument());
|
|
539
|
+
expect(queryChipsByName('Jellybean')).not.toBeInTheDocument();
|
|
540
|
+
expect(queryAllChips()).toHaveLength(1);
|
|
541
|
+
});
|
|
501
542
|
});
|
|
502
543
|
});
|
|
503
544
|
});
|
|
@@ -541,6 +582,31 @@ describe('packages/combobox', () => {
|
|
|
541
582
|
}
|
|
542
583
|
});
|
|
543
584
|
|
|
585
|
+
test('Clicking an option fires onChange', () => {
|
|
586
|
+
const onChange = jest.fn();
|
|
587
|
+
const { openMenu } = renderCombobox(select, {
|
|
588
|
+
onChange,
|
|
589
|
+
});
|
|
590
|
+
const { optionElements } = openMenu();
|
|
591
|
+
expect(optionElements).not.toBeUndefined();
|
|
592
|
+
const option3 = (optionElements as HTMLCollectionOf<HTMLLIElement>)[2];
|
|
593
|
+
act(() => {
|
|
594
|
+
userEvent.click(option3);
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
if (select === 'multiple') {
|
|
598
|
+
expect(onChange).toHaveBeenCalledWith(
|
|
599
|
+
expect.arrayContaining(['carrot']),
|
|
600
|
+
expect.objectContaining({
|
|
601
|
+
diffType: 'insert',
|
|
602
|
+
value: 'carrot',
|
|
603
|
+
}),
|
|
604
|
+
);
|
|
605
|
+
} else {
|
|
606
|
+
expect(onChange).toHaveBeenCalledWith('carrot');
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
|
|
544
610
|
testSingleSelect('Clicking selected option closes menu', async () => {
|
|
545
611
|
const { openMenu } = renderCombobox(select, {
|
|
546
612
|
initialValue: 'apple',
|
|
@@ -749,6 +815,32 @@ describe('packages/combobox', () => {
|
|
|
749
815
|
});
|
|
750
816
|
});
|
|
751
817
|
|
|
818
|
+
testMultiSelect(
|
|
819
|
+
'Clicking chip X button fires onChange with diff',
|
|
820
|
+
async () => {
|
|
821
|
+
const onChange = jest.fn();
|
|
822
|
+
const initialValue = ['apple', 'banana', 'carrot'];
|
|
823
|
+
const { queryChipsByName } = renderCombobox(select, {
|
|
824
|
+
onChange,
|
|
825
|
+
initialValue,
|
|
826
|
+
});
|
|
827
|
+
const appleChip = queryChipsByName('Apple');
|
|
828
|
+
expect(appleChip).not.toBeNull();
|
|
829
|
+
const appleChipButton = appleChip!.querySelector('button')!;
|
|
830
|
+
userEvent.click(appleChipButton);
|
|
831
|
+
await waitFor(() => {
|
|
832
|
+
expect(appleChip).not.toBeInTheDocument();
|
|
833
|
+
expect(onChange).toHaveBeenCalledWith(
|
|
834
|
+
expect.arrayContaining(['banana', 'carrot']),
|
|
835
|
+
expect.objectContaining({
|
|
836
|
+
diffType: 'delete',
|
|
837
|
+
value: 'apple',
|
|
838
|
+
}),
|
|
839
|
+
);
|
|
840
|
+
});
|
|
841
|
+
},
|
|
842
|
+
);
|
|
843
|
+
|
|
752
844
|
testMultiSelect('Clicking chip text focuses the chip', () => {
|
|
753
845
|
const initialValue = ['apple', 'banana', 'carrot'];
|
|
754
846
|
const { queryChipsByName, queryAllChips } = renderCombobox(select, {
|
|
@@ -825,6 +917,17 @@ describe('packages/combobox', () => {
|
|
|
825
917
|
expect(menuContainerEl).toBeInTheDocument();
|
|
826
918
|
});
|
|
827
919
|
|
|
920
|
+
test('does not make a selection when clicking enter on a closed menu', () => {
|
|
921
|
+
const { getMenuElements, inputEl } = renderCombobox(select);
|
|
922
|
+
userEvent.tab();
|
|
923
|
+
userEvent.keyboard('{enter}');
|
|
924
|
+
expect(inputEl).toHaveValue('');
|
|
925
|
+
const { menuContainerEl } = getMenuElements();
|
|
926
|
+
expect(menuContainerEl).not.toBeNull();
|
|
927
|
+
expect(menuContainerEl).toBeInTheDocument();
|
|
928
|
+
expect(inputEl).toHaveValue('');
|
|
929
|
+
});
|
|
930
|
+
|
|
828
931
|
test('selects highlighted option', () => {
|
|
829
932
|
const { inputEl, openMenu, queryChipsByName } =
|
|
830
933
|
renderCombobox(select);
|
|
@@ -842,9 +945,18 @@ describe('packages/combobox', () => {
|
|
|
842
945
|
const { inputEl, openMenu } = renderCombobox(select, { onChange });
|
|
843
946
|
openMenu();
|
|
844
947
|
userEvent.type(inputEl!, '{arrowdown}{enter}');
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
948
|
+
|
|
949
|
+
if (select === 'multiple') {
|
|
950
|
+
expect(onChange).toHaveBeenCalledWith(
|
|
951
|
+
['banana'],
|
|
952
|
+
expect.objectContaining({
|
|
953
|
+
diffType: 'insert',
|
|
954
|
+
value: 'banana',
|
|
955
|
+
}),
|
|
956
|
+
);
|
|
957
|
+
} else {
|
|
958
|
+
expect(onChange).toHaveBeenCalledWith('banana');
|
|
959
|
+
}
|
|
848
960
|
});
|
|
849
961
|
|
|
850
962
|
test('does not fire onClear handler', () => {
|
|
@@ -1359,7 +1471,8 @@ describe('packages/combobox', () => {
|
|
|
1359
1471
|
*/
|
|
1360
1472
|
describe('onClear', () => {
|
|
1361
1473
|
test('Clear button calls onClear callback', () => {
|
|
1362
|
-
const initialValue =
|
|
1474
|
+
const initialValue =
|
|
1475
|
+
select === 'multiple' ? ['apple', 'banana'] : 'apple';
|
|
1363
1476
|
const onClear = jest.fn();
|
|
1364
1477
|
const { clearButtonEl } = renderCombobox(select, {
|
|
1365
1478
|
initialValue,
|
|
@@ -1370,7 +1483,8 @@ describe('packages/combobox', () => {
|
|
|
1370
1483
|
});
|
|
1371
1484
|
|
|
1372
1485
|
test('Clear button does not force the menu to reopen', () => {
|
|
1373
|
-
const initialValue =
|
|
1486
|
+
const initialValue =
|
|
1487
|
+
select === 'multiple' ? ['apple', 'banana'] : 'apple';
|
|
1374
1488
|
const onClear = jest.fn();
|
|
1375
1489
|
const { clearButtonEl, queryByRole } = renderCombobox(select, {
|
|
1376
1490
|
initialValue,
|
|
@@ -1381,8 +1495,9 @@ describe('packages/combobox', () => {
|
|
|
1381
1495
|
expect(queryByRole('listbox')).not.toBeInTheDocument();
|
|
1382
1496
|
});
|
|
1383
1497
|
|
|
1384
|
-
test('Clear button clears the value of the input', () => {
|
|
1385
|
-
const initialValue =
|
|
1498
|
+
test('Clear button clears the value of the input', async () => {
|
|
1499
|
+
const initialValue =
|
|
1500
|
+
select === 'multiple' ? ['apple', 'banana'] : 'apple';
|
|
1386
1501
|
const { inputEl, clearButtonEl, queryChipsByName } = renderCombobox(
|
|
1387
1502
|
select,
|
|
1388
1503
|
{
|
|
@@ -1396,10 +1511,34 @@ describe('packages/combobox', () => {
|
|
|
1396
1511
|
expect(inputEl).toHaveValue('Apple');
|
|
1397
1512
|
}
|
|
1398
1513
|
|
|
1399
|
-
|
|
1400
|
-
|
|
1514
|
+
userEvent.click(clearButtonEl!);
|
|
1515
|
+
await waitFor(() => {
|
|
1516
|
+
expect(inputEl).toHaveValue('');
|
|
1517
|
+
});
|
|
1518
|
+
});
|
|
1519
|
+
|
|
1520
|
+
test('Clear button calls onChange callback', () => {
|
|
1521
|
+
const onChange = jest.fn();
|
|
1522
|
+
const initialValue =
|
|
1523
|
+
select === 'multiple' ? ['apple', 'banana'] : 'apple';
|
|
1524
|
+
const { clearButtonEl } = renderCombobox(select, {
|
|
1525
|
+
initialValue,
|
|
1526
|
+
onChange,
|
|
1401
1527
|
});
|
|
1402
|
-
|
|
1528
|
+
|
|
1529
|
+
userEvent.click(clearButtonEl!);
|
|
1530
|
+
|
|
1531
|
+
if (select === 'multiple') {
|
|
1532
|
+
expect(onChange).toHaveBeenCalledWith(
|
|
1533
|
+
[],
|
|
1534
|
+
expect.objectContaining({
|
|
1535
|
+
diffType: 'delete',
|
|
1536
|
+
value: ['apple', 'banana'],
|
|
1537
|
+
}),
|
|
1538
|
+
);
|
|
1539
|
+
} else {
|
|
1540
|
+
expect(onChange).toHaveBeenCalledWith(null);
|
|
1541
|
+
}
|
|
1403
1542
|
});
|
|
1404
1543
|
|
|
1405
1544
|
test('Focus returns to input element after clear button is clicked', async () => {
|
|
@@ -1440,13 +1579,6 @@ describe('packages/combobox', () => {
|
|
|
1440
1579
|
expect(onChange).toHaveBeenCalled();
|
|
1441
1580
|
});
|
|
1442
1581
|
|
|
1443
|
-
test('Typing does not call onChange callback', () => {
|
|
1444
|
-
const onChange = jest.fn();
|
|
1445
|
-
const { inputEl } = renderCombobox(select, { onChange });
|
|
1446
|
-
userEvent.type(inputEl, 'a');
|
|
1447
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
1448
|
-
});
|
|
1449
|
-
|
|
1450
1582
|
test('Closing the menu without making a selection does not call onChange callback', async () => {
|
|
1451
1583
|
const onChange = jest.fn();
|
|
1452
1584
|
const { containerEl, openMenu } = renderCombobox(select, { onChange });
|