mirror of https://github.com/harness/drone.git
feat: [AH-964]: add unit test coverage for artifact details page and version list (#3418)
* feat: [AH-964]: add unit test coverage for artifact details page and version listpull/3616/head
parent
a906259562
commit
26d28e748b
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright 2024 Harness, Inc.
|
||||
*
|
||||
* 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 userEvent from '@testing-library/user-event'
|
||||
import { useGetArtifactSummaryQuery } from '@harnessio/react-har-service-client'
|
||||
import { getByTestId, queryByTestId, render, waitFor } from '@testing-library/react'
|
||||
|
||||
import '@ar/pages/version-details/VersionFactory'
|
||||
import '@ar/pages/repository-details/RepositoryFactory'
|
||||
import { DEFAULT_DATE_TIME_FORMAT } from '@ar/constants'
|
||||
import { getReadableDateTime } from '@ar/common/dateUtils'
|
||||
import ArTestWrapper from '@ar/utils/testUtils/ArTestWrapper'
|
||||
|
||||
import ArtifactDetailsPage from '../ArtifactDetailsPage'
|
||||
import { MOCK_GENERIC_ARTIFACT_SUMMARY } from './__mockData__'
|
||||
|
||||
jest.mock('@harnessio/react-har-service-client', () => ({
|
||||
useGetArtifactSummaryQuery: jest.fn().mockImplementation(() => {
|
||||
return {
|
||||
data: MOCK_GENERIC_ARTIFACT_SUMMARY,
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
}),
|
||||
useGetAllArtifactVersionsQuery: jest.fn().mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: [] } },
|
||||
error: null,
|
||||
loading: false,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
}))
|
||||
|
||||
describe('Verify Artifact Details Page', () => {
|
||||
test('Should render Header without any error', () => {
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<ArtifactDetailsPage />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const pageHeader = getByTestId(container, 'page-header')
|
||||
expect(pageHeader).toBeInTheDocument()
|
||||
|
||||
const data = MOCK_GENERIC_ARTIFACT_SUMMARY.content.data
|
||||
expect(pageHeader).toHaveTextContent(data.imageName)
|
||||
expect(pageHeader?.querySelector('span[data-icon=generic-repository-type]')).toBeInTheDocument()
|
||||
expect(pageHeader).toHaveTextContent('artifactDetails.totalDownloads' + data.downloadsCount)
|
||||
expect(pageHeader).toHaveTextContent(getReadableDateTime(Number(data.createdAt), DEFAULT_DATE_TIME_FORMAT))
|
||||
expect(pageHeader).toHaveTextContent(getReadableDateTime(Number(data.modifiedAt), DEFAULT_DATE_TIME_FORMAT))
|
||||
})
|
||||
|
||||
test('Should show error message with retry button if failed to load summary api', async () => {
|
||||
const retryFn = jest.fn()
|
||||
;(useGetArtifactSummaryQuery as jest.Mock).mockImplementation(() => {
|
||||
return {
|
||||
data: null,
|
||||
loading: false,
|
||||
error: { message: 'Failed to load with custom error message' },
|
||||
refetch: retryFn
|
||||
}
|
||||
})
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<ArtifactDetailsPage />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
expect(container.querySelector('span[icon="error"]')).toBeInTheDocument()
|
||||
expect(container).toHaveTextContent('Failed to load with custom error message')
|
||||
const retryBtn = container.querySelector('button[aria-label="Retry"]')
|
||||
expect(retryBtn).toBeInTheDocument()
|
||||
|
||||
await userEvent.click(retryBtn!)
|
||||
await waitFor(() => {
|
||||
expect(retryFn).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
test('Should not render header if no data or empty data', async () => {
|
||||
const retryFn = jest.fn()
|
||||
;(useGetArtifactSummaryQuery as jest.Mock).mockImplementation(() => {
|
||||
return {
|
||||
data: {},
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: retryFn
|
||||
}
|
||||
})
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<ArtifactDetailsPage />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const pageHeader = queryByTestId(container, 'page-header')
|
||||
expect(pageHeader).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
test('Should show loading for api loading', async () => {
|
||||
const retryFn = jest.fn()
|
||||
;(useGetArtifactSummaryQuery as jest.Mock).mockImplementation(() => {
|
||||
return {
|
||||
data: null,
|
||||
isFetching: true,
|
||||
error: null,
|
||||
refetch: retryFn
|
||||
}
|
||||
})
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<ArtifactDetailsPage />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const pageSpinner = queryByTestId(container, 'page-spinner')
|
||||
expect(pageSpinner).toBeInTheDocument()
|
||||
})
|
||||
})
|
|
@ -14,13 +14,16 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { ArtifactSummary } from '@harnessio/react-har-service-client'
|
||||
|
||||
export const ArtifactDetailsSummary: ArtifactSummary = {
|
||||
imageName: 'Artifact 1',
|
||||
labels: ['label1', 'label2'],
|
||||
packageType: 'DOCKER',
|
||||
downloadsCount: 1000,
|
||||
createdAt: '1713247878550',
|
||||
modifiedAt: '1713247878550'
|
||||
export const MOCK_GENERIC_ARTIFACT_SUMMARY = {
|
||||
content: {
|
||||
data: {
|
||||
createdAt: '1738048875014',
|
||||
downloadsCount: 0,
|
||||
imageName: 'artifact name',
|
||||
labels: null,
|
||||
modifiedAt: '1738048875014',
|
||||
packageType: 'GENERIC'
|
||||
},
|
||||
status: 'SUCCESS'
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@
|
|||
div[class*='TableV2--cells'],
|
||||
div[class*='TableV2--header'] {
|
||||
display: grid !important;
|
||||
grid-template-columns: minmax(var(--har-table-name-column-min-width), 1fr) 10rem 10rem 10rem 20rem 10rem 50px !important;
|
||||
grid-template-columns: minmax(var(--har-table-name-column-min-width), 1fr) 1fr 1fr 1fr 1fr 1fr !important;
|
||||
}
|
||||
|
||||
div[class*='TableV2--header'] {
|
||||
|
|
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
* Copyright 2024 Harness, Inc.
|
||||
*
|
||||
* 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 copy from 'clipboard-copy'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { fireEvent, getByText, render, waitFor } from '@testing-library/react'
|
||||
import {
|
||||
useGetAllArtifactVersionsQuery as _useGetAllArtifactVersionsQuery,
|
||||
useGetDockerArtifactManifestsQuery as _useGetDockerArtifactManifestsQuery,
|
||||
ArtifactVersionMetadata,
|
||||
DockerManifestDetails
|
||||
} from '@harnessio/react-har-service-client'
|
||||
|
||||
import '@ar/pages/version-details/VersionFactory'
|
||||
import '@ar/pages/repository-details/RepositoryFactory'
|
||||
|
||||
import { getShortDigest } from '@ar/pages/digest-list/utils'
|
||||
import ArTestWrapper from '@ar/utils/testUtils/ArTestWrapper'
|
||||
import VersionListPage from '@ar/pages/version-list/VersionListPage'
|
||||
import { getTableColumn, getTableRow } from '@ar/utils/testUtils/utils'
|
||||
|
||||
import { mockDockerLatestVersionListTableData, mockDockerManifestListTableData } from './__mockData__'
|
||||
|
||||
const useGetAllArtifactVersionsQuery = _useGetAllArtifactVersionsQuery as jest.Mock
|
||||
const useGetDockerArtifactManifestsQuery = _useGetDockerArtifactManifestsQuery as jest.Mock
|
||||
|
||||
jest.mock('@harnessio/react-har-service-client', () => ({
|
||||
useGetAllArtifactVersionsQuery: jest.fn(),
|
||||
useGetDockerArtifactManifestsQuery: jest.fn()
|
||||
}))
|
||||
|
||||
jest.mock('clipboard-copy', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn()
|
||||
}))
|
||||
|
||||
describe('Verify DockerVersion List Page', () => {
|
||||
test('Should render empty list text if response is empty', () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: [] } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
|
||||
const { getByText: getByTextLocal } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="DOCKER" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const noItemsText = getByTextLocal('versionList.table.noVersionsTitle')
|
||||
expect(noItemsText).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test('Should render docker version list', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockDockerLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
const { container, getByTestId } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="DOCKER" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const artifact = mockDockerLatestVersionListTableData.artifactVersions?.[0] as ArtifactVersionMetadata
|
||||
|
||||
const table = container.querySelector('[class*="TableV2--table"]')
|
||||
expect(table).toBeInTheDocument()
|
||||
|
||||
const rows = container.querySelectorAll('[class*="TableV2--row"]')
|
||||
expect(rows).toHaveLength(1)
|
||||
|
||||
const getFirstRowColumn = (col: number) => getTableColumn(1, col) as HTMLElement
|
||||
|
||||
const name = getByText(getFirstRowColumn(2), artifact.name as string)
|
||||
expect(name).toBeInTheDocument()
|
||||
|
||||
const nonProdDep = getByTestId('nonProdDeployments')
|
||||
const prodDep = getByTestId('prodDeployments')
|
||||
|
||||
expect(getByText(nonProdDep, artifact.deploymentMetadata?.nonProdEnvCount as number)).toBeInTheDocument()
|
||||
expect(getByText(nonProdDep, 'nonProd')).toBeInTheDocument()
|
||||
|
||||
expect(getByText(prodDep, artifact.deploymentMetadata?.prodEnvCount as number)).toBeInTheDocument()
|
||||
expect(getByText(prodDep, 'prod')).toBeInTheDocument()
|
||||
|
||||
const digestValue = getByText(getFirstRowColumn(4), artifact.digestCount as number)
|
||||
expect(digestValue).toBeInTheDocument()
|
||||
|
||||
const curlColumn = getFirstRowColumn(6)
|
||||
expect(curlColumn).toHaveTextContent('copy')
|
||||
const copyCurlBtn = curlColumn.querySelector('[data-icon="code-copy"]') as HTMLElement
|
||||
expect(copyCurlBtn).toBeInTheDocument()
|
||||
await userEvent.click(copyCurlBtn)
|
||||
expect(copy).toHaveBeenCalled()
|
||||
|
||||
const expandIcon = getFirstRowColumn(1).querySelector('[data-icon="chevron-down"') as HTMLElement
|
||||
expect(expandIcon).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test('Should render docker manifest list', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockDockerLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
useGetDockerArtifactManifestsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: mockDockerManifestListTableData },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="DOCKER" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const getFirstRowColumn = (col: number) => getTableColumn(1, col, container) as HTMLElement
|
||||
|
||||
const expandIcon = getFirstRowColumn(1).querySelector('[data-icon="chevron-down"') as HTMLElement
|
||||
expect(expandIcon).toBeInTheDocument()
|
||||
await userEvent.click(expandIcon)
|
||||
|
||||
const digestTableData = mockDockerManifestListTableData.data.manifests?.[0] as DockerManifestDetails
|
||||
const digestListTable = getTableRow(1, container) as HTMLElement
|
||||
const getFirstDigestRowColumn = (col: number) => getTableColumn(1, col, digestListTable) as HTMLElement
|
||||
|
||||
const digestName = getFirstDigestRowColumn(1)
|
||||
expect(digestName).toHaveTextContent(getShortDigest(digestTableData.digest))
|
||||
|
||||
const osArch = getFirstDigestRowColumn(2)
|
||||
expect(osArch).toHaveTextContent(digestTableData.osArch)
|
||||
|
||||
const size = getFirstDigestRowColumn(3)
|
||||
expect(size).toHaveTextContent(digestTableData.size as string)
|
||||
|
||||
const downloads = getFirstDigestRowColumn(5)
|
||||
expect(downloads).toHaveTextContent(digestTableData.downloadsCount?.toString() as string)
|
||||
})
|
||||
|
||||
test('Should show error message docker manifest list ', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockDockerLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
const mockRefetchFn = jest.fn().mockImplementation(() => undefined)
|
||||
|
||||
useGetDockerArtifactManifestsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: null,
|
||||
loading: false,
|
||||
error: { message: 'failed to load data' },
|
||||
refetch: mockRefetchFn
|
||||
}
|
||||
})
|
||||
|
||||
const { container, getByText: getByTextLocal } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="DOCKER" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const getFirstRowColumn = (col: number) => getTableColumn(1, col, container) as HTMLElement
|
||||
|
||||
const expandIcon = getFirstRowColumn(1).querySelector('[data-icon="chevron-down"') as HTMLElement
|
||||
expect(expandIcon).toBeInTheDocument()
|
||||
await userEvent.click(expandIcon)
|
||||
|
||||
const errorText = getByTextLocal('failed to load data')
|
||||
expect(errorText).toBeInTheDocument()
|
||||
|
||||
const retryBtn = getByTextLocal('Retry')
|
||||
expect(retryBtn).toBeInTheDocument()
|
||||
|
||||
await userEvent.click(retryBtn)
|
||||
expect(mockRefetchFn).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('Pagination should work', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockDockerLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
const { getByText: getByTextLocal, getByTestId } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="DOCKER" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const nextPageBtn = getByTextLocal('Next')
|
||||
await userEvent.click(nextPageBtn)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 1, search_term: '', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
|
||||
const pageSizeSelect = getByTestId('dropdown-button')
|
||||
await userEvent.click(pageSizeSelect)
|
||||
const pageSize20option = getByTextLocal('20')
|
||||
await userEvent.click(pageSize20option)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 20, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
test('Filters should work', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockDockerLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
const { getByText: getByTextLocal, getByPlaceholderText } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="DOCKER" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
|
||||
useGetAllArtifactVersionsQuery.mockImplementationOnce(() => {
|
||||
return {
|
||||
data: { content: { data: { artifactVersions: [] } } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
|
||||
const searchInput = getByPlaceholderText('search')
|
||||
expect(searchInput).toBeInTheDocument()
|
||||
fireEvent.change(searchInput, { target: { value: '1234' } })
|
||||
|
||||
await waitFor(async () => {
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '1234', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
const clearAllFiltersBtn = getByTextLocal('clearFilters')
|
||||
await userEvent.click(clearAllFiltersBtn)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
test('Sorting should work', async () => {
|
||||
const { getByText: getByTextLocal } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="DOCKER" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const artifactNameSortIcon = getByTextLocal('versionList.table.columns.version').nextSibling
|
||||
?.firstChild as HTMLElement
|
||||
await userEvent.click(artifactNameSortIcon)
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 50, sort_field: 'name', sort_order: 'ASC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
test('Should show error message with which listing api fails', async () => {
|
||||
const mockRefetchFn = jest.fn().mockImplementation(() => undefined)
|
||||
useGetAllArtifactVersionsQuery.mockImplementationOnce(() => {
|
||||
return {
|
||||
data: null,
|
||||
loading: false,
|
||||
error: { message: 'error message' },
|
||||
refetch: mockRefetchFn
|
||||
}
|
||||
})
|
||||
|
||||
const { getByText: getByTextLocal } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="DOCKER" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
const errorText = getByTextLocal('error message')
|
||||
expect(errorText).toBeInTheDocument()
|
||||
|
||||
const retryBtn = getByTextLocal('Retry')
|
||||
expect(retryBtn).toBeInTheDocument()
|
||||
|
||||
await userEvent.click(retryBtn)
|
||||
expect(mockRefetchFn).toHaveBeenCalled()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright 2024 Harness, Inc.
|
||||
*
|
||||
* 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 type { DockerManifestsResponseResponse, ListArtifactVersion } from '@harnessio/react-har-service-client'
|
||||
|
||||
export const mockDockerLatestVersionListTableData: ListArtifactVersion = {
|
||||
artifactVersions: [
|
||||
{
|
||||
deploymentMetadata: {
|
||||
nonProdEnvCount: 0,
|
||||
prodEnvCount: 0
|
||||
},
|
||||
digestCount: 1,
|
||||
islatestVersion: true,
|
||||
lastModified: '1730978736333',
|
||||
name: '1.0.0',
|
||||
packageType: 'DOCKER',
|
||||
pullCommand: 'docker pull pkg.qa.harness.io/iwnhltqp7q/docker-repo/podinfo-artifact:1.0.0',
|
||||
registryIdentifier: '',
|
||||
registryPath: '',
|
||||
size: '69.56MB'
|
||||
}
|
||||
],
|
||||
itemCount: 55,
|
||||
pageCount: 2,
|
||||
pageIndex: 0,
|
||||
pageSize: 50
|
||||
}
|
||||
|
||||
export const mockDockerManifestListTableData: DockerManifestsResponseResponse = {
|
||||
data: {
|
||||
imageName: 'maven-app',
|
||||
manifests: [
|
||||
{
|
||||
createdAt: '1738923119376',
|
||||
digest: 'sha256:144cdab68a435424250fe06e9a4f8a5f6b6b8a8a55d257bc6ee77476a6ec520d',
|
||||
downloadsCount: 11,
|
||||
osArch: 'linux/arm64',
|
||||
size: '246.43MB',
|
||||
stoExecutionId: 'Tbi7s6nETjmOMKU3Qrnm7A',
|
||||
stoPipelineId: 'HARNESS_ARTIFACT_SCAN_PIPELINE'
|
||||
},
|
||||
{
|
||||
createdAt: '1738923119376',
|
||||
digest: 'sha256:144cdab68a435424250fe06e9a4f8a5f6b6b8a8a55d257bc6ee77476a6ec520d',
|
||||
downloadsCount: 11,
|
||||
osArch: 'linux/arm64',
|
||||
size: '246.43MB'
|
||||
}
|
||||
],
|
||||
version: '1.0.0'
|
||||
},
|
||||
status: 'SUCCESS'
|
||||
}
|
|
@ -43,10 +43,10 @@ export class GenericVersionType extends VersionStep<ArtifactVersionSummary> {
|
|||
]
|
||||
|
||||
versionListTableColumnConfig: CommonVersionListTableProps['columnConfigs'] = {
|
||||
[VersionListColumnEnum.Name]: { width: '30%' },
|
||||
[VersionListColumnEnum.Size]: { width: '30%' },
|
||||
[VersionListColumnEnum.FileCount]: { width: '20%' },
|
||||
[VersionListColumnEnum.LastModified]: { width: '20%' }
|
||||
[VersionListColumnEnum.Name]: { width: '100%' },
|
||||
[VersionListColumnEnum.Size]: { width: '100%' },
|
||||
[VersionListColumnEnum.FileCount]: { width: '100%' },
|
||||
[VersionListColumnEnum.LastModified]: { width: '100%' }
|
||||
}
|
||||
|
||||
renderVersionListTable(props: VersionListTableProps): JSX.Element {
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* Copyright 2024 Harness, Inc.
|
||||
*
|
||||
* 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 userEvent from '@testing-library/user-event'
|
||||
import { fireEvent, getByText, render, waitFor } from '@testing-library/react'
|
||||
import {
|
||||
useGetAllArtifactVersionsQuery as _useGetAllArtifactVersionsQuery,
|
||||
ArtifactVersionMetadata
|
||||
} from '@harnessio/react-har-service-client'
|
||||
|
||||
import '@ar/pages/version-details/VersionFactory'
|
||||
import '@ar/pages/repository-details/RepositoryFactory'
|
||||
|
||||
import { getTableColumn } from '@ar/utils/testUtils/utils'
|
||||
import ArTestWrapper from '@ar/utils/testUtils/ArTestWrapper'
|
||||
import VersionListPage from '@ar/pages/version-list/VersionListPage'
|
||||
|
||||
import { mockGenericLatestVersionListTableData } from './__mockData__'
|
||||
|
||||
const useGetAllArtifactVersionsQuery = _useGetAllArtifactVersionsQuery as jest.Mock
|
||||
|
||||
jest.mock('@harnessio/react-har-service-client', () => ({
|
||||
useGetAllArtifactVersionsQuery: jest.fn()
|
||||
}))
|
||||
|
||||
jest.mock('clipboard-copy', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn()
|
||||
}))
|
||||
|
||||
describe('Verify GenericVersion List Page', () => {
|
||||
test('Should render empty list text if response is empty', () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: [] } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
|
||||
const { getByText: getByTextLocal } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="GENERIC" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const noItemsText = getByTextLocal('versionList.table.noVersionsTitle')
|
||||
expect(noItemsText).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test('Should render generic version list', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockGenericLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="GENERIC" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const artifact = mockGenericLatestVersionListTableData.artifactVersions?.[0] as ArtifactVersionMetadata
|
||||
|
||||
const table = container.querySelector('[class*="TableV2--table"]')
|
||||
expect(table).toBeInTheDocument()
|
||||
|
||||
const rows = container.querySelectorAll('[class*="TableV2--row"]')
|
||||
expect(rows).toHaveLength(1)
|
||||
|
||||
const getFirstRowColumn = (col: number) => getTableColumn(1, col) as HTMLElement
|
||||
|
||||
const name = getByText(getFirstRowColumn(1), artifact.name as string)
|
||||
expect(name).toBeInTheDocument()
|
||||
|
||||
const size = getByText(getFirstRowColumn(2), artifact.size as string)
|
||||
expect(size).toBeInTheDocument()
|
||||
|
||||
const fileCount = getByText(getFirstRowColumn(3), artifact.fileCount?.toString() as string)
|
||||
expect(fileCount).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test('Pagination should work', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockGenericLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
const { getByText: getByTextLocal, getByTestId } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="GENERIC" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const nextPageBtn = getByTextLocal('Next')
|
||||
await userEvent.click(nextPageBtn)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 1, search_term: '', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
|
||||
const pageSizeSelect = getByTestId('dropdown-button')
|
||||
await userEvent.click(pageSizeSelect)
|
||||
const pageSize20option = getByTextLocal('20')
|
||||
await userEvent.click(pageSize20option)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 20, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
test('Filters should work', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockGenericLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
const { getByText: getByTextLocal, getByPlaceholderText } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="GENERIC" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
|
||||
useGetAllArtifactVersionsQuery.mockImplementationOnce(() => {
|
||||
return {
|
||||
data: { content: { data: { artifactVersions: [] } } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
|
||||
const searchInput = getByPlaceholderText('search')
|
||||
expect(searchInput).toBeInTheDocument()
|
||||
fireEvent.change(searchInput, { target: { value: '1234' } })
|
||||
|
||||
await waitFor(async () => {
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '1234', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
const clearAllFiltersBtn = getByTextLocal('clearFilters')
|
||||
await userEvent.click(clearAllFiltersBtn)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
test('Sorting should work', async () => {
|
||||
const { getByText: getByTextLocal } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="GENERIC" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const artifactNameSortIcon = getByTextLocal('versionList.table.columns.version').nextSibling
|
||||
?.firstChild as HTMLElement
|
||||
await userEvent.click(artifactNameSortIcon)
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 50, sort_field: 'name', sort_order: 'ASC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
test('Should show error message with which listing api fails', async () => {
|
||||
const mockRefetchFn = jest.fn().mockImplementation(() => undefined)
|
||||
useGetAllArtifactVersionsQuery.mockImplementationOnce(() => {
|
||||
return {
|
||||
data: null,
|
||||
loading: false,
|
||||
error: { message: 'error message' },
|
||||
refetch: mockRefetchFn
|
||||
}
|
||||
})
|
||||
|
||||
const { getByText: getByTextLocal } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="GENERIC" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
const errorText = getByTextLocal('error message')
|
||||
expect(errorText).toBeInTheDocument()
|
||||
|
||||
const retryBtn = getByTextLocal('Retry')
|
||||
expect(retryBtn).toBeInTheDocument()
|
||||
|
||||
await userEvent.click(retryBtn)
|
||||
expect(mockRefetchFn).toHaveBeenCalled()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2024 Harness, Inc.
|
||||
*
|
||||
* 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 type { ListArtifactVersion } from '@harnessio/react-har-service-client'
|
||||
|
||||
export const mockGenericLatestVersionListTableData: ListArtifactVersion = {
|
||||
artifactVersions: [
|
||||
{
|
||||
fileCount: 10,
|
||||
lastModified: '1730978736333',
|
||||
name: '1.0.0',
|
||||
packageType: 'GENERIC',
|
||||
registryIdentifier: '',
|
||||
registryPath: '',
|
||||
size: '69.56MB'
|
||||
}
|
||||
],
|
||||
itemCount: 55,
|
||||
pageCount: 2,
|
||||
pageIndex: 0,
|
||||
pageSize: 50
|
||||
}
|
|
@ -43,11 +43,11 @@ export class HelmVersionType extends VersionStep<ArtifactVersionSummary> {
|
|||
VersionDetailsTab.CODE
|
||||
]
|
||||
versionListTableColumnConfig: CommonVersionListTableProps['columnConfigs'] = {
|
||||
[VersionListColumnEnum.Name]: { width: '30%' },
|
||||
[VersionListColumnEnum.Size]: { width: '8%' },
|
||||
[VersionListColumnEnum.DownloadCount]: { width: '10%' },
|
||||
[VersionListColumnEnum.LastModified]: { width: '12%' },
|
||||
[VersionListColumnEnum.PullCommand]: { width: '40%' }
|
||||
[VersionListColumnEnum.Name]: { width: '100%' },
|
||||
[VersionListColumnEnum.Size]: { width: '100%' },
|
||||
[VersionListColumnEnum.DownloadCount]: { width: '100%' },
|
||||
[VersionListColumnEnum.LastModified]: { width: '100%' },
|
||||
[VersionListColumnEnum.PullCommand]: { width: '100%' }
|
||||
}
|
||||
|
||||
renderVersionListTable(props: VersionListTableProps): JSX.Element {
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* Copyright 2024 Harness, Inc.
|
||||
*
|
||||
* 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 copy from 'clipboard-copy'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { fireEvent, getByText, render, waitFor } from '@testing-library/react'
|
||||
import {
|
||||
useGetAllArtifactVersionsQuery as _useGetAllArtifactVersionsQuery,
|
||||
ArtifactVersionMetadata
|
||||
} from '@harnessio/react-har-service-client'
|
||||
|
||||
import '@ar/pages/version-details/VersionFactory'
|
||||
import '@ar/pages/repository-details/RepositoryFactory'
|
||||
|
||||
import { getTableColumn } from '@ar/utils/testUtils/utils'
|
||||
import ArTestWrapper from '@ar/utils/testUtils/ArTestWrapper'
|
||||
import VersionListPage from '@ar/pages/version-list/VersionListPage'
|
||||
|
||||
import { mockHelmLatestVersionListTableData } from './__mockData__'
|
||||
|
||||
const useGetAllArtifactVersionsQuery = _useGetAllArtifactVersionsQuery as jest.Mock
|
||||
|
||||
jest.mock('@harnessio/react-har-service-client', () => ({
|
||||
useGetAllArtifactVersionsQuery: jest.fn()
|
||||
}))
|
||||
|
||||
jest.mock('clipboard-copy', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn()
|
||||
}))
|
||||
|
||||
describe('Verify HelmVersion List Page', () => {
|
||||
test('Should render empty list text if response is empty', () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: [] } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
|
||||
const { getByText: getByTextLocal } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="HELM" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const noItemsText = getByTextLocal('versionList.table.noVersionsTitle')
|
||||
expect(noItemsText).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test('Should render helm version list', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockHelmLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="HELM" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const artifact = mockHelmLatestVersionListTableData.artifactVersions?.[0] as ArtifactVersionMetadata
|
||||
|
||||
const table = container.querySelector('[class*="TableV2--table"]')
|
||||
expect(table).toBeInTheDocument()
|
||||
|
||||
const rows = container.querySelectorAll('[class*="TableV2--row"]')
|
||||
expect(rows).toHaveLength(1)
|
||||
|
||||
const getFirstRowColumn = (col: number) => getTableColumn(1, col) as HTMLElement
|
||||
|
||||
const name = getByText(getFirstRowColumn(1), artifact.name as string)
|
||||
expect(name).toBeInTheDocument()
|
||||
|
||||
const size = getByText(getFirstRowColumn(2), artifact.size as string)
|
||||
expect(size).toBeInTheDocument()
|
||||
|
||||
const downloads = getByText(getFirstRowColumn(3), artifact.downloadsCount?.toString() as string)
|
||||
expect(downloads).toBeInTheDocument()
|
||||
|
||||
const curlColumn = getFirstRowColumn(5)
|
||||
expect(curlColumn).toHaveTextContent('copy')
|
||||
const copyCurlBtn = curlColumn.querySelector('[data-icon="code-copy"]') as HTMLElement
|
||||
expect(copyCurlBtn).toBeInTheDocument()
|
||||
await userEvent.click(copyCurlBtn)
|
||||
expect(copy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('Pagination should work', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockHelmLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
const { getByText: getByTextLocal, getByTestId } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="HELM" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const nextPageBtn = getByTextLocal('Next')
|
||||
await userEvent.click(nextPageBtn)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 1, search_term: '', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
|
||||
const pageSizeSelect = getByTestId('dropdown-button')
|
||||
await userEvent.click(pageSizeSelect)
|
||||
const pageSize20option = getByTextLocal('20')
|
||||
await userEvent.click(pageSize20option)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 20, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
test('Filters should work', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockHelmLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
const { getByText: getByTextLocal, getByPlaceholderText } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="HELM" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
|
||||
useGetAllArtifactVersionsQuery.mockImplementationOnce(() => {
|
||||
return {
|
||||
data: { content: { data: { artifactVersions: [] } } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
|
||||
const searchInput = getByPlaceholderText('search')
|
||||
expect(searchInput).toBeInTheDocument()
|
||||
fireEvent.change(searchInput, { target: { value: '1234' } })
|
||||
|
||||
await waitFor(async () => {
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '1234', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
const clearAllFiltersBtn = getByTextLocal('clearFilters')
|
||||
await userEvent.click(clearAllFiltersBtn)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
test('Sorting should work', async () => {
|
||||
const { getByText: getByTextLocal } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="HELM" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const artifactNameSortIcon = getByTextLocal('versionList.table.columns.version').nextSibling
|
||||
?.firstChild as HTMLElement
|
||||
await userEvent.click(artifactNameSortIcon)
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 50, sort_field: 'name', sort_order: 'ASC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
test('Should show error message with which listing api fails', async () => {
|
||||
const mockRefetchFn = jest.fn().mockImplementation(() => undefined)
|
||||
useGetAllArtifactVersionsQuery.mockImplementationOnce(() => {
|
||||
return {
|
||||
data: null,
|
||||
loading: false,
|
||||
error: { message: 'error message' },
|
||||
refetch: mockRefetchFn
|
||||
}
|
||||
})
|
||||
|
||||
const { getByText: getByTextLocal } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="HELM" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
const errorText = getByTextLocal('error message')
|
||||
expect(errorText).toBeInTheDocument()
|
||||
|
||||
const retryBtn = getByTextLocal('Retry')
|
||||
expect(retryBtn).toBeInTheDocument()
|
||||
|
||||
await userEvent.click(retryBtn)
|
||||
expect(mockRefetchFn).toHaveBeenCalled()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2024 Harness, Inc.
|
||||
*
|
||||
* 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 type { ListArtifactVersion } from '@harnessio/react-har-service-client'
|
||||
|
||||
export const mockHelmLatestVersionListTableData: ListArtifactVersion = {
|
||||
artifactVersions: [
|
||||
{
|
||||
digestCount: 1,
|
||||
downloadsCount: 100,
|
||||
islatestVersion: true,
|
||||
lastModified: '1730978736333',
|
||||
name: '1.0.0',
|
||||
packageType: 'HELM',
|
||||
pullCommand: 'docker pull pkg.qa.harness.io/iwnhltqp7q/docker-repo/podinfo-artifact:1.0.0',
|
||||
registryIdentifier: '',
|
||||
registryPath: '',
|
||||
size: '69.56MB'
|
||||
}
|
||||
],
|
||||
itemCount: 55,
|
||||
pageCount: 2,
|
||||
pageIndex: 0,
|
||||
pageSize: 50
|
||||
}
|
|
@ -45,10 +45,10 @@ export class MavenVersionType extends VersionStep<ArtifactVersionSummary> {
|
|||
]
|
||||
|
||||
versionListTableColumnConfig: CommonVersionListTableProps['columnConfigs'] = {
|
||||
[VersionListColumnEnum.Name]: { width: '30%' },
|
||||
[VersionListColumnEnum.Size]: { width: '30%' },
|
||||
[VersionListColumnEnum.FileCount]: { width: '20%' },
|
||||
[VersionListColumnEnum.LastModified]: { width: '20%' }
|
||||
[VersionListColumnEnum.Name]: { width: '100%' },
|
||||
[VersionListColumnEnum.Size]: { width: '100%' },
|
||||
[VersionListColumnEnum.FileCount]: { width: '100%' },
|
||||
[VersionListColumnEnum.LastModified]: { width: '100%' }
|
||||
}
|
||||
|
||||
renderVersionListTable(props: VersionListTableProps): JSX.Element {
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* Copyright 2024 Harness, Inc.
|
||||
*
|
||||
* 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 userEvent from '@testing-library/user-event'
|
||||
import { fireEvent, getByText, render, waitFor } from '@testing-library/react'
|
||||
import {
|
||||
useGetAllArtifactVersionsQuery as _useGetAllArtifactVersionsQuery,
|
||||
ArtifactVersionMetadata
|
||||
} from '@harnessio/react-har-service-client'
|
||||
|
||||
import '@ar/pages/version-details/VersionFactory'
|
||||
import '@ar/pages/repository-details/RepositoryFactory'
|
||||
|
||||
import { getTableColumn } from '@ar/utils/testUtils/utils'
|
||||
import ArTestWrapper from '@ar/utils/testUtils/ArTestWrapper'
|
||||
import VersionListPage from '@ar/pages/version-list/VersionListPage'
|
||||
|
||||
import { mockMavenLatestVersionListTableData } from './__mockData__'
|
||||
|
||||
const useGetAllArtifactVersionsQuery = _useGetAllArtifactVersionsQuery as jest.Mock
|
||||
|
||||
jest.mock('@harnessio/react-har-service-client', () => ({
|
||||
useGetAllArtifactVersionsQuery: jest.fn()
|
||||
}))
|
||||
|
||||
jest.mock('clipboard-copy', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn()
|
||||
}))
|
||||
|
||||
describe('Verify MavenVersion List Page', () => {
|
||||
test('Should render empty list text if response is empty', () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: [] } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
|
||||
const { getByText: getByTextLocal } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="MAVEN" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const noItemsText = getByTextLocal('versionList.table.noVersionsTitle')
|
||||
expect(noItemsText).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test('Should render maven version list', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockMavenLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="MAVEN" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const artifact = mockMavenLatestVersionListTableData.artifactVersions?.[0] as ArtifactVersionMetadata
|
||||
|
||||
const table = container.querySelector('[class*="TableV2--table"]')
|
||||
expect(table).toBeInTheDocument()
|
||||
|
||||
const rows = container.querySelectorAll('[class*="TableV2--row"]')
|
||||
expect(rows).toHaveLength(1)
|
||||
|
||||
const getFirstRowColumn = (col: number) => getTableColumn(1, col) as HTMLElement
|
||||
|
||||
const name = getByText(getFirstRowColumn(1), artifact.name as string)
|
||||
expect(name).toBeInTheDocument()
|
||||
|
||||
const size = getByText(getFirstRowColumn(2), artifact.size as string)
|
||||
expect(size).toBeInTheDocument()
|
||||
|
||||
const fileCount = getByText(getFirstRowColumn(3), artifact.fileCount?.toString() as string)
|
||||
expect(fileCount).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test('Pagination should work', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockMavenLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
const { getByText: getByTextLocal, getByTestId } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="MAVEN" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const nextPageBtn = getByTextLocal('Next')
|
||||
await userEvent.click(nextPageBtn)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 1, search_term: '', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
|
||||
const pageSizeSelect = getByTestId('dropdown-button')
|
||||
await userEvent.click(pageSizeSelect)
|
||||
const pageSize20option = getByTextLocal('20')
|
||||
await userEvent.click(pageSize20option)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 20, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
test('Filters should work', async () => {
|
||||
useGetAllArtifactVersionsQuery.mockImplementation(() => {
|
||||
return {
|
||||
data: { content: { data: mockMavenLatestVersionListTableData } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
const { getByText: getByTextLocal, getByPlaceholderText } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="MAVEN" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
|
||||
useGetAllArtifactVersionsQuery.mockImplementationOnce(() => {
|
||||
return {
|
||||
data: { content: { data: { artifactVersions: [] } } },
|
||||
loading: false,
|
||||
error: null,
|
||||
refetch: jest.fn()
|
||||
}
|
||||
})
|
||||
|
||||
const searchInput = getByPlaceholderText('search')
|
||||
expect(searchInput).toBeInTheDocument()
|
||||
fireEvent.change(searchInput, { target: { value: '1234' } })
|
||||
|
||||
await waitFor(async () => {
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '1234', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
const clearAllFiltersBtn = getByTextLocal('clearFilters')
|
||||
await userEvent.click(clearAllFiltersBtn)
|
||||
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 50, sort_field: 'updatedAt', sort_order: 'DESC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
test('Sorting should work', async () => {
|
||||
const { getByText: getByTextLocal } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="MAVEN" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const artifactNameSortIcon = getByTextLocal('versionList.table.columns.version').nextSibling
|
||||
?.firstChild as HTMLElement
|
||||
await userEvent.click(artifactNameSortIcon)
|
||||
expect(useGetAllArtifactVersionsQuery).toHaveBeenLastCalledWith({
|
||||
artifact: 'undefined/+',
|
||||
queryParams: { page: 0, search_term: '', size: 50, sort_field: 'name', sort_order: 'ASC' },
|
||||
registry_ref: 'undefined/+',
|
||||
stringifyQueryParamsOptions: { arrayFormat: 'repeat' }
|
||||
})
|
||||
})
|
||||
|
||||
test('Should show error message with which listing api fails', async () => {
|
||||
const mockRefetchFn = jest.fn().mockImplementation(() => undefined)
|
||||
useGetAllArtifactVersionsQuery.mockImplementationOnce(() => {
|
||||
return {
|
||||
data: null,
|
||||
loading: false,
|
||||
error: { message: 'error message' },
|
||||
refetch: mockRefetchFn
|
||||
}
|
||||
})
|
||||
|
||||
const { getByText: getByTextLocal } = render(
|
||||
<ArTestWrapper>
|
||||
<VersionListPage packageType="MAVEN" />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
const errorText = getByTextLocal('error message')
|
||||
expect(errorText).toBeInTheDocument()
|
||||
|
||||
const retryBtn = getByTextLocal('Retry')
|
||||
expect(retryBtn).toBeInTheDocument()
|
||||
|
||||
await userEvent.click(retryBtn)
|
||||
expect(mockRefetchFn).toHaveBeenCalled()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2024 Harness, Inc.
|
||||
*
|
||||
* 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 type { ListArtifactVersion } from '@harnessio/react-har-service-client'
|
||||
|
||||
export const mockMavenLatestVersionListTableData: ListArtifactVersion = {
|
||||
artifactVersions: [
|
||||
{
|
||||
fileCount: 10,
|
||||
lastModified: '1730978736333',
|
||||
name: '1.0.0',
|
||||
packageType: 'MAVEN',
|
||||
registryIdentifier: '',
|
||||
registryPath: '',
|
||||
size: '69.56MB'
|
||||
}
|
||||
],
|
||||
itemCount: 55,
|
||||
pageCount: 2,
|
||||
pageIndex: 0,
|
||||
pageSize: 50
|
||||
}
|
|
@ -44,7 +44,7 @@
|
|||
div[class*='TableV2--cells'],
|
||||
div[class*='TableV2--header'] {
|
||||
display: grid !important;
|
||||
grid-template-columns: 40px minmax(var(--har-table-name-column-min-width), 1fr) 10rem 10rem 38rem;
|
||||
grid-template-columns: 40px minmax(var(--har-table-name-column-min-width), 1fr) 1fr 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@
|
|||
div[class*='TableV2--cells'],
|
||||
div[class*='TableV2--header'] {
|
||||
display: grid !important;
|
||||
grid-template-columns: 40px minmax(var(--har-table-name-column-min-width), 1fr) 15rem 10rem 10rem 30rem;
|
||||
grid-template-columns: 40px minmax(var(--har-table-name-column-min-width), 1fr) 1fr 1fr 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,14 +98,20 @@ export const getTableHeaderColumn = (column: number) => {
|
|||
return document.querySelector(`div[class*="TableV2--header--"] [class*="TableV2--cell"]:nth-child(${column})`)
|
||||
}
|
||||
|
||||
export const getTableRow = (row: number) => {
|
||||
return document.querySelector(`div[class*="TableV2--body--"] [class*="TableV2--row"]:nth-child(${row})`)
|
||||
export const getTableRow = (row: number, container: Document | Element = document): HTMLDivElement | null => {
|
||||
return container.querySelector(`div[class*="TableV2--body--"] [class*="TableV2--row"]:nth-child(${row})`)
|
||||
}
|
||||
|
||||
export const getTableColumn = (row: number, column: number): HTMLDivElement | null => {
|
||||
return document.querySelector(
|
||||
`div[class*="TableV2--body--"] [class*="TableV2--row"]:nth-child(${row}) [class*="TableV2--cell--"]:nth-child(${column})`
|
||||
)
|
||||
export const getTableColumn = (
|
||||
row: number,
|
||||
column: number,
|
||||
container: Document | Element = document
|
||||
): HTMLDivElement | null => {
|
||||
const rowElement = getTableRow(row, container)
|
||||
if (rowElement) {
|
||||
return rowElement.querySelector(`[class*="TableV2--cell--"]:nth-child(${column})`)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export const testSelectChange = async (
|
||||
|
|
Loading…
Reference in New Issue