Merge pull request #24405 from Nikunj0601/backup-backup/EntityListComponent-uses-CatalogAPI

feat(EntityListComponent): use EntityPresentationApi instead of humanizeEntityRef to display entity
This commit is contained in:
Fredrik Adelöw
2024-05-10 14:59:44 +02:00
committed by GitHub
5 changed files with 117 additions and 57 deletions
+1
View File
@@ -78,6 +78,7 @@
"@backstage/cli": "workspace:^",
"@backstage/core-app-api": "workspace:^",
"@backstage/dev-utils": "workspace:^",
"@backstage/plugin-catalog": "workspace:^",
"@backstage/test-utils": "workspace:^",
"@testing-library/dom": "^10.0.0",
"@testing-library/jest-dom": "^6.0.0",
@@ -14,11 +14,16 @@
* limitations under the License.
*/
import { Entity, CompoundEntityRef } from '@backstage/catalog-model';
import { useApp } from '@backstage/core-plugin-api';
import {
Entity,
CompoundEntityRef,
stringifyEntityRef,
} from '@backstage/catalog-model';
import { useApi } from '@backstage/core-plugin-api';
import {
EntityDisplayName,
EntityRefLink,
humanizeEntityRef,
entityPresentationApiRef,
} from '@backstage/plugin-catalog-react';
import Collapse from '@material-ui/core/Collapse';
import IconButton from '@material-ui/core/IconButton';
@@ -38,12 +43,6 @@ const useStyles = makeStyles(theme => ({
},
}));
function sortEntities(entities: Array<CompoundEntityRef | Entity>) {
return entities.sort((a, b) =>
humanizeEntityRef(a).localeCompare(humanizeEntityRef(b)),
);
}
/**
* Props for {@link EntityListComponent}.
*
@@ -76,9 +75,8 @@ export const EntityListComponent = (props: EntityListComponentProps) => {
withLinks = false,
} = props;
const app = useApp();
const classes = useStyles();
const entityPresentationApi = useApi(entityPresentationApiRef);
const [expandedUrls, setExpandedUrls] = useState<string[]>([]);
const handleClick = (url: string) => {
@@ -87,6 +85,17 @@ export const EntityListComponent = (props: EntityListComponentProps) => {
);
};
function sortEntities(entities: Array<CompoundEntityRef | Entity>) {
return entities.sort((a, b) =>
entityPresentationApi
.forEntity(stringifyEntityRef(a))
.snapshot.entityRef.localeCompare(
entityPresentationApi.forEntity(stringifyEntityRef(b)).snapshot
.entityRef,
),
);
}
return (
<List>
{firstListItem}
@@ -124,12 +133,9 @@ export const EntityListComponent = (props: EntityListComponentProps) => {
>
<List component="div" disablePadding dense>
{sortEntities(r.entities).map(entity => {
const Icon = app.getSystemIcon(
`kind:${entity.kind.toLocaleLowerCase('en-US')}`,
);
return (
<ListItem
key={humanizeEntityRef(entity)}
key={stringifyEntityRef(entity)}
className={classes.nested}
{...(withLinks
? {
@@ -139,8 +145,9 @@ export const EntityListComponent = (props: EntityListComponentProps) => {
}
: {})}
>
<ListItemIcon>{Icon && <Icon />}</ListItemIcon>
<ListItemText primary={humanizeEntityRef(entity)} />
<ListItemText
primary={<EntityDisplayName entityRef={entity} />}
/>
</ListItem>
);
})}
@@ -14,14 +14,22 @@
* limitations under the License.
*/
import { renderInTestApp } from '@backstage/test-utils';
import { TestApiProvider, renderInTestApp } from '@backstage/test-utils';
import { act, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { AnalyzeResult } from '../../api';
import { StepPrepareSelectLocations } from './StepPrepareSelectLocations';
import {
CatalogApi,
catalogApiRef,
entityPresentationApiRef,
} from '@backstage/plugin-catalog-react';
import { DefaultEntityPresentationApi } from '@backstage/plugin-catalog';
import { Entity } from '@backstage/catalog-model';
describe('<StepPrepareSelectLocations />', () => {
let entities: Entity[];
const analyzeResult = {
type: 'locations',
locations: [
@@ -53,17 +61,43 @@ describe('<StepPrepareSelectLocations />', () => {
],
} as Extract<AnalyzeResult, { type: 'locations' }>;
const catalogApi: jest.Mocked<CatalogApi> = {
getLocationById: jest.fn(),
getEntityByName: jest.fn(),
getEntities: jest.fn(async () => ({ items: entities })),
addLocation: jest.fn(),
getLocationByRef: jest.fn(),
removeEntityByUid: jest.fn(),
} as any;
let Wrapper: React.ComponentType<React.PropsWithChildren<{}>>;
beforeEach(() => {
jest.resetAllMocks();
catalogApi.getEntities.mockResolvedValue({ items: entities });
Wrapper = ({ children }: { children?: React.ReactNode }) => (
<TestApiProvider
apis={[
[catalogApiRef, catalogApi],
[
entityPresentationApiRef,
DefaultEntityPresentationApi.create({ catalogApi }),
],
]}
>
{children}
</TestApiProvider>
);
});
it('renders display locations to be added', async () => {
await renderInTestApp(
<StepPrepareSelectLocations
analyzeResult={analyzeResult}
onPrepare={() => undefined}
onGoBack={() => undefined}
/>,
<Wrapper>
<StepPrepareSelectLocations
analyzeResult={analyzeResult}
onPrepare={() => undefined}
onGoBack={() => undefined}
/>
</Wrapper>,
);
expect(screen.getByText('url-1')).toBeInTheDocument();
@@ -96,11 +130,13 @@ describe('<StepPrepareSelectLocations />', () => {
} as Extract<AnalyzeResult, { type: 'locations' }>;
await renderInTestApp(
<StepPrepareSelectLocations
analyzeResult={analyzeResultWithExistingLocation}
onPrepare={() => undefined}
onGoBack={() => undefined}
/>,
<Wrapper>
<StepPrepareSelectLocations
analyzeResult={analyzeResultWithExistingLocation}
onPrepare={() => undefined}
onGoBack={() => undefined}
/>
</Wrapper>,
);
expect(screen.getByText(/my-target/)).toBeInTheDocument();
@@ -112,11 +148,13 @@ describe('<StepPrepareSelectLocations />', () => {
it('should select and deselect all', async () => {
await renderInTestApp(
<StepPrepareSelectLocations
analyzeResult={analyzeResult}
onPrepare={() => undefined}
onGoBack={() => undefined}
/>,
<Wrapper>
<StepPrepareSelectLocations
analyzeResult={analyzeResult}
onPrepare={() => undefined}
onGoBack={() => undefined}
/>
</Wrapper>,
);
const checkboxes = screen.getAllByRole('checkbox');
@@ -144,15 +182,17 @@ describe('<StepPrepareSelectLocations />', () => {
it('should preselect prepared locations', async () => {
await renderInTestApp(
<StepPrepareSelectLocations
analyzeResult={analyzeResult}
prepareResult={{
...analyzeResult,
locations: [...analyzeResult.locations.slice(0, 1)],
}}
onPrepare={() => undefined}
onGoBack={() => undefined}
/>,
<Wrapper>
<StepPrepareSelectLocations
analyzeResult={analyzeResult}
prepareResult={{
...analyzeResult,
locations: [...analyzeResult.locations.slice(0, 1)],
}}
onPrepare={() => undefined}
onGoBack={() => undefined}
/>
</Wrapper>,
);
const checkboxes = screen.getAllByRole('checkbox');
@@ -164,11 +204,13 @@ describe('<StepPrepareSelectLocations />', () => {
it('should select items', async () => {
await renderInTestApp(
<StepPrepareSelectLocations
analyzeResult={analyzeResult}
onPrepare={() => undefined}
onGoBack={() => undefined}
/>,
<Wrapper>
<StepPrepareSelectLocations
analyzeResult={analyzeResult}
onPrepare={() => undefined}
onGoBack={() => undefined}
/>
</Wrapper>,
);
const checkboxes = screen.getAllByRole('checkbox');
@@ -193,11 +235,13 @@ describe('<StepPrepareSelectLocations />', () => {
const onGoBack = jest.fn();
await renderInTestApp(
<StepPrepareSelectLocations
analyzeResult={analyzeResult}
onPrepare={() => undefined}
onGoBack={onGoBack}
/>,
<Wrapper>
<StepPrepareSelectLocations
analyzeResult={analyzeResult}
onPrepare={() => undefined}
onGoBack={onGoBack}
/>
</Wrapper>,
);
await act(async () => {
@@ -211,11 +255,13 @@ describe('<StepPrepareSelectLocations />', () => {
const onPrepare = jest.fn();
await renderInTestApp(
<StepPrepareSelectLocations
analyzeResult={analyzeResult}
onPrepare={onPrepare}
onGoBack={() => undefined}
/>,
<Wrapper>
<StepPrepareSelectLocations
analyzeResult={analyzeResult}
onPrepare={onPrepare}
onGoBack={() => undefined}
/>
</Wrapper>,
);
const checkboxes = screen.getAllByRole('checkbox');