diff --git a/packages/catalog-model/examples/acme/team-a-group.yaml b/packages/catalog-model/examples/acme/team-a-group.yaml index e343209d5f..6f2be963b7 100644 --- a/packages/catalog-model/examples/acme/team-a-group.yaml +++ b/packages/catalog-model/examples/acme/team-a-group.yaml @@ -21,7 +21,7 @@ spec: # Intentional no displayName for testing email: breanna-davison@example.com picture: https://avatars.dicebear.com/api/avataaars/breanna-davison@example.com.svg?background=%23fff - memberOf: [team-a] + memberOf: [team-a, team-not-exist] --- apiVersion: backstage.io/v1alpha1 kind: User diff --git a/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.test.tsx b/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.test.tsx index b0a6b46bf5..71ff25c746 100644 --- a/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.test.tsx +++ b/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.test.tsx @@ -14,11 +14,20 @@ * limitations under the License. */ -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { screen } from '@testing-library/react'; import React from 'react'; import { entityRouteRef } from '../../routes'; import { EntityRefLink } from './EntityRefLink'; +import { catalogApiRef } from '../../api'; +import { CatalogApi } from '@backstage/catalog-client'; +import { ApiProvider } from '@backstage/core-app-api'; + +const catalogApi: jest.Mocked = { + getEntityByRef: jest.fn(), +} as any; + +const apis = TestApiRegistry.from([catalogApiRef, catalogApi]); describe('', () => { it('renders link for entity in default namespace', async () => { @@ -34,11 +43,16 @@ describe('', () => { lifecycle: 'production', }, }; - await renderInTestApp(, { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, + await renderInTestApp( + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + }, }, - }); + ); expect(screen.getByText('component:software')).toHaveAttribute( 'href', @@ -60,11 +74,16 @@ describe('', () => { lifecycle: 'production', }, }; - await renderInTestApp(, { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, + await renderInTestApp( + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + }, }, - }); + ); expect(screen.getByText('component:test/software')).toHaveAttribute( 'href', '/catalog/test/component/software', @@ -86,7 +105,9 @@ describe('', () => { }, }; await renderInTestApp( - , + + + , { mountedRoutes: { '/catalog/:namespace/:kind/:name/*': entityRouteRef, @@ -105,11 +126,16 @@ describe('', () => { namespace: 'default', name: 'software', }; - await renderInTestApp(, { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, + await renderInTestApp( + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + }, }, - }); + ); expect(screen.getByText('component:software')).toHaveAttribute( 'href', '/catalog/default/component/software', @@ -122,11 +148,16 @@ describe('', () => { namespace: 'test', name: 'software', }; - await renderInTestApp(, { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, + await renderInTestApp( + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + }, }, - }); + ); expect(screen.getByText('component:test/software')).toHaveAttribute( 'href', '/catalog/test/component/software', @@ -140,7 +171,9 @@ describe('', () => { name: 'software', }; await renderInTestApp( - , + + + , { mountedRoutes: { '/catalog/:namespace/:kind/:name/*': entityRouteRef, @@ -160,9 +193,11 @@ describe('', () => { name: 'software', }; await renderInTestApp( - - Custom Children - , + + + Custom Children + + , { mountedRoutes: { '/catalog/:namespace/:kind/:name/*': entityRouteRef, diff --git a/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx b/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx index 329f52ea74..c1d699421e 100644 --- a/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx +++ b/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx @@ -47,6 +47,7 @@ import EmailIcon from '@material-ui/icons/Email'; import InfoIcon from '@material-ui/icons/Info'; import useAsync from 'react-use/lib/useAsync'; import { catalogApiRef } from '../../api'; +import { Alert } from '@material-ui/lab'; /** * Props for {@link EntityRefLink}. @@ -77,13 +78,21 @@ export const PeekAheadPopover = ({ popupState, entityRef, }: PeekAheadPopoverProps) => { - const catalogApi = useApi(catalogApiRef); const entityRoute = useRouteRef(entityRouteRef); const classes = useStyles(); + const catalogApi = useApi(catalogApiRef); - const { value, loading, error } = useAsync(async () => { + const { + value: entity, + loading, + error, + } = useAsync(async () => { if (popupState.isOpen) { - return catalogApi.getEntityByRef(entityRef); + const retrievedEntity = await catalogApi.getEntityByRef(entityRef); + if (!retrievedEntity) { + throw new Error(`${entityRef.name} was not found`); + } + return retrievedEntity; } return undefined; }, [popupState]); @@ -115,25 +124,25 @@ export const PeekAheadPopover = ({ {entityRef.kind} - {error && error.message} - {value && ( + {error && {error.message}} + {entity && ( <> - {value.metadata.description} + {entity.metadata.description}

- {value.spec?.type} + {entity.spec?.type} )}
- {value && - (isUserEntity(value) || isGroupEntity(value)) && - value.spec.profile?.email && ( - + {entity && + (isUserEntity(entity) || isGroupEntity(entity)) && + entity.spec.profile?.email && ( +