mirror of https://github.com/harness/drone.git
feat: [AH-609]: Add unit tests for create virtual registry flow (#2944)
* feat: [AH-609]: pass not supported type instead of GENERIC * feat: [AH-609]: Add unit tests for create virtual registry flowpull/3586/head
parent
042df435bd
commit
92bea1dfbf
|
@ -59,3 +59,27 @@ Object.defineProperty(window, 'matchMedia', {
|
|||
})
|
||||
|
||||
jest.mock('react-timeago', () => () => 'dummy date')
|
||||
|
||||
class MockIntersectionObserver {
|
||||
constructor() {
|
||||
this.root = null
|
||||
this.rootMargin = ''
|
||||
this.thresholds = []
|
||||
this.disconnect = () => null
|
||||
this.observe = () => null
|
||||
this.takeRecords = () => []
|
||||
this.unobserve = () => null
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(window, 'IntersectionObserver', {
|
||||
writable: true,
|
||||
configurable: true,
|
||||
value: MockIntersectionObserver
|
||||
})
|
||||
|
||||
Object.defineProperty(global, 'IntersectionObserver', {
|
||||
writable: true,
|
||||
configurable: true,
|
||||
value: MockIntersectionObserver
|
||||
})
|
||||
|
|
|
@ -61,7 +61,7 @@ function FormContent(props: FormContentProps): JSX.Element {
|
|||
const { getString } = useStrings()
|
||||
const { values } = formikProps
|
||||
const { packageType, config } = values
|
||||
const { type } = config
|
||||
const { type } = config || {}
|
||||
|
||||
useEffect(() => {
|
||||
const newDefaultValues = getDefaultValuesByRepositoryType(packageType as RepositoryPackageType, values)
|
||||
|
@ -113,7 +113,7 @@ function RepositoryCreateForm(props: RepositoryCreateFormProps, formikRef: Formi
|
|||
const { isLoading: createLoading, mutateAsync: createRepository } = useCreateRegistryMutation()
|
||||
|
||||
useEffect(() => {
|
||||
setShowOverlay?.(createLoading)
|
||||
setShowOverlay(createLoading)
|
||||
}, [createLoading])
|
||||
|
||||
const getDefaultValuesByRepositoryType = useCallback(
|
||||
|
@ -136,7 +136,7 @@ function RepositoryCreateForm(props: RepositoryCreateFormProps, formikRef: Formi
|
|||
|
||||
const handleSubmit = async (values: VirtualRegistryRequest): Promise<void> => {
|
||||
try {
|
||||
const packageType = values?.packageType
|
||||
const packageType = values.packageType
|
||||
const repositoryType = factory.getRepositoryType(packageType)
|
||||
if (repositoryType) {
|
||||
const formattedValues = repositoryType.processRepositoryFormData(values) as VirtualRegistryRequest
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* 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 type { FormikProps } from 'formik'
|
||||
import { useToaster } from '@harnessio/uicore'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { fireEvent, render, waitFor } from '@testing-library/react'
|
||||
import { useCreateRegistryMutation } from '@harnessio/react-har-service-client'
|
||||
|
||||
import { RepositoryPackageType } from '@ar/common/types'
|
||||
import ArTestWrapper from '@ar/utils/testUtils/ArTestWrapper'
|
||||
import repositoryFactory from '@ar/frameworks/RepositoryStep/RepositoryFactory'
|
||||
import { HelmRepositoryType } from '@ar/pages/repository-details/HelmRepository/HelmRepositoryType'
|
||||
import { DockerRepositoryType } from '@ar/pages/repository-details/DockerRepository/DockerRepositoryType'
|
||||
|
||||
import { queryByNameAttribute } from 'utils/test/testUtils'
|
||||
import RepositoryCreateForm from '../RepositoryCreateForm'
|
||||
|
||||
const mutateCreateRegistrySuccess = jest.fn().mockImplementation(
|
||||
() =>
|
||||
new Promise(onSuccess => {
|
||||
onSuccess({
|
||||
content: {
|
||||
status: 'SUCCESS',
|
||||
data: { identifier: '1234' }
|
||||
}
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
const mutateCreateRegistryFailure = jest.fn().mockImplementation(
|
||||
() =>
|
||||
new Promise((_, onFailed) => {
|
||||
onFailed({
|
||||
message: 'Custom message for failed scenario'
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
jest.mock('@harnessio/react-har-service-client', () => ({
|
||||
useCreateRegistryMutation: jest.fn()
|
||||
}))
|
||||
|
||||
jest.mock('@harnessio/uicore', () => ({
|
||||
...jest.requireActual('@harnessio/uicore'),
|
||||
useToaster: jest.fn().mockImplementation(() => ({
|
||||
showSuccess: jest.fn,
|
||||
showError: jest.fn(),
|
||||
clear: jest.fn()
|
||||
}))
|
||||
}))
|
||||
|
||||
describe('Verify RepositoryCreateForm', () => {
|
||||
beforeAll(() => {
|
||||
repositoryFactory.registerStep(new DockerRepositoryType())
|
||||
repositoryFactory.registerStep(new HelmRepositoryType())
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
test('Should render form without error and should submit form without error', async () => {
|
||||
;(useCreateRegistryMutation as jest.Mock).mockImplementation(() => ({
|
||||
isLoading: false,
|
||||
mutateAsync: mutateCreateRegistrySuccess
|
||||
}))
|
||||
|
||||
const setShowOverlay = jest.fn()
|
||||
const onSuccess = jest.fn()
|
||||
const formikRef = React.createRef<FormikProps<unknown>>()
|
||||
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<RepositoryCreateForm setShowOverlay={setShowOverlay} onSuccess={onSuccess} ref={formikRef} />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const selectPackageTypeLabel = 'repositoryDetails.repositoryForm.selectRepoType'
|
||||
expect(container).toHaveTextContent(selectPackageTypeLabel)
|
||||
|
||||
const dockerType = container.querySelector('input[type="checkbox"][name="packageType"][value="DOCKER"]')
|
||||
expect(dockerType).toBeChecked()
|
||||
|
||||
const helmType = container.querySelector('input[type="checkbox"][name="packageType"][value="HELM"]')
|
||||
expect(helmType).not.toBeChecked()
|
||||
await userEvent.click(container.querySelector('span[data-icon="service-helm"]')!)
|
||||
await waitFor(() => {
|
||||
expect(helmType).toBeChecked()
|
||||
})
|
||||
|
||||
const nameField = queryByNameAttribute('identifier', container)
|
||||
expect(nameField).toBeInTheDocument()
|
||||
fireEvent.change(nameField!, { target: { value: 'helm-repo-1' } })
|
||||
|
||||
formikRef.current?.submitForm()
|
||||
await waitFor(() => {
|
||||
expect(mutateCreateRegistrySuccess).toHaveBeenCalledWith({
|
||||
body: {
|
||||
cleanupPolicy: [],
|
||||
config: { type: 'VIRTUAL', upstreamProxies: [] },
|
||||
identifier: 'helm-repo-1',
|
||||
packageType: 'HELM',
|
||||
parentRef: 'undefined',
|
||||
scanners: []
|
||||
},
|
||||
queryParams: { space_ref: 'undefined' }
|
||||
})
|
||||
})
|
||||
await waitFor(() => {
|
||||
expect(onSuccess).toHaveBeenCalledWith({ identifier: '1234' })
|
||||
})
|
||||
})
|
||||
|
||||
test('Should work form validations correctly', async () => {
|
||||
;(useCreateRegistryMutation as jest.Mock).mockImplementation(() => ({
|
||||
isLoading: false,
|
||||
mutateAsync: mutateCreateRegistrySuccess
|
||||
}))
|
||||
|
||||
const setShowOverlay = jest.fn()
|
||||
const onSuccess = jest.fn()
|
||||
const formikRef = React.createRef<FormikProps<unknown>>()
|
||||
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<RepositoryCreateForm setShowOverlay={setShowOverlay} onSuccess={onSuccess} ref={formikRef} />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
formikRef.current?.submitForm()
|
||||
await waitFor(() => {
|
||||
expect(mutateCreateRegistrySuccess).not.toHaveBeenCalled()
|
||||
})
|
||||
await waitFor(() => {
|
||||
expect(onSuccess).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
const nameField = queryByNameAttribute('identifier', container)
|
||||
expect(nameField).toBeInTheDocument()
|
||||
fireEvent.change(nameField!, { target: { value: 'repo-1' } })
|
||||
|
||||
formikRef.current?.submitForm()
|
||||
await waitFor(() => {
|
||||
expect(mutateCreateRegistrySuccess).toHaveBeenCalled()
|
||||
})
|
||||
await waitFor(() => {
|
||||
expect(onSuccess).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
test('Should select default type based on defaultType prop', () => {
|
||||
const formikRef = React.createRef<FormikProps<unknown>>()
|
||||
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<RepositoryCreateForm
|
||||
defaultType={RepositoryPackageType.HELM}
|
||||
setShowOverlay={jest.fn}
|
||||
onSuccess={jest.fn}
|
||||
ref={formikRef}
|
||||
/>
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const dockerType = container.querySelector('input[type="checkbox"][name="packageType"][value="DOCKER"]')
|
||||
expect(dockerType).not.toBeChecked()
|
||||
|
||||
const helmType = container.querySelector('input[type="checkbox"][name="packageType"][value="HELM"]')
|
||||
expect(helmType).toBeChecked()
|
||||
})
|
||||
|
||||
test('Should disable types based on allowedTypes prop', () => {
|
||||
const formikRef = React.createRef<FormikProps<unknown>>()
|
||||
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<RepositoryCreateForm
|
||||
allowedPackageTypes={[RepositoryPackageType.HELM]}
|
||||
setShowOverlay={jest.fn}
|
||||
onSuccess={jest.fn}
|
||||
ref={formikRef}
|
||||
/>
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const dockerType = container.querySelector('input[type="checkbox"][name="packageType"][value="DOCKER"]')
|
||||
expect(dockerType).toBeDisabled()
|
||||
|
||||
const helmType = container.querySelector('input[type="checkbox"][name="packageType"][value="HELM"]')
|
||||
expect(helmType).not.toBeDisabled()
|
||||
expect(helmType).toBeChecked()
|
||||
})
|
||||
|
||||
test('Should show error if failed to create registry', async () => {
|
||||
;(useCreateRegistryMutation as jest.Mock).mockImplementation(() => ({
|
||||
isLoading: false,
|
||||
mutateAsync: mutateCreateRegistryFailure
|
||||
}))
|
||||
|
||||
const showError = jest.fn()
|
||||
;(useToaster as jest.Mock).mockImplementation(() => ({
|
||||
showSuccess: jest.fn,
|
||||
showError,
|
||||
clear: jest.fn()
|
||||
}))
|
||||
|
||||
const setShowOverlay = jest.fn()
|
||||
const onSuccess = jest.fn()
|
||||
const formikRef = React.createRef<FormikProps<unknown>>()
|
||||
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<RepositoryCreateForm setShowOverlay={setShowOverlay} onSuccess={onSuccess} ref={formikRef} />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const nameField = queryByNameAttribute('identifier', container)
|
||||
expect(nameField).toBeInTheDocument()
|
||||
fireEvent.change(nameField!, { target: { value: 'docker-repo-1' } })
|
||||
|
||||
formikRef.current?.submitForm()
|
||||
await waitFor(() => {
|
||||
expect(mutateCreateRegistryFailure).toHaveBeenCalledWith({
|
||||
body: {
|
||||
cleanupPolicy: [],
|
||||
config: { type: 'VIRTUAL', upstreamProxies: [] },
|
||||
identifier: 'docker-repo-1',
|
||||
packageType: 'DOCKER',
|
||||
parentRef: 'undefined',
|
||||
scanners: []
|
||||
},
|
||||
queryParams: { space_ref: 'undefined' }
|
||||
})
|
||||
})
|
||||
await waitFor(() => {
|
||||
expect(showError).toHaveBeenCalledWith('Custom message for failed scenario')
|
||||
})
|
||||
})
|
||||
|
||||
test('Should render default text if passed incorrect type or disabled type to defaultType', () => {
|
||||
const formikRef = React.createRef<FormikProps<unknown>>()
|
||||
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<RepositoryCreateForm
|
||||
defaultType={'RANDOM' as RepositoryPackageType}
|
||||
setShowOverlay={jest.fn}
|
||||
onSuccess={jest.fn}
|
||||
ref={formikRef}
|
||||
/>
|
||||
</ArTestWrapper>
|
||||
)
|
||||
const nameField = queryByNameAttribute('identifier', container)
|
||||
expect(nameField).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* 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 { Button } from '@harnessio/uicore'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { fireEvent, render, waitFor } from '@testing-library/react'
|
||||
|
||||
import { RepositoryPackageType } from '@ar/common/types'
|
||||
import ArTestWrapper from '@ar/utils/testUtils/ArTestWrapper'
|
||||
import repositoryFactory from '@ar/frameworks/RepositoryStep/RepositoryFactory'
|
||||
import { CreateRepository } from '@ar/pages/repository-list/components/CreateRepository/CreateRepository'
|
||||
|
||||
import { queryByNameAttribute } from 'utils/test/testUtils'
|
||||
import { HelmRepositoryType } from '../../HelmRepository/HelmRepositoryType'
|
||||
import { DockerRepositoryType } from '../../DockerRepository/DockerRepositoryType'
|
||||
import {
|
||||
useCreateRepositoryModal,
|
||||
useCreateRepositoryModalProps
|
||||
} from '../useCreateRepositoryModal/useCreateRepositoryModal'
|
||||
|
||||
const mutateCreateRegistry = jest.fn().mockImplementation(
|
||||
() =>
|
||||
new Promise(onSuccess => {
|
||||
onSuccess({
|
||||
content: {
|
||||
status: 'SUCCESS',
|
||||
data: { identifier: '1234' }
|
||||
}
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
jest.mock('@harnessio/react-har-service-client', () => ({
|
||||
useCreateRegistryMutation: jest.fn().mockImplementation(() => ({
|
||||
isLoading: false,
|
||||
mutateAsync: mutateCreateRegistry
|
||||
}))
|
||||
}))
|
||||
|
||||
const openModalDialog = async (container: HTMLElement): Promise<HTMLElement> => {
|
||||
const mainBtn = container.querySelector('button[aria-label="repositoryList.newRepository"]')
|
||||
expect(mainBtn!).toBeInTheDocument()
|
||||
await userEvent.click(mainBtn!)
|
||||
|
||||
const modalDialog = document.querySelector('div.bp3-dialog') as HTMLElement
|
||||
await waitFor(() => {
|
||||
expect(modalDialog).toBeInTheDocument()
|
||||
})
|
||||
return modalDialog
|
||||
}
|
||||
|
||||
const CustomCreateRepositoryModal = (props: useCreateRepositoryModalProps) => {
|
||||
const [open] = useCreateRepositoryModal(props)
|
||||
return <Button text="repositoryList.newRepository" onClick={open} />
|
||||
}
|
||||
|
||||
describe('Verify CreateRepositoryModal', () => {
|
||||
beforeAll(() => {
|
||||
repositoryFactory.registerStep(new DockerRepositoryType())
|
||||
repositoryFactory.registerStep(new HelmRepositoryType())
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
test('should able to open create repository form and able to submit without any error', async () => {
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<CreateRepository />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
|
||||
const modalDialog = await openModalDialog(container)
|
||||
|
||||
const modalHeader = modalDialog.querySelector('[data-testid="modaldialog-header"]')
|
||||
expect(modalHeader).toBeInTheDocument()
|
||||
expect(modalHeader).toHaveTextContent('repositoryDetails.repositoryForm.modalTitle')
|
||||
expect(modalHeader).toHaveTextContent('repositoryDetails.repositoryForm.modalSubTitle')
|
||||
|
||||
const nameField = queryByNameAttribute('identifier', modalDialog)
|
||||
expect(nameField).toBeInTheDocument()
|
||||
fireEvent.change(nameField!, { target: { value: 'repo1' } })
|
||||
|
||||
const submitBtn = modalDialog.querySelector('button[aria-label="repositoryDetails.repositoryForm.create"]')
|
||||
expect(submitBtn).toBeInTheDocument()
|
||||
await userEvent.click(submitBtn!)
|
||||
await waitFor(() => {
|
||||
expect(mutateCreateRegistry).toHaveBeenCalledWith({
|
||||
body: {
|
||||
cleanupPolicy: [],
|
||||
config: { type: 'VIRTUAL', upstreamProxies: [] },
|
||||
identifier: 'repo1',
|
||||
packageType: 'DOCKER',
|
||||
parentRef: 'undefined',
|
||||
scanners: []
|
||||
},
|
||||
queryParams: { space_ref: 'undefined' }
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test('should able to close the modal on click on Close button', async () => {
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<CreateRepository />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
const modalDialog = await openModalDialog(container)
|
||||
|
||||
const cancelBtn = modalDialog.querySelector('button[aria-label="cancel"]')
|
||||
expect(cancelBtn).toBeInTheDocument()
|
||||
await userEvent.click(cancelBtn!)
|
||||
await waitFor(() => {
|
||||
expect(modalDialog).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
const modalDialogAgain = await openModalDialog(container)
|
||||
const closeIcon = modalDialogAgain.querySelector('span[data-icon="Stroke"]')
|
||||
expect(closeIcon).toBeInTheDocument()
|
||||
await userEvent.click(closeIcon!)
|
||||
await waitFor(() => {
|
||||
expect(modalDialog).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
test('should render modal with allowed types correctly', async () => {
|
||||
const { container } = render(
|
||||
<ArTestWrapper>
|
||||
<CustomCreateRepositoryModal onSuccess={jest.fn()} allowedPackageTypes={[RepositoryPackageType.HELM]} />
|
||||
</ArTestWrapper>
|
||||
)
|
||||
const dialog = await openModalDialog(container)
|
||||
const dockerType = dialog.querySelector('input[type="checkbox"][name="packageType"][value="DOCKER"]')
|
||||
expect(dockerType).toBeDisabled()
|
||||
const helmType = dialog.querySelector('input[type="checkbox"][name="packageType"][value="HELM"]')
|
||||
expect(helmType).not.toBeDisabled()
|
||||
})
|
||||
})
|
|
@ -25,7 +25,7 @@ import type { RepositoryPackageType } from '@ar/common/types'
|
|||
import RepositoryCreateForm from '@ar/pages/repository-details/components/Forms/RepositoryCreateForm'
|
||||
import type { Repository } from '@ar/pages/repository-details/types'
|
||||
|
||||
interface useCreateRepositoryModalProps {
|
||||
export interface useCreateRepositoryModalProps {
|
||||
onSuccess: (data: Repository) => void
|
||||
allowedPackageTypes?: RepositoryPackageType[]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue