@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.
@@ -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>) => void : (value: SelectValueType<false>) => void;
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,GACtC,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"}
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"}
@@ -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,3 @@
1
+ import { SelectValueType } from '../types';
2
+ export declare const doesSelectionExist: <M extends boolean>(selection?: SelectValueType<M> | null | undefined) => boolean;
3
+ //# sourceMappingURL=doesSelectionExist.d.ts.map
@@ -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": "7.1.0",
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.20",
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.0.0",
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.0.0",
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.2.0",
37
- "@leafygreen-ui/typography": "^18.0.0",
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.9"
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
- * Controlled
441
- * (i.e. `value` prop)
442
- */
443
- describe('When value is controlled', () => {
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
- testSingleSelect('Text input renders with value update', () => {
455
- let value = 'apple';
456
- const { inputEl, rerenderCombobox } = renderCombobox(select, {
457
- value,
458
- });
459
- expect(inputEl).toHaveValue('Apple');
460
- value = 'banana';
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
- testSingleSelect('Invalid option passed as value is not selected', () => {
466
- const value = 'jellybean';
467
- const { inputEl } = renderCombobox(select, { value });
468
- expect(inputEl).toHaveValue('');
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
- testMultiSelect('Updating `value` updates the chips', () => {
472
- let value = ['apple', 'banana'];
473
- const { queryChipsByName, queryAllChips, rerenderCombobox } =
474
- renderCombobox(select, {
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
- waitFor(() => {
478
- const allChips = queryChipsByName(['Apple', 'Banana']);
479
- allChips?.forEach(chip => expect(chip).toBeInTheDocument());
480
- expect(queryAllChips()).toHaveLength(2);
481
- value = ['banana', 'carrot'];
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(['Carrot', 'Banana']);
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
- testMultiSelect('Invalid options are not selected', () => {
492
- const value = ['apple', 'jellybean'];
493
- const { queryChipsByName, queryAllChips } = renderCombobox(select, {
494
- value,
495
- });
496
- waitFor(() => {
497
- const allChips = queryChipsByName(['Apple']);
498
- allChips?.forEach(chip => expect(chip).toBeInTheDocument());
499
- expect(queryChipsByName('Jellybean')).not.toBeInTheDocument();
500
- expect(queryAllChips()).toHaveLength(1);
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
- expect(onChange).toHaveBeenCalledWith(
846
- select === 'single' ? 'banana' : ['banana'],
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 = select === 'multiple' ? ['apple'] : 'apple';
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 = select === 'multiple' ? ['apple'] : 'apple';
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 = select === 'multiple' ? ['apple'] : 'apple';
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
- act(() => {
1400
- userEvent.click(clearButtonEl!);
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
- expect(inputEl).toHaveValue('');
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 });