From 26dede1636126a36e2cf815423ff085a477ad91c Mon Sep 17 00:00:00 2001 From: Ugo Stephant Date: Fri, 25 Nov 2022 16:18:36 +0100 Subject: [PATCH] fix(react): correctly handle controlled selectfields --- packages/react/lib/SelectField/index.d.ts | 1 - packages/react/lib/SelectField/index.js | 4 +- .../react/lib/SelectField/index.stories.js | 18 +++++++ packages/react/lib/SelectField/index.test.js | 39 +++++++++++++- .../react/lib/SelectField/index.test.js.snap | 52 +++++++++++++++++++ 5 files changed, 109 insertions(+), 5 deletions(-) diff --git a/packages/react/lib/SelectField/index.d.ts b/packages/react/lib/SelectField/index.d.ts index e8a72b620..c65f147b5 100644 --- a/packages/react/lib/SelectField/index.d.ts +++ b/packages/react/lib/SelectField/index.d.ts @@ -31,7 +31,6 @@ declare interface SelectFieldProps extends React.ComponentPropsWithRef { searchThreshold?: number; required?: Boolean; onChange?: (props: { value: any; valid: Boolean }) => void; - parseItem?: (option: any) => any; parseTitle?: (option: any) => String; parseValue?: (option: any) => any; onBlur?: (event: Event) => void; diff --git a/packages/react/lib/SelectField/index.js b/packages/react/lib/SelectField/index.js index c3ff6e3c0..9c0b8a37d 100644 --- a/packages/react/lib/SelectField/index.js +++ b/packages/react/lib/SelectField/index.js @@ -44,7 +44,6 @@ const SelectField = forwardRef(({ searchThreshold = 400, required = false, onChange, - parseItem = val => val, parseTitle = val => val?.toString?.(), parseValue = val => val, onBlur, @@ -317,7 +316,7 @@ const SelectField = forwardRef(({ const findOptions = val => { const isMultiple = multiple && Array.isArray(val); const res = (isMultiple ? val : [val]).map(v => - findDeep(options, o => parseItem(o) === parseItem(v), o => o.options) || + findDeep(options, o => parseValue(o) === parseValue(v), o => o.options) || v ); @@ -479,7 +478,6 @@ SelectField.propTypes = { onKeyUp: PropTypes.func, onSearch: PropTypes.func, onValidate: PropTypes.func, - parseItem: PropTypes.func, parseTitle: PropTypes.func, parseValue: PropTypes.func, }; diff --git a/packages/react/lib/SelectField/index.stories.js b/packages/react/lib/SelectField/index.stories.js index e503e72ea..2a26023ac 100644 --- a/packages/react/lib/SelectField/index.stories.js +++ b/packages/react/lib/SelectField/index.stories.js @@ -1,4 +1,6 @@ +import { useState } from 'react'; import { slideInDownMenu } from '@junipero/transitions'; +import { action } from '@storybook/addon-actions'; import FieldControl from '../FieldControl'; import Label from '../Label'; @@ -11,9 +13,25 @@ export const basic = () => ( ); +export const controlled = () => { + const [value, setValue] = useState('Item 1'); + + return ( + o.title || o} + parseValue={o => o.value || o} + onChange={field => setValue(field.value)} + /> + ); +}; + export const autoFocused = () => ( ', () => { unmount(); }); + + it('should allow to use object options and display custom titles on a ' + + 'controlled field', async () => { + const user = userEvent.setup(); + + const ControlledField = () => { + const [value, setValue] = useState('Item 1'); + + return ( + <> +

Value: { value }

+ o.title || o} + parseValue={o => o.value || o} + onChange={field => setValue(field.value)} + /> + + ); + }; + + const { unmount, container, getByText } = render(); + + const input = container.querySelector('input'); + await user.click(input); + await user.click(getByText('Item 3')); + + expect(container).toMatchSnapshot(); + + unmount(); + }); }); diff --git a/packages/react/lib/SelectField/index.test.js.snap b/packages/react/lib/SelectField/index.test.js.snap index d310d4448..930ab707f 100644 --- a/packages/react/lib/SelectField/index.test.js.snap +++ b/packages/react/lib/SelectField/index.test.js.snap @@ -1382,6 +1382,58 @@ exports[` should allow to search for an external value 2`] = ` `; +exports[` should allow to use object options and display custom titles on a controlled field 1`] = ` +
+

+ Value: + item-3 +

+ +
+`; + exports[` should be invalid if validation fails 1`] = `