From 337822c822de09620cfa13604c31b9e10a53845f Mon Sep 17 00:00:00 2001 From: Allan Alexandre Date: Tue, 11 Feb 2020 03:59:29 -0300 Subject: [PATCH] [Autocomplete] Make options required (#19648) --- docs/pages/api/autocomplete.md | 2 +- .../src/Autocomplete/Autocomplete.js | 4 +- .../src/Autocomplete/Autocomplete.test.js | 77 +++++++++++++++++-- .../src/useAutocomplete/useAutocomplete.d.ts | 2 +- .../src/useAutocomplete/useAutocomplete.js | 2 +- 5 files changed, 75 insertions(+), 12 deletions(-) diff --git a/docs/pages/api/autocomplete.md b/docs/pages/api/autocomplete.md index 3785943a126bed..5084808b95ec06 100644 --- a/docs/pages/api/autocomplete.md +++ b/docs/pages/api/autocomplete.md @@ -65,7 +65,7 @@ You can learn more about the difference by [reading this guide](/guides/minimizi | onOpen | func | | Callback fired when the popup requests to be opened. Use in controlled mode (see open).

**Signature:**
`function(event: object) => void`
*event:* The event source of the callback. | | open | bool | | Control the popup` open state. | | openText | string | 'Open' | Override the default text for the *open popup* icon button.
For localization purposes, you can use the provided [translations](/guides/localization/). | -| options | array | [] | Array of options. | +| options * | array | | Array of options. | | PaperComponent | elementType | Paper | The component used to render the body of the popup. | | PopperComponent | elementType | Popper | The component used to position the popup. | | popupIcon | node | <ArrowDropDownIcon /> | The icon to display in place of the default popup icon. | diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.js b/packages/material-ui-lab/src/Autocomplete/Autocomplete.js index 7c556b77758217..ec09d620efb569 100644 --- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.js +++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.js @@ -277,7 +277,7 @@ const Autocomplete = React.forwardRef(function Autocomplete(props, ref) { onOpen, open, openText = 'Open', - options = [], + options, PaperComponent = Paper, PopperComponent: PopperComponentProp = Popper, popupIcon = , @@ -700,7 +700,7 @@ Autocomplete.propTypes = { /** * Array of options. */ - options: PropTypes.array, + options: PropTypes.array.isRequired, /** * The component used to render the body of the popup. */ diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js index f53f87f26787e9..1f9c5eec4286fa 100644 --- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js +++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js @@ -13,13 +13,16 @@ describe('', () => { let mount; let classes; const render = createClientRender(); + const defaultProps = { + options: [], + }; before(() => { - classes = getClasses( null} />); + classes = getClasses( null} />); mount = createMount({ strict: true }); }); - describeConformance( null} />, () => ({ + describeConformance( null} />, () => ({ classes, inheritComponent: 'div', mount, @@ -31,7 +34,7 @@ describe('', () => { describe('combobox', () => { it('should clear the input when blur', () => { const { getByRole } = render( - } />, + } />, ); const input = getByRole('textbox'); input.focus(); @@ -43,7 +46,7 @@ describe('', () => { it('should apply the icon classes', () => { const { container } = render( - } />, + } />, ); expect(container.querySelector(`.${classes.root}`)).to.have.class(classes.hasClearIcon); expect(container.querySelector(`.${classes.root}`)).to.have.class(classes.hasPopupIcon); @@ -55,6 +58,7 @@ describe('', () => { const options = ['one', 'two']; const { getByRole } = render( ', () => { render( ', () => { const options = ['one', 'two']; render( ', () => { const handleChange = spy(); render( ', () => { describe('prop: multiple', () => { it('should not crash', () => { const { getByRole } = render( - } multiple />, + } + multiple + />, ); const input = getByRole('textbox'); input.focus(); @@ -149,6 +160,7 @@ describe('', () => { const options = ['one', 'two']; const { container } = render( ', () => { const options = ['one', 'two']; const { getByRole } = render( ', () => { const handleSubmit = spy(); const { setProps } = render( { if (!event.defaultPrevented && event.key === 'Enter') { @@ -223,7 +237,7 @@ describe('', () => { describe('WAI-ARIA conforming markup', () => { specify('when closed', () => { const { getAllByRole, getByRole, queryByRole } = render( - } />, + } />, ); const combobox = getByRole('combobox'); @@ -259,6 +273,7 @@ describe('', () => { specify('when open', () => { const { getAllByRole, getByRole } = render( } @@ -300,6 +315,7 @@ describe('', () => { it('should add and remove aria-activedescendant', () => { const { getAllByRole, getByRole, setProps } = render( } @@ -325,6 +341,7 @@ describe('', () => { const handleOpen = spy(); render( } />, @@ -338,6 +355,7 @@ describe('', () => { const handleChange = spy(); const { container } = render( ', () => { const handleOpen = spy(); const { getByRole } = render( } @@ -377,6 +396,7 @@ describe('', () => { const handleChange = spy(); render( ', () => { const handleClose = spy(); render( ', () => { it('moves focus to the first option on ArrowDown', () => { const { getAllByRole, getByRole } = render( } />, @@ -427,6 +449,7 @@ describe('', () => { it('moves focus to the last option on ArrowUp', () => { const { getAllByRole, getByRole } = render( } />, @@ -446,6 +469,7 @@ describe('', () => { it('disables open on input focus', () => { const { getByRole } = render( } @@ -480,6 +504,7 @@ describe('', () => { it('wraps around when navigating the list by default', () => { const { getAllByRole } = render( } />, @@ -498,6 +523,7 @@ describe('', () => { it('selects the first item if on the last item and pressing up by default', () => { const { getAllByRole } = render( } />, @@ -517,6 +543,7 @@ describe('', () => { it('considers the textbox the predessor of the first option when pressing Up', () => { render( } @@ -532,6 +559,7 @@ describe('', () => { it('considers the textbox the successor of the last option when pressing Down', () => { render( } @@ -549,6 +577,7 @@ describe('', () => { it('keeps focus on the first item if focus is on the first item and pressing Up', () => { const { getAllByRole } = render( } @@ -567,6 +596,7 @@ describe('', () => { it('focuses the last item when pressing Up when no option is active', () => { const { getAllByRole, getByRole } = render( } @@ -587,6 +617,7 @@ describe('', () => { it('keeps focus on the last item if focus is on the last item and pressing Down', () => { const { getAllByRole, getByRole } = render( } @@ -610,6 +641,7 @@ describe('', () => { it('should disable the input', () => { const { getByRole } = render( } @@ -622,6 +654,7 @@ describe('', () => { it('should disable the popup button', () => { const { queryByTitle } = render( } @@ -633,6 +666,7 @@ describe('', () => { it('should not render the clear button', () => { const { queryByTitle } = render( } @@ -644,6 +678,7 @@ describe('', () => { it('should not apply the hasClearIcon class', () => { const { container } = render( } @@ -658,6 +693,7 @@ describe('', () => { it('should not render the clear button', () => { const { queryByTitle, container } = render( } @@ -683,6 +719,7 @@ describe('', () => { const handleChange = spy(); render( ', () => { it('should keep focus on selected option and not reset to top option when options updated', () => { const { getByRole, setProps } = render( } />, @@ -732,6 +770,7 @@ describe('', () => { const handleChange = spy(); const { getByRole } = render( } @@ -753,6 +792,7 @@ describe('', () => { const handleChange = spy(); render( } @@ -771,6 +811,7 @@ describe('', () => { const options = [{ name: 'one' }, { name: 'two ' }]; render( ', () => { it('add a completion string', () => { render( } @@ -812,7 +854,11 @@ describe('', () => { describe('click input', () => { it('toggles if empty', () => { const { getByRole } = render( - } />, + } + />, ); const textbox = getByRole('textbox'); const combobox = getByRole('combobox'); @@ -826,6 +872,7 @@ describe('', () => { it('selects all the first time', () => { const { getByRole } = render( } @@ -849,6 +896,7 @@ describe('', () => { }; return ( } @@ -870,6 +918,7 @@ describe('', () => { const handleInputChange = spy(); render( ', () => { it('should ignore object keys by default', () => { const { queryAllByRole } = render( ', () => { const filterOptions = createFilterOptions({ limit: 2 }); const { queryAllByRole } = render( } filterOptions={filterOptions} @@ -929,6 +980,7 @@ describe('', () => { const filterOptions = createFilterOptions({}); const { queryAllByRole } = render( } filterOptions={filterOptions} @@ -944,6 +996,7 @@ describe('', () => { const options = [{ name: 'foo' }]; render( ', () => { const options = ['one', 'two']; const { container } = render( ', () => { const handleChange = spy(); render( } @@ -1005,6 +1060,7 @@ describe('', () => { const options = [{ name: 'foo' }]; render( option.name} @@ -1022,6 +1078,7 @@ describe('', () => { const options = [{ name: 'foo' }]; render( option.name} @@ -1041,6 +1098,7 @@ describe('', () => { const options = [{ name: 'foo' }]; const { getByRole, queryByTitle } = render( option.name} renderInput={params => } @@ -1066,6 +1124,7 @@ describe('', () => { const options = [{ name: 'foo' }]; const { getByRole, queryByTitle } = render( option.name} renderInput={params => } @@ -1089,6 +1148,7 @@ describe('', () => { const options = [{ name: 'foo' }]; const { getByRole, queryByTitle } = render( option.name} renderInput={params => } @@ -1113,6 +1173,7 @@ describe('', () => { it('is considered for falsy values when filtering the the list of options', () => { const { getAllByRole } = render( (option === 0 ? 'Any' : option.toString())} renderInput={params => } @@ -1127,6 +1188,7 @@ describe('', () => { it('is not considered for nullish values when filtering the list of options', () => { const { getAllByRole } = render( (option === null ? 'Any' : option.toString())} renderInput={params => } @@ -1152,6 +1214,7 @@ describe('', () => { ]; const { getAllByRole } = render( option.value} renderInput={params => } diff --git a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.d.ts b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.d.ts index 6684db824215af..86de086256f888 100644 --- a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.d.ts +++ b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.d.ts @@ -157,7 +157,7 @@ export interface UseAutocompleteCommonProps { /** * Array of options. */ - options?: T[]; + options: T[]; /** * If `true`, the input's text will be selected on focus. */ diff --git a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js index dfd6171c8ef983..c8b32008482e56 100644 --- a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js +++ b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js @@ -108,7 +108,7 @@ export default function useAutocomplete(props) { onOpen, onInputChange, open: openProp, - options = [], + options, selectOnFocus = !props.freeSolo, value: valueProp, componentName = 'useAutocomplete',