mirror of
https://github.com/ansible/awx.git
synced 2026-05-16 05:47:38 -02:30
Merge pull request #10713 from keithjgrant/10563-a11y-fixes
Fix multiple accessibility violations
This commit is contained in:
@@ -17,6 +17,7 @@ import Popover from '../Popover';
|
|||||||
function CodeDetail({ value, label, mode, rows, helpText, dataCy }) {
|
function CodeDetail({ value, label, mode, rows, helpText, dataCy }) {
|
||||||
const labelCy = dataCy ? `${dataCy}-label` : null;
|
const labelCy = dataCy ? `${dataCy}-label` : null;
|
||||||
const valueCy = dataCy ? `${dataCy}-value` : null;
|
const valueCy = dataCy ? `${dataCy}-value` : null;
|
||||||
|
const editorId = dataCy ? `${dataCy}-editor` : 'code-editor';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -27,12 +28,13 @@ function CodeDetail({ value, label, mode, rows, helpText, dataCy }) {
|
|||||||
data-cy={labelCy}
|
data-cy={labelCy}
|
||||||
>
|
>
|
||||||
<div className="pf-c-form__label">
|
<div className="pf-c-form__label">
|
||||||
<span
|
<label
|
||||||
|
htmlFor={editorId}
|
||||||
className="pf-c-form__label-text"
|
className="pf-c-form__label-text"
|
||||||
css="font-weight: var(--pf-global--FontWeight--bold)"
|
css="font-weight: var(--pf-global--FontWeight--bold)"
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</label>
|
||||||
{helpText && (
|
{helpText && (
|
||||||
<Popover header={label} content={helpText} id={dataCy} />
|
<Popover header={label} content={helpText} id={dataCy} />
|
||||||
)}
|
)}
|
||||||
@@ -45,6 +47,7 @@ function CodeDetail({ value, label, mode, rows, helpText, dataCy }) {
|
|||||||
data-cy={valueCy}
|
data-cy={valueCy}
|
||||||
>
|
>
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
|
id={editorId}
|
||||||
mode={mode}
|
mode={mode}
|
||||||
value={value}
|
value={value}
|
||||||
readOnly
|
readOnly
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const DetailValue = styled(
|
|||||||
${(props) =>
|
${(props) =>
|
||||||
(props.isEncrypted || props.isNotConfigured) &&
|
(props.isEncrypted || props.isNotConfigured) &&
|
||||||
`
|
`
|
||||||
color: var(--pf-global--Color--400);
|
color: var(--pf-global--disabled-color--100);
|
||||||
`}
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ function ExecutionEnvironmentDetail({
|
|||||||
virtualEnvironment,
|
virtualEnvironment,
|
||||||
verifyMissingVirtualEnv,
|
verifyMissingVirtualEnv,
|
||||||
helpText,
|
helpText,
|
||||||
|
dataCy,
|
||||||
}) {
|
}) {
|
||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
const docsLink = `${getDocsBaseUrl(
|
const docsLink = `${getDocsBaseUrl(
|
||||||
@@ -51,7 +52,7 @@ function ExecutionEnvironmentDetail({
|
|||||||
</Link>
|
</Link>
|
||||||
}
|
}
|
||||||
helpText={helpText}
|
helpText={helpText}
|
||||||
dataCy="execution-environment-detail"
|
dataCy={dataCy}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -89,7 +90,7 @@ function ExecutionEnvironmentDetail({
|
|||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
dataCy="missing-execution-environment-detail"
|
dataCy={`missing-${dataCy}`}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -113,7 +114,7 @@ function ExecutionEnvironmentDetail({
|
|||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
dataCy="execution-environment-detail"
|
dataCy={dataCy}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -127,6 +128,7 @@ ExecutionEnvironmentDetail.propTypes = {
|
|||||||
virtualEnvironment: string,
|
virtualEnvironment: string,
|
||||||
verifyMissingVirtualEnv: bool,
|
verifyMissingVirtualEnv: bool,
|
||||||
helpText: string,
|
helpText: string,
|
||||||
|
dataCy: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
ExecutionEnvironmentDetail.defaultProps = {
|
ExecutionEnvironmentDetail.defaultProps = {
|
||||||
@@ -135,6 +137,7 @@ ExecutionEnvironmentDetail.defaultProps = {
|
|||||||
virtualEnvironment: '',
|
virtualEnvironment: '',
|
||||||
verifyMissingVirtualEnv: true,
|
verifyMissingVirtualEnv: true,
|
||||||
helpText: '',
|
helpText: '',
|
||||||
|
dataCy: 'execution-environment-detail',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ExecutionEnvironmentDetail;
|
export default ExecutionEnvironmentDetail;
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ function JobListItem({
|
|||||||
<ReLaunchDropDown
|
<ReLaunchDropDown
|
||||||
handleRelaunch={handleRelaunch}
|
handleRelaunch={handleRelaunch}
|
||||||
isLaunching={isLaunching}
|
isLaunching={isLaunching}
|
||||||
|
id={`relaunch-job-${job.id}`}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</LaunchButton>
|
</LaunchButton>
|
||||||
@@ -214,6 +215,7 @@ function JobListItem({
|
|||||||
<ExecutionEnvironmentDetail
|
<ExecutionEnvironmentDetail
|
||||||
executionEnvironment={execution_environment}
|
executionEnvironment={execution_environment}
|
||||||
verifyMissingVirtualEnv={false}
|
verifyMissingVirtualEnv={false}
|
||||||
|
dataCy={`execution-environment-detail-${job.id}`}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{credentials && credentials.length > 0 && (
|
{credentials && credentials.length > 0 && (
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ function ReLaunchDropDown({
|
|||||||
isPrimary = false,
|
isPrimary = false,
|
||||||
handleRelaunch,
|
handleRelaunch,
|
||||||
isLaunching,
|
isLaunching,
|
||||||
|
id = 'relaunch-job',
|
||||||
ouiaId,
|
ouiaId,
|
||||||
}) {
|
}) {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
@@ -75,7 +75,7 @@ function ReLaunchDropDown({
|
|||||||
toggleIndicator={null}
|
toggleIndicator={null}
|
||||||
onToggle={onToggle}
|
onToggle={onToggle}
|
||||||
aria-label={t`relaunch jobs`}
|
aria-label={t`relaunch jobs`}
|
||||||
id="relaunch_jobs"
|
id={id}
|
||||||
isPrimary
|
isPrimary
|
||||||
>
|
>
|
||||||
{t`Relaunch`}
|
{t`Relaunch`}
|
||||||
@@ -97,7 +97,7 @@ function ReLaunchDropDown({
|
|||||||
toggleIndicator={null}
|
toggleIndicator={null}
|
||||||
onToggle={onToggle}
|
onToggle={onToggle}
|
||||||
aria-label={t`relaunch jobs`}
|
aria-label={t`relaunch jobs`}
|
||||||
id="relaunch_jobs"
|
id={id}
|
||||||
>
|
>
|
||||||
<RocketIcon />
|
<RocketIcon />
|
||||||
</DropdownToggle>
|
</DropdownToggle>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ const QS_CONFIG = getQSConfig('execution_environments', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function ExecutionEnvironmentLookup({
|
function ExecutionEnvironmentLookup({
|
||||||
|
id,
|
||||||
globallyAvailable,
|
globallyAvailable,
|
||||||
helperTextInvalid,
|
helperTextInvalid,
|
||||||
isDefaultEnvironment,
|
isDefaultEnvironment,
|
||||||
@@ -154,7 +155,7 @@ function ExecutionEnvironmentLookup({
|
|||||||
const renderLookup = () => (
|
const renderLookup = () => (
|
||||||
<>
|
<>
|
||||||
<Lookup
|
<Lookup
|
||||||
id="execution-environments"
|
id={id}
|
||||||
header={t`Execution Environment`}
|
header={t`Execution Environment`}
|
||||||
value={value}
|
value={value}
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
@@ -213,7 +214,7 @@ function ExecutionEnvironmentLookup({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
fieldId="execution-environment-lookup"
|
fieldId={id}
|
||||||
label={renderLabel(isGlobalDefaultEnvironment, isDefaultEnvironment)}
|
label={renderLabel(isGlobalDefaultEnvironment, isDefaultEnvironment)}
|
||||||
labelIcon={popoverContent && <Popover content={popoverContent} />}
|
labelIcon={popoverContent && <Popover content={popoverContent} />}
|
||||||
helperTextInvalid={helperTextInvalid}
|
helperTextInvalid={helperTextInvalid}
|
||||||
@@ -231,6 +232,7 @@ function ExecutionEnvironmentLookup({
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExecutionEnvironmentLookup.propTypes = {
|
ExecutionEnvironmentLookup.propTypes = {
|
||||||
|
id: string,
|
||||||
value: ExecutionEnvironment,
|
value: ExecutionEnvironment,
|
||||||
popoverContent: string,
|
popoverContent: string,
|
||||||
onChange: func.isRequired,
|
onChange: func.isRequired,
|
||||||
@@ -243,6 +245,7 @@ ExecutionEnvironmentLookup.propTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ExecutionEnvironmentLookup.defaultProps = {
|
ExecutionEnvironmentLookup.defaultProps = {
|
||||||
|
id: 'execution-environments',
|
||||||
popoverContent: '',
|
popoverContent: '',
|
||||||
isDefaultEnvironment: false,
|
isDefaultEnvironment: false,
|
||||||
isGlobalDefaultEnvironment: false,
|
isGlobalDefaultEnvironment: false,
|
||||||
|
|||||||
@@ -236,6 +236,7 @@ function InventoryLookup({
|
|||||||
}
|
}
|
||||||
|
|
||||||
InventoryLookup.propTypes = {
|
InventoryLookup.propTypes = {
|
||||||
|
fieldId: string,
|
||||||
value: Inventory,
|
value: Inventory,
|
||||||
onChange: func.isRequired,
|
onChange: func.isRequired,
|
||||||
required: bool,
|
required: bool,
|
||||||
@@ -247,6 +248,7 @@ InventoryLookup.propTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
InventoryLookup.defaultProps = {
|
InventoryLookup.defaultProps = {
|
||||||
|
fieldId: 'inventory',
|
||||||
value: null,
|
value: null,
|
||||||
required: false,
|
required: false,
|
||||||
isOverrideDisabled: false,
|
isOverrideDisabled: false,
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ function Lookup(props) {
|
|||||||
<InputGroup onBlur={onBlur}>
|
<InputGroup onBlur={onBlur}>
|
||||||
<Button
|
<Button
|
||||||
aria-label={t`Search`}
|
aria-label={t`Search`}
|
||||||
id={id}
|
id={`${id}-open`}
|
||||||
onClick={() => dispatch({ type: 'TOGGLE_MODAL' })}
|
onClick={() => dispatch({ type: 'TOGGLE_MODAL' })}
|
||||||
variant={ButtonVariant.control}
|
variant={ButtonVariant.control}
|
||||||
isDisabled={isLoading || isDisabled}
|
isDisabled={isLoading || isDisabled}
|
||||||
@@ -149,7 +149,7 @@ function Lookup(props) {
|
|||||||
</ChipHolder>
|
</ChipHolder>
|
||||||
) : (
|
) : (
|
||||||
<TextInput
|
<TextInput
|
||||||
id={`${id}-input`}
|
id={id}
|
||||||
value={typedText}
|
value={typedText}
|
||||||
onChange={(inputValue) => {
|
onChange={(inputValue) => {
|
||||||
setTypedText(inputValue);
|
setTypedText(inputValue);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ const QS_CONFIG = getQSConfig('organizations', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function OrganizationLookup({
|
function OrganizationLookup({
|
||||||
|
id,
|
||||||
helperTextInvalid,
|
helperTextInvalid,
|
||||||
isValid,
|
isValid,
|
||||||
onBlur,
|
onBlur,
|
||||||
@@ -94,7 +95,7 @@ function OrganizationLookup({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
fieldId="organization"
|
fieldId={id}
|
||||||
helperTextInvalid={helperTextInvalid}
|
helperTextInvalid={helperTextInvalid}
|
||||||
isRequired={required}
|
isRequired={required}
|
||||||
validated={isValid ? 'default' : 'error'}
|
validated={isValid ? 'default' : 'error'}
|
||||||
@@ -103,7 +104,7 @@ function OrganizationLookup({
|
|||||||
>
|
>
|
||||||
<Lookup
|
<Lookup
|
||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
id="organization"
|
id={id}
|
||||||
header={t`Organization`}
|
header={t`Organization`}
|
||||||
value={value}
|
value={value}
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
@@ -158,6 +159,7 @@ function OrganizationLookup({
|
|||||||
}
|
}
|
||||||
|
|
||||||
OrganizationLookup.propTypes = {
|
OrganizationLookup.propTypes = {
|
||||||
|
id: string,
|
||||||
helperTextInvalid: node,
|
helperTextInvalid: node,
|
||||||
isValid: bool,
|
isValid: bool,
|
||||||
onBlur: func,
|
onBlur: func,
|
||||||
@@ -171,6 +173,7 @@ OrganizationLookup.propTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
OrganizationLookup.defaultProps = {
|
OrganizationLookup.defaultProps = {
|
||||||
|
id: 'organization',
|
||||||
helperTextInvalid: '',
|
helperTextInvalid: '',
|
||||||
isValid: true,
|
isValid: true,
|
||||||
onBlur: () => {},
|
onBlur: () => {},
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ describe('<ApplicationAdd/>', () => {
|
|||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(wrapper.find('input#name').prop('value')).toBe('new foo');
|
expect(wrapper.find('input#name').prop('value')).toBe('new foo');
|
||||||
expect(wrapper.find('input#description').prop('value')).toBe('new bar');
|
expect(wrapper.find('input#description').prop('value')).toBe('new bar');
|
||||||
expect(wrapper.find('input#organization-input').prop('value')).toBe(
|
expect(wrapper.find('input#organization').prop('value')).toBe(
|
||||||
'organization'
|
'organization'
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ describe('<ApplicationEdit/>', () => {
|
|||||||
});
|
});
|
||||||
expect(wrapper.find('ApplicationEdit').length).toBe(1);
|
expect(wrapper.find('ApplicationEdit').length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should cancel form properly', async () => {
|
test('should cancel form properly', async () => {
|
||||||
const history = createMemoryHistory({
|
const history = createMemoryHistory({
|
||||||
initialEntries: ['/applications/1/edit'],
|
initialEntries: ['/applications/1/edit'],
|
||||||
@@ -110,6 +111,7 @@ describe('<ApplicationEdit/>', () => {
|
|||||||
expect(history.location.pathname).toBe('/applications/1/details');
|
expect(history.location.pathname).toBe('/applications/1/details');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should throw error on submit', async () => {
|
test('should throw error on submit', async () => {
|
||||||
const error = {
|
const error = {
|
||||||
response: {
|
response: {
|
||||||
@@ -147,6 +149,7 @@ describe('<ApplicationEdit/>', () => {
|
|||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(wrapper.find('FormSubmitError').length).toBe(1);
|
expect(wrapper.find('FormSubmitError').length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('expect values to be updated and submitted properly', async () => {
|
test('expect values to be updated and submitted properly', async () => {
|
||||||
const history = createMemoryHistory({
|
const history = createMemoryHistory({
|
||||||
initialEntries: ['/applications/1/edit'],
|
initialEntries: ['/applications/1/edit'],
|
||||||
@@ -188,7 +191,7 @@ describe('<ApplicationEdit/>', () => {
|
|||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(wrapper.find('input#name').prop('value')).toBe('new foo');
|
expect(wrapper.find('input#name').prop('value')).toBe('new foo');
|
||||||
expect(wrapper.find('input#description').prop('value')).toBe('new bar');
|
expect(wrapper.find('input#description').prop('value')).toBe('new bar');
|
||||||
expect(wrapper.find('input#organization-input').prop('value')).toBe(
|
expect(wrapper.find('input#organization').prop('value')).toBe(
|
||||||
'organization'
|
'organization'
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ describe('<ApplicationForm', () => {
|
|||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(wrapper.find('input#name').prop('value')).toBe('new foo');
|
expect(wrapper.find('input#name').prop('value')).toBe('new foo');
|
||||||
expect(wrapper.find('input#description').prop('value')).toBe('new bar');
|
expect(wrapper.find('input#description').prop('value')).toBe('new bar');
|
||||||
expect(wrapper.find('input#organization-input').prop('value')).toBe(
|
expect(wrapper.find('input#organization').prop('value')).toBe(
|
||||||
'organization'
|
'organization'
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function TeamListItem({ team, isSelected, onSelect, detailUrl, rowIndex }) {
|
|||||||
dataLabel={t`Selected`}
|
dataLabel={t`Selected`}
|
||||||
/>
|
/>
|
||||||
<Td id={labelId} dataLabel={t`Name`}>
|
<Td id={labelId} dataLabel={t`Name`}>
|
||||||
<Link id={labelId} to={`${detailUrl}`}>
|
<Link to={`${detailUrl}`}>
|
||||||
<b>{team.name}</b>
|
<b>{team.name}</b>
|
||||||
</Link>
|
</Link>
|
||||||
</Td>
|
</Td>
|
||||||
|
|||||||
@@ -339,9 +339,7 @@ describe('<JobTemplateEdit />', () => {
|
|||||||
name: 'Other Inventory',
|
name: 'Other Inventory',
|
||||||
});
|
});
|
||||||
|
|
||||||
wrapper.find('TextInput#execution-environments-input').invoke('onChange')(
|
wrapper.find('TextInput#execution-environments').invoke('onChange')('');
|
||||||
''
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
|
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ function JobTemplateForm({
|
|||||||
/>
|
/>
|
||||||
</FieldWithPrompt>
|
</FieldWithPrompt>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
fieldId="inventory-lookup"
|
fieldId="template-inventory"
|
||||||
validated={
|
validated={
|
||||||
!(inventoryMeta.touched || askInventoryOnLaunchField.value) ||
|
!(inventoryMeta.touched || askInventoryOnLaunchField.value) ||
|
||||||
!inventoryMeta.error
|
!inventoryMeta.error
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ describe('<WebhookSubForm />', () => {
|
|||||||
.find('TextInputBase[aria-label="workflow job template webhook key"]')
|
.find('TextInputBase[aria-label="workflow job template webhook key"]')
|
||||||
.prop('value')
|
.prop('value')
|
||||||
).toBe('webhook key');
|
).toBe('webhook key');
|
||||||
expect(wrapper.find('input#credential-input').prop('value')).toBe(
|
expect(wrapper.find('input#credential').prop('value')).toBe(
|
||||||
'Github credential'
|
'Github credential'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user