From 2f94cc30ae83ccff5ba30132d4f27720b2c3d04b Mon Sep 17 00:00:00 2001 From: Raul Kele Date: Tue, 21 Mar 2023 16:47:11 +0200 Subject: [PATCH] patch: referrers from image query Signed-off-by: Raul Kele --- src/__tests__/TagPage/ReferredBy.test.js | 82 ++++++++++-------------- src/api.js | 2 +- src/components/Tag/Tabs/ReferredBy.jsx | 51 ++++----------- src/components/Tag/TagDetails.jsx | 2 +- src/utilities/objectModels.js | 1 + 5 files changed, 49 insertions(+), 89 deletions(-) diff --git a/src/__tests__/TagPage/ReferredBy.test.js b/src/__tests__/TagPage/ReferredBy.test.js index 96a4e82f..ddd2599e 100644 --- a/src/__tests__/TagPage/ReferredBy.test.js +++ b/src/__tests__/TagPage/ReferredBy.test.js @@ -1,47 +1,42 @@ -import { render, screen, waitFor } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { api } from 'api'; import ReferredBy from 'components/Tag/Tabs/ReferredBy'; import React from 'react'; -const mockReferrersList = { - data: { - Referrers: [ +const mockReferrersList = [ + { + MediaType: 'application/vnd.oci.artifact.manifest.v1+json', + ArtifactType: 'application/vnd.example.icecream.v1', + Size: 466, + Digest: 'sha256:be7a3d01c35a2cf53c502e9dc50cdf36b15d9361c81c63bf319f1d5cbe44ab7c', + Annotations: [ { - MediaType: 'application/vnd.oci.artifact.manifest.v1+json', - ArtifactType: 'application/vnd.example.icecream.v1', - Size: 466, - Digest: 'sha256:be7a3d01c35a2cf53c502e9dc50cdf36b15d9361c81c63bf319f1d5cbe44ab7c', - Annotations: [ - { - Key: 'demo', - Value: 'true' - }, - { - Key: 'format', - Value: 'oci' - } - ] + Key: 'demo', + Value: 'true' }, { - MediaType: 'application/vnd.oci.artifact.manifest.v1+json', - ArtifactType: 'application/vnd.example.icecream.v1', - Size: 466, - Digest: 'sha256:d9ad22f41d9cb9797c134401416eee2a70446cee1a8eb76fc6b191f4320dade2', - Annotations: [ - { - Key: 'demo', - Value: 'true' - }, - { - Key: 'format', - Value: 'oci' - } - ] + Key: 'format', + Value: 'oci' + } + ] + }, + { + MediaType: 'application/vnd.oci.artifact.manifest.v1+json', + ArtifactType: 'application/vnd.example.icecream.v1', + Size: 466, + Digest: 'sha256:d9ad22f41d9cb9797c134401416eee2a70446cee1a8eb76fc6b191f4320dade2', + Annotations: [ + { + Key: 'demo', + Value: 'true' + }, + { + Key: 'format', + Value: 'oci' } ] } -}; +]; // useNavigate mock const mockedUsedNavigate = jest.fn(); @@ -57,27 +52,17 @@ afterEach(() => { describe('Referred by tab', () => { it('should render referrers if there are any', async () => { - jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: mockReferrersList }); - render(); + render(); expect(await screen.findAllByText('Media type: application/vnd.oci.artifact.manifest.v1+json')).toHaveLength(2); }); it("renders no referrers if there aren't any", async () => { - jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: { Referrers: [] } } }); - render(); + render(); expect(await screen.findByText(/Nothing found/i)).toBeInTheDocument(); }); - it('should log an error if the request fails', async () => { - jest.spyOn(api, 'get').mockRejectedValue({ status: 500, data: {} }); - const error = jest.spyOn(console, 'error').mockImplementation(() => {}); - render(); - await waitFor(() => expect(error).toBeCalledTimes(1)); - }); - it('should display the digest when clicking the dropdowns', async () => { - jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: mockReferrersList }); - render(); + render(); const firstDigest = (await screen.findAllByText(/digest/i))[0]; expect(firstDigest).toBeInTheDocument(); await userEvent.click(firstDigest); @@ -91,8 +76,7 @@ describe('Referred by tab', () => { }); it('should display the annotations when clicking the dropdown', async () => { - jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: mockReferrersList }); - render(); + render(); const firstAnnotations = (await screen.findAllByText(/ANNOTATIONS/i))[0]; expect(firstAnnotations).toBeInTheDocument(); await userEvent.click(firstAnnotations); diff --git a/src/api.js b/src/api.js index a6fb426c..1ee27461 100644 --- a/src/api.js +++ b/src/api.js @@ -78,7 +78,7 @@ const endpoints = { 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 NewestImage {RepoName IsSigned Vulnerabilities {MaxSeverity Count} Manifests {Digest} Tag Title Documentation DownloadCount Source Description Licenses}}}}`, detailedImageInfo: (name, tag) => - `/v2/_zot/ext/search?query={Image(image: "${name}:${tag}"){RepoName IsSigned Vulnerabilities {MaxSeverity Count} Tag Manifests {History {Layer {Size Digest} HistoryDescription {CreatedBy EmptyLayer}} Digest ConfigDigest LastUpdated Size Platform {Os Arch}} Vendor Licenses }}`, + `/v2/_zot/ext/search?query={Image(image: "${name}:${tag}"){RepoName IsSigned Vulnerabilities {MaxSeverity Count} Referrers {MediaType ArtifactType Size Digest Annotations{Key Value}} Tag Manifests {History {Layer {Size Digest} HistoryDescription {CreatedBy EmptyLayer}} Digest ConfigDigest LastUpdated Size Platform {Os Arch}} Vendor Licenses }}`, vulnerabilitiesForRepo: (name, { pageNumber = 1, pageSize = 15 }, searchTerm = '') => { let query = `/v2/_zot/ext/search?query={CVEListForImage(image: "${name}", requestedPage: {limit:${pageSize} offset:${ (pageNumber - 1) * pageSize diff --git a/src/components/Tag/Tabs/ReferredBy.jsx b/src/components/Tag/Tabs/ReferredBy.jsx index 9bf93da6..2cadb19f 100644 --- a/src/components/Tag/Tabs/ReferredBy.jsx +++ b/src/components/Tag/Tabs/ReferredBy.jsx @@ -1,11 +1,9 @@ -import React, { useEffect, useState, useMemo } from 'react'; +import React, { useEffect, useState } from 'react'; import { makeStyles } from '@mui/styles'; import { isEmpty } from 'lodash'; import { Divider, Typography, Stack } from '@mui/material'; import ReferrerCard from '../../Shared/ReferrerCard'; import Loading from '../../Shared/Loading'; -import { api, endpoints } from 'api'; -import { host } from '../../../host'; import { mapReferrer } from 'utilities/objectModels'; const useStyles = makeStyles(() => ({ @@ -17,36 +15,24 @@ const useStyles = makeStyles(() => ({ })); function ReferredBy(props) { - const { repoName, digest } = props; - const [referrers, setReferrers] = useState([]); + const { referrers } = props; + const [referrersData, setReferrersData] = useState([]); const [isLoading, setIsLoading] = useState(true); const classes = useStyles(); - const abortController = useMemo(() => new AbortController(), []); useEffect(() => { - api - .get(`${host()}${endpoints.referrers({ repo: repoName, digest })}`, abortController.signal) - .then((response) => { - if (response.data && response.data.data) { - let referrersData = response.data.data.Referrers?.map((referrer) => mapReferrer(referrer)); - if (!isEmpty(referrersData)) { - setReferrers(referrersData); - } - } - setIsLoading(false); - }) - .catch((e) => { - console.error(e); - setIsLoading(false); - }); - return () => { - abortController.abort(); - }; + if (!isEmpty(referrers)) { + const mappedReferrersData = referrers.map((referrer) => mapReferrer(referrer)); + setReferrersData(mappedReferrersData); + } else { + setReferrersData([]); + } + setIsLoading(false); }, []); const renderReferrers = () => { - return !isEmpty(referrers) ? ( - referrers.map((referrer, index) => { + return !isEmpty(referrersData) ? ( + referrersData.map((referrer, index) => { return ( { - if (isLoading) { - return ; - } - if (!isLoading) { - return
; - } - return; - }; - return (
- {renderReferrers()} - {renderListBottom()} + {isLoading ? : renderReferrers()}
diff --git a/src/components/Tag/TagDetails.jsx b/src/components/Tag/TagDetails.jsx index e1da78b6..e5f873e0 100644 --- a/src/components/Tag/TagDetails.jsx +++ b/src/components/Tag/TagDetails.jsx @@ -580,7 +580,7 @@ function TagDetails() { - + diff --git a/src/utilities/objectModels.js b/src/utilities/objectModels.js index 8d027589..cefaffd9 100644 --- a/src/utilities/objectModels.js +++ b/src/utilities/objectModels.js @@ -44,6 +44,7 @@ const mapToImage = (responseImage) => { repoName: responseImage.RepoName, tag: responseImage.Tag, manifests: responseImage.Manifests?.map((manifest) => mapToManifest(manifest)) || [], + referrers: responseImage.Referrers, size: responseImage.Size, downloadCount: responseImage.DownloadCount, lastUpdated: responseImage.LastUpdated,