diff --git a/src/Components/CreateImageWizard/CreateImageWizard.js b/src/Components/CreateImageWizard/CreateImageWizard.js index 25c2d45f..c174fd37 100644 --- a/src/Components/CreateImageWizard/CreateImageWizard.js +++ b/src/Components/CreateImageWizard/CreateImageWizard.js @@ -19,6 +19,7 @@ import { packages, imageOutput, fileSystemConfiguration, + details } from './steps'; import { @@ -62,6 +63,7 @@ const onSave = (values) => { if (values['target-environment']?.aws) { let request = { distribution: values.release, + image_name: values?.['image-name'], image_requests: [ { architecture: 'x86_64', @@ -97,6 +99,7 @@ const onSave = (values) => { let request = { distribution: values.release, + image_name: values?.['image-name'], image_requests: [ { architecture: 'x86_64', @@ -117,6 +120,7 @@ const onSave = (values) => { if (values['target-environment']?.azure) { let request = { distribution: values.release, + image_name: values?.['image-name'], image_requests: [ { architecture: 'x86_64', @@ -138,6 +142,7 @@ const onSave = (values) => { if (values['target-environment']?.vsphere) { let request = { distribution: values.release, + image_name: values?.['image-name'], image_requests: [ { architecture: 'x86_64', @@ -155,6 +160,7 @@ const onSave = (values) => { if (values['target-environment']?.['guest-image']) { let request = { distribution: values.release, + image_name: values?.['image-name'], image_requests: [ { architecture: 'x86_64', @@ -172,6 +178,7 @@ const onSave = (values) => { if (values['target-environment']?.['image-installer']) { let request = { distribution: values.release, + image_name: values?.['image-name'], image_requests: [ { architecture: 'x86_64', @@ -254,6 +261,7 @@ https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/up // order in this array does not reflect order in wizard nav, this order is managed inside // of each step by `nextStep` property! fields: [ + details, imageOutput, awsTarget, googleCloudTarger, diff --git a/src/Components/CreateImageWizard/formComponents/ReviewStep.js b/src/Components/CreateImageWizard/formComponents/ReviewStep.js index 86dc7308..7ad6d1f8 100644 --- a/src/Components/CreateImageWizard/formComponents/ReviewStep.js +++ b/src/Components/CreateImageWizard/formComponents/ReviewStep.js @@ -95,8 +95,12 @@ const ReviewStep = () => { Review the information and click "Create image" to create the image using the following criteria. - + + Image name + + {getState()?.values?.['image-name']} + Release {releaseValues?.[getState()?.values?.release]} diff --git a/src/Components/CreateImageWizard/steps/details.js b/src/Components/CreateImageWizard/steps/details.js new file mode 100644 index 00000000..6ca8681b --- /dev/null +++ b/src/Components/CreateImageWizard/steps/details.js @@ -0,0 +1,31 @@ +import React from 'react'; +import componentTypes from '@data-driven-forms/react-form-renderer/component-types'; +import validatorTypes from '@data-driven-forms/react-form-renderer/validator-types'; + +export default { + name: 'details', + title: 'Details', + nextStep: 'image-output', + fields: [ + { + component: componentTypes.PLAIN_TEXT, + name: 'plain-text-component', + label:

+ Enter a name to easily identify your image later. If left empty, the image's UUID will be displayed. +

+ }, + { + component: componentTypes.TEXT_FIELD, + name: 'image-name', + type: 'text', + label: 'Image name', + validate: [ + { + type: validatorTypes.PATTERN, + pattern: /^[\w-]+$/i, + message: 'Can only contain letters, numbers, hyphens (-), and underscores (_)', + } + ] + } + ] +}; diff --git a/src/Components/CreateImageWizard/steps/index.js b/src/Components/CreateImageWizard/steps/index.js index 39c09ea1..bc63c7b6 100644 --- a/src/Components/CreateImageWizard/steps/index.js +++ b/src/Components/CreateImageWizard/steps/index.js @@ -7,3 +7,4 @@ export { default as review } from './review'; export { default as imageOutput } from './imageOutput'; export { default as nextStepMapper } from './imageOutputStepMapper'; export { default as fileSystemConfiguration } from './fileSystemConfiguration'; +export { default as details } from './details'; diff --git a/src/test/Components/CreateImageWizard/CreateImageWizard.test.js b/src/test/Components/CreateImageWizard/CreateImageWizard.test.js index 02888d39..6e8fb72c 100644 --- a/src/test/Components/CreateImageWizard/CreateImageWizard.test.js +++ b/src/test/Components/CreateImageWizard/CreateImageWizard.test.js @@ -156,8 +156,9 @@ describe('Create Image Wizard', () => { // check heading screen.getByRole('heading', { name: /Create image/ }); + screen.getByRole('button', { name: 'Details' }); screen.getByRole('button', { name: 'Image output' }); - screen.getByRole('button', { name: 'Registration' }); + screen.getByRole('button', { name: 'Packages' }); screen.getByRole('button', { name: 'Review' }); }); }); @@ -165,6 +166,10 @@ describe('Create Image Wizard', () => { describe('Step Image output', () => { const setUp = () => { history = renderWithReduxRouter().history; + const [ next, , ] = verifyButtons(); + // Click through the details page + next.click(); + const imageOutputLink = screen.getByRole('button', { name: 'Image output' }); // select aws as upload destination @@ -184,14 +189,14 @@ describe('Step Image output', () => { screen.getByText('AWS account ID'); }); - test('Back button is disabled', () => { + test('clicking Back loads Details', () => { setUp(); const [ , back, ] = verifyButtons(); - // note: there is no `disabled` attribute and - // .toBeDissabled() fails - expect(back).toHaveClass('pf-m-disabled'); + back.click(); + + screen.getByText('Image name'); }); test('clicking Cancel loads landing page', () => { @@ -221,12 +226,15 @@ describe('Step Image output', () => { describe('Step Upload to AWS', () => { const setUp = () => { history = renderWithReduxRouter().history; + const [ next, , ] = verifyButtons(); + // Click through the details page + next.click(); // select aws as upload destination const awsTile = screen.getByTestId('upload-aws'); awsTile.click(); - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); }; test('clicking Next loads Registration', async () => { @@ -272,12 +280,15 @@ describe('Step Upload to AWS', () => { describe('Step Upload to Google', () => { const setUp = () => { history = renderWithReduxRouter().history; + const [ next, , ] = verifyButtons(); + // Click through the details page + next.click(); // select aws as upload destination const awsTile = screen.getByTestId('upload-google'); awsTile.click(); - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); }; test('clicking Next loads Registration', async () => { @@ -335,11 +346,14 @@ describe('Step Upload to Google', () => { describe('Step Upload to Azure', () => { const setUp = () => { history = renderWithReduxRouter().history; + const [ next, , ] = verifyButtons(); + // Click through the details page + next.click(); // select aws as upload destination const awsTile = screen.getByTestId('upload-azure'); awsTile.click(); - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); }; test('clicking Next loads Registration', async () => { @@ -398,15 +412,18 @@ describe('Step Upload to Azure', () => { describe('Step Registration', () => { const setUp = async () => { history = renderWithReduxRouter().history; + const [ next, , ] = verifyButtons(); + // Click through the details page + next.click(); // select aws as upload destination const awsTile = screen.getByTestId('upload-aws'); awsTile.click(); - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); userEvent.type(screen.getByTestId('aws-account-id'), '012345678901'); - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); await screen.findByRole('textbox', { name: 'Select activation key' @@ -517,15 +534,18 @@ describe('Step Registration', () => { describe('Step Packages', () => { const setUp = async () => { history = renderWithReduxRouter().history; + const [ next, , ] = verifyButtons(); + // Click through the details page + next.click(); // select aws as upload destination const awsTile = screen.getByTestId('upload-aws'); awsTile.click(); - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); // aws step userEvent.type(screen.getByTestId('aws-account-id'), '012345678901'); - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); // skip registration await screen.findByRole('textbox', { name: 'Select activation key' @@ -533,10 +553,10 @@ describe('Step Packages', () => { const registerLaterRadio = screen.getByLabelText('Register later'); userEvent.click(registerLaterRadio); - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); // skip fsc - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); }; test('clicking Next loads Review', async () => { @@ -850,15 +870,18 @@ describe('Step Packages', () => { describe('Step Review', () => { const setUp = async () => { history = renderWithReduxRouter().history; + const [ next, , ] = verifyButtons(); + // Click through the details page + next.click(); // select aws as upload destination const awsTile = screen.getByTestId('upload-aws'); awsTile.click(); - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); // aws step userEvent.type(screen.getByTestId('aws-account-id'), '012345678901'); - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); await screen.findByRole('textbox', { name: 'Select activation key' @@ -867,19 +890,23 @@ describe('Step Review', () => { // skip registration const registerLaterRadio = screen.getByLabelText('Register later'); userEvent.click(registerLaterRadio); - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); // skip fsc - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); // skip packages - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); }; // eslint-disable-next-line no-unused-vars const setUpCentOS = () => { history = renderWithReduxRouter().history; + const [ next, , ] = verifyButtons(); + // Click through the details page + next.click(); + // This is the best way to open the menu since ddf doesn't support data-testid for the select const releaseMenu = screen.getByRole('button', { name: /open menu/i @@ -893,17 +920,17 @@ describe('Step Review', () => { // select aws as upload destination const awsTile = screen.getByTestId('upload-aws'); awsTile.click(); - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); // aws step userEvent.type(screen.getByTestId('aws-account-id'), '012345678901'); - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); // skip fsc - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); // skip packages - screen.getByRole('button', { name: /Next/ }).click(); + next.click(); }; test('has 3 buttons', async () => { @@ -984,6 +1011,12 @@ describe('Click through all steps', () => { await setUp(); const next = screen.getByRole('button', { name: /Next/ }); + // Enter image name + const detailsInput = screen.getByRole('textbox', { + name: 'Image name' + }); + userEvent.type(detailsInput, 'MyImageName'); + next.click(); // select image output // userEvent.selectOptions(screen.getByTestId('release-select'), [ RHEL_8 ]); @@ -1088,6 +1121,7 @@ describe('Click through all steps', () => { if (body.image_requests[0].upload_request.type === 'aws') { expect(body).toEqual({ distribution: RHEL_8, + image_name: 'MyImageName', image_requests: [{ architecture: 'x86_64', image_type: 'ami', @@ -1127,6 +1161,7 @@ describe('Click through all steps', () => { } else if (body.image_requests[0].upload_request.type === 'gcp') { expect(body).toEqual({ distribution: RHEL_8, + image_name: 'MyImageName', image_requests: [{ architecture: 'x86_64', image_type: 'vhd', @@ -1166,6 +1201,7 @@ describe('Click through all steps', () => { } else if (body.image_requests[0].upload_request.type === 'azure') { expect(body).toEqual({ distribution: RHEL_8, + image_name: 'MyImageName', image_requests: [{ architecture: 'x86_64', image_type: 'vhd', @@ -1207,6 +1243,7 @@ describe('Click through all steps', () => { } else if (body.image_requests[0].image_type === 'vsphere') { expect(body).toEqual({ distribution: RHEL_8, + image_name: 'MyImageName', image_requests: [{ architecture: 'x86_64', image_type: 'vsphere', @@ -1244,6 +1281,7 @@ describe('Click through all steps', () => { } else if (body.image_requests[0].image_type === 'guest-image') { expect(body).toEqual({ distribution: RHEL_8, + image_name: 'MyImageName', image_requests: [{ architecture: 'x86_64', image_type: 'guest-image', @@ -1281,6 +1319,7 @@ describe('Click through all steps', () => { } else if (body.image_requests[0].image_type === 'image-installer') { expect(body).toEqual({ distribution: RHEL_8, + image_name: 'MyImageName', image_requests: [{ architecture: 'x86_64', image_type: 'image-installer',