diff --git a/.changeset/empty-mugs-agree.md b/.changeset/empty-mugs-agree.md new file mode 100644 index 0000000000..80dd35b8cf --- /dev/null +++ b/.changeset/empty-mugs-agree.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Filter MultiEntityPicker options based on rendered option value diff --git a/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.test.tsx index acae3418b9..a02d793a34 100644 --- a/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.test.tsx @@ -947,4 +947,81 @@ describe('', () => { expect(getByText(description.fromUiSchema)).toBeInTheDocument(); }); }); + + describe('entity presentation', () => { + beforeEach(() => { + uiSchema = { + 'ui:options': { + defaultKind: 'Group', + }, + }; + props = { + onChange, + schema, + required, + uiSchema, + rawErrors, + formData, + } as unknown as FieldProps; + }); + + it('renders and filters selection displayName', async () => { + catalogApi.getEntities.mockResolvedValue({ + items: entities.map(item => ({ + ...item, + spec: { + profile: { displayName: item.metadata.name.replace('-', ' ') }, + }, + })), + }); + + const { getByRole, getByText } = await renderInTestApp( + + + , + ); + + const input = getByRole('textbox'); + + fireEvent.change(input, { target: { value: 'team a' } }); + + expect(getByText('team a')).toBeInTheDocument(); + + fireEvent.change(input, { target: { value: 'squad b' } }); + + expect(getByText('squad b')).toBeInTheDocument(); + + fireEvent.blur(input); + }); + + it('renders and filters selection title', async () => { + catalogApi.getEntities.mockResolvedValue({ + items: entities.map(item => ({ + ...item, + metadata: { + ...item.metadata, + title: item.metadata.name.replace('-', ' ').toUpperCase(), + }, + })), + }); + + const { getByRole, getByText } = await renderInTestApp( + + + , + ); + + const input = getByRole('textbox'); + + fireEvent.change(input, { target: { value: 'team a' } }); + + expect(getByText('TEAM A')).toBeInTheDocument(); + + fireEvent.change(input, { target: { value: 'squad b' } }); + + expect(getByText('SQUAD B')).toBeInTheDocument(); + + fireEvent.blur(input); + }); + }); }); diff --git a/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx b/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx index e7dcf0f996..57c4b87d6d 100644 --- a/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/MultiEntityPicker/MultiEntityPicker.tsx @@ -32,6 +32,7 @@ import { import TextField from '@material-ui/core/TextField'; import Autocomplete, { AutocompleteChangeReason, + createFilterOptions, } from '@material-ui/lab/Autocomplete'; import { useCallback, useEffect, useState } from 'react'; import useAsync from 'react-use/esm/useAsync'; @@ -203,6 +204,11 @@ export const MultiEntityPicker = (props: MultiEntityPickerProps) => { }} /> )} + filterOptions={createFilterOptions({ + stringify: option => + entities?.entityRefToPresentation.get(stringifyEntityRef(option)) + ?.primaryTitle!, + })} ListboxComponent={VirtualizedListbox} />