diff --git a/.github/workflows/end-to-end-test.yml b/.github/workflows/end-to-end-test.yml index d3c9998..a74408b 100644 --- a/.github/workflows/end-to-end-test.yml +++ b/.github/workflows/end-to-end-test.yml @@ -94,7 +94,7 @@ jobs: - name: Build zot run: | cd $GITHUB_WORKSPACE/zot - make binary + make binary ZUI_BUILD_PATH=$GITHUB_WORKSPACE/build ls -l bin/ - name: Bringup zot server diff --git a/src/__tests__/Explore/Explore.test.js b/src/__tests__/Explore/Explore.test.js index 1e456db..b19c54b 100644 --- a/src/__tests__/Explore/Explore.test.js +++ b/src/__tests__/Explore/Explore.test.js @@ -34,6 +34,7 @@ const mockImageList = { Size: '2806985', LastUpdated: '2022-08-09T17:19:53.274069586Z', IsBookmarked: false, + IsStarred: false, NewestImage: { Tag: 'latest', Description: 'w', @@ -58,6 +59,7 @@ const mockImageList = { Size: '231383863', LastUpdated: '2022-08-02T01:30:49.193203152Z', IsBookmarked: false, + IsStarred: false, NewestImage: { Tag: 'latest', Description: '', @@ -82,6 +84,7 @@ const mockImageList = { Size: '369311301', LastUpdated: '2022-08-23T00:20:40.144281895Z', IsBookmarked: false, + IsStarred: false, NewestImage: { Tag: 'latest', Description: '', @@ -106,6 +109,7 @@ const mockImageList = { Size: '369311301', LastUpdated: '2022-08-23T00:20:40.144281895Z', IsBookmarked: false, + IsStarred: false, NewestImage: { Tag: 'latest', Description: '', @@ -130,6 +134,7 @@ const mockImageList = { Size: '369311301', LastUpdated: '2022-08-23T00:20:40.144281895Z', IsBookmarked: false, + IsStarred: false, NewestImage: { Tag: 'latest', Description: '', @@ -158,6 +163,7 @@ const mockImageList = { Size: '369311301', LastUpdated: '2022-08-23T00:20:40.144281895Z', IsBookmarked: false, + IsStarred: false, NewestImage: { Tag: 'latest', Description: '', @@ -182,6 +188,7 @@ const mockImageList = { Size: '369311301', LastUpdated: '2022-08-23T00:20:40.144281895Z', IsBookmarked: false, + IsStarred: false, NewestImage: { Tag: 'latest', Description: '', @@ -338,4 +345,13 @@ describe('Explore component', () => { await userEvent.click(bookmarkButton); expect(await screen.findAllByTestId('bookmarked')).toHaveLength(1); }); + + it('should star a repo if star button is clicked', async () => { + jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageList } }); + render(); + const starButton = (await screen.findAllByTestId('star-button'))[0]; + jest.spyOn(api, 'put').mockResolvedValueOnce({ status: 200, data: {} }); + await userEvent.click(starButton); + expect(await screen.findAllByTestId('starred')).toHaveLength(1); + }); }); diff --git a/src/__tests__/HomePage/Home.test.js b/src/__tests__/HomePage/Home.test.js index e0a3e32..0ef55a5 100644 --- a/src/__tests__/HomePage/Home.test.js +++ b/src/__tests__/HomePage/Home.test.js @@ -164,6 +164,48 @@ const mockImageListBookmarks = { } }; +const mockImageListStars = { + GlobalSearch: { + Page: { TotalCount: 3, ItemCount: 2 }, + Repos: [ + { + Name: 'alpine', + Size: '2806985', + LastUpdated: '2022-08-09T17:19:53.274069586Z', + NewestImage: { + Tag: 'latest', + Description: 'w', + IsSigned: false, + Licenses: '', + Vendor: '', + Labels: '', + Vulnerabilities: { + MaxSeverity: 'LOW', + Count: 7 + } + } + }, + { + Name: 'mongo', + Size: '231383863', + LastUpdated: '2022-08-02T01:30:49.193203152Z', + NewestImage: { + Tag: 'latest', + Description: '', + IsSigned: true, + Licenses: '', + Vendor: '', + Labels: '', + Vulnerabilities: { + MaxSeverity: 'HIGH', + Count: 2 + } + } + } + ] + } +}; + beforeEach(() => { window.scrollTo = jest.fn(); }); @@ -178,8 +220,8 @@ describe('Home component', () => { jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageList } }); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageListRecent } }); render(); - await waitFor(() => expect(screen.getAllByText(/alpine/i)).toHaveLength(3)); - await waitFor(() => expect(screen.getAllByText(/mongo/i)).toHaveLength(3)); + await waitFor(() => expect(screen.getAllByText(/alpine/i)).toHaveLength(4)); + await waitFor(() => expect(screen.getAllByText(/mongo/i)).toHaveLength(4)); await waitFor(() => expect(screen.getAllByText(/node/i)).toHaveLength(1)); }); @@ -187,16 +229,16 @@ describe('Home component', () => { jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageList } }); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageListRecent } }); render(); - expect(await screen.findAllByTestId('unverified-icon')).toHaveLength(3); - expect(await screen.findAllByTestId('verified-icon')).toHaveLength(4); + expect(await screen.findAllByTestId('unverified-icon')).toHaveLength(4); + expect(await screen.findAllByTestId('verified-icon')).toHaveLength(5); }); it('renders vulnerability icons', async () => { jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageList } }); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageListRecent } }); render(); - expect(await screen.findAllByTestId('low-vulnerability-icon')).toHaveLength(3); - expect(await screen.findAllByTestId('high-vulnerability-icon')).toHaveLength(3); + expect(await screen.findAllByTestId('low-vulnerability-icon')).toHaveLength(4); + expect(await screen.findAllByTestId('high-vulnerability-icon')).toHaveLength(4); expect(await screen.findAllByTestId('critical-vulnerability-icon')).toHaveLength(1); }); @@ -204,16 +246,17 @@ describe('Home component', () => { jest.spyOn(api, 'get').mockRejectedValue({ status: 500, data: {} }); const error = jest.spyOn(console, 'error').mockImplementation(() => {}); render(); - await waitFor(() => expect(error).toBeCalledTimes(3)); + await waitFor(() => expect(error).toBeCalledTimes(4)); }); it('should redirect to explore page when clicking view all popular', async () => { jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageList } }); jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageListRecent } }); jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageListBookmarks } }); + jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageListStars } }); render(); const viewAllButtons = await screen.findAllByText(/view all/i); - expect(viewAllButtons).toHaveLength(3); + expect(viewAllButtons).toHaveLength(4); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: [] } }); fireEvent.click(viewAllButtons[0]); expect(mockedUsedNavigate).toHaveBeenCalledWith({ @@ -230,5 +273,10 @@ describe('Home component', () => { pathname: `/explore`, search: createSearchParams({ filter: 'IsBookmarked' }).toString() }); + fireEvent.click(viewAllButtons[3]); + expect(mockedUsedNavigate).toHaveBeenCalledWith({ + pathname: `/explore`, + search: createSearchParams({ filter: 'IsStarred' }).toString() + }); }); }); diff --git a/src/__tests__/RepoPage/Repo.test.js b/src/__tests__/RepoPage/Repo.test.js index 233d753..b95d357 100644 --- a/src/__tests__/RepoPage/Repo.test.js +++ b/src/__tests__/RepoPage/Repo.test.js @@ -47,6 +47,7 @@ const mockRepoDetailsData = { Size: '451554070', Vendors: ['[The Node.js Docker Team](https://github.com/nodejs/docker-node)\n'], IsBookmarked: false, + IsStarred: false, NewestImage: { RepoName: 'mongo', IsSigned: true, @@ -316,4 +317,13 @@ describe('Repo details component', () => { await userEvent.click(bookmarkButton); expect(await screen.findByTestId('bookmarked')).toBeInTheDocument(); }); + + it('should star a repo if star button is clicked', async () => { + jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockRepoDetailsData } }); + render(); + const starButton = await screen.findByTestId('star-button'); + jest.spyOn(api, 'put').mockResolvedValue({ status: 200, data: {} }); + await userEvent.click(starButton); + expect(await screen.findByTestId('starred')).toBeInTheDocument(); + }); }); diff --git a/src/api.js b/src/api.js index fe4ead4..15b7f79 100644 --- a/src/api.js +++ b/src/api.js @@ -84,7 +84,7 @@ const endpoints = { repoList: ({ pageNumber = 1, pageSize = 15 } = {}) => `/v2/_zot/ext/search?query={RepoListWithNewestImage(requestedPage: {limit:${pageSize} offset:${ (pageNumber - 1) * pageSize - }}){Results {Name LastUpdated Size Platforms {Os Arch} NewestImage { Tag Vulnerabilities {MaxSeverity Count} Description Licenses Title Source IsSigned SignatureInfo { Tool IsTrusted Author } Documentation Vendor Labels} IsStarred IsBookmarked DownloadCount}}}`, + }}){Results {Name LastUpdated Size Platforms {Os Arch} NewestImage { Tag Vulnerabilities {MaxSeverity Count} Description Licenses Title Source IsSigned SignatureInfo { Tool IsTrusted Author } Documentation Vendor Labels} IsStarred IsBookmarked StarCount DownloadCount}}}`, detailedRepoInfo: (name) => `/v2/_zot/ext/search?query={ExpandedRepoInfo(repo:"${name}"){Images {Manifests {Digest Platform {Os Arch} Size} Vulnerabilities {MaxSeverity Count} Tag LastUpdated Vendor } Summary {Name LastUpdated Size Platforms {Os Arch} Vendors IsStarred IsBookmarked NewestImage {RepoName IsSigned SignatureInfo { Tool IsTrusted Author } Vulnerabilities {MaxSeverity Count} Manifests {Digest} Tag Vendor Title Documentation DownloadCount Source Description Licenses}}}}`, detailedImageInfo: (name, tag) => @@ -134,9 +134,10 @@ const endpoints = { if (filter.Arch) filterParam += ` Arch:${!isEmpty(filter.Arch) ? `${JSON.stringify(filter.Arch)}` : '""'}`; if (filter.HasToBeSigned) filterParam += ` HasToBeSigned: ${filter.HasToBeSigned}`; if (filter.IsBookmarked) filterParam += ` IsBookmarked: ${filter.IsBookmarked}`; + if (filter.IsStarred) filterParam += ` IsStarred: ${filter.IsStarred}`; filterParam += '}'; if (Object.keys(filter).length === 0) filterParam = ''; - return `/v2/_zot/ext/search?query={GlobalSearch(${searchParam}, ${paginationParam} ${filterParam}) {Page {TotalCount ItemCount} Repos {Name LastUpdated Size Platforms { Os Arch } IsStarred IsBookmarked NewestImage { Tag Vulnerabilities {MaxSeverity Count} Description IsSigned SignatureInfo { Tool IsTrusted Author } Licenses Vendor Labels } DownloadCount}}}`; + return `/v2/_zot/ext/search?query={GlobalSearch(${searchParam}, ${paginationParam} ${filterParam}) {Page {TotalCount ItemCount} Repos {Name LastUpdated Size Platforms { Os Arch } IsStarred IsBookmarked NewestImage { Tag Vulnerabilities {MaxSeverity Count} Description IsSigned SignatureInfo { Tool IsTrusted Author } Licenses Vendor Labels } StarCount DownloadCount}}}`; }, imageSuggestions: ({ searchQuery = '""', pageNumber = 1, pageSize = 15 }) => { const searchParam = searchQuery !== '' ? `query:"${searchQuery}"` : `query:""`; @@ -145,7 +146,8 @@ const endpoints = { }, referrers: ({ repo, digest, type = '' }) => `/v2/_zot/ext/search?query={Referrers(repo: "${repo}" digest: "${digest}" type: "${type}"){MediaType ArtifactType Size Digest Annotations{Key Value}}}`, - bookmarkToggle: (repo) => `/v2/_zot/ext/userprefs?repo=${repo}&action=toggleBookmark` + bookmarkToggle: (repo) => `/v2/_zot/ext/userprefs?repo=${repo}&action=toggleBookmark`, + starToggle: (repo) => `/v2/_zot/ext/userprefs?repo=${repo}&action=toggleStar` }; export { api, endpoints }; diff --git a/src/components/Explore/Explore.jsx b/src/components/Explore/Explore.jsx index 27d663a..8ccfaf5 100644 --- a/src/components/Explore/Explore.jsx +++ b/src/components/Explore/Explore.jsx @@ -220,9 +220,11 @@ function Explore({ searchInputValue }) { version={item.latestVersion} description={item.description} downloads={item.downloads} + stars={item.stars} isSigned={item.isSigned} signatureInfo={item.signatureInfo} isBookmarked={item.isBookmarked} + isStarred={item.isStarred} vendor={item.vendor} platforms={item.platforms} key={index} diff --git a/src/components/Home/Home.jsx b/src/components/Home/Home.jsx index 8330602..addd47d 100644 --- a/src/components/Home/Home.jsx +++ b/src/components/Home/Home.jsx @@ -8,7 +8,12 @@ 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, HOME_BOOKMARKS_PAGE_SIZE } from 'utilities/paginationConstants'; +import { + HOME_POPULAR_PAGE_SIZE, + HOME_RECENT_PAGE_SIZE, + HOME_BOOKMARKS_PAGE_SIZE, + HOME_STARS_PAGE_SIZE +} from 'utilities/paginationConstants'; import { isEmpty } from 'lodash'; import NoDataComponent from 'components/Shared/NoDataComponent'; @@ -89,6 +94,8 @@ function Home() { const [isLoadingRecent, setIsLoadingRecent] = useState(true); const [bookmarkData, setBookmarkData] = useState([]); const [isLoadingBookmarks, setIsLoadingBookmarks] = useState(true); + const [starData, setStarData] = useState([]); + const [isLoadingStars, setIsLoadingStars] = useState(true); const navigate = useNavigate(); const abortController = useMemo(() => new AbortController(), []); @@ -185,12 +192,44 @@ function Home() { }); }; + const getStars = () => { + setIsLoadingStars(true); + api + .get( + `${host()}${endpoints.globalSearch({ + searchQuery: '', + pageNumber: 1, + pageSize: HOME_STARS_PAGE_SIZE, + sortBy: sortByCriteria.relevance?.value, + filter: { IsStarred: true } + })}`, + 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); + }); + setStarData(repoData); + setIsLoading(false); + setIsLoadingStars(false); + } + }) + .catch((e) => { + setIsLoading(false); + setIsLoadingStars(false); + console.error(e); + }); + }; + useEffect(() => { window.scrollTo(0, 0); setIsLoading(true); getPopularData(); getRecentData(); getBookmarks(); + getStars(); return () => { abortController.abort(); }; @@ -203,9 +242,11 @@ function Home() { const isNoData = () => !isLoading && !isLoadingBookmarks && + !isLoadingStars && !isLoadingPopular && !isLoadingRecent && bookmarkData.length === 0 && + starData.length === 0 && popularData.length === 0 && recentData.length === 0; @@ -219,9 +260,11 @@ function Home() { version={item.latestVersion} description={item.description} downloads={item.downloads} + stars={item.stars} isSigned={item.isSigned} signatureInfo={item.signatureInfo} isBookmarked={item.isBookmarked} + isStarred={item.isStarred} vendor={item.vendor} platforms={item.platforms} key={index} @@ -294,6 +337,27 @@ function Home() { {isLoadingBookmarks ? : renderCards(bookmarkData, isLoadingBookmarks)} )} + {!isEmpty(starData) && ( + <> + +
+ + Stars + +
+
+ handleClickViewAll('filter', 'IsStarred')} + > + View all + +
+
+ {isLoadingStars ? : renderCards(starData, isLoadingStars)} + + )} ); }; diff --git a/src/components/Repo/RepoDetails.jsx b/src/components/Repo/RepoDetails.jsx index f6d50f8..b3df2e9 100644 --- a/src/components/Repo/RepoDetails.jsx +++ b/src/components/Repo/RepoDetails.jsx @@ -14,6 +14,8 @@ import { useParams, useNavigate, createSearchParams } from 'react-router-dom'; import { Card, CardContent, CardMedia, Chip, Grid, Stack, Tooltip, Typography, IconButton } from '@mui/material'; import BookmarkIcon from '@mui/icons-material/Bookmark'; import BookmarkBorderIcon from '@mui/icons-material/BookmarkBorder'; +import StarIcon from '@mui/icons-material/Star'; +import StarBorderIcon from '@mui/icons-material/StarBorder'; import makeStyles from '@mui/styles/makeStyles'; // placeholder images @@ -230,6 +232,17 @@ function RepoDetails() { }); }; + const handleStarClick = () => { + api.put(`${host()}${endpoints.starToggle(name)}`, abortController.signal).then((response) => { + if (response.status === 200) { + setRepoDetailData((prevState) => ({ + ...prevState, + isStarred: !prevState.isStarred + })); + } + }); + }; + const getVendor = () => { return `${repoDetailData.newestTag?.Vendor || 'Vendor not available'} •`; }; @@ -276,15 +289,26 @@ function RepoDetails() { signatureInfo={repoDetailData.signatureInfo} /> - {isAuthenticated() && ( - - {repoDetailData?.isBookmarked ? ( - - ) : ( - - )} - - )} + + {isAuthenticated() && ( + + {repoDetailData?.isStarred ? ( + + ) : ( + + )} + + )} + {isAuthenticated() && ( + + {repoDetailData?.isBookmarked ? ( + + ) : ( + + )} + + )} + {repoDetailData?.title || 'Title not available'} diff --git a/src/components/Shared/RepoCard.jsx b/src/components/Shared/RepoCard.jsx index f2003e4..5718885 100644 --- a/src/components/Shared/RepoCard.jsx +++ b/src/components/Shared/RepoCard.jsx @@ -28,6 +28,8 @@ import { import makeStyles from '@mui/styles/makeStyles'; import BookmarkIcon from '@mui/icons-material/Bookmark'; import BookmarkBorderIcon from '@mui/icons-material/BookmarkBorder'; +import StarIcon from '@mui/icons-material/Star'; +import StarBorderIcon from '@mui/icons-material/StarBorder'; import { useTheme } from '@emotion/react'; // placeholder images @@ -183,17 +185,24 @@ function RepoCard(props) { platforms, description, downloads, + stars, isSigned, signatureInfo, lastUpdated, version, vulnerabilityData, - isBookmarked + isBookmarked, + isStarred } = props; // keep a local bookmark state to display in the ui dynamically on updates const [currentBookmarkValue, setCurrentBookmarkValue] = useState(isBookmarked); + // keep a local star state to display in the ui dynamically on updates + const [currentStarValue, setCurrentStarValue] = useState(isStarred); + + const [currentStarCount, setCurrentStarCount] = useState(stars); + const goToDetails = () => { navigate(`/image/${encodeURIComponent(name)}`); }; @@ -215,6 +224,23 @@ function RepoCard(props) { }); }; + const handleStarClick = (event) => { + event.stopPropagation(); + event.preventDefault(); + api.put(`${host()}${endpoints.starToggle(name)}`, abortController.signal).then((response) => { + if (response.status === 200) { + setCurrentStarValue((prevState) => !prevState); + currentStarValue + ? setCurrentStarCount((prevState) => { + return !isNaN(prevState) ? prevState - 1 : prevState; + }) + : setCurrentStarCount((prevState) => { + return !isNaN(prevState) ? prevState + 1 : prevState; + }); + } + }); + }; + const platformChips = () => { const filteredPlatforms = uniq(platforms?.flatMap((platform) => [platform.Os, platform.Arch])); const hiddenChips = filteredPlatforms.length - MAX_PLATFORM_CHIPS; @@ -260,6 +286,16 @@ function RepoCard(props) { ); }; + const renderStar = () => { + return ( + isAuthenticated() && ( + + {currentStarValue ? : } + + ) + ); + }; + return ( */} + + {renderStar()} + + Stars • + + + {!isNaN(currentStarCount) ? currentStarCount : `not available`} + + {renderBookmark()} diff --git a/src/utilities/filterConstants.js b/src/utilities/filterConstants.js index 5ae7878..8eb4a32 100644 --- a/src/utilities/filterConstants.js +++ b/src/utilities/filterConstants.js @@ -19,6 +19,11 @@ const imageFilters = [ label: 'Bookmarks', value: 'IsBookmarked', type: 'boolean' + }, + { + label: 'Starred Repositories', + value: 'IsStarred', + type: 'boolean' } ]; diff --git a/src/utilities/objectModels.js b/src/utilities/objectModels.js index e823658..34bb880 100644 --- a/src/utilities/objectModels.js +++ b/src/utilities/objectModels.js @@ -15,6 +15,7 @@ const mapToRepo = (responseRepo) => { logo: responseRepo.NewestImage?.Logo, lastUpdated: responseRepo.LastUpdated, downloads: responseRepo.DownloadCount, + stars: responseRepo.StarCount, vulnerabiltySeverity: responseRepo.NewestImage?.Vulnerabilities?.MaxSeverity, vulnerabilityCount: responseRepo.NewestImage?.Vulnerabilities?.Count }; @@ -33,6 +34,7 @@ const mapToRepoFromRepoInfo = (responseRepoInfo) => { title: responseRepoInfo.Summary?.NewestImage?.Title, source: responseRepoInfo.Summary?.NewestImage?.Source, downloads: responseRepoInfo.Summary?.NewestImage?.DownloadCount, + stars: responseRepoInfo.Summary?.NewestImage?.StarCount, overview: responseRepoInfo.Summary?.NewestImage?.Documentation, license: responseRepoInfo.Summary?.NewestImage?.Licenses, vulnerabilitySeverity: responseRepoInfo.Summary?.NewestImage?.Vulnerabilities?.MaxSeverity, @@ -53,6 +55,7 @@ const mapToImage = (responseImage) => { referrers: responseImage.Referrers, size: responseImage.Size, downloadCount: responseImage.DownloadCount, + starCount: responseImage.StarCount, lastUpdated: responseImage.LastUpdated, description: responseImage.Description, isSigned: responseImage.IsSigned, @@ -79,6 +82,7 @@ const mapToManifest = (responseManifest) => { size: responseManifest.Size, platform: responseManifest.Platform, downloadCount: responseManifest.DownloadCount, + starCount: responseManifest.StarCount, layers: responseManifest.Layers, history: responseManifest.History, vulnerabilities: responseManifest.Vulnerabilities diff --git a/src/utilities/paginationConstants.js b/src/utilities/paginationConstants.js index 9d407da..bfc4b93 100644 --- a/src/utilities/paginationConstants.js +++ b/src/utilities/paginationConstants.js @@ -4,6 +4,7 @@ const HOME_PAGE_SIZE = 10; const HOME_POPULAR_PAGE_SIZE = 3; const HOME_RECENT_PAGE_SIZE = 2; const HOME_BOOKMARKS_PAGE_SIZE = 2; +const HOME_STARS_PAGE_SIZE = 2; const CVE_FIXEDIN_PAGE_SIZE = 5; export { @@ -13,5 +14,6 @@ export { CVE_FIXEDIN_PAGE_SIZE, HOME_POPULAR_PAGE_SIZE, HOME_RECENT_PAGE_SIZE, - HOME_BOOKMARKS_PAGE_SIZE + HOME_BOOKMARKS_PAGE_SIZE, + HOME_STARS_PAGE_SIZE }; diff --git a/tests/values/test-constants.js b/tests/values/test-constants.js index a05e302..819cdae 100644 --- a/tests/values/test-constants.js +++ b/tests/values/test-constants.js @@ -17,13 +17,13 @@ const pageSizes = { }; const endpoints = { - repoList: `/v2/_zot/ext/search?query={RepoListWithNewestImage(requestedPage:%20{limit:15%20offset:0}){Results%20{Name%20LastUpdated%20Size%20Platforms%20{Os%20Arch}%20%20NewestImage%20{%20Tag%20Vulnerabilities%20{MaxSeverity%20Count}%20Description%20%20Licenses%20Logo%20Title%20Source%20IsSigned%20Documentation%20Vendor%20Labels}%20DownloadCount}}}`, + repoList: `/v2/_zot/ext/search?query={RepoListWithNewestImage(requestedPage:%20{limit:15%20offset:0}){Results%20{Name%20LastUpdated%20Size%20Platforms%20{Os%20Arch}%20%20NewestImage%20{%20Tag%20Vulnerabilities%20{MaxSeverity%20Count}%20Description%20%20Licenses%20Logo%20Title%20Source%20IsSigned%20Documentation%20Vendor%20Labels}%20StarCount%20DownloadCount}}}`, detailedRepoInfo: (name) => `/v2/_zot/ext/search?query={ExpandedRepoInfo(repo:%22${name}%22){Images%20{Manifests%20{Digest%20Platform%20{Os%20Arch}%20Size}%20Vulnerabilities%20{MaxSeverity%20Count}%20Tag%20LastUpdated%20Vendor%20}%20Summary%20{Name%20LastUpdated%20Size%20Platforms%20{Os%20Arch}%20Vendors%20NewestImage%20{RepoName%20IsSigned%20Vulnerabilities%20{MaxSeverity%20Count}%20Manifests%20{Digest}%20Tag%20Title%20Documentation%20DownloadCount%20Source%20Description%20Licenses}}}}`, globalSearch: (searchTerm, sortCriteria, pageNumber = 1, pageSize = 10) => `/v2/_zot/ext/search?query={GlobalSearch(query:%22${searchTerm}%22,%20requestedPage:%20{limit:${pageSize}%20offset:${ 10 * (pageNumber - 1) - }%20sortBy:%20${sortCriteria}}%20)%20{Page%20{TotalCount%20ItemCount}%20Repos%20{Name%20LastUpdated%20Size%20Platforms%20{%20Os%20Arch%20}%20IsStarred%20IsBookmarked%20NewestImage%20{%20Tag%20Vulnerabilities%20{MaxSeverity%20Count}%20Description%20IsSigned%20SignatureInfo%20{%20Tool%20IsTrusted%20Author%20}%20Licenses%20Vendor%20Labels%20}%20DownloadCount}}}`, + }%20sortBy:%20${sortCriteria}}%20)%20{Page%20{TotalCount%20ItemCount}%20Repos%20{Name%20LastUpdated%20Size%20Platforms%20{%20Os%20Arch%20}%20IsStarred%20IsBookmarked%20NewestImage%20{%20Tag%20Vulnerabilities%20{MaxSeverity%20Count}%20Description%20IsSigned%20SignatureInfo%20{%20Tool%20IsTrusted%20Author%20}%20Licenses%20Vendor%20Labels%20}%20StarCount%20DownloadCount}}}`, image: (name) => `/v2/_zot/ext/search?query={Image(image:%20%22${name}%22){RepoName%20IsSigned%20SignatureInfo%20{%20Tool%20IsTrusted%20Author%20}%20Vulnerabilities%20{MaxSeverity%20Count}%20%20Referrers%20{MediaType%20ArtifactType%20Size%20Digest%20Annotations{Key%20Value}}%20Tag%20Manifests%20{History%20{Layer%20{Size%20Digest}%20HistoryDescription%20{CreatedBy%20EmptyLayer}}%20Digest%20ConfigDigest%20LastUpdated%20Size%20Platform%20{Os%20Arch}}%20Vendor%20Licenses%20}}` };