adds translation linting and addresses issues the linter found

This commit is contained in:
Alex Corey
2021-01-14 15:25:58 -05:00
parent 0f0857747d
commit 1f81592b5c
46 changed files with 146 additions and 70 deletions

View File

@@ -8,8 +8,8 @@
"modules": true "modules": true
} }
}, },
"plugins": ["react-hooks", "jsx-a11y"], "plugins": ["react-hooks", "jsx-a11y", "i18next"],
"extends": ["airbnb", "prettier", "prettier/react", "plugin:jsx-a11y/strict"], "extends": ["airbnb", "prettier", "prettier/react", "plugin:jsx-a11y/strict", "plugin:i18next/recommended"],
"settings": { "settings": {
"react": { "react": {
"version": "16.5.2" "version": "16.5.2"
@@ -24,6 +24,7 @@
"window": true "window": true
}, },
"rules": { "rules": {
"i18next/no-literal-string": [2, {"markupOnly": true, "ignoreAttribute": ["to", "streamType", "path", "component", "variant", "key", "position", "promptName", "color","promptId", "headingLevel", "size", "target", "autoComplete","trigger", "from", "name", "fieldId", "css", "gutter", "dataCy", "tooltipMaxWidth", "mode", "aria-labelledby","aria-hidden","sortKey", "ouiaId", "credentialTypeNamespace", "link", "value", "credentialTypeKind", "linkTo", "scrollToAlignment", "displayKey", "sortedColumnKey", "maxHeight", "role", "aria-haspopup", "dropDirection", "resizeOrientation", "src", "theme"], "ignore":["Ansible", "Tower", "JSON", "YAML", "lg", "START"],"ignoreComponent":["code", "Omit","PotentialLink", "TypeRedirect", "Radio", "RunOnRadio", "NodeTypeLetter", "SelectableItem", "Dash"], "ignoreCallee": ["describe"] }],
"camelcase": "off", "camelcase": "off",
"arrow-parens": "off", "arrow-parens": "off",
"comma-dangle": "off", "comma-dangle": "off",

View File

@@ -7172,6 +7172,15 @@
"lodash": "^4.17.15" "lodash": "^4.17.15"
} }
}, },
"eslint-plugin-i18next": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-i18next/-/eslint-plugin-i18next-5.0.0.tgz",
"integrity": "sha512-ixbgSMrSb0dZsO6WPElg4JvPiQKLDA3ZpBuayxToADan1TKcbzKXT2A42Vyc0lEDhJRPL6uZnmm8vPjODDJypg==",
"dev": true,
"requires": {
"requireindex": "~1.1.0"
}
},
"eslint-plugin-import": { "eslint-plugin-import": {
"version": "2.22.1", "version": "2.22.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz",
@@ -15163,6 +15172,12 @@
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
"dev": true "dev": true
}, },
"requireindex": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz",
"integrity": "sha1-5UBLgVV+91225JxacgBIk/4D4WI=",
"dev": true
},
"requires-port": { "requires-port": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",

View File

@@ -43,6 +43,7 @@
"eslint-config-airbnb": "^17.1.0", "eslint-config-airbnb": "^17.1.0",
"eslint-config-prettier": "^5.0.0", "eslint-config-prettier": "^5.0.0",
"eslint-import-resolver-webpack": "0.11.1", "eslint-import-resolver-webpack": "0.11.1",
"eslint-plugin-i18next": "^5.0.0",
"eslint-plugin-import": "^2.14.0", "eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.11.1", "eslint-plugin-react": "^7.11.1",

View File

@@ -1,6 +1,7 @@
import 'styled-components/macro'; import 'styled-components/macro';
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { node, number, oneOfType, shape, string, arrayOf } from 'prop-types'; import { node, number, oneOfType, shape, string, arrayOf } from 'prop-types';
import { Trans, withI18n } from '@lingui/react';
import { Split, SplitItem, TextListItemVariants } from '@patternfly/react-core'; import { Split, SplitItem, TextListItemVariants } from '@patternfly/react-core';
import { DetailName, DetailValue } from '../DetailList'; import { DetailName, DetailValue } from '../DetailList';
import MultiButtonToggle from '../MultiButtonToggle'; import MultiButtonToggle from '../MultiButtonToggle';
@@ -111,7 +112,7 @@ function VariablesDetail({ dataCy, helpText, value, label, rows, fullHeight }) {
css="color: var(--pf-global--danger-color--100); css="color: var(--pf-global--danger-color--100);
font-size: var(--pf-global--FontSize--sm" font-size: var(--pf-global--FontSize--sm"
> >
Error: {error.message} <Trans>Error:</Trans> {error.message}
</div> </div>
)} )}
</DetailValue> </DetailValue>
@@ -131,4 +132,4 @@ VariablesDetail.defaultProps = {
helpText: '', helpText: '',
}; };
export default VariablesDetail; export default withI18n()(VariablesDetail);

