Wizard: Add validation for kernel step
This adds validation for the Kernel step.
This commit is contained in:
parent
2d011c52e1
commit
bfef28999d
5 changed files with 64 additions and 1 deletions
|
|
@ -40,6 +40,7 @@ import {
|
||||||
useDetailsValidation,
|
useDetailsValidation,
|
||||||
useRegistrationValidation,
|
useRegistrationValidation,
|
||||||
useHostnameValidation,
|
useHostnameValidation,
|
||||||
|
useKernelValidation,
|
||||||
} from './utilities/useValidation';
|
} from './utilities/useValidation';
|
||||||
import {
|
import {
|
||||||
isAwsAccountIdValid,
|
isAwsAccountIdValid,
|
||||||
|
|
@ -223,6 +224,8 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
|
||||||
const fileSystemValidation = useFilesystemValidation();
|
const fileSystemValidation = useFilesystemValidation();
|
||||||
// Hostname
|
// Hostname
|
||||||
const hostnameValidation = useHostnameValidation();
|
const hostnameValidation = useHostnameValidation();
|
||||||
|
// Kernel
|
||||||
|
const kernelValidation = useKernelValidation();
|
||||||
// Firstboot
|
// Firstboot
|
||||||
const firstBootValidation = useFirstBootValidation();
|
const firstBootValidation = useFirstBootValidation();
|
||||||
// Details
|
// Details
|
||||||
|
|
@ -510,8 +513,12 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
|
||||||
key="wizard-kernel"
|
key="wizard-kernel"
|
||||||
navItem={customStatusNavItem}
|
navItem={customStatusNavItem}
|
||||||
isHidden={!isKernelEnabled}
|
isHidden={!isKernelEnabled}
|
||||||
|
status={kernelValidation.disabledNext ? 'error' : 'default'}
|
||||||
footer={
|
footer={
|
||||||
<CustomWizardFooter disableNext={false} optional={true} />
|
<CustomWizardFooter
|
||||||
|
disableNext={kernelValidation.disabledNext}
|
||||||
|
optional={true}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<KernelStep />
|
<KernelStep />
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import { FormGroup } from '@patternfly/react-core';
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
Button,
|
Button,
|
||||||
|
HelperText,
|
||||||
|
HelperTextItem,
|
||||||
MenuToggle,
|
MenuToggle,
|
||||||
MenuToggleElement,
|
MenuToggleElement,
|
||||||
Select,
|
Select,
|
||||||
|
|
@ -20,6 +22,7 @@ import {
|
||||||
changeKernelName,
|
changeKernelName,
|
||||||
selectKernel,
|
selectKernel,
|
||||||
} from '../../../../../store/wizardSlice';
|
} from '../../../../../store/wizardSlice';
|
||||||
|
import { useKernelValidation } from '../../../utilities/useValidation';
|
||||||
|
|
||||||
const initialOptions = ['kernel', 'kernel-debug'];
|
const initialOptions = ['kernel', 'kernel-debug'];
|
||||||
let kernelOptions = initialOptions;
|
let kernelOptions = initialOptions;
|
||||||
|
|
@ -28,6 +31,8 @@ const KernelName = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const kernel = useAppSelector(selectKernel).name;
|
const kernel = useAppSelector(selectKernel).name;
|
||||||
|
|
||||||
|
const stepValidation = useKernelValidation();
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [inputValue, setInputValue] = useState<string>('');
|
const [inputValue, setInputValue] = useState<string>('');
|
||||||
const [filterValue, setFilterValue] = useState<string>('');
|
const [filterValue, setFilterValue] = useState<string>('');
|
||||||
|
|
@ -166,6 +171,13 @@ const KernelName = () => {
|
||||||
))}
|
))}
|
||||||
</SelectList>
|
</SelectList>
|
||||||
</Select>
|
</Select>
|
||||||
|
{stepValidation.errors.kernel && (
|
||||||
|
<HelperText>
|
||||||
|
<HelperTextItem variant={'error'}>
|
||||||
|
{stepValidation.errors.kernel}
|
||||||
|
</HelperTextItem>
|
||||||
|
</HelperText>
|
||||||
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import {
|
||||||
selectActivationKey,
|
selectActivationKey,
|
||||||
selectRegistrationType,
|
selectRegistrationType,
|
||||||
selectHostname,
|
selectHostname,
|
||||||
|
selectKernel,
|
||||||
} from '../../../store/wizardSlice';
|
} from '../../../store/wizardSlice';
|
||||||
import {
|
import {
|
||||||
getDuplicateMountPoints,
|
getDuplicateMountPoints,
|
||||||
|
|
@ -27,6 +28,7 @@ import {
|
||||||
isMountpointMinSizeValid,
|
isMountpointMinSizeValid,
|
||||||
isSnapshotValid,
|
isSnapshotValid,
|
||||||
isHostnameValid,
|
isHostnameValid,
|
||||||
|
isKernelNameValid,
|
||||||
} from '../validators';
|
} from '../validators';
|
||||||
|
|
||||||
export type StepValidation = {
|
export type StepValidation = {
|
||||||
|
|
@ -41,6 +43,7 @@ export function useIsBlueprintValid(): boolean {
|
||||||
const filesystem = useFilesystemValidation();
|
const filesystem = useFilesystemValidation();
|
||||||
const snapshot = useSnapshotValidation();
|
const snapshot = useSnapshotValidation();
|
||||||
const hostname = useHostnameValidation();
|
const hostname = useHostnameValidation();
|
||||||
|
const kernel = useKernelValidation();
|
||||||
const firstBoot = useFirstBootValidation();
|
const firstBoot = useFirstBootValidation();
|
||||||
const details = useDetailsValidation();
|
const details = useDetailsValidation();
|
||||||
return (
|
return (
|
||||||
|
|
@ -48,6 +51,7 @@ export function useIsBlueprintValid(): boolean {
|
||||||
!filesystem.disabledNext &&
|
!filesystem.disabledNext &&
|
||||||
!snapshot.disabledNext &&
|
!snapshot.disabledNext &&
|
||||||
!hostname.disabledNext &&
|
!hostname.disabledNext &&
|
||||||
|
!kernel.disabledNext &&
|
||||||
!firstBoot.disabledNext &&
|
!firstBoot.disabledNext &&
|
||||||
!details.disabledNext
|
!details.disabledNext
|
||||||
);
|
);
|
||||||
|
|
@ -155,6 +159,20 @@ export function useHostnameValidation(): StepValidation {
|
||||||
return { errors: {}, disabledNext: false };
|
return { errors: {}, disabledNext: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useKernelValidation(): StepValidation {
|
||||||
|
const kernel = useAppSelector(selectKernel);
|
||||||
|
|
||||||
|
if (!isKernelNameValid(kernel.name)) {
|
||||||
|
return {
|
||||||
|
errors: {
|
||||||
|
kernel: 'Invalid format.',
|
||||||
|
},
|
||||||
|
disabledNext: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { errors: {}, disabledNext: false };
|
||||||
|
}
|
||||||
|
|
||||||
export function useDetailsValidation(): StepValidation {
|
export function useDetailsValidation(): StepValidation {
|
||||||
const name = useAppSelector(selectBlueprintName);
|
const name = useAppSelector(selectBlueprintName);
|
||||||
const description = useAppSelector(selectBlueprintDescription);
|
const description = useAppSelector(selectBlueprintDescription);
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,17 @@ export const isHostnameValid = (hostname: string) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const isKernelNameValid = (kernelName: string) => {
|
||||||
|
if (!kernelName) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
kernelName.length < 65 &&
|
||||||
|
/^[a-z0-9]|[a-z0-9][a-z0-9-_.+]*[a-z0-9]$/.test(kernelName)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const isPortValid = (port: string) => {
|
export const isPortValid = (port: string) => {
|
||||||
return /^(\d{1,5}|[a-z]{1,6})(-\d{1,5})?:[a-z]{1,6}$/.test(port);
|
return /^(\d{1,5}|[a-z]{1,6})(-\d{1,5})?:[a-z]{1,6}$/.test(port);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import {
|
||||||
clickBack,
|
clickBack,
|
||||||
clickNext,
|
clickNext,
|
||||||
enterBlueprintName,
|
enterBlueprintName,
|
||||||
|
getNextButton,
|
||||||
interceptBlueprintRequest,
|
interceptBlueprintRequest,
|
||||||
openAndDismissSaveAndBuildModal,
|
openAndDismissSaveAndBuildModal,
|
||||||
verifyCancelButton,
|
verifyCancelButton,
|
||||||
|
|
@ -121,6 +122,20 @@ describe('Step Kernel', () => {
|
||||||
await openKernelNameOptions(kernelNameDropdown);
|
await openKernelNameOptions(kernelNameDropdown);
|
||||||
await screen.findByText(CUSTOM_NAME);
|
await screen.findByText(CUSTOM_NAME);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('disable Next with invalid custom kernel name', async () => {
|
||||||
|
await renderCreateMode();
|
||||||
|
await goToKernelStep();
|
||||||
|
|
||||||
|
await selectCustomKernelName('-----------');
|
||||||
|
await screen.findByText(/Invalid format/);
|
||||||
|
const nextButton = await getNextButton();
|
||||||
|
expect(nextButton).toBeDisabled();
|
||||||
|
|
||||||
|
await clearKernelName();
|
||||||
|
expect(screen.queryByText(/Invalid format/)).not.toBeInTheDocument();
|
||||||
|
expect(nextButton).toBeEnabled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Kernel request generated correctly', () => {
|
describe('Kernel request generated correctly', () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue