diff --git a/packages/react-aria-components/test/Select.test.js b/packages/react-aria-components/test/Select.test.js index df4906037d2..a14bfb2cbce 100644 --- a/packages/react-aria-components/test/Select.test.js +++ b/packages/react-aria-components/test/Select.test.js @@ -95,6 +95,112 @@ describe('Select', () => { expect(trigger).toHaveTextContent('Dog'); }); + it('should bubble a change event from the hidden select when a ListBox option is selected', async () => { + let onChange = jest.fn(); + let {getByTestId} = render( +
onChange(e.target)}> + + + ); + let wrapper = getByTestId('select'); + let selectTester = testUtilUser.createTester('Select', {root: wrapper}); + let hiddenSelect = document.querySelector('select[name="animal"]'); + + await selectTester.toggleOptionSelection({option: 'Dog'}); + + expect(onChange).toHaveBeenCalledTimes(1); + expect(onChange).toHaveBeenCalledWith(hiddenSelect); + expect(hiddenSelect).toHaveValue('dog'); + }); + + it('should bubble a native change event from the hidden select only once', async () => { + let onChange = jest.fn(); + render( +
onChange(e.target)}> + + + ); + let hiddenSelect = document.querySelector('select[name="animal"]'); + + await user.selectOptions(hiddenSelect, 'dog'); + + expect(onChange).toHaveBeenCalledTimes(1); + expect(onChange).toHaveBeenCalledWith(hiddenSelect); + expect(hiddenSelect).toHaveValue('dog'); + }); + + it('should bubble a change event for a controlled select', async () => { + let onChange = jest.fn(); + let values = []; + + function ControlledSelect() { + let [value, setValue] = useState('cat'); + return ( + { + onChange(value); + setValue(value); + }} + /> + ); + } + + let {getByTestId} = render( +
values.push(e.target.value)}> + + + ); + let wrapper = getByTestId('select'); + let selectTester = testUtilUser.createTester('Select', {root: wrapper}); + let hiddenSelect = document.querySelector('select[name="animal"]'); + + await selectTester.toggleOptionSelection({option: 'Dog'}); + + expect(onChange).toHaveBeenCalledWith('dog'); + expect(values).toEqual(['dog']); + expect(hiddenSelect).toHaveValue('dog'); + }); + + it('should not bubble a change event when the form is reset', async () => { + let onChange = jest.fn(); + let formRef = React.createRef(); + let {getByTestId} = render( +
+ + + ); + let wrapper = getByTestId('select'); + let selectTester = testUtilUser.createTester('Select', {root: wrapper}); + let hiddenSelect = document.querySelector('select[name="animal"]'); + + await selectTester.toggleOptionSelection({option: 'Dog'}); + expect(onChange).toHaveBeenCalledTimes(1); + onChange.mockClear(); + + act(() => formRef.current.reset()); + + expect(onChange).not.toHaveBeenCalled(); + expect(hiddenSelect).toHaveValue('cat'); + }); + + it('should bubble change events with the selected options for multiple selection', async () => { + let values = []; + let {getByTestId} = render( +
values.push([...e.target.selectedOptions].map(option => option.value))}> + + + ); + let wrapper = getByTestId('select'); + let selectTester = testUtilUser.createTester('Select', {root: wrapper}); + + await selectTester.toggleOptionSelection({option: 'Cat'}); + await selectTester.toggleOptionSelection({option: 'Dog'}); + + expect(values).toEqual([['cat'], ['cat', 'dog']]); + }); + it('should support slot', () => { let {getByTestId} = render( @@ -748,12 +854,16 @@ describe('Select', () => { it('should support multiple selection form integration with many items', async () => { let items = []; + let values = []; for (let i = 0; i < 320; i++) { items.push({id: i, name: 'item' + i}); } let {getByTestId} = render( -
e.preventDefault()}> + values.push([...e.target.selectedOptions].map(option => option.value))} + onSubmit={e => e.preventDefault()}> cannot have `display: none` or `hidden` for autofill to work. // In Firefox, there must be a