Repository: mui/material-ui (TypeScript)
Date: 2019-11-06 11:16:17+00:00
Task type: Bug Fix

Issue:
Autocomplete crash in multiple selection mode
<!-- Provide a general summary of the issue in the Title above -->
When multiple selections are enabled on an Autocomplete component, it's possible to crash the component by 
1. Clearing all options
2. Selecting a valid option
3. Pressing `Enter`

This can be duplicated on the Autocomplete [demo page](https://material-ui.com/components/autocomplete/).

![ezgif com-video-to-gif](https://user-images.githubusercontent.com/21050226/68244122-216d1700-ffe2-11e9-91cb-f19ae0cdd280.gif)

- [x] The issue is present in the latest release.
- [x] I have searched the [issues](https://github.com/mui-org/material-ui/issues) of this repository and believe that this is not a duplicate.

## Current Behavior 😯

I am using a similar `getOptionLabel ` function as the demo page, where the title property of the given option is returned as the label. Instead of the `Enter` keypress being ignored when no value is selected, an `undefined` filter value is passed along and the `getOptionLabel` can't resolve a property of an undefined error.

## Expected Behavior 🤔

Empty filter values should short-circuit long before the `getOptionLabel` function is called.

## Steps to Reproduce 🕹

See above.

## Context 🔦

A workaround for this looks like this in code:
```
getOptionLabel={option => (option ? option.title : '')}
```
and this in the Autocomplete text field...

![Screen Shot 2019-11-05 at 3 46 27 PM](https://user-images.githubusercontent.com/21050226/68244742-73fb0300-ffe3-11e9-9e00-ebc17085ad47.png)

... which is nasty.

## Your Environment 🌎

As mentioned above, this happens on the Autocomplete demo page using Chrome 78. This seems like a pretty straightforward bug.



Issue discussion:
@stevemoncada Thank you for the report, It's the same root cause as #18211. The proposed fix applies here too. 

Solution patch:
diff --git a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
--- a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
+++ b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
@@ -527,7 +527,7 @@ export default function useAutocomplete(props) {
         handleFocusTag(event, 'next');
         break;
       case 'Enter':
-        if (highlightedIndexRef.current !== -1) {
+        if (highlightedIndexRef.current !== -1 && popupOpen) {
           // We don't want to validate the form.
           event.preventDefault();
           selectNewValue(event, filteredOptions[highlightedIndexRef.current]);


Test patch:
diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js
--- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js
+++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js
@@ -421,7 +421,7 @@ describe('<Autocomplete />', () => {
         <Autocomplete
           freeSolo
           onChange={handleChange}
-          options={[{ name: 'test' }, { name: 'foo' }]}
+          options={[{ name: 'one' }, { name: 'two ' }]}
           getOptionLabel={option => option.name}
           renderInput={params => <TextField {...params} />}
         />,
@@ -437,4 +437,47 @@ describe('<Autocomplete />', () => {
       );
     });
   });
+
+  describe('enter', () => {
+    it('select a single value when enter is pressed', () => {
+      const handleChange = spy();
+      const { container } = render(
+        <Autocomplete
+          onChange={handleChange}
+          options={['one', 'two  ']}
+          renderInput={params => <TextField {...params} />}
+        />,
+      );
+      const input = container.querySelector('input');
+      fireEvent.keyDown(input, { key: 'ArrowDown' });
+      fireEvent.keyDown(input, { key: 'ArrowDown' });
+      fireEvent.keyDown(input, { key: 'Enter' });
+      expect(handleChange.callCount).to.equal(1);
+      expect(handleChange.args[0][1]).to.equal('one');
+      fireEvent.keyDown(input, { key: 'Enter' });
+      expect(handleChange.callCount).to.equal(1);
+    });
+
+    it('select multiple value when enter is pressed', () => {
+      const handleChange = spy();
+      const options = [{ name: 'one' }, { name: 'two ' }];
+      const { container } = render(
+        <Autocomplete
+          multiple
+          onChange={handleChange}
+          options={options}
+          getOptionLabel={option => option.name}
+          renderInput={params => <TextField {...params} />}
+        />,
+      );
+      const input = container.querySelector('input');
+      fireEvent.keyDown(input, { key: 'ArrowDown' });
+      fireEvent.keyDown(input, { key: 'ArrowDown' });
+      fireEvent.keyDown(input, { key: 'Enter' });
+      expect(handleChange.callCount).to.equal(1);
+      expect(handleChange.args[0][1]).to.deep.equal([options[0]]);
+      fireEvent.keyDown(input, { key: 'Enter' });
+      expect(handleChange.callCount).to.equal(1);
+    });
+  });
 });