diff --git a/.changeset/entity-picker-display-fix.md b/.changeset/entity-picker-display-fix.md new file mode 100644 index 0000000000..f5a3f2b0bc --- /dev/null +++ b/.changeset/entity-picker-display-fix.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Fixed `EntityPicker` display inconsistency between dropdown options and selected value. diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx index ab3092e3ed..2424d76f5a 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx @@ -812,4 +812,97 @@ describe('', () => { expect(onChange).toHaveBeenCalledWith(undefined); }); }); + + describe('rendering consistency', () => { + beforeEach(() => { + uiSchema = { 'ui:options': {} }; + props = { + onChange, + schema, + required, + uiSchema, + rawErrors, + formData: 'group:default/team-a', + } as unknown as FieldProps; + }); + + it('renders consistent entity display between dropdown and selected value', async () => { + // Mock the presentation API to return specific values for testing + const mockEntityPresentation = { + entityRef: 'group:default/team-a', + primaryTitle: 'Team A', + }; + + // Create a catalog API that includes the specific test entity + const testCatalogApi = catalogApiMock.mock({ + getEntities: jest.fn().mockResolvedValue({ + items: [makeEntity('Group', 'default', 'team-a')], + }), + }); + + // Create mock entity presentation mapping + const entityRefToPresentation = new Map(); + entityRefToPresentation.set( + 'group:default/team-a', + mockEntityPresentation, + ); + + const renderResult = await renderInTestApp( + + + , + ); + + // Wait for the entity data to load and be processed + // This is needed because the EntityPicker uses useAsync + await new Promise(resolve => setTimeout(resolve, 100)); + + // Force a re-render to apply the mocked data + renderResult.rerender( + + + , + ); + + // Force update to complete + await new Promise(resolve => setTimeout(resolve, 100)); + + // Verify the selected value shows the correct display + const input = screen.getByRole('textbox'); + expect(input).toHaveValue('Team A'); + + // Open the dropdown + fireEvent.mouseDown(input); + + // Check if dropdown shows the same representation + const option = await screen.findByText('Team A'); + expect(option).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx index b15c197945..fa62795b40 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx @@ -204,7 +204,7 @@ export const EntityPicker = (props: EntityPickerProps) => { typeof option === 'string' ? option : entities?.entityRefToPresentation.get(stringifyEntityRef(option)) - ?.entityRef! + ?.primaryTitle || stringifyEntityRef(option) } autoSelect freeSolo={allowArbitraryValues}