repo page tests
added coverage, fixed some small linting issues Signed-off-by: Raul Kele <raulkeleblk@gmail.com>
This commit is contained in:
parent
1b91668036
commit
b4b5259469
88
src/__tests__/RepoPage/Repo.test.js
Normal file
88
src/__tests__/RepoPage/Repo.test.js
Normal file
@ -0,0 +1,88 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import RepoDetails from 'components/RepoDetails';
|
||||
import React from 'react';
|
||||
import { api } from 'api';
|
||||
|
||||
|
||||
// uselocation mock
|
||||
const mockUseLocationValue = {
|
||||
pathname: "'localhost:3000/image/test'",
|
||||
search: '',
|
||||
hash: '',
|
||||
state:{ lastDate: '' }
|
||||
}
|
||||
|
||||
jest.mock("react-router-dom", () => ({
|
||||
// @ts-ignore
|
||||
...jest.requireActual("react-router-dom"),
|
||||
useParams: () =>{return {name:'test'} },
|
||||
useLocation: () => {
|
||||
return mockUseLocationValue;
|
||||
}
|
||||
}));
|
||||
|
||||
// mock clipboard copy fn
|
||||
const mockCopyToClipboard = jest.fn();
|
||||
Object.assign(navigator, {
|
||||
clipboard: {
|
||||
writeText: mockCopyToClipboard,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
const mockRepoDetailsData = {
|
||||
"ExpandedRepoInfo": {
|
||||
"Manifests": [
|
||||
{
|
||||
"Digest": "2aa7ff5ca352d4d25fc6548f9930a436aacd64d56b1bd1f9ff4423711b9c8718",
|
||||
"Tag": "latest",
|
||||
"Layers": [
|
||||
{
|
||||
"Size": "2798889",
|
||||
"Digest": "2408cc74d12b6cd092bb8b516ba7d5e290f485d3eb9672efc00f0583730179e8"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
// restore the spy created with spyOn
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('Repo details component', () => {
|
||||
it('fetches repo detailed data and renders',async () => {
|
||||
// @ts-ignore
|
||||
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsData } });
|
||||
render(<RepoDetails/>);
|
||||
expect(await screen.findByText('test')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should log error if data can\'t be fetched', async () => {
|
||||
jest.spyOn(api, 'get').mockRejectedValue({ status: 500, data: { } })
|
||||
const error = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
render(<RepoDetails/>);
|
||||
await waitFor(() => expect(error).toBeCalledTimes(1));
|
||||
});
|
||||
|
||||
it('should switch between tabs', async () => {
|
||||
// @ts-ignore
|
||||
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsData } });
|
||||
render(<RepoDetails/>);
|
||||
expect(screen.getByTestId('overview-container')).toBeInTheDocument();
|
||||
fireEvent.click(await screen.findByText(/tags/i));
|
||||
expect(screen.getByTestId('tags-container')).toBeInTheDocument();
|
||||
expect(screen.queryByTestId('overview-container')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should copy the pull string to clipboard',async () => {
|
||||
// @ts-ignore
|
||||
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsData } });
|
||||
render(<RepoDetails/>);
|
||||
fireEvent.click(screen.getByTestId('pullcopy-btn'));
|
||||
await waitFor(() => expect(mockCopyToClipboard).toHaveBeenCalledWith('Pull test'));
|
||||
});
|
||||
});
|
||||
|
30
src/__tests__/RepoPage/RepoPage.test.js
Normal file
30
src/__tests__/RepoPage/RepoPage.test.js
Normal file
@ -0,0 +1,30 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import RepoPage from 'pages/RepoPage';
|
||||
import React from 'react';
|
||||
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
||||
|
||||
jest.mock("react-router-dom", () => ({
|
||||
// @ts-ignore
|
||||
...jest.requireActual("react-router-dom"),
|
||||
useLocation: () => ({
|
||||
pathname:'localhost:3000/image/test',
|
||||
state: { lastDate: '' }
|
||||
})
|
||||
}));
|
||||
|
||||
afterEach(() => {
|
||||
// restore the spy created with spyOn
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('renders the repository page component', () => {
|
||||
render(
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
<Route path="*" element={<RepoPage updateKeywords={() => {}}/>} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
);
|
||||
expect(screen.getByTestId('repo-container')).toBeInTheDocument();
|
||||
});
|
||||
|
29
src/__tests__/RepoPage/Tags.test.js
Normal file
29
src/__tests__/RepoPage/Tags.test.js
Normal file
@ -0,0 +1,29 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import Tags from 'components/Tags';
|
||||
import React from 'react';
|
||||
|
||||
const mockedTagsData = {
|
||||
name: 'test',
|
||||
tags: [
|
||||
{
|
||||
"Digest": "2aa7ff5ca352d4d25fc6548f9930a436aacd64d56b1bd1f9ff4423711b9c8718",
|
||||
"Tag": "latest",
|
||||
"Layers": [
|
||||
{
|
||||
"Size": "2798889",
|
||||
"Digest": "2408cc74d12b6cd092bb8b516ba7d5e290f485d3eb9672efc00f0583730179e8"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
describe('Tags component', () => {
|
||||
it('should open and close details dropdown for tags', () => {
|
||||
render(<Tags data={mockedTagsData}/>);
|
||||
const openBtn = screen.getByText(/see layers/i);
|
||||
fireEvent.click(openBtn);
|
||||
expect(screen.queryByText(/see layers/i)).not.toBeInTheDocument();
|
||||
expect(screen.getByText(/hide layers/i)).toBeInTheDocument();
|
||||
});
|
||||
})
|
41
src/__tests__/Shared/PreviewCard.test.js
Normal file
41
src/__tests__/Shared/PreviewCard.test.js
Normal file
@ -0,0 +1,41 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import PreviewCard from 'components/PreviewCard';
|
||||
|
||||
|
||||
// usenavigate mock
|
||||
const mockedUsedNavigate = jest.fn();
|
||||
jest.mock("react-router-dom", () => ({
|
||||
// @ts-ignore
|
||||
...jest.requireActual("react-router-dom"),
|
||||
useNavigate: () => mockedUsedNavigate
|
||||
}));
|
||||
|
||||
// image mock
|
||||
const mockImage = {
|
||||
name: "alpine",
|
||||
latestVersion: "latest",
|
||||
lastUpdated: "2022-05-23T19:19:30.413290187Z",
|
||||
description: "",
|
||||
licenses: "",
|
||||
vendor: "",
|
||||
size: "585",
|
||||
tags: ""
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
// restore the spy created with spyOn
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('Preview card component', () => {
|
||||
it('navigates to repo page when clicked',async () => {
|
||||
render(<PreviewCard name={mockImage.name} lastUpdated={mockImage.lastUpdated}/>);
|
||||
const cardTitle = await screen.findByText('alpine');
|
||||
expect(cardTitle).toBeInTheDocument();
|
||||
userEvent.click(cardTitle);
|
||||
expect(mockedUsedNavigate).toBeCalledWith(`/image/${mockImage.name}`, expect.anything());
|
||||
});
|
||||
});
|
||||
|
53
src/__tests__/Shared/RepoCard.test.js
Normal file
53
src/__tests__/Shared/RepoCard.test.js
Normal file
@ -0,0 +1,53 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import PreviewCard from 'components/PreviewCard';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
|
||||
// usenavigate mock
|
||||
const mockedUsedNavigate = jest.fn();
|
||||
jest.mock("react-router-dom", () => ({
|
||||
// @ts-ignore
|
||||
...jest.requireActual("react-router-dom"),
|
||||
useNavigate: () => mockedUsedNavigate
|
||||
}));
|
||||
|
||||
// image mock
|
||||
const mockImage = {
|
||||
name: "alpine",
|
||||
latestVersion: "latest",
|
||||
lastUpdated: "2022-05-23T19:19:30.413290187Z",
|
||||
description: "",
|
||||
licenses: "",
|
||||
vendor: "",
|
||||
size: "585",
|
||||
tags: ""
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
// restore the spy created with spyOn
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('Repo card component', () => {
|
||||
it('navigates to repo page when clicked',async () => {
|
||||
render(<PreviewCard
|
||||
name={mockImage.name}
|
||||
version={mockImage.latestVersion}
|
||||
description={mockImage.description}
|
||||
tags={mockImage.tags}
|
||||
vendor={mockImage.vendor}
|
||||
size={mockImage.size}
|
||||
licenses={mockImage.licenses}
|
||||
key={1}
|
||||
data={mockImage}
|
||||
lastUpdated={mockImage.lastUpdated}
|
||||
shown={true}
|
||||
/>);
|
||||
const cardTitle = await screen.findByText('alpine');
|
||||
expect(cardTitle).toBeInTheDocument();
|
||||
userEvent.click(cardTitle);
|
||||
expect(mockedUsedNavigate).toBeCalledWith(`/image/${mockImage.name}`, expect.anything());
|
||||
});
|
||||
});
|
||||
|
@ -11,7 +11,6 @@ import makeStyles from '@mui/styles/makeStyles';
|
||||
import React from "react";
|
||||
|
||||
const useStyles = makeStyles((theme) => {
|
||||
console.log("theme", theme)
|
||||
return {
|
||||
exploreHeader: {
|
||||
backgroundColor: "#FFFFFF",
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Card, CardActionArea, CardContent, CardMedia, Chip, Grid, Stack, Typography } from '@mui/material';
|
||||
import { Card, CardActionArea, CardContent, CardMedia, Grid, Stack, Typography } from '@mui/material';
|
||||
import { makeStyles } from '@mui/styles';
|
||||
import { DateTime } from 'luxon';
|
||||
import React from 'react';
|
||||
@ -61,7 +61,7 @@ const useStyles = makeStyles(() => ({
|
||||
}
|
||||
}));
|
||||
|
||||
function RepoCard(props) {
|
||||
function PreviewCard(props) {
|
||||
const classes = useStyles();
|
||||
const navigate = useNavigate();
|
||||
const { name, lastUpdated } = props;
|
||||
@ -110,4 +110,4 @@ function RepoCard(props) {
|
||||
);
|
||||
};
|
||||
|
||||
export default RepoCard;
|
||||
export default PreviewCard;
|
@ -5,7 +5,7 @@ import { useNavigate } from "react-router-dom";
|
||||
// utility
|
||||
import { DateTime } from 'luxon';
|
||||
// components
|
||||
import { Card, CardActionArea, CardMedia, CardContent, Typography, Stack, Chip, Box, Grid } from '@mui/material';
|
||||
import { Card, CardActionArea, CardMedia, CardContent, Typography, Stack, Chip, Grid } from '@mui/material';
|
||||
import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined';
|
||||
import BookmarkIcon from '@mui/icons-material/Bookmark';
|
||||
import makeStyles from '@mui/styles/makeStyles';
|
||||
|
@ -108,9 +108,9 @@ function RepoDetails (props) {
|
||||
|
||||
// get url param from <Route here (i.e. image name)
|
||||
const {name} = useParams();
|
||||
const {state} = useLocation();
|
||||
const {state} = useLocation() || {};
|
||||
// @ts-ignore
|
||||
const {lastDate} = state;
|
||||
const {lastDate} = state || {};
|
||||
const classes = useStyles();
|
||||
const {description, overviewTitle, dependencies, dependents} = props;
|
||||
|
||||
@ -163,7 +163,7 @@ function RepoDetails (props) {
|
||||
|
||||
const renderOverview = () => {
|
||||
return (
|
||||
<Card className={classes.card}>
|
||||
<Card className={classes.card} data-testid='overview-container'>
|
||||
<CardContent>
|
||||
<Typography variant="h4" align="left">{overviewTitle || 'Quickstart'}</Typography>
|
||||
<Typography variant="body1" sx={{color:"rgba(0, 0, 0, 0.6)", fontSize:"1rem",lineHeight:"150%", marginTop:"5%"}}>{description || mockData.loremIpsum}</Typography>
|
||||
@ -232,7 +232,7 @@ function RepoDetails (props) {
|
||||
value={`Pull ${name}`}
|
||||
endAdornment={
|
||||
<InputAdornment position="end">
|
||||
<IconButton aria-label='copy' edge="end" onClick={() => navigator.clipboard.writeText(`Pull ${name}`)}>
|
||||
<IconButton aria-label='copy' edge="end" onClick={() => navigator.clipboard.writeText(`Pull ${name}`)} data-testid='pullcopy-btn'>
|
||||
<ContentCopyIcon/>
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
|
@ -89,7 +89,6 @@ TagCard.propTypes = {
|
||||
row: PropTypes.shape({
|
||||
Layers: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
amount: PropTypes.number.isRequired,
|
||||
Digest: PropTypes.string.isRequired,
|
||||
Size: PropTypes.string.isRequired,
|
||||
}),
|
||||
@ -109,13 +108,13 @@ const renderTags = (tags) => {
|
||||
}
|
||||
|
||||
|
||||
export default function CollapsibleTable(props) {
|
||||
export default function Tags(props) {
|
||||
const classes = useStyles();
|
||||
const {data} = props;
|
||||
const {tags} = data;
|
||||
|
||||
return (
|
||||
<Card className={classes.card}>
|
||||
<Card className={classes.card} data-testid='tags-container'>
|
||||
<CardContent className={classes.content}>
|
||||
<Typography variant="h4" gutterBottom component="div" align="left" style={{color: "rgba(0, 0, 0, 0.87)"}}>Tags history</Typography>
|
||||
<Divider variant="fullWidth" sx={{margin:"5% 0% 5% 0%", background:"rgba(0, 0, 0, 0.38)", height:"0.0625rem", width:"100%"}}/>
|
||||
|
@ -33,7 +33,7 @@ function RepoPage(props) {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<Stack direction="column" className={classes.pageWrapper}>
|
||||
<Stack direction="column" className={classes.pageWrapper} data-testid='repo-container'>
|
||||
<Header updateKeywords={props.updateKeywords}></Header>
|
||||
<Container className={classes.container} >
|
||||
<ExploreHeader/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user