mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	fix: improve selecting projects
Adds tests to the form for creating API tokens.
This commit is contained in:
		
							parent
							
								
									b5db7b8326
								
							
						
					
					
						commit
						bb8ceabbaf
					
				| @ -3,5 +3,6 @@ import { makeStyles } from '@material-ui/core/styles'; | ||||
| export const useStyles = makeStyles(theme => ({ | ||||
|     selectOptionsLink: { | ||||
|         cursor: 'pointer', | ||||
|         fontSize: theme.fontSizes.bodySize, | ||||
|     }, | ||||
| })); | ||||
|  | ||||
| @ -15,7 +15,11 @@ export const SelectAllButton: FC<SelectAllButtonProps> = ({ | ||||
| 
 | ||||
|     return ( | ||||
|         <Box sx={{ ml: 3.5, my: 0.5 }}> | ||||
|             <Link onClick={onClick} className={styles.selectOptionsLink}> | ||||
|             <Link | ||||
|                 onClick={onClick} | ||||
|                 className={styles.selectOptionsLink} | ||||
|                 component="button" | ||||
|             > | ||||
|                 {isAllSelected ? 'Deselect all' : 'Select all'} | ||||
|             </Link> | ||||
|         </Box> | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import React from 'react'; | ||||
| import { screen, within } from '@testing-library/react'; | ||||
| import { screen, waitFor, within } from '@testing-library/react'; | ||||
| import userEvent from '@testing-library/user-event'; | ||||
| import { render } from 'utils/testRenderer'; | ||||
| import { | ||||
| @ -14,6 +14,7 @@ const mockProps: ISelectProjectInputProps = { | ||||
|     options: [ | ||||
|         { label: 'Project1', value: 'project1' }, | ||||
|         { label: 'Project2', value: 'project2' }, | ||||
|         { label: 'Project3', value: 'project3' }, | ||||
|     ], | ||||
|     defaultValue: ['*'], | ||||
|     onChange, | ||||
| @ -59,4 +60,106 @@ describe('SelectProjectInput', () => { | ||||
| 
 | ||||
|         expect(screen.getByLabelText('Projects')).toBeDisabled(); | ||||
|     }); | ||||
| 
 | ||||
|     it('renders with autocomplete enabled if default value is not a wildcard', () => { | ||||
|         render( | ||||
|             <SelectProjectInput {...mockProps} defaultValue={['project1']} /> | ||||
|         ); | ||||
| 
 | ||||
|         const checkbox = screen.getByLabelText( | ||||
|             /all current and future projects/i | ||||
|         ); | ||||
|         expect(checkbox).not.toBeChecked(); | ||||
| 
 | ||||
|         const selectInputContainer = screen.getByTestId('select-input'); | ||||
|         const input = within(selectInputContainer).getByRole('textbox'); | ||||
|         expect(input).toBeEnabled(); | ||||
|     }); | ||||
| 
 | ||||
|     describe('Select/Deselect projects in dropdown', () => { | ||||
|         it('selects and deselects all options', async () => { | ||||
|             const user = userEvent.setup(); | ||||
|             render(<SelectProjectInput {...mockProps} defaultValue={[]} />); | ||||
|             await user.click(screen.getByLabelText('Projects')); | ||||
| 
 | ||||
|             let button = screen.getByRole('button', { | ||||
|                 name: /select all/i, | ||||
|             }); | ||||
|             expect(button).toBeInTheDocument(); | ||||
|             await user.click(button); | ||||
| 
 | ||||
|             expect(onChange).toHaveBeenCalledWith([ | ||||
|                 'project1', | ||||
|                 'project2', | ||||
|                 'project3', | ||||
|             ]); | ||||
| 
 | ||||
|             button = screen.getByRole('button', { | ||||
|                 name: /deselect all/i, | ||||
|             }); | ||||
|             expect(button).toBeInTheDocument(); | ||||
|             await user.click(button); | ||||
|             expect(onChange).toHaveBeenCalledWith([]); | ||||
|         }); | ||||
| 
 | ||||
|         it("doesn't show up for less than 3 options", async () => { | ||||
|             const user = userEvent.setup(); | ||||
|             render( | ||||
|                 <SelectProjectInput | ||||
|                     {...mockProps} | ||||
|                     defaultValue={[]} | ||||
|                     options={[ | ||||
|                         { label: 'Project1', value: 'project1' }, | ||||
|                         { label: 'Project2', value: 'project2' }, | ||||
|                     ]} | ||||
|                 /> | ||||
|             ); | ||||
|             await user.click(screen.getByLabelText('Projects')); | ||||
| 
 | ||||
|             const button = screen.queryByRole('button', { | ||||
|                 name: /select all/i, | ||||
|             }); | ||||
|             expect(button).not.toBeInTheDocument(); | ||||
|         }); | ||||
|     }); | ||||
| 
 | ||||
|     it('can filter options', async () => { | ||||
|         const user = userEvent.setup(); | ||||
|         render( | ||||
|             <SelectProjectInput | ||||
|                 {...mockProps} | ||||
|                 defaultValue={[]} | ||||
|                 options={[ | ||||
|                     { label: 'Alpha', value: 'alpha' }, | ||||
|                     { label: 'Bravo', value: 'bravo' }, | ||||
|                     { label: 'Charlie', value: 'charlie' }, | ||||
|                     { label: 'Alpaca', value: 'alpaca' }, | ||||
|                 ]} | ||||
|             /> | ||||
|         ); | ||||
|         const input = await screen.findByLabelText('Projects'); | ||||
|         user.type(input, 'alp'); | ||||
| 
 | ||||
|         await waitFor(() => { | ||||
|             expect(screen.getByText('Alpha')).toBeVisible(); | ||||
|         }); | ||||
|         await waitFor(() => { | ||||
|             expect(screen.queryByText('Bravo')).not.toBeInTheDocument(); | ||||
|         }); | ||||
|         await waitFor(() => { | ||||
|             expect(screen.queryByText('Charlie')).not.toBeInTheDocument(); | ||||
|         }); | ||||
|         await waitFor(() => { | ||||
|             expect(screen.getByText('Alpaca')).toBeVisible(); | ||||
|         }); | ||||
| 
 | ||||
|         user.clear(input); | ||||
|         user.type(input, 'bravo'); | ||||
|         await waitFor(() => { | ||||
|             expect(screen.getByText('Bravo')).toBeVisible(); | ||||
|         }); | ||||
|         await waitFor(() => { | ||||
|             expect(screen.queryByText('Alpha')).not.toBeInTheDocument(); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| @ -17,6 +17,7 @@ import CheckBoxIcon from '@material-ui/icons/CheckBox'; | ||||
| import { IAutocompleteBoxOption } from 'component/common/AutocompleteBox/AutocompleteBox'; | ||||
| import { useStyles } from '../ApiTokenForm.styles'; | ||||
| import { SelectAllButton } from './SelectAllButton/SelectAllButton'; | ||||
| import ConditionallyRender from 'component/common/ConditionallyRender'; | ||||
| 
 | ||||
| const ALL_PROJECTS = '*'; | ||||
| 
 | ||||
| @ -47,7 +48,10 @@ export const SelectProjectInput: VFC<ISelectProjectInputProps> = ({ | ||||
|     const [isWildcardSelected, selectWildcard] = useState( | ||||
|         typeof defaultValue === 'string' || defaultValue.includes(ALL_PROJECTS) | ||||
|     ); | ||||
|     const isAllSelected = projects.length === options.length; | ||||
|     const isAllSelected = | ||||
|         projects.length > 0 && | ||||
|         projects.length === options.length && | ||||
|         projects[0] !== ALL_PROJECTS; | ||||
| 
 | ||||
|     const onAllProjectsChange = ( | ||||
|         e: ChangeEvent<HTMLInputElement>, | ||||
| @ -62,6 +66,14 @@ export const SelectProjectInput: VFC<ISelectProjectInputProps> = ({ | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     const onSelectAllClick = () => { | ||||
|         const newProjects = isAllSelected | ||||
|             ? [] | ||||
|             : options.map(({ value }) => value); | ||||
|         setProjects(newProjects); | ||||
|         onChange(newProjects); | ||||
|     }; | ||||
| 
 | ||||
|     const renderOption = ( | ||||
|         option: IAutocompleteBoxOption, | ||||
|         { selected }: AutocompleteRenderOptionState | ||||
| @ -79,13 +91,14 @@ export const SelectProjectInput: VFC<ISelectProjectInputProps> = ({ | ||||
| 
 | ||||
|     const renderGroup = ({ key, children }: AutocompleteRenderGroupParams) => ( | ||||
|         <Fragment key={key}> | ||||
|             <SelectAllButton | ||||
|                 isAllSelected={isAllSelected} | ||||
|                 onClick={() => { | ||||
|                     setProjects( | ||||
|                         isAllSelected ? [] : options.map(({ value }) => value) | ||||
|                     ); | ||||
|                 }} | ||||
|             <ConditionallyRender | ||||
|                 condition={options.length > 2} | ||||
|                 show={ | ||||
|                     <SelectAllButton | ||||
|                         isAllSelected={isAllSelected} | ||||
|                         onClick={onSelectAllClick} | ||||
|                     /> | ||||
|                 } | ||||
|             /> | ||||
|             {children} | ||||
|         </Fragment> | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user