fix: homepage incorrect data
Signed-off-by: Raul Kele <raulkeleblk@gmail.com>
This commit is contained in:
parent
60ca6d21d5
commit
ecff33fe01
@ -13,8 +13,9 @@ jest.mock('react-router-dom', () => ({
|
||||
}));
|
||||
|
||||
const mockImageList = {
|
||||
RepoListWithNewestImage: {
|
||||
Results: [
|
||||
GlobalSearch: {
|
||||
Page: { TotalCount: 6, ItemCount: 3 },
|
||||
Repos: [
|
||||
{
|
||||
Name: 'alpine',
|
||||
Size: '2806985',
|
||||
@ -65,28 +66,36 @@ const mockImageList = {
|
||||
Count: 10
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const mockImageListRecent = {
|
||||
GlobalSearch: {
|
||||
Page: { TotalCount: 6, ItemCount: 2 },
|
||||
Repos: [
|
||||
{
|
||||
Name: 'centos',
|
||||
Size: '369311301',
|
||||
LastUpdated: '2022-08-23T00:20:40.144281895Z',
|
||||
Name: 'alpine',
|
||||
Size: '2806985',
|
||||
LastUpdated: '2022-08-09T17:19:53.274069586Z',
|
||||
NewestImage: {
|
||||
Tag: 'latest',
|
||||
Description: '',
|
||||
IsSigned: true,
|
||||
Description: 'w',
|
||||
IsSigned: false,
|
||||
Licenses: '',
|
||||
Vendor: '',
|
||||
Labels: '',
|
||||
Vulnerabilities: {
|
||||
MaxSeverity: 'NONE',
|
||||
Count: 10
|
||||
MaxSeverity: 'LOW',
|
||||
Count: 7
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
Name: 'debian',
|
||||
Size: '369311301',
|
||||
LastUpdated: '2022-08-23T00:20:40.144281895Z',
|
||||
Name: 'mongo',
|
||||
Size: '231383863',
|
||||
LastUpdated: '2022-08-02T01:30:49.193203152Z',
|
||||
NewestImage: {
|
||||
Tag: 'latest',
|
||||
Description: '',
|
||||
@ -95,25 +104,8 @@ const mockImageList = {
|
||||
Vendor: '',
|
||||
Labels: '',
|
||||
Vulnerabilities: {
|
||||
MaxSeverity: 'MEDIUM',
|
||||
Count: 10
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
Name: 'mysql',
|
||||
Size: '369311301',
|
||||
LastUpdated: '2022-08-23T00:20:40.144281895Z',
|
||||
NewestImage: {
|
||||
Tag: 'latest',
|
||||
Description: '',
|
||||
IsSigned: true,
|
||||
Licenses: '',
|
||||
Vendor: '',
|
||||
Labels: '',
|
||||
Vulnerabilities: {
|
||||
MaxSeverity: 'UNKNOWN',
|
||||
Count: 10
|
||||
MaxSeverity: 'HIGH',
|
||||
Count: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,7 +124,8 @@ afterEach(() => {
|
||||
|
||||
describe('Home component', () => {
|
||||
it('fetches image data and renders popular, bookmarks and recently updated', async () => {
|
||||
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageList } });
|
||||
jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageList } });
|
||||
jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageListRecent } });
|
||||
render(<Home />);
|
||||
await waitFor(() => expect(screen.getAllByText(/alpine/i)).toHaveLength(2));
|
||||
await waitFor(() => expect(screen.getAllByText(/mongo/i)).toHaveLength(2));
|
||||
@ -140,14 +133,16 @@ describe('Home component', () => {
|
||||
});
|
||||
|
||||
it('renders signature icons', async () => {
|
||||
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageList } });
|
||||
jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageList } });
|
||||
jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageListRecent } });
|
||||
render(<Home />);
|
||||
expect(await screen.findAllByTestId('unverified-icon')).toHaveLength(2);
|
||||
expect(await screen.findAllByTestId('verified-icon')).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('renders vulnerability icons', async () => {
|
||||
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageList } });
|
||||
jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageList } });
|
||||
jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageListRecent } });
|
||||
render(<Home />);
|
||||
expect(await screen.findAllByTestId('low-vulnerability-icon')).toHaveLength(2);
|
||||
expect(await screen.findAllByTestId('high-vulnerability-icon')).toHaveLength(2);
|
||||
@ -158,11 +153,12 @@ describe('Home component', () => {
|
||||
jest.spyOn(api, 'get').mockRejectedValue({ status: 500, data: {} });
|
||||
const error = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
render(<Home />);
|
||||
await waitFor(() => expect(error).toBeCalledTimes(1));
|
||||
await waitFor(() => expect(error).toBeCalledTimes(2));
|
||||
});
|
||||
|
||||
it('should redirect to explore page when clicking view all popular', async () => {
|
||||
jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageList } });
|
||||
jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageList } });
|
||||
jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageListRecent } });
|
||||
render(<Home />);
|
||||
const viewAllButtons = await screen.findAllByText(/view all/i);
|
||||
expect(viewAllButtons).toHaveLength(2);
|
||||
|
@ -99,7 +99,7 @@ function SearchSuggestion({ setSearchCurrentValue = () => {} }) {
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [suggestionData, setSuggestionData] = useState([]);
|
||||
const [queryParams] = useSearchParams();
|
||||
const search = queryParams.get('search');
|
||||
const search = queryParams.get('search') || '';
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isFailedSearch, setIsFailedSearch] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
|
@ -8,6 +8,7 @@ import { mapToRepo } from 'utilities/objectModels';
|
||||
import Loading from '../Shared/Loading';
|
||||
import { useNavigate, createSearchParams } from 'react-router-dom';
|
||||
import { sortByCriteria } from 'utilities/sortCriteria';
|
||||
import { HOME_POPULAR_PAGE_SIZE, HOME_RECENT_PAGE_SIZE } from 'utilities/paginationConstants';
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
gridWrapper: {
|
||||
@ -60,29 +61,70 @@ const useStyles = makeStyles(() => ({
|
||||
|
||||
function Home() {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [homeData, setHomeData] = useState([]);
|
||||
const [popularData, setPopularData] = useState([]);
|
||||
const [recentData, setRecentData] = useState([]);
|
||||
const navigate = useNavigate();
|
||||
const abortController = useMemo(() => new AbortController(), []);
|
||||
const classes = useStyles();
|
||||
|
||||
useEffect(() => {
|
||||
window.scrollTo(0, 0);
|
||||
const getPopularData = () => {
|
||||
setIsLoading(true);
|
||||
api
|
||||
.get(`${host()}${endpoints.repoList()}`, abortController.signal)
|
||||
.get(
|
||||
`${host()}${endpoints.globalSearch({
|
||||
searchQuery: '',
|
||||
pageNumber: 1,
|
||||
pageSize: HOME_POPULAR_PAGE_SIZE,
|
||||
sortBy: sortByCriteria.downloads?.value
|
||||
})}`,
|
||||
abortController.signal
|
||||
)
|
||||
.then((response) => {
|
||||
if (response.data && response.data.data) {
|
||||
let repoList = response.data.data.RepoListWithNewestImage.Results;
|
||||
let repoList = response.data.data.GlobalSearch.Repos;
|
||||
let repoData = repoList.map((responseRepo) => {
|
||||
return mapToRepo(responseRepo);
|
||||
});
|
||||
setHomeData(repoData);
|
||||
setPopularData(repoData);
|
||||
setIsLoading(false);
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
};
|
||||
|
||||
const getRecentData = () => {
|
||||
setIsLoading(true);
|
||||
api
|
||||
.get(
|
||||
`${host()}${endpoints.globalSearch({
|
||||
searchQuery: '',
|
||||
pageNumber: 1,
|
||||
pageSize: HOME_RECENT_PAGE_SIZE,
|
||||
sortBy: sortByCriteria.updateTime?.value
|
||||
})}`,
|
||||
abortController.signal
|
||||
)
|
||||
.then((response) => {
|
||||
if (response.data && response.data.data) {
|
||||
let repoList = response.data.data.GlobalSearch.Repos;
|
||||
let repoData = repoList.map((responseRepo) => {
|
||||
return mapToRepo(responseRepo);
|
||||
});
|
||||
setRecentData(repoData);
|
||||
setIsLoading(false);
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.scrollTo(0, 0);
|
||||
getPopularData();
|
||||
getRecentData();
|
||||
return () => {
|
||||
abortController.abort();
|
||||
};
|
||||
@ -94,8 +136,8 @@ function Home() {
|
||||
|
||||
const renderMostPopular = () => {
|
||||
return (
|
||||
homeData &&
|
||||
homeData.slice(0, 3).map((item, index) => {
|
||||
popularData &&
|
||||
popularData.map((item, index) => {
|
||||
return (
|
||||
<RepoCard
|
||||
name={item.name}
|
||||
@ -120,8 +162,8 @@ function Home() {
|
||||
|
||||
const renderRecentlyUpdated = () => {
|
||||
return (
|
||||
homeData &&
|
||||
homeData.slice(0, 2).map((item, index) => {
|
||||
recentData &&
|
||||
recentData.map((item, index) => {
|
||||
return (
|
||||
<RepoCard
|
||||
name={item.name}
|
||||
|
@ -349,7 +349,7 @@ function TagDetails() {
|
||||
{/* <BookmarkIcon sx={{color:"#52637A"}}/> */}
|
||||
</Stack>
|
||||
|
||||
<Stack>
|
||||
<Stack sx={{ width: { xs: '100%', md: 'auto' } }}>
|
||||
<FormControl sx={{ m: '1', minWidth: '4.6875rem' }} className={classes.sortForm} size="small">
|
||||
<InputLabel>OS/Arch</InputLabel>
|
||||
{!isEmpty(selectedManifest) && (
|
||||
|
@ -1,6 +1,15 @@
|
||||
const HEADER_SEARCH_PAGE_SIZE = 9;
|
||||
const EXPLORE_PAGE_SIZE = 10;
|
||||
const HOME_PAGE_SIZE = 10;
|
||||
const HOME_POPULAR_PAGE_SIZE = 3;
|
||||
const HOME_RECENT_PAGE_SIZE = 2;
|
||||
const CVE_FIXEDIN_PAGE_SIZE = 5;
|
||||
|
||||
export { HEADER_SEARCH_PAGE_SIZE, EXPLORE_PAGE_SIZE, HOME_PAGE_SIZE, CVE_FIXEDIN_PAGE_SIZE };
|
||||
export {
|
||||
HEADER_SEARCH_PAGE_SIZE,
|
||||
EXPLORE_PAGE_SIZE,
|
||||
HOME_PAGE_SIZE,
|
||||
CVE_FIXEDIN_PAGE_SIZE,
|
||||
HOME_POPULAR_PAGE_SIZE,
|
||||
HOME_RECENT_PAGE_SIZE
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user