mirror of
https://github.com/ansible/awx.git
synced 2026-05-17 06:17:36 -02:30
Merge pull request #7921 from mabashian/6172-schedule-detail-vars
Adds extra variables to schedule details Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
@@ -1,10 +1,15 @@
|
|||||||
import 'styled-components/macro';
|
import 'styled-components/macro';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { string, node, number } from 'prop-types';
|
import { node, number, oneOfType, shape, string } from 'prop-types';
|
||||||
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';
|
||||||
import { yamlToJson, jsonToYaml, isJson } from '../../util/yaml';
|
import {
|
||||||
|
yamlToJson,
|
||||||
|
jsonToYaml,
|
||||||
|
isJsonObject,
|
||||||
|
isJsonString,
|
||||||
|
} from '../../util/yaml';
|
||||||
import CodeMirrorInput from './CodeMirrorInput';
|
import CodeMirrorInput from './CodeMirrorInput';
|
||||||
import { JSON_MODE, YAML_MODE } from './constants';
|
import { JSON_MODE, YAML_MODE } from './constants';
|
||||||
|
|
||||||
@@ -15,7 +20,7 @@ function getValueAsMode(value, mode) {
|
|||||||
}
|
}
|
||||||
return '---';
|
return '---';
|
||||||
}
|
}
|
||||||
const modeMatches = isJson(value) === (mode === JSON_MODE);
|
const modeMatches = isJsonString(value) === (mode === JSON_MODE);
|
||||||
if (modeMatches) {
|
if (modeMatches) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@@ -23,12 +28,21 @@ function getValueAsMode(value, mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function VariablesDetail({ value, label, rows, fullHeight }) {
|
function VariablesDetail({ value, label, rows, fullHeight }) {
|
||||||
const [mode, setMode] = useState(isJson(value) ? JSON_MODE : YAML_MODE);
|
const [mode, setMode] = useState(
|
||||||
const [currentValue, setCurrentValue] = useState(value || '---');
|
isJsonObject(value) || isJsonString(value) ? JSON_MODE : YAML_MODE
|
||||||
|
);
|
||||||
|
const [currentValue, setCurrentValue] = useState(
|
||||||
|
isJsonObject(value) ? JSON.stringify(value, null, 2) : value || '---'
|
||||||
|
);
|
||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrentValue(getValueAsMode(value, mode));
|
setCurrentValue(
|
||||||
|
getValueAsMode(
|
||||||
|
isJsonObject(value) ? JSON.stringify(value, null, 2) : value,
|
||||||
|
mode
|
||||||
|
)
|
||||||
|
);
|
||||||
/* eslint-disable-next-line react-hooks/exhaustive-deps */
|
/* eslint-disable-next-line react-hooks/exhaustive-deps */
|
||||||
}, [value]);
|
}, [value]);
|
||||||
|
|
||||||
@@ -95,7 +109,7 @@ function VariablesDetail({ value, label, rows, fullHeight }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
VariablesDetail.propTypes = {
|
VariablesDetail.propTypes = {
|
||||||
value: string.isRequired,
|
value: oneOfType([shape({}), string]).isRequired,
|
||||||
label: node.isRequired,
|
label: node.isRequired,
|
||||||
rows: number,
|
rows: number,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import styled from 'styled-components';
|
|||||||
import { Split, SplitItem } from '@patternfly/react-core';
|
import { Split, SplitItem } from '@patternfly/react-core';
|
||||||
import { CheckboxField, FieldTooltip } from '../FormField';
|
import { CheckboxField, FieldTooltip } from '../FormField';
|
||||||
import MultiButtonToggle from '../MultiButtonToggle';
|
import MultiButtonToggle from '../MultiButtonToggle';
|
||||||
import { yamlToJson, jsonToYaml, isJson } from '../../util/yaml';
|
import { yamlToJson, jsonToYaml, isJsonString } from '../../util/yaml';
|
||||||
import CodeMirrorInput from './CodeMirrorInput';
|
import CodeMirrorInput from './CodeMirrorInput';
|
||||||
import { JSON_MODE, YAML_MODE } from './constants';
|
import { JSON_MODE, YAML_MODE } from './constants';
|
||||||
|
|
||||||
@@ -30,7 +30,9 @@ function VariablesField({
|
|||||||
tooltip,
|
tooltip,
|
||||||
}) {
|
}) {
|
||||||
const [field, meta, helpers] = useField(name);
|
const [field, meta, helpers] = useField(name);
|
||||||
const [mode, setMode] = useState(isJson(field.value) ? JSON_MODE : YAML_MODE);
|
const [mode, setMode] = useState(
|
||||||
|
isJsonString(field.value) ? JSON_MODE : YAML_MODE
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="pf-c-form__group">
|
<div className="pf-c-form__group">
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
|||||||
import { string, func, bool, number } from 'prop-types';
|
import { string, func, bool, number } from 'prop-types';
|
||||||
import { Split, SplitItem } from '@patternfly/react-core';
|
import { Split, SplitItem } from '@patternfly/react-core';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { yamlToJson, jsonToYaml, isJson } from '../../util/yaml';
|
import { yamlToJson, jsonToYaml, isJsonString } from '../../util/yaml';
|
||||||
import MultiButtonToggle from '../MultiButtonToggle';
|
import MultiButtonToggle from '../MultiButtonToggle';
|
||||||
import CodeMirrorInput from './CodeMirrorInput';
|
import CodeMirrorInput from './CodeMirrorInput';
|
||||||
import { JSON_MODE, YAML_MODE } from './constants';
|
import { JSON_MODE, YAML_MODE } from './constants';
|
||||||
@@ -18,11 +18,11 @@ const SplitItemRight = styled(SplitItem)`
|
|||||||
function VariablesInput(props) {
|
function VariablesInput(props) {
|
||||||
const { id, label, readOnly, rows, error, onError, className } = props;
|
const { id, label, readOnly, rows, error, onError, className } = props;
|
||||||
/* eslint-disable react/destructuring-assignment */
|
/* eslint-disable react/destructuring-assignment */
|
||||||
const defaultValue = isJson(props.value)
|
const defaultValue = isJsonString(props.value)
|
||||||
? formatJson(props.value)
|
? formatJson(props.value)
|
||||||
: props.value;
|
: props.value;
|
||||||
const [value, setValue] = useState(defaultValue);
|
const [value, setValue] = useState(defaultValue);
|
||||||
const [mode, setMode] = useState(isJson(value) ? JSON_MODE : YAML_MODE);
|
const [mode, setMode] = useState(isJsonString(value) ? JSON_MODE : YAML_MODE);
|
||||||
const isControlled = !!props.onChange;
|
const isControlled = !!props.onChange;
|
||||||
/* eslint-enable react/destructuring-assignment */
|
/* eslint-enable react/destructuring-assignment */
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ import {
|
|||||||
mountWithContexts,
|
mountWithContexts,
|
||||||
waitForElement,
|
waitForElement,
|
||||||
} from '../../../testUtils/enzymeHelpers';
|
} from '../../../testUtils/enzymeHelpers';
|
||||||
import { SchedulesAPI } from '../../api';
|
import { JobTemplatesAPI, SchedulesAPI } from '../../api';
|
||||||
import Schedule from './Schedule';
|
import Schedule from './Schedule';
|
||||||
|
|
||||||
|
jest.mock('../../api/models/JobTemplates');
|
||||||
jest.mock('../../api/models/Schedules');
|
jest.mock('../../api/models/Schedules');
|
||||||
|
jest.mock('../../api/models/WorkflowJobTemplates');
|
||||||
|
|
||||||
SchedulesAPI.readDetail.mockResolvedValue({
|
SchedulesAPI.readDetail.mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
@@ -62,6 +64,22 @@ SchedulesAPI.readCredentials.mockResolvedValue({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
JobTemplatesAPI.readLaunch.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
ask_credential_on_launch: false,
|
||||||
|
ask_diff_mode_on_launch: false,
|
||||||
|
ask_inventory_on_launch: false,
|
||||||
|
ask_job_type_on_launch: false,
|
||||||
|
ask_limit_on_launch: false,
|
||||||
|
ask_scm_branch_on_launch: false,
|
||||||
|
ask_skip_tags_on_launch: false,
|
||||||
|
ask_tags_on_launch: false,
|
||||||
|
ask_variables_on_launch: false,
|
||||||
|
ask_verbosity_on_launch: false,
|
||||||
|
survey_enabled: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
describe('<Schedule />', () => {
|
describe('<Schedule />', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
let history;
|
let history;
|
||||||
|
|||||||
@@ -17,10 +17,15 @@ import ScheduleOccurrences from '../ScheduleOccurrences';
|
|||||||
import ScheduleToggle from '../ScheduleToggle';
|
import ScheduleToggle from '../ScheduleToggle';
|
||||||
import { formatDateString } from '../../../util/dates';
|
import { formatDateString } from '../../../util/dates';
|
||||||
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||||
import { SchedulesAPI } from '../../../api';
|
import {
|
||||||
|
JobTemplatesAPI,
|
||||||
|
SchedulesAPI,
|
||||||
|
WorkflowJobTemplatesAPI,
|
||||||
|
} from '../../../api';
|
||||||
import DeleteButton from '../../DeleteButton';
|
import DeleteButton from '../../DeleteButton';
|
||||||
import ErrorDetail from '../../ErrorDetail';
|
import ErrorDetail from '../../ErrorDetail';
|
||||||
import ChipGroup from '../../ChipGroup';
|
import ChipGroup from '../../ChipGroup';
|
||||||
|
import { VariablesDetail } from '../../CodeMirrorInput';
|
||||||
|
|
||||||
const PromptTitle = styled(Title)`
|
const PromptTitle = styled(Title)`
|
||||||
--pf-c-title--m-md--FontWeight: 700;
|
--pf-c-title--m-md--FontWeight: 700;
|
||||||
@@ -35,9 +40,9 @@ function ScheduleDetail({ schedule, i18n }) {
|
|||||||
diff_mode,
|
diff_mode,
|
||||||
dtend,
|
dtend,
|
||||||
dtstart,
|
dtstart,
|
||||||
|
extra_data,
|
||||||
job_tags,
|
job_tags,
|
||||||
job_type,
|
job_type,
|
||||||
inventory,
|
|
||||||
limit,
|
limit,
|
||||||
modified,
|
modified,
|
||||||
name,
|
name,
|
||||||
@@ -67,20 +72,47 @@ function ScheduleDetail({ schedule, i18n }) {
|
|||||||
const { error, dismissError } = useDismissableError(deleteError);
|
const { error, dismissError } = useDismissableError(deleteError);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
result: [credentials, preview],
|
result: [credentials, preview, launchData],
|
||||||
isLoading,
|
isLoading,
|
||||||
error: readContentError,
|
error: readContentError,
|
||||||
request: fetchCredentialsAndPreview,
|
request: fetchCredentialsAndPreview,
|
||||||
} = useRequest(
|
} = useRequest(
|
||||||
useCallback(async () => {
|
useCallback(async () => {
|
||||||
const [{ data }, { data: schedulePreview }] = await Promise.all([
|
const promises = [
|
||||||
SchedulesAPI.readCredentials(id),
|
SchedulesAPI.readCredentials(id),
|
||||||
SchedulesAPI.createPreview({
|
SchedulesAPI.createPreview({
|
||||||
rrule,
|
rrule,
|
||||||
}),
|
}),
|
||||||
]);
|
];
|
||||||
return [data.results, schedulePreview];
|
|
||||||
}, [id, rrule]),
|
if (
|
||||||
|
schedule?.summary_fields?.unified_job_template?.unified_job_type ===
|
||||||
|
'job'
|
||||||
|
) {
|
||||||
|
promises.push(
|
||||||
|
JobTemplatesAPI.readLaunch(
|
||||||
|
schedule.summary_fields.unified_job_template.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else if (
|
||||||
|
schedule?.summary_fields?.unified_job_template?.unified_job_type ===
|
||||||
|
'workflow_job'
|
||||||
|
) {
|
||||||
|
promises.push(
|
||||||
|
WorkflowJobTemplatesAPI.readLaunch(
|
||||||
|
schedule.summary_fields.unified_job_template.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
promises.push(Promise.resolve());
|
||||||
|
}
|
||||||
|
|
||||||
|
const [{ data }, { data: schedulePreview }, launch] = await Promise.all(
|
||||||
|
promises
|
||||||
|
);
|
||||||
|
|
||||||
|
return [data.results, schedulePreview, launch?.data];
|
||||||
|
}, [id, schedule, rrule]),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -93,15 +125,33 @@ function ScheduleDetail({ schedule, i18n }) {
|
|||||||
rule.options.freq === RRule.MINUTELY && dtstart === dtend
|
rule.options.freq === RRule.MINUTELY && dtstart === dtend
|
||||||
? i18n._(t`None (Run Once)`)
|
? i18n._(t`None (Run Once)`)
|
||||||
: rule.toText().replace(/^\w/, c => c.toUpperCase());
|
: rule.toText().replace(/^\w/, c => c.toUpperCase());
|
||||||
|
|
||||||
|
const {
|
||||||
|
ask_credential_on_launch,
|
||||||
|
ask_diff_mode_on_launch,
|
||||||
|
ask_inventory_on_launch,
|
||||||
|
ask_job_type_on_launch,
|
||||||
|
ask_limit_on_launch,
|
||||||
|
ask_scm_branch_on_launch,
|
||||||
|
ask_skip_tags_on_launch,
|
||||||
|
ask_tags_on_launch,
|
||||||
|
ask_variables_on_launch,
|
||||||
|
ask_verbosity_on_launch,
|
||||||
|
survey_enabled,
|
||||||
|
} = launchData || {};
|
||||||
|
|
||||||
const showPromptedFields =
|
const showPromptedFields =
|
||||||
(credentials && credentials.length > 0) ||
|
ask_credential_on_launch ||
|
||||||
job_type ||
|
ask_diff_mode_on_launch ||
|
||||||
(inventory && summary_fields.inventory) ||
|
ask_inventory_on_launch ||
|
||||||
scm_branch ||
|
ask_job_type_on_launch ||
|
||||||
limit ||
|
ask_limit_on_launch ||
|
||||||
typeof diff_mode === 'boolean' ||
|
ask_scm_branch_on_launch ||
|
||||||
(job_tags && job_tags.length > 0) ||
|
ask_skip_tags_on_launch ||
|
||||||
(skip_tags && skip_tags.length > 0);
|
ask_tags_on_launch ||
|
||||||
|
ask_variables_on_launch ||
|
||||||
|
ask_verbosity_on_launch ||
|
||||||
|
survey_enabled;
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <ContentLoading />;
|
return <ContentLoading />;
|
||||||
@@ -144,8 +194,10 @@ function ScheduleDetail({ schedule, i18n }) {
|
|||||||
<PromptTitle headingLevel="h2">
|
<PromptTitle headingLevel="h2">
|
||||||
{i18n._(t`Prompted Fields`)}
|
{i18n._(t`Prompted Fields`)}
|
||||||
</PromptTitle>
|
</PromptTitle>
|
||||||
<Detail label={i18n._(t`Job Type`)} value={job_type} />
|
{ask_job_type_on_launch && (
|
||||||
{inventory && summary_fields.inventory && (
|
<Detail label={i18n._(t`Job Type`)} value={job_type} />
|
||||||
|
)}
|
||||||
|
{ask_inventory_on_launch && (
|
||||||
<Detail
|
<Detail
|
||||||
label={i18n._(t`Inventory`)}
|
label={i18n._(t`Inventory`)}
|
||||||
value={
|
value={
|
||||||
@@ -161,18 +213,22 @@ function ScheduleDetail({ schedule, i18n }) {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Detail
|
{ask_scm_branch_on_launch && (
|
||||||
label={i18n._(t`Source Control Branch`)}
|
<Detail
|
||||||
value={scm_branch}
|
label={i18n._(t`Source Control Branch`)}
|
||||||
/>
|
value={scm_branch}
|
||||||
<Detail label={i18n._(t`Limit`)} value={limit} />
|
/>
|
||||||
{typeof diff_mode === 'boolean' && (
|
)}
|
||||||
|
{ask_limit_on_launch && (
|
||||||
|
<Detail label={i18n._(t`Limit`)} value={limit} />
|
||||||
|
)}
|
||||||
|
{ask_diff_mode_on_launch && typeof diff_mode === 'boolean' && (
|
||||||
<Detail
|
<Detail
|
||||||
label={i18n._(t`Show Changes`)}
|
label={i18n._(t`Show Changes`)}
|
||||||
value={diff_mode ? 'On' : 'Off'}
|
value={diff_mode ? 'On' : 'Off'}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{credentials && credentials.length > 0 && (
|
{ask_credential_on_launch && (
|
||||||
<Detail
|
<Detail
|
||||||
fullWidth
|
fullWidth
|
||||||
label={i18n._(t`Credentials`)}
|
label={i18n._(t`Credentials`)}
|
||||||
@@ -185,7 +241,7 @@ function ScheduleDetail({ schedule, i18n }) {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{job_tags && job_tags.length > 0 && (
|
{ask_tags_on_launch && job_tags && job_tags.length > 0 && (
|
||||||
<Detail
|
<Detail
|
||||||
fullWidth
|
fullWidth
|
||||||
label={i18n._(t`Job Tags`)}
|
label={i18n._(t`Job Tags`)}
|
||||||
@@ -203,7 +259,7 @@ function ScheduleDetail({ schedule, i18n }) {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{skip_tags && skip_tags.length > 0 && (
|
{ask_skip_tags_on_launch && skip_tags && skip_tags.length > 0 && (
|
||||||
<Detail
|
<Detail
|
||||||
fullWidth
|
fullWidth
|
||||||
label={i18n._(t`Skip Tags`)}
|
label={i18n._(t`Skip Tags`)}
|
||||||
@@ -221,6 +277,13 @@ function ScheduleDetail({ schedule, i18n }) {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{(ask_variables_on_launch || survey_enabled) && (
|
||||||
|
<VariablesDetail
|
||||||
|
value={extra_data}
|
||||||
|
rows={4}
|
||||||
|
label={i18n._(t`Variables`)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</DetailList>
|
</DetailList>
|
||||||
|
|||||||
@@ -2,14 +2,48 @@ import React from 'react';
|
|||||||
import { Route } from 'react-router-dom';
|
import { Route } from 'react-router-dom';
|
||||||
import { createMemoryHistory } from 'history';
|
import { createMemoryHistory } from 'history';
|
||||||
import { act } from 'react-dom/test-utils';
|
import { act } from 'react-dom/test-utils';
|
||||||
import { SchedulesAPI } from '../../../api';
|
import { SchedulesAPI, JobTemplatesAPI } from '../../../api';
|
||||||
import {
|
import {
|
||||||
mountWithContexts,
|
mountWithContexts,
|
||||||
waitForElement,
|
waitForElement,
|
||||||
} from '../../../../testUtils/enzymeHelpers';
|
} from '../../../../testUtils/enzymeHelpers';
|
||||||
import ScheduleDetail from './ScheduleDetail';
|
import ScheduleDetail from './ScheduleDetail';
|
||||||
|
|
||||||
|
jest.mock('../../../api/models/JobTemplates');
|
||||||
jest.mock('../../../api/models/Schedules');
|
jest.mock('../../../api/models/Schedules');
|
||||||
|
jest.mock('../../../api/models/WorkflowJobTemplates');
|
||||||
|
|
||||||
|
const allPrompts = {
|
||||||
|
data: {
|
||||||
|
ask_credential_on_launch: true,
|
||||||
|
ask_diff_mode_on_launch: true,
|
||||||
|
ask_inventory_on_launch: true,
|
||||||
|
ask_job_type_on_launch: true,
|
||||||
|
ask_limit_on_launch: true,
|
||||||
|
ask_scm_branch_on_launch: true,
|
||||||
|
ask_skip_tags_on_launch: true,
|
||||||
|
ask_tags_on_launch: true,
|
||||||
|
ask_variables_on_launch: true,
|
||||||
|
ask_verbosity_on_launch: true,
|
||||||
|
survey_enabled: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const noPrompts = {
|
||||||
|
data: {
|
||||||
|
ask_credential_on_launch: false,
|
||||||
|
ask_diff_mode_on_launch: false,
|
||||||
|
ask_inventory_on_launch: false,
|
||||||
|
ask_job_type_on_launch: false,
|
||||||
|
ask_limit_on_launch: false,
|
||||||
|
ask_scm_branch_on_launch: false,
|
||||||
|
ask_skip_tags_on_launch: false,
|
||||||
|
ask_tags_on_launch: false,
|
||||||
|
ask_variables_on_launch: false,
|
||||||
|
ask_verbosity_on_launch: false,
|
||||||
|
survey_enabled: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const schedule = {
|
const schedule = {
|
||||||
url: '/api/v2/schedules/1',
|
url: '/api/v2/schedules/1',
|
||||||
@@ -53,6 +87,7 @@ const schedule = {
|
|||||||
dtstart: '2020-03-16T04:00:00Z',
|
dtstart: '2020-03-16T04:00:00Z',
|
||||||
dtend: '2020-07-06T04:00:00Z',
|
dtend: '2020-07-06T04:00:00Z',
|
||||||
next_run: '2020-03-16T04:00:00Z',
|
next_run: '2020-03-16T04:00:00Z',
|
||||||
|
extra_data: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
SchedulesAPI.createPreview.mockResolvedValue({
|
SchedulesAPI.createPreview.mockResolvedValue({
|
||||||
@@ -79,6 +114,7 @@ describe('<ScheduleDetail />', () => {
|
|||||||
results: [],
|
results: [],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
JobTemplatesAPI.readLaunch.mockResolvedValueOnce(noPrompts);
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper = mountWithContexts(
|
wrapper = mountWithContexts(
|
||||||
<Route
|
<Route
|
||||||
@@ -134,6 +170,7 @@ describe('<ScheduleDetail />', () => {
|
|||||||
expect(wrapper.find('Detail[label="Credentials"]').length).toBe(0);
|
expect(wrapper.find('Detail[label="Credentials"]').length).toBe(0);
|
||||||
expect(wrapper.find('Detail[label="Job Tags"]').length).toBe(0);
|
expect(wrapper.find('Detail[label="Job Tags"]').length).toBe(0);
|
||||||
expect(wrapper.find('Detail[label="Skip Tags"]').length).toBe(0);
|
expect(wrapper.find('Detail[label="Skip Tags"]').length).toBe(0);
|
||||||
|
expect(wrapper.find('VariablesDetail').length).toBe(0);
|
||||||
});
|
});
|
||||||
test('details should render with the proper values with prompts', async () => {
|
test('details should render with the proper values with prompts', async () => {
|
||||||
SchedulesAPI.readCredentials.mockResolvedValue({
|
SchedulesAPI.readCredentials.mockResolvedValue({
|
||||||
@@ -151,6 +188,7 @@ describe('<ScheduleDetail />', () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
JobTemplatesAPI.readLaunch.mockResolvedValueOnce(allPrompts);
|
||||||
const scheduleWithPrompts = {
|
const scheduleWithPrompts = {
|
||||||
...schedule,
|
...schedule,
|
||||||
job_type: 'run',
|
job_type: 'run',
|
||||||
@@ -161,6 +199,7 @@ describe('<ScheduleDetail />', () => {
|
|||||||
limit: 'localhost',
|
limit: 'localhost',
|
||||||
diff_mode: true,
|
diff_mode: true,
|
||||||
verbosity: 1,
|
verbosity: 1,
|
||||||
|
extra_data: { foo: 'fii' },
|
||||||
};
|
};
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper = mountWithContexts(
|
wrapper = mountWithContexts(
|
||||||
@@ -182,7 +221,6 @@ describe('<ScheduleDetail />', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||||
// await waitForElement(wrapper, 'Title', el => el.length > 0);
|
|
||||||
expect(
|
expect(
|
||||||
wrapper
|
wrapper
|
||||||
.find('Detail[label="Name"]')
|
.find('Detail[label="Name"]')
|
||||||
@@ -231,6 +269,7 @@ describe('<ScheduleDetail />', () => {
|
|||||||
expect(wrapper.find('Detail[label="Credentials"]').length).toBe(1);
|
expect(wrapper.find('Detail[label="Credentials"]').length).toBe(1);
|
||||||
expect(wrapper.find('Detail[label="Job Tags"]').length).toBe(1);
|
expect(wrapper.find('Detail[label="Job Tags"]').length).toBe(1);
|
||||||
expect(wrapper.find('Detail[label="Skip Tags"]').length).toBe(1);
|
expect(wrapper.find('Detail[label="Skip Tags"]').length).toBe(1);
|
||||||
|
expect(wrapper.find('VariablesDetail').length).toBe(1);
|
||||||
});
|
});
|
||||||
test('error shown when error encountered fetching credentials', async () => {
|
test('error shown when error encountered fetching credentials', async () => {
|
||||||
SchedulesAPI.readCredentials.mockRejectedValueOnce(
|
SchedulesAPI.readCredentials.mockRejectedValueOnce(
|
||||||
@@ -245,6 +284,7 @@ describe('<ScheduleDetail />', () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
JobTemplatesAPI.readLaunch.mockResolvedValueOnce(noPrompts);
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper = mountWithContexts(
|
wrapper = mountWithContexts(
|
||||||
<Route
|
<Route
|
||||||
@@ -274,6 +314,7 @@ describe('<ScheduleDetail />', () => {
|
|||||||
results: [],
|
results: [],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
JobTemplatesAPI.readLaunch.mockResolvedValueOnce(noPrompts);
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper = mountWithContexts(
|
wrapper = mountWithContexts(
|
||||||
<Route
|
<Route
|
||||||
@@ -313,6 +354,7 @@ describe('<ScheduleDetail />', () => {
|
|||||||
results: [],
|
results: [],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
JobTemplatesAPI.readLaunch.mockResolvedValueOnce(noPrompts);
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper = mountWithContexts(
|
wrapper = mountWithContexts(
|
||||||
<Route
|
<Route
|
||||||
|
|||||||
@@ -22,7 +22,11 @@ export function jsonToYaml(jsonString) {
|
|||||||
return yaml.safeDump(value);
|
return yaml.safeDump(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isJson(jsonString) {
|
export function isJsonObject(value) {
|
||||||
|
return typeof value === 'object' && value !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isJsonString(jsonString) {
|
||||||
if (typeof jsonString !== 'string') {
|
if (typeof jsonString !== 'string') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -40,7 +44,7 @@ export function parseVariableField(variableField) {
|
|||||||
if (variableField === '---' || variableField === '{}') {
|
if (variableField === '---' || variableField === '{}') {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (!isJson(variableField)) {
|
if (!isJsonString(variableField)) {
|
||||||
variableField = yamlToJson(variableField);
|
variableField = yamlToJson(variableField);
|
||||||
}
|
}
|
||||||
variableField = JSON.parse(variableField);
|
variableField = JSON.parse(variableField);
|
||||||
|
|||||||
Reference in New Issue
Block a user