feat: use refactored hooks in components and component tests for basic rendering of the plugin

Signed-off-by: Kamil Wolny <mrwolny@gmail.com>
This commit is contained in:
Kamil Wolny
2022-08-09 23:43:17 +01:00
parent 19eb649999
commit f9f9aa64f8
4 changed files with 142 additions and 34 deletions
@@ -0,0 +1,127 @@
/*
* Copyright 2022 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 React from 'react';
import { renderInTestApp, TestApiProvider } from '@backstage/test-utils';
import {
EntityProvider,
catalogApiRef,
CatalogApi,
} from '@backstage/plugin-catalog-react';
import { generateTestIssue } from '../../utils';
import { GitHubIssuesApi, gitHubIssuesApiRef } from '../../api';
import { GitHubIssues } from './GitHubIssues';
import { Entity } from '@backstage/catalog-model';
jest
.useFakeTimers()
.setSystemTime(new Date('2020-04-20T08:15:47.614Z').getTime());
const entityComponent = {
metadata: {
annotations: {
'github.com/project-slug': 'backstage/backstage',
},
name: 'backstage',
},
apiVersion: 'backstage.io/v1alpha1',
kind: 'Component',
} as unknown as Entity;
const mockCatalogApi = {
getEntities: () => ({}),
} as CatalogApi;
describe('GitHubIssues', () => {
it('should render correctly when there are no issues in GitHub', async () => {
const mockApi = {
fetchIssuesByRepoFromGitHub: async () => ({
backstage: {
issues: {
totalCount: 0,
edges: [],
},
},
}),
} as GitHubIssuesApi;
const apis = [
[gitHubIssuesApiRef, mockApi],
[catalogApiRef, mockCatalogApi],
] as const;
const { getByTestId } = await renderInTestApp(
<TestApiProvider apis={apis}>
<EntityProvider entity={entityComponent}>
<GitHubIssues />
</EntityProvider>
</TestApiProvider>,
);
expect(getByTestId('no-issues-msg')).toHaveTextContent(
'Hurray! No Issues 🚀',
);
});
it('should render correctly', async () => {
const testIssue = generateTestIssue({
createdAt: '2020-04-19T10:15:47.614Z',
updatedAt: '2020-04-20T00:15:47.614Z',
});
const mockApi = {
fetchIssuesByRepoFromGitHub: async () => ({
backstage: {
issues: {
totalCount: 1,
edges: [testIssue],
},
},
}),
} as GitHubIssuesApi;
const apis = [
[gitHubIssuesApiRef, mockApi],
[catalogApiRef, mockCatalogApi],
] as const;
const { getByText, getByTestId } = await renderInTestApp(
<TestApiProvider apis={apis}>
<EntityProvider entity={entityComponent}>
<GitHubIssues />
</EntityProvider>
</TestApiProvider>,
);
getByText('All repositories (1 Issue)');
expect(getByTestId(`issue-${testIssue.node.url}`)).toHaveTextContent(
testIssue.node.title,
);
expect(getByTestId(`issue-${testIssue.node.url}`)).toHaveTextContent(
testIssue.node.repository.nameWithOwner,
);
expect(getByTestId(`issue-${testIssue.node.url}`)).toHaveTextContent(
`Created at: 22 hours ago by ${testIssue.node.author.login}`,
);
expect(getByTestId(`issue-${testIssue.node.url}`)).toHaveTextContent(
`Last update at: 8 hours ago`,
);
});
});
@@ -20,12 +20,9 @@ import { InfoCard, Progress } from '@backstage/core-components';
import RefreshIcon from '@material-ui/icons/Refresh';
import { useEntityGitHubRepositories } from '../../hooks/useEntityGitHubRepositories';
import {
RepoIssues,
useGetIssuesByRepoFromGitHub,
} from '../../hooks/useGetIssuesByRepoFromGitHub';
import { useGetIssuesByRepoFromGitHub } from '../../hooks/useGetIssuesByRepoFromGitHub';
import { IssueList } from './IssuesList';
import { IssuesList } from './IssuesList';
import { NoRepositoriesInfo } from './NoRepositoriesInfo';
/**
@@ -39,29 +36,12 @@ export type GitHubIssuesProps = {
export const GitHubIssues = (props: GitHubIssuesProps) => {
const { itemsPerPage = 10, itemsPerRepo = 40 } = props;
const [isLoading, setIsLoading] = React.useState(true);
const [issuesByRepository, setIssuesByRepository] =
React.useState<Record<string, RepoIssues>>();
const { repositories } = useEntityGitHubRepositories();
const getIssues = useGetIssuesByRepoFromGitHub();
const fetchGitHubIssues = React.useCallback(async () => {
setIsLoading(true);
const issuesByRepo = await getIssues(repositories, itemsPerRepo);
setIssuesByRepository(issuesByRepo);
setIsLoading(false);
}, [itemsPerRepo, getIssues, repositories]);
React.useEffect(() => {
if (repositories.length) {
fetchGitHubIssues();
} else {
setIsLoading(false);
}
}, [repositories.length, fetchGitHubIssues]);
const {
isLoading,
gitHubIssuesByRepo: issuesByRepository,
retry,
} = useGetIssuesByRepoFromGitHub(repositories, itemsPerRepo);
if (!repositories.length) {
return <NoRepositoriesInfo />;
@@ -72,7 +52,7 @@ export const GitHubIssues = (props: GitHubIssuesProps) => {
title={
<Box display="flex" justifyContent="flex-start" alignItems="center">
<Typography variant="h5">Open GitHub Issues</Typography>
<IconButton color="secondary" onClick={fetchGitHubIssues}>
<IconButton color="secondary" onClick={retry}>
<RefreshIcon />
</IconButton>
</Box>
@@ -80,7 +60,7 @@ export const GitHubIssues = (props: GitHubIssuesProps) => {
>
{isLoading && <Progress />}
<IssueList
<IssuesList
issuesByRepository={issuesByRepository}
itemsPerPage={itemsPerPage}
/>
@@ -59,7 +59,7 @@ export const IssueCard = (props: IssueCardProps) => {
} = props;
return (
<Box marginBottom={1}>
<Box marginBottom={1} data-testid={`issue-${url}`}>
<Paper variant="outlined">
<CardActionArea href={url} target="_blank">
<Box padding={1}>
@@ -19,14 +19,14 @@ import { Box } from '@material-ui/core';
import { Pagination } from '@material-ui/lab';
import { IssueCard } from '../IssueCard';
import { RepoIssues } from '../../../hooks/useGetIssuesByRepoFromGitHub';
import { IssuesByRepo } from '../../../api';
import { RepositoryFilters } from './Filters';
export type PluginMode = 'page' | 'card';
export type IssueListProps = {
itemsPerPage?: number;
issuesByRepository?: Record<string, RepoIssues>;
issuesByRepository?: IssuesByRepo;
};
const getIssuesCountForFilterLabel = (
@@ -37,7 +37,7 @@ const getIssuesCountForFilterLabel = (
issuesAvailable < totalIssues ? '*' : ''
}`;
export const IssueList = ({
export const IssuesList = ({
itemsPerPage = 10,
issuesByRepository,
}: IssueListProps) => {
@@ -140,6 +140,7 @@ export const IssueList = ({
index,
) => (
<IssueCard
key={url}
even={Boolean(index % 2)}
title={title}
createdAt={createdAt}
@@ -154,7 +155,7 @@ export const IssueList = ({
),
)
) : (
<h1>Hurray! No Issues 🚀</h1>
<h1 data-testid="no-issues-msg">Hurray! No Issues 🚀</h1>
)}
{issues.length / itemsPerPage > 1 ? (
<Pagination