From 2a686e5da7cffcaa98bf33ae6ab04dfa52bfbe2c Mon Sep 17 00:00:00 2001 From: oziniak Date: Sun, 3 Nov 2019 17:00:56 +0200 Subject: [PATCH 1/3] issue/18123: autocomplere, free solo, options as array of objects --- .../src/Autocomplete/Autocomplete.test.js | 22 +++++++++++++++++++ .../src/useAutocomplete/useAutocomplete.js | 2 ++ 2 files changed, 24 insertions(+) diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js index c9d0372ac38577..97b2e88d20e02c 100644 --- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js +++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js @@ -6,6 +6,7 @@ import { spy } from 'sinon'; import { createClientRender, fireEvent } from 'test/utils/createClientRender'; import Autocomplete from './Autocomplete'; import TextField from '@material-ui/core/TextField'; +import { spy } from 'sinon'; describe('', () => { let mount; @@ -369,4 +370,25 @@ describe('', () => { }); }); }); + + describe('free solo', () => { + it('should accept any value', () => { + const options = [{ name: 'test' }, { name: 'foo' }]; + const handleChange = spy(); + const { container } = render( + option.name} + renderInput={params => } + />, + ); + const input = container.querySelector('input'); + fireEvent.change(input, { target: { value: 'a' } }); + fireEvent.keyDown(input, { key: 'Enter' }); + expect(handleChange.callCount).to.equal(1); + expect(handleChange.args[0][1]).to.equal('a'); + }); + }); }); diff --git a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js index 1d947d6ffc27e1..fba6b3480a3eaf 100644 --- a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js +++ b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js @@ -171,6 +171,8 @@ export default function useAutocomplete(props) { let newInputValue; if (multiple) { newInputValue = ''; + } else if (freeSolo && typeof newValue === 'string') { + newInputValue = newValue; } else { newInputValue = newValue != null ? getOptionLabel(newValue) : ''; } From e0e6996383c6df1f9720f574d5003d8378a083cd Mon Sep 17 00:00:00 2001 From: Olivier Tassinari Date: Sun, 3 Nov 2019 22:32:48 +0100 Subject: [PATCH 2/3] yarn prettier --- packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js index 97b2e88d20e02c..09f17e9d5513d7 100644 --- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js +++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js @@ -6,7 +6,6 @@ import { spy } from 'sinon'; import { createClientRender, fireEvent } from 'test/utils/createClientRender'; import Autocomplete from './Autocomplete'; import TextField from '@material-ui/core/TextField'; -import { spy } from 'sinon'; describe('', () => { let mount; From bb8de22f4562ac27bf3ebc2514ec6018beb23a3c Mon Sep 17 00:00:00 2001 From: Olivier Tassinari Date: Mon, 4 Nov 2019 10:40:02 +0100 Subject: [PATCH 3/3] use a warning + fallback --- .../src/Autocomplete/Autocomplete.test.js | 20 +++++++++++++---- .../src/useAutocomplete/useAutocomplete.js | 22 ++++++++++++++++--- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js index 09f17e9d5513d7..b463d22b2b8162 100644 --- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js +++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js @@ -2,6 +2,7 @@ import React from 'react'; import { expect } from 'chai'; import { createMount, getClasses } from '@material-ui/core/test-utils'; import describeConformance from '@material-ui/core/test-utils/describeConformance'; +import consoleErrorMock from 'test/utils/consoleErrorMock'; import { spy } from 'sinon'; import { createClientRender, fireEvent } from 'test/utils/createClientRender'; import Autocomplete from './Autocomplete'; @@ -370,15 +371,22 @@ describe('', () => { }); }); - describe('free solo', () => { - it('should accept any value', () => { - const options = [{ name: 'test' }, { name: 'foo' }]; + describe('warnings', () => { + beforeEach(() => { + consoleErrorMock.spy(); + }); + + afterEach(() => { + consoleErrorMock.reset(); + }); + + it('warn if getOptionLabel do not return a string', () => { const handleChange = spy(); const { container } = render( option.name} renderInput={params => } />, @@ -388,6 +396,10 @@ describe('', () => { fireEvent.keyDown(input, { key: 'Enter' }); expect(handleChange.callCount).to.equal(1); expect(handleChange.args[0][1]).to.equal('a'); + expect(consoleErrorMock.callCount()).to.equal(2); // strict mode renders twice + expect(consoleErrorMock.args()[0][0]).to.include( + 'For the input option: "a", `getOptionLabel` returns: undefined', + ); }); }); }); diff --git a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js index fba6b3480a3eaf..72d7c84c367f72 100644 --- a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js +++ b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js @@ -171,10 +171,26 @@ export default function useAutocomplete(props) { let newInputValue; if (multiple) { newInputValue = ''; - } else if (freeSolo && typeof newValue === 'string') { - newInputValue = newValue; + } else if (newValue == null) { + newInputValue = ''; } else { - newInputValue = newValue != null ? getOptionLabel(newValue) : ''; + const optionLabel = getOptionLabel(newValue); + + if (process.env.NODE_ENV !== 'production') { + if (typeof optionLabel !== 'string') { + console.error( + [ + 'Material-UI: the `getOptionLabel` method of useAutocomplete do not handle the options correctly.', + `The component expect a string but received ${typeof optionLabel}.`, + `For the input option: ${JSON.stringify( + newValue, + )}, \`getOptionLabel\` returns: ${newInputValue}.`, + ].join('\n'), + ); + } + } + + newInputValue = typeof optionLabel === 'string' ? optionLabel : ''; } setInputValue(newInputValue);