diff --git a/src/Components/CreateImageWizardV2/CreateImageWizard.scss b/src/Components/CreateImageWizardV2/CreateImageWizard.scss deleted file mode 100644 index 88651edb..00000000 --- a/src/Components/CreateImageWizardV2/CreateImageWizard.scss +++ /dev/null @@ -1,70 +0,0 @@ -.pf-v5-c-wizard__nav-list { - padding-right: 0px; -} - -.pf-v5-c-wizard__nav { - overflow-y: unset; -} - -.pf-c-popover[data-popper-reference-hidden="true"] { - font-weight: initial; - visibility: initial; - pointer-events: initial; -} - -.pf-v5-c-dual-list-selector { - --pf-v5-c-dual-list-selector__menu--MinHeight: 18rem; - --pf-v5-c-dual-list-selector--GridTemplateColumns--pane--MinMax--max: 100vw; -} - -.pf-c-form { - --pf-c-form--GridGap: var(--pf-global--spacer--md); -} - -.pf-c-form__group-label { - --pf-c-form__group-label--PaddingBottom: var(--pf-global--spacer--xs); -} - -.tiles { - display: flex; -} - -.tile { - flex: 1 0 0px; - max-width: 250px; -} - -.pf-c-tile:focus { - --pf-c-tile__title--Color: var(--pf-c-tile__title--Color); - --pf-c-tile__icon--Color: var(---pf-global--Color--100); - --pf-c-tile--before--BorderWidth: var(--pf-global--BorderWidth--sm); - --pf-c-tile--before--BorderColor: var(--pf-global--BorderColor--100); -} - -.pf-c-tile.pf-m-selected:focus { - --pf-c-tile__title--Color: var(--pf-c-tile--focus__title--Color); - --pf-c-tile__icon--Color: var(--pf-c-tile--focus__icon--Color); -} - -.provider-icon { - width: 1em; - height: 1em; -} - -.pf-u-min-width { - --pf-u-min-width--MinWidth: 18ch; -} - -.pf-u-max-width { - --pf-u-max-width--MaxWidth: 26rem; -} - -ul.pf-m-plain { - list-style: none; - padding-left: 0; - margin-left: 0; -} - -button.pf-v5-c-menu-toggle { - max-width: 100%; -} diff --git a/src/Components/CreateImageWizardV2/CreateImageWizard.tsx b/src/Components/CreateImageWizardV2/CreateImageWizard.tsx deleted file mode 100644 index a16e1fe2..00000000 --- a/src/Components/CreateImageWizardV2/CreateImageWizard.tsx +++ /dev/null @@ -1,152 +0,0 @@ -import React, { useState } from 'react'; - -import { - Button, - Wizard, - WizardFooterWrapper, - WizardStep, - useWizardContext, -} from '@patternfly/react-core'; -import { useNavigate } from 'react-router-dom'; - -import { - EnvironmentStateType, - filterEnvironment, - hasUserSelectedAtLeastOneEnv, - useGetAllowedTargets, -} from './steps/ImageOutput/Environment'; -import ImageOutputStep from './steps/ImageOutput/ImageOutput'; -import ReviewStep from './steps/Review/ReviewStep'; - -import { RHEL_9, X86_64 } from '../../constants'; -import './CreateImageWizard.scss'; -import { ArchitectureItem, Distributions } from '../../store/imageBuilderApi'; -import { resolveRelPath } from '../../Utilities/path'; -import { ImageBuilderHeader } from '../sharedComponents/ImageBuilderHeader'; - -/** - * @return true if the array in prevAllowedTargets is equivalent to the array - * allowedTargets, false otherwise - */ -const isIdenticalToPrev = ( - prevAllowedTargets: string[], - allowedTargets: string[] -) => { - let identicalToPrev = true; - if (allowedTargets.length === prevAllowedTargets.length) { - allowedTargets.forEach((elem) => { - if (!prevAllowedTargets.includes(elem)) { - identicalToPrev = false; - } - }); - } else { - identicalToPrev = false; - } - return identicalToPrev; -}; - -type CustomWizardFooterPropType = { - isNextDisabled: boolean; -}; -/** - * The custom wizard footer is only switching the order of the buttons compared - * to the default wizard footer from the PF5 library. - */ -const CustomWizardFooter = ({ isNextDisabled }: CustomWizardFooterPropType) => { - const { goToNextStep, goToPrevStep, close } = useWizardContext(); - return ( - - - - - - ); -}; - -const CreateImageWizard = () => { - const navigate = useNavigate(); - // Image output step states - const [release, setRelease] = useState(RHEL_9); - const [arch, setArch] = useState(X86_64); - const { - data: allowedTargets, - isFetching, - isSuccess, - isError, - } = useGetAllowedTargets({ - architecture: arch, - release: release, - }); - const [environment, setEnvironment] = useState( - filterEnvironment( - { - aws: { selected: false, authorized: false }, - azure: { selected: false, authorized: false }, - gcp: { selected: false, authorized: false }, - oci: { selected: false, authorized: false }, - 'vsphere-ova': { selected: false, authorized: false }, - vsphere: { selected: false, authorized: false }, - 'guest-image': { selected: false, authorized: false }, - 'image-installer': { selected: false, authorized: false }, - wsl: { selected: false, authorized: false }, - }, - allowedTargets - ) - ); - // Update of the environment when the architecture and release are changed. - // This pattern prevents the usage of a useEffect See https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes - const [prevAllowedTargets, setPrevAllowedTargets] = useState(allowedTargets); - if (!isIdenticalToPrev(prevAllowedTargets, allowedTargets)) { - setPrevAllowedTargets(allowedTargets); - setEnvironment(filterEnvironment(environment, allowedTargets)); - } - return ( - <> - -
- navigate(resolveRelPath(''))} isVisitRequired> - - } - > - - - } - > - - - -
- - ); -}; - -export default CreateImageWizard; diff --git a/src/Components/CreateImageWizardV2/steps/ImageOutput/ArchSelect.tsx b/src/Components/CreateImageWizardV2/steps/ImageOutput/ArchSelect.tsx deleted file mode 100644 index 66df666c..00000000 --- a/src/Components/CreateImageWizardV2/steps/ImageOutput/ArchSelect.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import React, { Dispatch, FormEvent, SetStateAction } from 'react'; - -import { - FormGroup, - FormSelect, - FormSelectOption, -} from '@patternfly/react-core'; - -import { ARCHS } from '../../../../constants'; -import { ArchitectureItem } from '../../../../store/imageBuilderApi'; - -type ArchSelectType = { - setArch: Dispatch>; - arch: ArchitectureItem['arch']; -}; - -/** - * Allows the user to pick the architecture to build - */ -const ArchSelect = ({ setArch, arch }: ArchSelectType) => { - const onChange = (_event: FormEvent, value: string) => { - setArch(value); - }; - - return ( - - - {ARCHS.map((arch, index) => ( - - ))} - - - ); -}; - -export default ArchSelect; diff --git a/src/Components/CreateImageWizardV2/steps/ImageOutput/CentOSAcknowledgement.tsx b/src/Components/CreateImageWizardV2/steps/ImageOutput/CentOSAcknowledgement.tsx deleted file mode 100644 index df9de1ea..00000000 --- a/src/Components/CreateImageWizardV2/steps/ImageOutput/CentOSAcknowledgement.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; - -import { Alert, Button } from '@patternfly/react-core'; -import { ExternalLinkAltIcon } from '@patternfly/react-icons'; - -const DeveloperProgramButton = () => { - return ( - - ); -}; - -const CentOSAcknowledgement = () => { - return ( - - CentOS Stream builds are intended for the development of future - versions of RHEL and are not supported for production workloads or - other use cases. - - } - > -

- Join the to learn about paid and no-cost RHEL - subscription options. -

-
- ); -}; - -export default CentOSAcknowledgement; diff --git a/src/Components/CreateImageWizardV2/steps/ImageOutput/Environment.tsx b/src/Components/CreateImageWizardV2/steps/ImageOutput/Environment.tsx deleted file mode 100644 index 0d6c8e8d..00000000 --- a/src/Components/CreateImageWizardV2/steps/ImageOutput/Environment.tsx +++ /dev/null @@ -1,406 +0,0 @@ -import React, { Dispatch, SetStateAction } from 'react'; - -import { - Checkbox, - FormGroup, - Popover, - Radio, - Text, - TextContent, - TextVariants, - Tile, -} from '@patternfly/react-core'; -import { HelpIcon } from '@patternfly/react-icons'; - -import { - useGetArchitecturesQuery, - Distributions, - ArchitectureItem, -} from '../../../../store/imageBuilderApi'; -import { provisioningApi } from '../../../../store/provisioningApi'; -import { useGetEnvironment } from '../../../../Utilities/useGetEnvironment'; - -type useGetAllowedTargetsPropType = { - architecture: ArchitectureItem['arch']; - release: Distributions; -}; - -/** - * Contacts the backend to get a list of valid targets based on the user - * requirements (release & architecture) - * - * @return an array of strings which contains the names of the authorized - * targets. Alongside the array, a couple of flags indicate the status of the - * request. isFetching stays true while the data are in transit. isError is set - * to true if anything wrong happened. isSuccess is set to true otherwise. - * - * @param architecture the selected arch (x86_64 or aarch64) - * @param release the selected release (see RELEASES in constants) - */ -export const useGetAllowedTargets = ({ - architecture, - release, -}: useGetAllowedTargetsPropType) => { - const { data, isFetching, isSuccess, isError } = useGetArchitecturesQuery({ - distribution: release, - }); - - let image_types: string[] = []; - if (isSuccess && data) { - data.forEach((elem) => { - if (elem.arch === architecture) { - image_types = elem.image_types; - } - }); - } - - return { - data: image_types, - isFetching: isFetching, - isSuccess: isSuccess, - isError: isError, - }; -}; - -/** - * Type to represent the state of a target. - * A target can be selected and/or authorized. An authorized target means the - * target can be displayed to the user, selected means the user has selected - * the target. - */ -type TargetType = { - selected: boolean; - authorized: boolean; -}; - -/** - * Defines all the possible targets a user can build. - */ -export type EnvironmentStateType = { - aws: TargetType; - azure: TargetType; - gcp: TargetType; - oci: TargetType; - 'vsphere-ova': TargetType; - vsphere: TargetType; - 'guest-image': TargetType; - 'image-installer': TargetType; - wsl: TargetType; -}; - -/** - * Takes an environment, a list of allowedTargets and updates the authorized - * status of each targets in the environment accordingly. - * - * @param environment the environment to update - * @param allowedTargets the list of targets authorized to get built - * @return an updated environment - */ -export const filterEnvironment = ( - environment: EnvironmentStateType, - allowedTargets: string[] -) => { - const newEnv = { ...environment }; - Object.keys(environment).forEach((target) => { - newEnv[target as keyof EnvironmentStateType].authorized = - allowedTargets.includes(target); - }); - return newEnv; -}; - -/** - * @return true if at least one target has both its flags selected and - * authorized set to true - * @param env the environment to scan - */ -export const hasUserSelectedAtLeastOneEnv = ( - env: EnvironmentStateType -): boolean => { - let atLeastOne = false; - Object.values(env).forEach(({ selected, authorized }) => { - atLeastOne = atLeastOne || (selected && authorized); - }); - return atLeastOne; -}; - -type EnvironmentPropType = { - environment: EnvironmentStateType; - setEnvironment: Dispatch>; -}; - -/** - * Displays a component that allows the user to pick the target they want - * to build on. - */ -const Environment = ({ setEnvironment, environment }: EnvironmentPropType) => { - const prefetchSources = provisioningApi.usePrefetch('getSourceList'); - const { isBeta } = useGetEnvironment(); - - const handleSetEnvironment = (env: string, checked: boolean) => - setEnvironment((prevEnv) => { - const newEnv: EnvironmentStateType = { - ...prevEnv, - }; - newEnv[env as keyof EnvironmentStateType].selected = checked; - return newEnv; - }); - - // each item the user can select is depending on what's compatible with the - // architecture and the distribution they previously selected. That's why - // every sub parts are conditional to the `authorized` status of its - // corresponding key in the state. - return ( - - Public cloud} - data-testid="target-public" - > -
- {environment['aws'].authorized && ( - - } - onClick={() => - handleSetEnvironment('aws', !environment.aws.selected) - } - onMouseEnter={() => prefetchSources({ provider: 'aws' })} - isSelected={environment.aws.selected} - isStacked - isDisplayLarge - /> - )} - {environment['gcp'].authorized && ( - - } - onClick={() => - handleSetEnvironment('gcp', !environment.gcp.selected) - } - isSelected={environment.gcp.selected} - onMouseEnter={() => prefetchSources({ provider: 'gcp' })} - isStacked - isDisplayLarge - /> - )} - {environment['azure'].authorized && ( - - } - onClick={() => - handleSetEnvironment('azure', !environment.azure.selected) - } - onMouseEnter={() => prefetchSources({ provider: 'azure' })} - isSelected={environment.azure.selected} - isStacked - isDisplayLarge - /> - )} - {environment.oci.authorized && isBeta() && ( - - } - onClick={() => - handleSetEnvironment('oci', !environment.oci.selected) - } - isSelected={environment.oci.selected} - isStacked - isDisplayLarge - /> - )} -
-
- {environment['vsphere'].authorized && ( - Private cloud} - className="pf-u-mt-sm" - data-testid="target-private" - > - { - handleSetEnvironment('vsphere-ova', checked); - handleSetEnvironment('vsphere', false); - }} - aria-label="VMware checkbox" - id="checkbox-vmware" - name="VMware" - data-testid="checkbox-vmware" - /> - - )} - {environment['vsphere'].authorized && ( - - {environment['vsphere-ova'].authorized && ( - - Open virtualization format (.ova) - - - An OVA file is a virtual appliance used by - virtualization platforms such as VMware vSphere. It is - a package that contains files used to describe a - virtual machine, which includes a VMDK image, OVF - descriptor file and a manifest file. - - - } - > - - - - } - onChange={(_event, checked) => { - handleSetEnvironment('vsphere-ova', checked); - handleSetEnvironment('vsphere', !checked); - }} - isChecked={environment['vsphere-ova'].selected} - isDisabled={ - !( - environment.vsphere.selected || - environment['vsphere-ova'].selected - ) - } - /> - )} - - Virtual disk (.vmdk) - - - A VMDK file is a virtual disk that stores the contents - of a virtual machine. This disk has to be imported into - vSphere using govc import.vmdk, use the OVA version when - using the vSphere UI. - - - } - > - - - - } - onChange={(_event, checked) => { - handleSetEnvironment('vsphere-ova', !checked); - handleSetEnvironment('vsphere', checked); - }} - isChecked={environment.vsphere.selected} - isDisabled={ - !( - environment.vsphere.selected || - environment['vsphere-ova'].selected - ) - } - /> - - )} - Other} - data-testid="target-other" - > - {environment['guest-image'].authorized && ( - - handleSetEnvironment('guest-image', checked) - } - aria-label="Virtualization guest image checkbox" - id="checkbox-guest-image" - name="Virtualization guest image" - data-testid="checkbox-guest-image" - /> - )} - {environment['image-installer'].authorized && ( - - handleSetEnvironment('image-installer', checked) - } - aria-label="Bare metal installer checkbox" - id="checkbox-image-installer" - name="Bare metal installer" - data-testid="checkbox-image-installer" - /> - )} - {environment['wsl'].authorized && isBeta() && ( - handleSetEnvironment('wsl', checked)} - aria-label="windows subsystem for linux checkbox" - id="checkbox-wsl" - name="WSL" - data-testid="checkbox-wsl" - /> - )} - -
- ); -}; - -export default Environment; diff --git a/src/Components/CreateImageWizardV2/steps/ImageOutput/ImageOutput.tsx b/src/Components/CreateImageWizardV2/steps/ImageOutput/ImageOutput.tsx deleted file mode 100644 index d40ee0c7..00000000 --- a/src/Components/CreateImageWizardV2/steps/ImageOutput/ImageOutput.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React, { Dispatch, SetStateAction } from 'react'; - -import { - Text, - Alert, - Bullseye, - Form, - Spinner, - Title, -} from '@patternfly/react-core'; - -import ArchSelect from './ArchSelect'; -import CentOSAcknowledgement from './CentOSAcknowledgement'; -import Environment, { EnvironmentStateType } from './Environment'; -import ReleaseSelect from './ReleaseSelect'; - -import { - ArchitectureItem, - Distributions, -} from '../../../../store/imageBuilderApi'; -import DocumentationButton from '../../../sharedComponents/DocumentationButton'; - -type ImageOutputPropTypes = { - release: Distributions; - setRelease: Dispatch>; - arch: ArchitectureItem['arch']; - setArch: Dispatch>; - environment: EnvironmentStateType; - setEnvironment: Dispatch>; - isFetching: boolean; - isError: boolean; - isSuccess: boolean; -}; - -/** - * Manages the form for the image output step by providing the user with a - * choice for: - * - a distribution - * - a release - * - a set of environments - */ -const ImageOutputStep = ({ - release, - setRelease, - arch, - setArch, - setEnvironment, - environment, - isFetching, - isError, - isSuccess, -}: ImageOutputPropTypes) => { - return ( -
- Image output - - Image builder allows you to create a custom image and push it to target - environments. -
- -
- - - {release.match('centos-*') && } - {isFetching && ( - - - - )} - {isError && ( - - API cannot be reached, try again later. - - )} - {isSuccess && !isFetching && ( - - )} - - ); -}; - -export default ImageOutputStep; diff --git a/src/Components/CreateImageWizardV2/steps/ImageOutput/ReleaseSelect.tsx b/src/Components/CreateImageWizardV2/steps/ImageOutput/ReleaseSelect.tsx deleted file mode 100644 index bc37e17a..00000000 --- a/src/Components/CreateImageWizardV2/steps/ImageOutput/ReleaseSelect.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import React, { - Dispatch, - ReactElement, - SetStateAction, - useRef, - useState, -} from 'react'; - -import { - Select, - SelectOption, - SelectList, - MenuToggle, - FormGroup, -} from '@patternfly/react-core'; - -import { RELEASES } from '../../../../constants'; -import { Distributions } from '../../../../store/imageBuilderApi'; -import isRhel from '../../../../Utilities/isRhel'; - -type ReleaseSelectType = { - setRelease: Dispatch>; - release: Distributions; -}; - -/** - * Allows the user to choose the release they want to build. - * Follows the PF5 pattern: https://www.patternfly.org/components/menus/select#view-more - */ -const ReleaseSelect = ({ setRelease, release }: ReleaseSelectType) => { - // By default the component doesn't show the Centos releases and only the RHEL - // ones. The user has the option to click on a button to make them appear. - const [showDevelopmentOptions, setShowDevelopmentOptions] = useState(false); - const releaseOptions = () => { - const options: ReactElement[] = []; - const filteredRhel = new Map(); - RELEASES.forEach((value, key) => { - // Only show non-RHEL distros if expanded - if (showDevelopmentOptions || isRhel(key)) { - filteredRhel.set(key, value); - } - }); - filteredRhel.forEach((value, key) => { - if (value && key) { - options.push( - - {RELEASES.get(key)} - - ); - } - }); - - return options; - }; - - const [isOpen, setIsOpen] = useState(false); - - const onToggleClick = () => { - setIsOpen(!isOpen); - }; - - const viewMoreRef = useRef(null); - const toggleRef = useRef(null); - const onSelect = ( - _event: React.MouseEvent | undefined, - value: string | number | undefined - ) => { - if (value !== 'loader') { - if (typeof value === 'string') { - setRelease(value as Distributions); - } - setIsOpen(false); - toggleRef?.current?.focus(); // Only focus the toggle when a non-loader option is selected - } - }; - - const toggle = ( - - {RELEASES.get(release)} - - ); - - return ( - - - - ); -}; - -export default ReleaseSelect; diff --git a/src/Components/CreateImageWizardV2/steps/Review/ReviewStep.tsx b/src/Components/CreateImageWizardV2/steps/Review/ReviewStep.tsx deleted file mode 100644 index 51864d9e..00000000 --- a/src/Components/CreateImageWizardV2/steps/Review/ReviewStep.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { useState } from 'react'; - -import { ExpandableSection, Form, Title } from '@patternfly/react-core'; - -import { ImageOutputList } from './imageOutput'; - -import { - ArchitectureItem, - Distributions, -} from '../../../../store/imageBuilderApi'; - -type ReviewStepPropTypes = { - release: Distributions; - arch: ArchitectureItem['arch']; -}; - -const ReviewStep = ({ release, arch }: ReviewStepPropTypes) => { - const [isExpandedImageOutput, setIsExpandedImageOutput] = useState(false); - - const onToggleImageOutput = (isExpandedImageOutput: boolean) => - setIsExpandedImageOutput(isExpandedImageOutput); - return ( - <> -
- Review - - onToggleImageOutput(isExpandedImageOutput) - } - isExpanded={isExpandedImageOutput} - isIndented - data-testid="image-output-expandable" - > - - -
- - ); -}; - -export default ReviewStep; diff --git a/src/Components/CreateImageWizardV2/steps/Review/imageOutput.tsx b/src/Components/CreateImageWizardV2/steps/Review/imageOutput.tsx deleted file mode 100644 index d9d24bed..00000000 --- a/src/Components/CreateImageWizardV2/steps/Review/imageOutput.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from 'react'; - -import { - TextContent, - TextList, - TextListItem, - TextListVariants, - TextListItemVariants, -} from '@patternfly/react-core'; - -import { RELEASES } from '../../../../constants'; -import { - ArchitectureItem, - Distributions, -} from '../../../../store/imageBuilderApi'; - -type ImageOutputListPropTypes = { - release: Distributions; - arch: ArchitectureItem['arch']; -}; - -export const ImageOutputList = ({ - release, - arch, -}: ImageOutputListPropTypes) => { - return ( - - - - Release - - - {RELEASES.get(release)} - - - Architecture - - {arch} - -
-
- ); -}; diff --git a/src/test/Components/CreateImageWizardV2/CreateImageWizard.test.tsx b/src/test/Components/CreateImageWizardV2/CreateImageWizard.test.tsx deleted file mode 100644 index 99891961..00000000 --- a/src/test/Components/CreateImageWizardV2/CreateImageWizard.test.tsx +++ /dev/null @@ -1,145 +0,0 @@ -import React from 'react'; - -import '@testing-library/jest-dom'; - -import { screen, within } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; - -import CreateImageWizard from '../../../Components/CreateImageWizardV2/CreateImageWizard'; -import ShareImageModal from '../../../Components/ShareImageModal/ShareImageModal'; -import { server } from '../../mocks/server.js'; -import { - clickNext, - renderCustomRoutesWithReduxRouter, - verifyCancelButton, -} from '../../testUtils'; - -const routes = [ - { - path: 'insights/image-builder/*', - element:
, - }, - { - path: 'insights/image-builder/imagewizard/:composeId?', - element: , - }, - { - path: 'insights/image-builder/share /:composeId', - element: , - }, -]; - -jest.mock('@redhat-cloud-services/frontend-components/useChrome', () => ({ - useChrome: () => ({ - auth: { - getUser: () => { - return { - identity: { - internal: { - org_id: 5, - }, - }, - }; - }, - }, - isBeta: () => true, - isProd: () => true, - getEnvironment: () => 'prod', - }), -})); - -jest.mock('@unleash/proxy-client-react', () => ({ - useUnleashContext: () => jest.fn(), - useFlag: jest.fn((flag) => - flag === 'image-builder.enable-content-sources' ? true : false - ), -})); - -beforeAll(() => { - // scrollTo is not defined in jsdom - window.HTMLElement.prototype.scrollTo = function () {}; -}); - -afterEach(() => { - jest.clearAllMocks(); - server.resetHandlers(); -}); - -describe('Create Image Wizard', () => { - test('renders component', () => { - renderCustomRoutesWithReduxRouter('imagewizard', {}, routes); - // check heading - screen.getByRole('heading', { name: /Image Builder/ }); - - screen.getByRole('button', { name: 'Image output' }); - }); -}); - -describe('Step Image output', () => { - test('clicking Next loads the review step with correct information about the image output', async () => { - const user = userEvent.setup(); - await renderCustomRoutesWithReduxRouter('imagewizard', {}, routes); - - // select aws as upload destination - await user.click(await screen.findByTestId('upload-aws')); - await screen.findByRole('heading', { name: 'Image output' }); - - await clickNext(); - - await screen.findByRole('heading', { name: 'Review' }); - const view = screen.getByTestId('image-output-expandable'); - await user.click(await within(view).findByText(/image output/i)); - expect(await screen.findByText(/x86_64/i)).not.toBeNaN(); - expect( - await screen.findByText(/red hat enterprise linux \(rhel\) 9/i) - ).not.toBeNaN(); - }); - - test('selecting rhel8 and aarch64 shows accordingly in the review step', async () => { - const user = userEvent.setup(); - await renderCustomRoutesWithReduxRouter('imagewizard', {}, routes); - - // select rhel8 - const releaseMenu = screen.getAllByRole('button', { - name: /Red Hat Enterprise Linux \(RHEL\) 9/, - })[0]; - await user.click(releaseMenu); - await user.click( - await screen.findByRole('option', { - name: /Red Hat Enterprise Linux \(RHEL\) 8/, - }) - ); - - // Change to aarch - await user.selectOptions( - await screen.findByRole('combobox', { - name: /architecture/i, - }), - 'aarch64' - ); - - // select aws as upload destination - await user.click(await screen.findByTestId('upload-aws')); - - await clickNext(); - - await screen.findByRole('heading', { name: 'Review' }); - const view = screen.getByTestId('image-output-expandable'); - await user.click(await within(view).findByText(/image output/i)); - expect(await screen.findByText(/aarch64/i)).not.toBeNaN(); - expect( - await screen.findByText(/red hat enterprise linux \(rhel\) 8/i) - ).not.toBeNaN(); - }); - - test('clicking Cancel loads landing page', async () => { - const { router } = await renderCustomRoutesWithReduxRouter( - 'imagewizard', - {}, - routes - ); - await clickNext(); - - await verifyCancelButton(router); - }); -}); diff --git a/src/test/Components/CreateImageWizardV2/steps/ImageOutput/ImageOutput.test.tsx b/src/test/Components/CreateImageWizardV2/steps/ImageOutput/ImageOutput.test.tsx deleted file mode 100644 index 089cb528..00000000 --- a/src/test/Components/CreateImageWizardV2/steps/ImageOutput/ImageOutput.test.tsx +++ /dev/null @@ -1,262 +0,0 @@ -import React from 'react'; -import '@testing-library/jest-dom'; - -import { screen, waitFor } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; - -import CreateImageWizard from '../../../../../Components/CreateImageWizardV2/CreateImageWizard'; -import { AARCH64, RHEL_8, RHEL_9, X86_64 } from '../../../../../constants'; -import { mockArchitecturesByDistro } from '../../../../fixtures/architectures'; -import { server } from '../../../../mocks/server'; -import { renderCustomRoutesWithReduxRouter } from '../../../../testUtils'; - -const routes = [ - { - path: 'insights/image-builder/imagewizard/:composeId?', - element: , - }, -]; -jest.mock('@redhat-cloud-services/frontend-components/useChrome', () => ({ - useChrome: () => ({ - auth: { - getUser: () => { - return { - identity: { - internal: { - org_id: 5, - }, - }, - }; - }, - }, - isBeta: () => true, - isProd: () => true, - getEnvironment: () => 'prod', - }), -})); - -beforeAll(() => { - // scrollTo is not defined in jsdom - window.HTMLElement.prototype.scrollTo = function () {}; -}); - -afterEach(() => { - jest.clearAllMocks(); - server.resetHandlers(); -}); - -describe('Check that the target filtering is in accordance to mock content', () => { - test('rhel9 x86_64', async () => { - await renderCustomRoutesWithReduxRouter('imagewizard', {}, routes); - - // make sure this test is in SYNC with the mocks - let images_types: string[] = []; - mockArchitecturesByDistro(RHEL_9).forEach((elem) => { - if (elem.arch === X86_64) { - images_types = elem.image_types; - } - }); - expect(images_types).toContain('aws'); - expect(images_types).toContain('gcp'); - expect(images_types).toContain('azure'); - expect(images_types).toContain('guest-image'); - expect(images_types).toContain('image-installer'); - expect(images_types).toContain('vsphere'); - expect(images_types).toContain('vsphere-ova'); - expect(images_types).not.toContain('wsl'); - // make sure the UX conforms to the mocks - await waitFor(async () => await screen.findByTestId('upload-aws')); - await screen.findByTestId('upload-google'); - await screen.findByTestId('upload-azure'); - await screen.findByTestId('checkbox-guest-image'); - await screen.findByTestId('checkbox-image-installer'); - await screen.findByText(/vmware vsphere/i); - await screen.findByText(/open virtualization format \(\.ova\)/i); - expect( - screen.queryByText(/wsl - windows subsystem for linux \(\.tar\.gz\)/i) - ).not.toBeInTheDocument(); - }); - - test('rhel8 x86_64', async () => { - const user = userEvent.setup(); - await renderCustomRoutesWithReduxRouter('imagewizard', {}, routes); - - // select rhel8 - const releaseMenu = screen.getAllByRole('button', { - name: /Red Hat Enterprise Linux \(RHEL\) 9/, - })[0]; - await user.click(releaseMenu); - await user.click( - await screen.findByRole('option', { - name: /Red Hat Enterprise Linux \(RHEL\) 8/, - }) - ); - - // make sure this test is in SYNC with the mocks - let images_types: string[] = []; - mockArchitecturesByDistro(RHEL_8).forEach((elem) => { - if (elem.arch === X86_64) { - images_types = elem.image_types; - } - }); - expect(images_types).toContain('aws'); - expect(images_types).toContain('gcp'); - expect(images_types).toContain('azure'); - expect(images_types).toContain('guest-image'); - expect(images_types).toContain('image-installer'); - expect(images_types).toContain('vsphere'); - expect(images_types).toContain('vsphere-ova'); - expect(images_types).toContain('wsl'); - // make sure the UX conforms to the mocks - await waitFor(async () => await screen.findByTestId('upload-aws')); - await screen.findByTestId('upload-google'); - await screen.findByTestId('upload-azure'); - await screen.findByTestId('checkbox-guest-image'); - await screen.findByTestId('checkbox-image-installer'); - await screen.findByText(/vmware vsphere/i); - await screen.findByText(/open virtualization format \(\.ova\)/i); - await screen.findByText(/wsl - windows subsystem for linux \(\.tar\.gz\)/i); - }); - - test('rhel9 aarch64', async () => { - const user = userEvent.setup(); - await renderCustomRoutesWithReduxRouter('imagewizard', {}, routes); - - // select aarch64 - await user.selectOptions( - await screen.findByRole('combobox', { - name: /architecture/i, - }), - 'aarch64' - ); - - // make sure this test is in SYNC with the mocks - let images_types: string[] = []; - mockArchitecturesByDistro(RHEL_9).forEach((elem) => { - if (elem.arch === AARCH64) { - images_types = elem.image_types; - } - }); - expect(images_types).toContain('aws'); - expect(images_types).not.toContain('gcp'); - expect(images_types).not.toContain('azure'); - expect(images_types).toContain('guest-image'); - expect(images_types).toContain('image-installer'); - expect(images_types).not.toContain('vsphere'); - expect(images_types).not.toContain('vsphere-ova'); - expect(images_types).not.toContain('wsl'); - // make sure the UX conforms to the mocks - await waitFor(async () => await screen.findByTestId('upload-aws')); - expect(screen.queryByTestId('upload-google')).not.toBeInTheDocument(); - expect(screen.queryByTestId('upload-azure')).not.toBeInTheDocument(); - await screen.findByTestId('checkbox-guest-image'); - await screen.findByTestId('checkbox-image-installer'); - expect(screen.queryByText(/vmware vsphere/i)).not.toBeInTheDocument(); - expect( - screen.queryByText(/open virtualization format \(\.ova\)/i) - ).not.toBeInTheDocument(); - expect( - screen.queryByText(/wsl - windows subsystem for linux \(\.tar\.gz\)/i) - ).not.toBeInTheDocument(); - }); - - test('rhel8 aarch64', async () => { - const user = userEvent.setup(); - await renderCustomRoutesWithReduxRouter('imagewizard', {}, routes); - - // select rhel8 - const releaseMenu = screen.getAllByRole('button', { - name: /Red Hat Enterprise Linux \(RHEL\) 9/, - })[0]; - await user.click(releaseMenu); - await user.click( - await screen.findByRole('option', { - name: /Red Hat Enterprise Linux \(RHEL\) 8/, - }) - ); - - // select aarch64 - await user.selectOptions( - await screen.findByRole('combobox', { - name: /architecture/i, - }), - 'aarch64' - ); - - // make sure this test is in SYNC with the mocks - let images_types: string[] = []; - mockArchitecturesByDistro(RHEL_8).forEach((elem) => { - if (elem.arch === AARCH64) { - images_types = elem.image_types; - } - }); - expect(images_types).toContain('aws'); - expect(images_types).not.toContain('gcp'); - expect(images_types).not.toContain('azure'); - expect(images_types).toContain('guest-image'); - expect(images_types).toContain('image-installer'); - expect(images_types).not.toContain('vsphere'); - expect(images_types).not.toContain('vsphere-ova'); - expect(images_types).not.toContain('wsl'); - // make sure the UX conforms to the mocks - await waitFor(async () => await screen.findByTestId('upload-aws')); - expect(screen.queryByTestId('upload-google')).not.toBeInTheDocument(); - expect(screen.queryByTestId('upload-azure')).not.toBeInTheDocument(); - await screen.findByTestId('checkbox-guest-image'); - await screen.findByTestId('checkbox-image-installer'); - expect(screen.queryByText(/vmware vsphere/i)).not.toBeInTheDocument(); - expect( - screen.queryByText(/open virtualization format \(\.ova\)/i) - ).not.toBeInTheDocument(); - expect( - screen.queryByText(/wsl - windows subsystem for linux \(\.tar\.gz\)/i) - ).not.toBeInTheDocument(); - }); -}); - -describe('Check step consistency', () => { - test('going back and forth with selected options only keeps the one compatible', async () => { - const user = userEvent.setup(); - await renderCustomRoutesWithReduxRouter('imagewizard', {}, routes); - - // select x86_64 - await user.selectOptions( - await screen.findByRole('combobox', { - name: /architecture/i, - }), - 'x86_64' - ); - await waitFor(async () => await screen.findByTestId('upload-aws')); - // select GCP, it's available for x86_64 - await user.click(await screen.findByTestId('upload-google')); - await waitFor(async () => - expect(await screen.findByRole('button', { name: /Next/ })).toBeEnabled() - ); - // Change to aarch - await user.selectOptions( - await screen.findByRole('combobox', { - name: /architecture/i, - }), - 'aarch64' - ); - // GCP not being compatible with arch, the next button is disabled - await waitFor(async () => - expect(await screen.findByRole('button', { name: /Next/ })).toBeDisabled() - ); - // clicking on AWS the user can go next - await user.click(await screen.findByTestId('upload-aws')); - await waitFor(async () => - expect(await screen.findByRole('button', { name: /Next/ })).toBeEnabled() - ); - // and going back to x86_64 the user should keep the next button visible - await user.selectOptions( - await screen.findByRole('combobox', { - name: /architecture/i, - }), - 'x86_64' - ); - await waitFor(async () => - expect(await screen.findByRole('button', { name: /Next/ })).toBeEnabled() - ); - }); -});