View File

@@ -1,13 +1,13 @@
import React from 'react'; import React from 'react';
import { act } from 'react-dom/test-utils'; import { act } from 'react-dom/test-utils';
import { shallow, mount } from 'enzyme'; import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
import VariablesDetail from './VariablesDetail'; import VariablesDetail from './VariablesDetail';
jest.mock('../../api'); jest.mock('../../api');
describe('<VariablesDetail>', () => { describe('<VariablesDetail>', () => {
test('should render readonly CodeMirrorInput', () => { test('should render readonly CodeMirrorInput', () => {
const wrapper = shallow( const wrapper = mountWithContexts(
<VariablesDetail value="---foo: bar" label="Variables" /> <VariablesDetail value="---foo: bar" label="Variables" />
); );
const input = wrapper.find('VariablesDetail___StyledCodeMirrorInput'); const input = wrapper.find('VariablesDetail___StyledCodeMirrorInput');
@@ -18,7 +18,7 @@ describe('<VariablesDetail>', () => {
}); });
test('should detect JSON', () => { test('should detect JSON', () => {
const wrapper = shallow( const wrapper = mountWithContexts(
<VariablesDetail value='{"foo": "bar"}' label="Variables" /> <VariablesDetail value='{"foo": "bar"}' label="Variables" />
); );
const input = wrapper.find('VariablesDetail___StyledCodeMirrorInput'); const input = wrapper.find('VariablesDetail___StyledCodeMirrorInput');
@@ -28,7 +28,7 @@ describe('<VariablesDetail>', () => {
}); });
test('should convert between modes', () => { test('should convert between modes', () => {
const wrapper = shallow( const wrapper = mountWithContexts(
<VariablesDetail value="---foo: bar" label="Variables" /> <VariablesDetail value="---foo: bar" label="Variables" />
); );
wrapper.find('MultiButtonToggle').invoke('onChange')('javascript'); wrapper.find('MultiButtonToggle').invoke('onChange')('javascript');
@@ -43,7 +43,9 @@ describe('<VariablesDetail>', () => {
}); });
test('should render label and value= --- when there are no values', () => { test('should render label and value= --- when there are no values', () => {
const wrapper = shallow(<VariablesDetail value="" label="Variables" />); const wrapper = mountWithContexts(
<VariablesDetail value="" label="Variables" />
);
expect(wrapper.find('VariablesDetail___StyledCodeMirrorInput').length).toBe( expect(wrapper.find('VariablesDetail___StyledCodeMirrorInput').length).toBe(
1 1
); );
@@ -51,7 +53,7 @@ describe('<VariablesDetail>', () => {
}); });
test('should update value if prop changes', () => { test('should update value if prop changes', () => {
const wrapper = mount( const wrapper = mountWithContexts(
<VariablesDetail value="---foo: bar" label="Variables" /> <VariablesDetail value="---foo: bar" label="Variables" />
); );
act(() => { act(() => {
@@ -67,13 +69,17 @@ describe('<VariablesDetail>', () => {
}); });
test('should default yaml value to "---"', () => { test('should default yaml value to "---"', () => {
const wrapper = shallow(<VariablesDetail value="" label="Variables" />); const wrapper = mountWithContexts(
<VariablesDetail value="" label="Variables" />
);
const input = wrapper.find('VariablesDetail___StyledCodeMirrorInput'); const input = wrapper.find('VariablesDetail___StyledCodeMirrorInput');
expect(input.prop('value')).toEqual('---'); expect(input.prop('value')).toEqual('---');
}); });
test('should default empty json to "{}"', () => { test('should default empty json to "{}"', () => {
const wrapper = mount(<VariablesDetail value="" label="Variables" />); const wrapper = mountWithContexts(
<VariablesDetail value="" label="Variables" />
);
act(() => { act(() => {
wrapper.find('MultiButtonToggle').invoke('onChange')('javascript'); wrapper.find('MultiButtonToggle').invoke('onChange')('javascript');
}); });

View File

@@ -258,7 +258,7 @@ function JobList({ i18n, defaultParams, showTypeColumn = false }) {
key="delete" key="delete"
onDelete={handleJobDelete} onDelete={handleJobDelete}
itemsToDelete={selected} itemsToDelete={selected}
pluralizedItemName="Jobs" pluralizedItemName={i18n._(t`Jobs`)}
/>, />,
<JobListCancelButton <JobListCancelButton
key="cancel" key="cancel"

View File

@@ -5,6 +5,7 @@ import { t } from '@lingui/macro';
import { Button, Chip } from '@patternfly/react-core'; import { Button, Chip } from '@patternfly/react-core';
import { Tr, Td, ExpandableRowContent } from '@patternfly/react-table'; import { Tr, Td, ExpandableRowContent } from '@patternfly/react-table';
import { RocketIcon } from '@patternfly/react-icons'; import { RocketIcon } from '@patternfly/react-icons';
import styled from 'styled-components';
import { ActionsTd, ActionItem } from '../PaginatedTable'; import { ActionsTd, ActionItem } from '../PaginatedTable';
import LaunchButton from '../LaunchButton'; import LaunchButton from '../LaunchButton';
import StatusLabel from '../StatusLabel'; import StatusLabel from '../StatusLabel';
@@ -14,6 +15,7 @@ import CredentialChip from '../CredentialChip';
import { formatDateString } from '../../util/dates'; import { formatDateString } from '../../util/dates';
import { JOB_TYPE_URL_SEGMENTS } from '../../constants'; import { JOB_TYPE_URL_SEGMENTS } from '../../constants';
const Dash = styled.span``;
function JobListItem({ function JobListItem({
i18n, i18n,
job, job,
@@ -58,7 +60,7 @@ function JobListItem({
<span> <span>
<Link to={`/jobs/${JOB_TYPE_URL_SEGMENTS[job.type]}/${job.id}`}> <Link to={`/jobs/${JOB_TYPE_URL_SEGMENTS[job.type]}/${job.id}`}>
<b> <b>
{job.id} &mdash; {job.name} {job.id} <Dash>&mdash;</Dash> {job.name}
</b> </b>
</Link> </Link>
</span> </span>

View File

@@ -103,7 +103,7 @@ function Lookup(props) {
<Fragment> <Fragment>
<InputGroup onBlur={onBlur}> <InputGroup onBlur={onBlur}>
<Button <Button
aria-label="Search" aria-label={i18n._(t`Search`)}
id={id} id={id}
onClick={() => dispatch({ type: 'TOGGLE_MODAL' })} onClick={() => dispatch({ type: 'TOGGLE_MODAL' })}
variant={ButtonVariant.control} variant={ButtonVariant.control}

View File

@@ -63,7 +63,7 @@ function NotificationListItem({
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={`items-list-item-${notification.id}`} aria-labelledby={`items-list-item-${notification.id}`}
id={`items-list-item-${notification.id}`} id={`items-list-item-${notification.id}`}
columns={showApprovalsToggle ? 4 : 3} columns={showApprovalsToggle ? 4 : 3}

View File

@@ -138,7 +138,7 @@ function PromptDetail({ i18n, resource, launchConfig = {}, overrides = {} }) {
<> <>
<Divider css="margin-top: var(--pf-global--spacer--lg)" /> <Divider css="margin-top: var(--pf-global--spacer--lg)" />
<PromptHeader>{i18n._(t`Prompted Values`)}</PromptHeader> <PromptHeader>{i18n._(t`Prompted Values`)}</PromptHeader>
<DetailList aria-label="Prompt Overrides"> <DetailList aria-label={i18n._(t`Prompt Overrides`)}>
{launchConfig.ask_job_type_on_launch && ( {launchConfig.ask_job_type_on_launch && (
<Detail <Detail
label={i18n._(t`Job Type`)} label={i18n._(t`Job Type`)}

View File

@@ -101,7 +101,7 @@ function ScheduleListItem({ i18n, isSelected, onSelect, schedule }) {
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
key="actions" key="actions"

View File

@@ -78,7 +78,7 @@ function ApplicationListItem({
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -83,7 +83,7 @@ function CredentialListItem({
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -60,7 +60,7 @@ function CredentialTypeListItem({
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -250,7 +250,7 @@ function DashboardTemplateList({ i18n }) {
key="delete" key="delete"
onDelete={handleTemplateDelete} onDelete={handleTemplateDelete}
itemsToDelete={selected} itemsToDelete={selected}
pluralizedItemName="Templates" pluralizedItemName={i18n._(t`Templates`)}
/>, />,
]} ]}
/> />

View File

@@ -111,7 +111,10 @@ function DashboardTemplateListItem({
</DataListCell>, </DataListCell>,
]} ]}
/> />
<DataListAction aria-label="actions" aria-labelledby={labelId}> <DataListAction
aria-label={i18n._(t`actions`)}
aria-labelledby={labelId}
>
{template.type === 'workflow_job_template' && ( {template.type === 'workflow_job_template' && (
<Tooltip content={i18n._(t`Visualizer`)} position="top"> <Tooltip content={i18n._(t`Visualizer`)} position="top">
<Button <Button

View File

@@ -42,7 +42,7 @@ function HostGroupItem({ i18n, group, inventoryId, isSelected, onSelect }) {
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -64,7 +64,7 @@ function HostListItem({ i18n, host, isSelected, onSelect, detailUrl }) {
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -173,7 +173,7 @@ function InstanceGroupListItem({
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -113,7 +113,7 @@ function InstanceListItem({
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -66,7 +66,7 @@ function InventoryGroupHostListItem({
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -48,7 +48,7 @@ function InventoryGroupItem({
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -48,7 +48,7 @@ function InventoryHostGroupItem({
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -59,7 +59,7 @@ function InventoryHostItem(props) {
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -56,7 +56,7 @@ function InventoryRelatedGroupListItem({
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -88,7 +88,7 @@ function InventorySourceListItem({
<DataListAction <DataListAction
id="actions" id="actions"
aria-labelledby="actions" aria-labelledby="actions"
aria-label="actions" aria-label={i18n._(t`actions`)}
> >
{source.summary_fields.user_capabilities.start && ( {source.summary_fields.user_capabilities.start && (
<InventorySourceSyncButton source={source} /> <InventorySourceSyncButton source={source} />

View File

@@ -152,7 +152,7 @@ function SmartInventoryDetail({ inventory, i18n }) {
{user_capabilities?.edit && ( {user_capabilities?.edit && (
<Button <Button
component={Link} component={Link}
aria-label="edit" aria-label={i18n._(t`edit`)}
to={`/inventories/smart_inventory/${id}/edit`} to={`/inventories/smart_inventory/${id}/edit`}
> >
{i18n._(t`Edit`)} {i18n._(t`Edit`)}

View File

@@ -127,7 +127,10 @@ function NotificationTemplateListItem({
</DataListCell>, </DataListCell>,
]} ]}
/> />
<DataListAction aria-label="actions" aria-labelledby={labelId}> <DataListAction
aria-label={i18n._(t`actions`)}
aria-labelledby={labelId}
>
<Tooltip content={i18n._(t`Test Notification`)} position="top"> <Tooltip content={i18n._(t`Test Notification`)} position="top">
<Button <Button
aria-label={i18n._(t`Test Notification`)} aria-label={i18n._(t`Test Notification`)}

View File

@@ -1,6 +1,6 @@
import 'styled-components/macro'; import 'styled-components/macro';
import React, { useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import { withI18n } from '@lingui/react'; import { Trans, withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { useField, useFormikContext } from 'formik'; import { useField, useFormikContext } from 'formik';
import { Switch, Text } from '@patternfly/react-core'; import { Switch, Text } from '@patternfly/react-core';
@@ -69,9 +69,11 @@ function CustomMessagesSubForm({ defaultMessages, type, i18n }) {
css="margin-bottom: var(--pf-c-content--MarginBottom)" css="margin-bottom: var(--pf-c-content--MarginBottom)"
> >
<small> <small>
Use custom messages to change the content of notifications sent <Trans>
when a job starts, succeeds, or fails. Use curly braces to access Use custom messages to change the content of notifications sent
information about the job:{' '} when a job starts, succeeds, or fails. Use curly braces to
access information about the job:{' '}
</Trans>
<code> <code>
{'{{'} job_friendly_name {'}}'} {'{{'} job_friendly_name {'}}'}
</code> </code>
@@ -79,12 +81,15 @@ function CustomMessagesSubForm({ defaultMessages, type, i18n }) {
<code> <code>
{'{{'} url {'}}'} {'{{'} url {'}}'}
</code> </code>
, or attributes of the job such as{' '} , <Trans>or attributes of the job such as</Trans>{' '}
<code> <code>
{'{{'} job.status {'}}'} {'{{'} job.status {'}}'}
</code> </code>
. You may apply a number of possible variables in the message. .{' '}
Refer to the{' '} <Trans>
You may apply a number of possible variables in the message.
Refer to the{' '}
</Trans>{' '}
<a <a
href="https://docs.ansible.com/ansible-tower/latest/html/userguide/notifications.html#create-custom-notifications" href="https://docs.ansible.com/ansible-tower/latest/html/userguide/notifications.html#create-custom-notifications"
target="_blank" target="_blank"
@@ -92,7 +97,7 @@ function CustomMessagesSubForm({ defaultMessages, type, i18n }) {
> >
Ansible Tower documentation Ansible Tower documentation
</a>{' '} </a>{' '}
for more details. <Trans>for more details.</Trans>
</small> </small>
</Text> </Text>
<FormFullWidthLayout> <FormFullWidthLayout>

View File

@@ -172,7 +172,7 @@ function OrganizationsList({ i18n }) {
key="delete" key="delete"
onDelete={handleOrgDelete} onDelete={handleOrgDelete}
itemsToDelete={selected} itemsToDelete={selected}
pluralizedItemName="Organizations" pluralizedItemName={i18n._(t`Organizations`)}
/>, />,
]} ]}
/> />

View File

@@ -32,7 +32,7 @@ function OrganizationTeamListItem({ i18n, team, detailUrl }) {
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -86,7 +86,7 @@ function ProjectJobTemplateListItem({
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -149,7 +149,7 @@ function ProjectListItem({
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -21,8 +21,16 @@ const ArchiveSubForm = ({
<span> <span>
{i18n._(t`Example URLs for Remote Archive Source Control include:`)} {i18n._(t`Example URLs for Remote Archive Source Control include:`)}
<ul css={{ margin: '10px 0 10px 20px' }}> <ul css={{ margin: '10px 0 10px 20px' }}>
<li>https://github.com/username/project/archive/v0.0.1.tar.gz</li> <li>
<li>https://github.com/username/project/archive/v0.0.2.zip</li> <code>
https://github.com/username/project/archive/v0.0.1.tar.gz
</code>
</li>
<li>
<code>
https://github.com/username/project/archive/v0.0.2.zip
</code>
</li>
</ul> </ul>
</span> </span>
} }

View File

@@ -23,9 +23,15 @@ const GitSubForm = ({
<span> <span>
{i18n._(t`Example URLs for GIT Source Control include:`)} {i18n._(t`Example URLs for GIT Source Control include:`)}
<ul css="margin: 10px 0 10px 20px"> <ul css="margin: 10px 0 10px 20px">
<li>https://github.com/ansible/ansible.git</li> <li>
<li>git@github.com:ansible/ansible.git</li> <code>https://github.com/ansible/ansible.git</code>
<li>git://servername.example.com/ansible.git</li> </li>
<li>
<code>git@github.com:ansible/ansible.git</code>
</li>
<li>
<code>git://servername.example.com/ansible.git</code>
</li>
</ul> </ul>
{i18n._(t`Note: When using SSH protocol for GitHub or {i18n._(t`Note: When using SSH protocol for GitHub or
Bitbucket, enter an SSH key only, do not enter a username Bitbucket, enter an SSH key only, do not enter a username
@@ -58,8 +64,12 @@ const GitSubForm = ({
<br /> <br />
{i18n._(t`Examples include:`)} {i18n._(t`Examples include:`)}
<ul css={{ margin: '10px 0 10px 20px' }}> <ul css={{ margin: '10px 0 10px 20px' }}>
<li>refs/*:refs/remotes/origin/*</li> <li>
<li>refs/pull/62/head:refs/remotes/origin/pull/62/head</li> <code>refs/*:refs/remotes/origin/*</code>
</li>
<li>
<code>refs/pull/62/head:refs/remotes/origin/pull/62/head</code>
</li>
</ul> </ul>
{i18n._(t`The first fetches all references. The second {i18n._(t`The first fetches all references. The second
fetches the Github pull request number 62, in this example fetches the Github pull request number 62, in this example

View File

@@ -22,9 +22,15 @@ const SvnSubForm = ({
<span> <span>
{i18n._(t`Example URLs for Subversion Source Control include:`)} {i18n._(t`Example URLs for Subversion Source Control include:`)}
<ul css={{ margin: '10px 0 10px 20px' }}> <ul css={{ margin: '10px 0 10px 20px' }}>
<li>https://github.com/ansible/ansible</li> <li>
<li>svn://servername.example.com/path</li> <code>https://github.com/ansible/ansible</code>
<li>svn+ssh://servername.example.com/path</li> </li>
<li>
<code>svn://servername.example.com/path</code>
</li>
<li>
<code>svn+ssh://servername.example.com/path</code>
</li>
</ul> </ul>
</span> </span>
} }

View File

@@ -68,7 +68,7 @@ function TeamListItem({ team, isSelected, onSelect, detailUrl, i18n }) {
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`Actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >

View File

@@ -247,7 +247,7 @@ function TemplateList({ i18n }) {
key="delete" key="delete"
onDelete={handleTemplateDelete} onDelete={handleTemplateDelete}
itemsToDelete={selected} itemsToDelete={selected}
pluralizedItemName="Templates" pluralizedItemName={i18n._(t`Templates`)}
/>, />,
]} ]}
/> />

View File

@@ -112,7 +112,10 @@ function TemplateListItem({
</DataListCell>, </DataListCell>,
]} ]}
/> />
<DataListAction aria-label="actions" aria-labelledby={labelId}> <DataListAction
aria-label={i18n._(t`actions`)}
aria-labelledby={labelId}
>
{template.type === 'workflow_job_template' && ( {template.type === 'workflow_job_template' && (
<Tooltip content={i18n._(t`Visualizer`)} position="top"> <Tooltip content={i18n._(t`Visualizer`)} position="top">
<Button <Button

View File

@@ -14,7 +14,7 @@ function LinkDeleteModal({ i18n }) {
return ( return (
<AlertModal <AlertModal
variant="danger" variant="danger"
title="Remove Link" title={i18n._(t`Remove Link`)}
isOpen={linkToDelete} isOpen={linkToDelete}
onClose={() => dispatch({ type: 'SET_LINK_TO_DELETE', value: null })} onClose={() => dispatch({ type: 'SET_LINK_TO_DELETE', value: null })}
actions={[ actions={[

View File

@@ -293,10 +293,14 @@ describe('<JobTemplateForm />', () => {
).toBe(true); ).toBe(true);
expect( expect(
wrapper.find('input[aria-label="wfjt-webhook-key"]').prop('readOnly') wrapper
.find('input[aria-label="workflow job template webhook key"]')
.prop('readOnly')
).toBe(true); ).toBe(true);
expect( expect(
wrapper.find('input[aria-label="wfjt-webhook-key"]').prop('value') wrapper
.find('input[aria-label="workflow job template webhook key"]')
.prop('value')
).toBe('webhook key'); ).toBe('webhook key');
await act(() => await act(() =>
wrapper.find('Button[aria-label="Update webhook key"]').prop('onClick')() wrapper.find('Button[aria-label="Update webhook key"]').prop('onClick')()

View File

@@ -196,7 +196,7 @@ function WebhookSubForm({ i18n, templateType }) {
<TextInput <TextInput
id="template-webhook_key" id="template-webhook_key"
isReadOnly isReadOnly
aria-label="wfjt-webhook-key" aria-label={i18n._(t`workflow job template webhook key`)}
value={webhookKeyField.value} value={webhookKeyField.value}
/> />
<Button <Button

View File

@@ -65,7 +65,9 @@ describe('<WebhookSubForm />', () => {
wrapper.find('TextInputBase[aria-label="Webhook URL"]').prop('value') wrapper.find('TextInputBase[aria-label="Webhook URL"]').prop('value')
).toContain('/api/v2/job_templates/51/github/'); ).toContain('/api/v2/job_templates/51/github/');
expect( expect(
wrapper.find('TextInputBase[aria-label="wfjt-webhook-key"]').prop('value') wrapper
.find('TextInputBase[aria-label="workflow job template webhook key"]')
.prop('value')
).toBe('webhook key'); ).toBe('webhook key');
expect( expect(
wrapper wrapper
@@ -89,7 +91,9 @@ describe('<WebhookSubForm />', () => {
wrapper.find('TextInputBase[aria-label="Webhook URL"]').prop('value') wrapper.find('TextInputBase[aria-label="Webhook URL"]').prop('value')
).toContain('/api/v2/job_templates/51/gitlab/'); ).toContain('/api/v2/job_templates/51/gitlab/');
expect( expect(
wrapper.find('TextInputBase[aria-label="wfjt-webhook-key"]').prop('value') wrapper
.find('TextInputBase[aria-label="workflow job template webhook key"]')
.prop('value')
).toBe('A NEW WEBHOOK KEY WILL BE GENERATED ON SAVE.'); ).toBe('A NEW WEBHOOK KEY WILL BE GENERATED ON SAVE.');
}); });
test('should have disabled button to update webhook key', async () => { test('should have disabled button to update webhook key', async () => {

View File

@@ -221,10 +221,14 @@ describe('<WorkflowJobTemplateForm/>', () => {
wrapper.find('Checkbox[aria-label="Enable Webhook"]').prop('isChecked') wrapper.find('Checkbox[aria-label="Enable Webhook"]').prop('isChecked')
).toBe(true); ).toBe(true);
expect( expect(
wrapper.find('input[aria-label="wfjt-webhook-key"]').prop('readOnly') wrapper
.find('input[aria-label="workflow job template webhook key"]')
.prop('readOnly')
).toBe(true); ).toBe(true);
expect( expect(
wrapper.find('input[aria-label="wfjt-webhook-key"]').prop('value') wrapper
.find('input[aria-label="workflow job template webhook key"]')
.prop('value')
).toBe('sdfghjklmnbvcdsew435678iokjhgfd'); ).toBe('sdfghjklmnbvcdsew435678iokjhgfd');
await act(() => await act(() =>
wrapper.find('Button[aria-label="Update webhook key"]').prop('onClick')() wrapper.find('Button[aria-label="Update webhook key"]').prop('onClick')()

View File

@@ -162,7 +162,7 @@ function UserList({ i18n }) {
key="delete" key="delete"
onDelete={handleUserDelete} onDelete={handleUserDelete}
itemsToDelete={selected} itemsToDelete={selected}
pluralizedItemName="Users" pluralizedItemName={i18n._(t`Users`)}
/>, />,
]} ]}
/> />

View File

@@ -95,7 +95,7 @@ function UserListItem({ user, isSelected, onSelect, detailUrl, i18n }) {
]} ]}
/> />
<DataListAction <DataListAction
aria-label="actions" aria-label={i18n._(t`actions`)}
aria-labelledby={labelId} aria-labelledby={labelId}
id={labelId} id={labelId}
> >