diff --git a/packages/components/src/custom-select-control-v2/legacy-component/index.tsx b/packages/components/src/custom-select-control-v2/legacy-component/index.tsx index 2e35965e86e982..6c5c1effaa377f 100644 --- a/packages/components/src/custom-select-control-v2/legacy-component/index.tsx +++ b/packages/components/src/custom-select-control-v2/legacy-component/index.tsx @@ -30,7 +30,9 @@ function CustomSelectControl( props: LegacyCustomSelectProps ) { // Forward props + store from v2 implementation const store = Ariakit.useSelectStore( { async setValue( nextValue ) { - if ( ! onChange ) return; + if ( ! onChange ) { + return; + } // Executes the logic in a microtask after the popup is closed. // This is simply to ensure the isOpen state matches that in Downshift. @@ -48,6 +50,7 @@ function CustomSelectControl( props: LegacyCustomSelectProps ) { selectedItem: option!, type: '', }; + onChange( changeObject ); }, } ); @@ -131,7 +134,6 @@ export default CustomSelectControl; // for backwards compatibility export function ClassicCustomSelectControl( props: LegacyCustomSelectProps ) { - console.debug( props ); return ( expect( screen.getByRole( 'option', { name } ) ).toHaveClass( - customClass + className ) ); @@ -160,7 +167,7 @@ describe.each( [ // assert against filtered array itemsWithoutClass.map( ( { name } ) => expect( screen.getByRole( 'option', { name } ) ).not.toHaveClass( - customClass + className ) ); } ); @@ -286,7 +293,7 @@ describe.each( [ expect.objectContaining( { inputValue: '', isOpen: false, - selectedItem: { key: 'violets', name: 'violets' }, + selectedItem: { key: 'flower1', name: 'violets' }, type: '', } ) ); @@ -302,8 +309,13 @@ describe.each( [ expect.objectContaining( { inputValue: '', isOpen: false, + selectedItem: expect.objectContaining( { name: 'aquamarine', + style: { + backgroundColor: 'rgb(127, 255, 212)', + rotate: '13deg', + }, } ), type: '', } ) @@ -328,7 +340,7 @@ describe.each( [ await type( 'p' ); await press.Enter(); - expect( mockOnChange ).toHaveReturnedWith( 'poppy' ); + expect( mockOnChange ).toHaveReturnedWith( 'flower1' ); } ); describe( 'Keyboard behavior and accessibility', () => { @@ -457,4 +469,39 @@ describe.each( [ ).toBeVisible(); } ); } ); + + // V1 styles items via a `style` or `className` metadata property in the option item object. Some consumers still expect it, e.g: + // + // - https://github.com/WordPress/gutenberg/blob/trunk/packages/block-editor/src/components/font-appearance-control/index.js#L216 + // + // Returning these properties as part of the item object was not tested as part of the V1 test. Possibly this was an accidental API? + // or was it intentional? If intentional, we might need to implement something similar in V2, too? The alternative is to rely on the + // `key` attriute for the item and get the actual data from some dictionary in a store somewhere, which would require refactoring + // consumers that rely on the self-contained `style` and `className` attributes. + it( 'Should return style metadata as part of the selected option from onChange', async () => { + const mockOnChange = jest.fn(); + + render( ); + + await click( + screen.getByRole( 'combobox', { + expanded: false, + } ) + ); + + await click( + screen.getByRole( 'option', { + name: 'aquarela', + } ) + ); + + expect( mockOnChange ).toHaveBeenCalledWith( + expect.objectContaining( { + selectedItem: expect.objectContaining( { + className, + style, + } ), + } ) + ); + } ); } );