fixes bug where one can launch erronously, adds tests for that bug

This commit is contained in:
Alex Corey 2020-10-07 12:04:18 -04:00
parent f051c4d58a
commit b04be850b5
4 changed files with 55 additions and 4 deletions

View File

@ -1,13 +1,26 @@
import React, { useState } from 'react';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { ExclamationCircleIcon as PFExclamationCircleIcon } from '@patternfly/react-icons';
import { Tooltip } from '@patternfly/react-core';
import { withFormik, useFormikContext } from 'formik';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import Wizard from '../Wizard';
import AdHocCredentialStep from './AdHocCredentialStep';
import AdHocDetailsStep from './AdHocDetailsStep';
const AlertText = styled.div`
color: var(--pf-global--danger-color--200);
font-weight: var(--pf-global--FontWeight--bold);
`;
const ExclamationCircleIcon = styled(PFExclamationCircleIcon)`
margin-left: 10px;
color: var(--pf-global--danger-color--100);
`;
function AdHocCommandsWizard({
onLaunch,
i18n,
@ -19,7 +32,7 @@ function AdHocCommandsWizard({
const [currentStepId, setCurrentStepId] = useState(1);
const [enableLaunch, setEnableLaunch] = useState(false);
const { values } = useFormikContext();
const { values, errors, touched } = useFormikContext();
const enabledNextOnDetailsStep = () => {
if (!values.module_name) {
@ -36,11 +49,26 @@ function AdHocCommandsWizard({
}
return undefined; // makes the linter happy;
};
const hasDetailsStepError = errors.module_args && touched.module_args;
const steps = [
{
id: 1,
key: 1,
name: i18n._(t`Details`),
name: hasDetailsStepError ? (
<AlertText>
{i18n._(t`Details`)}
<Tooltip
position="right"
content={i18n._(t`This step contains errors`)}
trigger="click mouseenter focus"
>
<ExclamationCircleIcon />
</Tooltip>
</AlertText>
) : (
i18n._(t`Details`)
),
component: (
<AdHocDetailsStep
moduleOptions={moduleOptions}
@ -60,7 +88,7 @@ function AdHocCommandsWizard({
onEnableLaunch={() => setEnableLaunch(true)}
/>
),
enableNext: enableLaunch,
enableNext: enableLaunch && Object.values(errors).length === 0,
nextButtonText: i18n._(t`Launch`),
canJumpTo: currentStepId >= 2,
},

View File

@ -148,6 +148,20 @@ describe('<AdHocCommandsWizard/>', () => {
expect(onLaunch).toHaveBeenCalled();
});
test('should show error in navigation bar', async () => {
await waitForElement(wrapper, 'WizardNavItem', el => el.length > 0);
await act(async () => {
wrapper.find('AnsibleSelect[name="module_name"]').prop('onChange')(
{},
'command'
);
wrapper.find('input#module_args').simulate('change', {
target: { value: '', name: 'module_args' },
});
});
waitForElement(wrapper, 'ExclamationCircleIcon', el => el.length > 0);
});
test('expect credential step to throw error', async () => {
CredentialsAPI.read.mockRejectedValue(

View File

@ -65,6 +65,7 @@ function AdHocCredentialStep({ i18n, credentialTypeId, onEnableLaunch }) {
<FormGroup
fieldId="credential"
label={i18n._(t`Machine Credential`)}
aria-label={i18n._(t`Machine Credential`)}
isRequired
validated={
!credentialMeta.touched || !credentialMeta.error ? 'default' : 'error'

View File

@ -47,7 +47,7 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
moduleNameField.value === 'command' || moduleNameField.value === 'shell';
const [, argumentsMeta, argumentsHelpers] = useField({
name: 'module_args',
validate: argumentsRequired ? required(null, i18n) : null,
validate: argumentsRequired && required(null, i18n),
});
const isValid = !argumentsMeta.error || !argumentsMeta.touched;
@ -58,6 +58,7 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
<FormFullWidthLayout>
<FormGroup
fieldId="module_name"
aria-label={i18n._(t`Module`)}
label={i18n._(t`Module`)}
isRequired
helperTextInvalid={moduleNameMeta.error}
@ -103,9 +104,11 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
<FormField
id="module_args"
name="module_args"
aria-label={i18n._(t`Arguments`)}
type="text"
label={i18n._(t`Arguments`)}
validated={isValid ? 'default' : 'error'}
onBlur={() => argumentsHelpers.setTouched(true)}
placeholder={i18n._(t`Enter arguments`)}
isRequired={
moduleNameField.value === 'command' ||
@ -133,6 +136,7 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
/>
<FormGroup
fieldId="verbosity"
aria-label={i18n._(t`Verbosity`)}
label={i18n._(t`Verbosity`)}
isRequired
validated={
@ -164,6 +168,7 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
name="limit"
type="text"
label={i18n._(t`Limit`)}
aria-label={i18n._(t`Limit`)}
tooltip={
<span>
{i18n._(
@ -185,6 +190,7 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
type="number"
min="0"
label={i18n._(t`Forks`)}
aria-label={i18n._(t`Forks`)}
tooltip={
<span>
{i18n._(
@ -203,6 +209,7 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
<FormColumnLayout>
<FormGroup
label={i18n._(t`Show changes`)}
aria-label={i18n._(t`Show changes`)}
labelIcon={
<FieldTooltip
content={i18n._(
@ -300,6 +307,7 @@ function AdHocDetailsStep({ i18n, verbosityOptions, moduleOptions }) {
</TooltipWrapper>
}
label={i18n._(t`Extra variables`)}
aria-label={i18n._(t`Extra variables`)}
/>
</FormFullWidthLayout>
</FormColumnLayout>