diff --git a/.changeset/purple-years-cross.md b/.changeset/purple-years-cross.md new file mode 100644 index 0000000000..e617e95204 --- /dev/null +++ b/.changeset/purple-years-cross.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-org': patch +--- + +Added support for `spec.profile.displayName` to be used in the `MyGroupsSidebarItem` component via the `EntityDisplayName` component when you are a member of multiple Groups. diff --git a/plugins/org/src/components/MyGroupsSidebarItem/MyGroupsSidebarItem.test.tsx b/plugins/org/src/components/MyGroupsSidebarItem/MyGroupsSidebarItem.test.tsx index de46be98be..c870d58cc1 100644 --- a/plugins/org/src/components/MyGroupsSidebarItem/MyGroupsSidebarItem.test.tsx +++ b/plugins/org/src/components/MyGroupsSidebarItem/MyGroupsSidebarItem.test.tsx @@ -24,8 +24,15 @@ import { MyGroupsSidebarItem } from './MyGroupsSidebarItem'; import GroupIcon from '@material-ui/icons/People'; import { identityApiRef } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; -import { catalogApiRef, entityRouteRef } from '@backstage/plugin-catalog-react'; +import { + catalogApiRef, + entityPresentationApiRef, + entityRouteRef, +} from '@backstage/plugin-catalog-react'; import { catalogApiMock } from '@backstage/plugin-catalog-react/testUtils'; +import { DefaultEntityPresentationApi } from '@backstage/plugin-catalog'; +import userEvent from '@testing-library/user-event'; +import { screen } from '@testing-library/react'; describe('MyGroupsSidebarItem Test', () => { describe('For guests or users with no groups', () => { @@ -40,6 +47,10 @@ describe('MyGroupsSidebarItem Test', () => { apis={[ [identityApiRef, identityApi], [catalogApiRef, catalogApi], + [ + entityPresentationApiRef, + DefaultEntityPresentationApi.create({ catalogApi }), + ], ]} > { apis={[ [identityApiRef, identityApi], [catalogApiRef, catalogApi], + [ + entityPresentationApiRef, + DefaultEntityPresentationApi.create({ catalogApi }), + ], ]} > { }); }); - describe('For users that are members of multiple groups', () => { - it('MyGroupsSidebarItem should display a sub-menu with all their groups and a link to each group', async () => { - const identityApi = mockApis.identity({ - userEntityRef: 'user:default/nigel.manning', - ownershipEntityRefs: ['user:default/nigel.manning'], - }); - const catalogApi = catalogApiMock.mock({ - getEntities: async () => ({ - items: [ - { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Group', - metadata: { - name: 'team-a', - title: 'Team A', - namespace: 'default', - }, - spec: { - type: 'team', - children: [], - }, + async function renderSideBarWithUserGroups() { + const identityApi = mockApis.identity({ + userEntityRef: 'user:default/nigel.manning', + ownershipEntityRefs: ['user:default/nigel.manning'], + }); + const catalogApi = catalogApiMock.mock({ + getEntities: async () => ({ + items: [ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'team-a', + namespace: 'default', }, - { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Group', - metadata: { - name: 'team-b', - title: 'Team B', - namespace: 'default', - }, - spec: { - type: 'team', - children: [], - }, + spec: { + type: 'team', + children: [], }, - { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Group', - metadata: { - name: 'team-c', - title: 'Team C', - namespace: 'default', - }, - spec: { - type: 'team', - children: [], - }, - }, - ] as Entity[], - }), - }); - const rendered = await renderInTestApp( - - - , - { - mountedRoutes: { - '/catalog/:namespace/:kind/:name': entityRouteRef, }, - }, - ); + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'team-b', + title: 'Team B', + namespace: 'default', + }, + spec: { + type: 'team', + children: [], + }, + }, + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'team-c', + namespace: 'default', + }, + spec: { + type: 'team', + children: [], + profile: { + displayName: 'Team C', + }, + }, + }, + ] as Entity[], + }), + }); - expect(rendered.getByLabelText('My Squads')).toBeInTheDocument(); + await renderInTestApp( + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name': entityRouteRef, + }, + }, + ); + } + + describe('For users that are members of multiple groups', () => { + beforeEach(async () => { + await renderSideBarWithUserGroups(); + }); + + it('MyGroupsSidebarItem should display a sub-menu with all their groups and a link to each group', async () => { + expect(screen.getByLabelText('My Squads')).toBeInTheDocument(); + }); + + it('MyGroupsSidebarItem should display the displayName for each group in the list instead of the metadata name using the entityPresentationApi', async () => { + await userEvent.hover(screen.getByLabelText('My Squads')); + expect(screen.getByText('team-a')).toBeInTheDocument(); + expect(screen.getByText('Team B')).toBeInTheDocument(); + expect(screen.getByText('Team C')).toBeInTheDocument(); }); }); describe('When an additional filter is not provided', () => { + const entityPresentationApi = { + forEntity: jest.fn(), + }; it('catalogApi.getEntities() should be called with the default filter', async () => { const identityApi = mockApis.identity({ userEntityRef: 'user:default/guest', @@ -197,6 +234,7 @@ describe('MyGroupsSidebarItem Test', () => { apis={[ [identityApiRef, identityApi], [catalogApiRef, mockCatalogApi], + [entityPresentationApiRef, entityPresentationApi], ]} > { }); describe('When an additional filter is provided', () => { + const entityPresentationApi = { + forEntity: jest.fn(), + }; + it('catalogApi.getEntities() should be called with an additional filter item', async () => { const identityApi = mockApis.identity({ userEntityRef: 'user:default/guest', @@ -235,6 +277,7 @@ describe('MyGroupsSidebarItem Test', () => { apis={[ [identityApiRef, identityApi], [catalogApiRef, mockCatalogApi], + [entityPresentationApiRef, entityPresentationApi], ]} > { const profile = await identityApi.getBackstageIdentity(); @@ -68,11 +71,9 @@ export const MyGroupsSidebarItem = (props: { ], fields: ['metadata', 'kind'], }); - return response.items; }, []); - // Not a member of any groups if (!groups?.length) { return null; } @@ -93,10 +94,11 @@ export const MyGroupsSidebarItem = (props: { return ( - {groups?.map(function groupsMap(group) { + {groups?.map(group => { + const entityDisplayName = entityPresentationApi.forEntity(group); return (