add testing

Signed-off-by: nikolar <reyna.nikolayev@autodesk.com>
This commit is contained in:
nikolar
2024-12-02 20:09:30 -08:00
parent cffde24a15
commit b6a8c56a81
4 changed files with 349 additions and 23 deletions
@@ -0,0 +1,191 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { renderInTestApp } from '@backstage/test-utils';
import { screen } from '@testing-library/react';
import React from 'react';
import { rootDocsRouteRef } from '../../../routes';
import { InfoCardGrid } from './InfoCardGrid';
describe('Entity Info Card Grid', () => {
beforeEach(() => {
jest.resetAllMocks();
});
it('should render multiple entities', async () => {
await renderInTestApp(
<InfoCardGrid
entities={[
{
apiVersion: 'version',
kind: 'TestKind',
metadata: {
name: 'testName',
title: 'TestTitle',
},
spec: {
owner: 'techdocs@example.com',
},
},
{
apiVersion: 'version',
kind: 'TestKind2',
metadata: {
name: 'testName2',
title: 'TestTitle2',
},
spec: {
owner: 'techdocs2@example.com',
},
},
]}
/>,
{
mountedRoutes: {
'/docs/:namespace/:kind/:name/*': rootDocsRouteRef,
},
},
);
expect(await screen.findByText('TestTitle')).toBeInTheDocument();
expect(await screen.findByText('TestTitle2')).toBeInTheDocument();
});
it('should handle missing data gracefully', async () => {
await renderInTestApp(
<InfoCardGrid
entities={[
{
apiVersion: 'version',
kind: 'TestKind',
metadata: {
name: 'testName',
},
spec: {
owner: 'techdocs@example.com',
},
},
]}
/>,
{
mountedRoutes: {
'/docs/:namespace/:kind/:name/*': rootDocsRouteRef,
},
},
);
expect(await screen.findByText('testName')).toBeInTheDocument();
});
it('should render links correctly', async () => {
await renderInTestApp(
<InfoCardGrid
entities={[
{
apiVersion: 'version',
kind: 'TestKind',
metadata: {
name: 'testName',
title: 'TestTitle',
},
spec: {
owner: 'techdocs@example.com',
},
},
{
apiVersion: 'version',
kind: 'TestKind2',
metadata: {
name: 'testName2',
title: 'TestTitle2',
},
spec: {
owner: 'techdocs2@example.com',
},
},
]}
/>,
{
mountedRoutes: {
'/docs/:namespace/:kind/:name/*': rootDocsRouteRef,
},
},
);
expect(await screen.findByText('TestTitle')).toBeInTheDocument();
expect(await screen.findByText('TestTitle2')).toBeInTheDocument();
const [button1, button2] = await screen.findAllByTestId('read-docs-link');
expect(button1.getAttribute('href')).toContain(
'/docs/default/testkind/testname',
);
expect(button2.getAttribute('href')).toContain(
'/docs/default/testkind2/testname2',
);
});
it('should render entity title if available', async () => {
await renderInTestApp(
<InfoCardGrid
entities={[
{
apiVersion: 'version',
kind: 'TestKind',
metadata: {
name: 'testName',
title: 'TestTitle',
},
spec: {
owner: 'techdocs@example.com',
},
},
]}
/>,
{
mountedRoutes: {
'/docs/:namespace/:kind/:name/*': rootDocsRouteRef,
},
},
);
expect(await screen.findByText('TestTitle')).toBeInTheDocument();
});
it('should render entity name if title is not available', async () => {
await renderInTestApp(
<InfoCardGrid
entities={[
{
apiVersion: 'version',
kind: 'TestKind',
metadata: {
name: 'testName',
},
spec: {
owner: 'techdocs@example.com',
},
},
]}
/>,
{
mountedRoutes: {
'/docs/:namespace/:kind/:name/*': rootDocsRouteRef,
},
},
);
expect(await screen.findByText('testName')).toBeInTheDocument();
});
});
@@ -38,11 +38,11 @@ const useStyles = makeStyles(
);
/**
* Props for {@link InfoCardGird}
* Props for {@link InfoCardGrid}
*
* @public
*/
export type InfoCardGirdProps = {
export type InfoCardGridProps = {
entities: Entity[] | undefined;
linkContent?: string | JSX.Element;
linkDest?: (entity: Entity) => string;
@@ -53,37 +53,40 @@ export type InfoCardGirdProps = {
*
* @public
*/
export const InfoCardGird = (props: InfoCardGirdProps) => {
export const InfoCardGrid = (props: InfoCardGridProps) => {
const { entities, linkContent, linkDest } = props;
const classes = useStyles();
const getRouteToReaderPageFor = useRouteRef(rootDocsRouteRef);
const config = useApi(configApiRef);
const linkDestination = (entity: Entity) =>
typeof linkDest === 'function'
? linkDest(entity)
: getRouteToReaderPageFor({
namespace: toLowerMaybe(
entity.metadata.namespace ?? 'default',
config,
),
kind: toLowerMaybe(entity.kind, config),
name: toLowerMaybe(entity.metadata.name, config),
});
if (!entities) return null;
return (
<ItemCardGrid data-testid="docs-card-container">
<ItemCardGrid data-testid="info-card-container">
{!entities?.length
? null
: entities.map(entity => (
<InfoCard
data-cy={entity?.metadata?.title}
title={entity?.metadata?.title}
key={entity.metadata.name}
data-testid={entity?.metadata?.title}
title={entity?.metadata?.title || entity?.metadata?.name}
>
<div>{entity?.metadata?.description}</div>
<div className={classes.linkSpacer} />
<Link
to={
typeof linkDest === 'function'
? linkDest(entity)
: getRouteToReaderPageFor({
namespace: toLowerMaybe(
entity.metadata.namespace ?? 'default',
config,
),
kind: toLowerMaybe(entity.kind, config),
name: toLowerMaybe(entity.metadata.name, config),
})
}
to={linkDestination(entity)}
className={classes.readMoreLink}
data-testid="read-docs-link"
>
{linkContent || 'Read Docs'}
</Link>
@@ -96,4 +96,133 @@ describe('TechDocsCustomHome', () => {
await screen.findByText('Second Tab Description'),
).toBeInTheDocument();
});
it('should render ContentHeader based on showHeader prop', async () => {
const tabsConfig = [
{
label: 'First Tab',
panels: [
{
title: 'First Tab',
description: 'First Tab Description',
panelType: 'DocsCardGrid' as PanelType,
panelProps: { showHeader: false },
filterPredicate: () => true,
},
],
},
];
await renderInTestApp(
<ApiProvider apis={apiRegistry}>
<TechDocsCustomHome tabsConfig={tabsConfig} />
</ApiProvider>,
{
mountedRoutes: {
'/docs/:namespace/:kind/:name/*': rootDocsRouteRef,
},
},
);
expect(
screen.queryByText('Discover documentation in your ecosystem.'),
).not.toBeInTheDocument();
});
it('should render SupportButton based on hideSupport prop', async () => {
const tabsConfig = [
{
label: 'First Tab',
panels: [
{
title: 'First Tab',
description: 'First Tab Description',
panelType: 'DocsCardGrid' as PanelType,
filterPredicate: () => true,
panelProps: { hideSupport: true },
},
],
},
];
await renderInTestApp(
<ApiProvider apis={apiRegistry}>
<TechDocsCustomHome tabsConfig={tabsConfig} />
</ApiProvider>,
{
mountedRoutes: {
'/docs/:namespace/:kind/:name/*': rootDocsRouteRef,
},
},
);
expect(
screen.queryByText('Discover documentation in your ecosystem.'),
).not.toBeInTheDocument();
});
it('should hide subtitle when hideSubtitle is true', async () => {
const tabsConfig = [
{
label: 'First Tab',
panels: [
{
title: 'First Tab',
description: 'First Tab Description',
panelType: 'DocsCardGrid' as PanelType,
filterPredicate: () => true,
},
],
},
];
await renderInTestApp(
<ApiProvider apis={apiRegistry}>
<TechDocsCustomHome
tabsConfig={tabsConfig}
title="Custom Title"
subtitle="Custom Subtitle"
hideSubtitle
/>
</ApiProvider>,
{
mountedRoutes: {
'/docs/:namespace/:kind/:name/*': rootDocsRouteRef,
},
},
);
expect(screen.getByText('Custom Title')).toBeInTheDocument();
expect(screen.queryByText('Custom Subtitle')).not.toBeInTheDocument();
});
it('should render title and subtitle', async () => {
const tabsConfig = [
{
label: 'First Tab',
panels: [
{
title: 'First Tab',
description: 'First Tab Description',
panelType: 'DocsCardGrid' as PanelType,
filterPredicate: () => true,
},
],
},
];
await renderInTestApp(
<ApiProvider apis={apiRegistry}>
<TechDocsCustomHome
tabsConfig={tabsConfig}
title="Custom Title"
subtitle="Custom Subtitle"
/>
</ApiProvider>,
{
mountedRoutes: {
'/docs/:namespace/:kind/:name/*': rootDocsRouteRef,
},
},
);
expect(screen.getByText('Custom Title')).toBeInTheDocument();
expect(screen.getByText('Custom Subtitle')).toBeInTheDocument();
});
});
@@ -26,7 +26,7 @@ import {
} from '@backstage/plugin-catalog-react';
import { Entity } from '@backstage/catalog-model';
import { DocsTable } from './Tables';
import { DocsCardGrid, InfoCardGird } from './Grids';
import { DocsCardGrid, InfoCardGrid } from './Grids';
import { TechDocsPageWrapper } from './TechDocsPageWrapper';
import { TechDocsIndexPage } from './TechDocsIndexPage';
@@ -47,7 +47,7 @@ const panels = {
DocsTable: DocsTable,
DocsCardGrid: DocsCardGrid,
TechDocsIndexPage: TechDocsIndexPage,
InfoCardGird: InfoCardGird,
InfoCardGrid: InfoCardGrid,
};
/**
@@ -59,7 +59,7 @@ export type PanelType =
| 'DocsCardGrid'
| 'DocsTable'
| 'TechDocsIndexPage'
| 'InfoCardGird';
| 'InfoCardGrid';
/**
* Type representing a TechDocsCustomHome panel.
@@ -172,7 +172,8 @@ export const TechDocsCustomHome = (props: TechDocsCustomHomeProps) => {
error,
} = useAsync(async () => {
const response = await catalogApi.getEntities({
filter: filter || {
filter: {
...filter,
[`metadata.annotations.${TECHDOCS_ANNOTATION}`]: CATALOG_FILTER_EXISTS,
},
fields: [
@@ -184,7 +185,9 @@ export const TechDocsCustomHome = (props: TechDocsCustomHomeProps) => {
'spec.type',
],
});
return response.items;
return response.items.filter((entity: Entity) => {
return !!entity.metadata.annotations?.[TECHDOCS_ANNOTATION];
});
});
const currentTabConfig = tabsConfig[selectedTab];