mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 01:57:35 -03:30
Merge pull request #9544 from AlexSCorey/9485-9319-7516-fix
Fixes Several Bugs SUMMARY This address #9485 (Job template project field validate), #9319 (Job Details view only would show job type run, even if it was a job type check, #7516 (changes the Completed Jobs tab for a JT or WFJT to show Jobs since it show completed and pending/running jobs). ISSUE TYPE Bugfix Pull Request COMPONENT NAME UI Reviewed-by: Jake McDermott <yo@jakemcdermott.me> Reviewed-by: John Mitchell <None> Reviewed-by: Tiago Góes <tiago.goes2009@gmail.com>
This commit is contained in:
commit
7d190da1c4
@ -94,4 +94,56 @@ describe('<ProjectLookup />', () => {
|
||||
expect(wrapper.find('ProjectLookup')).toHaveLength(1);
|
||||
expect(wrapper.find('Lookup').prop('isDisabled')).toBe(true);
|
||||
});
|
||||
|
||||
test('should not show helper text', async () => {
|
||||
let wrapper;
|
||||
|
||||
ProjectsAPI.readOptions.mockReturnValue({
|
||||
data: {
|
||||
actions: {
|
||||
GET: {},
|
||||
},
|
||||
related_search_fields: [],
|
||||
},
|
||||
});
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<ProjectLookup
|
||||
isValid
|
||||
helperTextInvalid="select value"
|
||||
onChange={() => {}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.find('div#project-helper').length).toBe(0);
|
||||
});
|
||||
|
||||
test('should not show helper text', async () => {
|
||||
let wrapper;
|
||||
|
||||
ProjectsAPI.readOptions.mockReturnValue({
|
||||
data: {
|
||||
actions: {
|
||||
GET: {},
|
||||
},
|
||||
related_search_fields: [],
|
||||
},
|
||||
});
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<ProjectLookup
|
||||
isValid={false}
|
||||
helperTextInvalid="select value"
|
||||
onChange={() => {}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.find('div#project-helper').text('helperTextInvalid')).toBe(
|
||||
'select value'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -64,8 +64,8 @@ function Host({ i18n, setBreadcrumb }) {
|
||||
id: 2,
|
||||
},
|
||||
{
|
||||
name: i18n._(t`Completed Jobs`),
|
||||
link: `${match.url}/completed_jobs`,
|
||||
name: i18n._(t`Jobs`),
|
||||
link: `${match.url}/jobs`,
|
||||
id: 3,
|
||||
},
|
||||
];
|
||||
@ -122,7 +122,7 @@ function Host({ i18n, setBreadcrumb }) {
|
||||
<Route path="/hosts/:id/groups" key="groups">
|
||||
<HostGroups host={host} />
|
||||
</Route>,
|
||||
<Route path="/hosts/:id/completed_jobs" key="completed-jobs">
|
||||
<Route path="/hosts/:id/jobs" key="jobs">
|
||||
<JobList defaultParams={{ job__hosts: host.id }} />
|
||||
</Route>,
|
||||
]}
|
||||
|
||||
@ -29,7 +29,7 @@ function Hosts({ i18n }) {
|
||||
[`/hosts/${host.id}/details`]: i18n._(t`Details`),
|
||||
[`/hosts/${host.id}/facts`]: i18n._(t`Facts`),
|
||||
[`/hosts/${host.id}/groups`]: i18n._(t`Groups`),
|
||||
[`/hosts/${host.id}/completed_jobs`]: i18n._(t`Completed Jobs`),
|
||||
[`/hosts/${host.id}/jobs`]: i18n._(t`Jobs`),
|
||||
});
|
||||
},
|
||||
[i18n]
|
||||
|
||||
@ -56,7 +56,7 @@ function Inventories({ i18n }) {
|
||||
...initScreenHeader.current,
|
||||
[inventoryPath]: `${inventory.name}`,
|
||||
[`${inventoryPath}/access`]: i18n._(t`Access`),
|
||||
[`${inventoryPath}/completed_jobs`]: i18n._(t`Completed jobs`),
|
||||
[`${inventoryPath}/jobs`]: i18n._(t`Jobs`),
|
||||
[`${inventoryPath}/details`]: i18n._(t`Details`),
|
||||
[`${inventoryPath}/edit`]: i18n._(t`Edit details`),
|
||||
|
||||
@ -69,9 +69,7 @@ function Inventories({ i18n }) {
|
||||
[`${inventoryHostsPath}/${nestedObject?.id}/details`]: i18n._(
|
||||
t`Host details`
|
||||
),
|
||||
[`${inventoryHostsPath}/${nestedObject?.id}/completed_jobs`]: i18n._(
|
||||
t`Completed jobs`
|
||||
),
|
||||
[`${inventoryHostsPath}/${nestedObject?.id}/jobs`]: i18n._(t`Jobs`),
|
||||
[`${inventoryHostsPath}/${nestedObject?.id}/facts`]: i18n._(t`Facts`),
|
||||
[`${inventoryHostsPath}/${nestedObject?.id}/groups`]: i18n._(t`Groups`),
|
||||
|
||||
|
||||
@ -65,8 +65,8 @@ function Inventory({ i18n, setBreadcrumb }) {
|
||||
{ name: i18n._(t`Hosts`), link: `${match.url}/hosts`, id: 3 },
|
||||
{ name: i18n._(t`Sources`), link: `${match.url}/sources`, id: 4 },
|
||||
{
|
||||
name: i18n._(t`Completed Jobs`),
|
||||
link: `${match.url}/completed_jobs`,
|
||||
name: i18n._(t`Jobs`),
|
||||
link: `${match.url}/jobs`,
|
||||
id: 5,
|
||||
},
|
||||
];
|
||||
@ -160,10 +160,7 @@ function Inventory({ i18n, setBreadcrumb }) {
|
||||
setBreadcrumb={setBreadcrumb}
|
||||
/>
|
||||
</Route>,
|
||||
<Route
|
||||
path="/inventories/inventory/:id/completed_jobs"
|
||||
key="completed_jobs"
|
||||
>
|
||||
<Route path="/inventories/inventory/:id/jobs" key="jobs">
|
||||
<JobList
|
||||
defaultParams={{
|
||||
or__job__inventory: inventory.id,
|
||||
|
||||
@ -85,8 +85,8 @@ function InventoryHost({ i18n, setBreadcrumb, inventory }) {
|
||||
id: 3,
|
||||
},
|
||||
{
|
||||
name: i18n._(t`Completed Jobs`),
|
||||
link: `${match.url}/completed_jobs`,
|
||||
name: i18n._(t`Jobs`),
|
||||
link: `${match.url}/jobs`,
|
||||
id: 4,
|
||||
},
|
||||
];
|
||||
@ -151,8 +151,8 @@ function InventoryHost({ i18n, setBreadcrumb, inventory }) {
|
||||
<InventoryHostGroups />
|
||||
</Route>
|
||||
<Route
|
||||
key="completed-jobs"
|
||||
path="/inventories/inventory/:id/hosts/:hostId/completed_jobs"
|
||||
key="jobs"
|
||||
path="/inventories/inventory/:id/hosts/:hostId/jobs"
|
||||
>
|
||||
<JobList defaultParams={{ job__hosts: host.id }} />
|
||||
</Route>
|
||||
|
||||
@ -49,7 +49,7 @@ describe('<InventoryHost />', () => {
|
||||
'Details',
|
||||
'Facts',
|
||||
'Groups',
|
||||
'Completed Jobs',
|
||||
'Jobs',
|
||||
];
|
||||
wrapper.find('RoutedTabs li').forEach((tab, index) => {
|
||||
expect(tab.text()).toEqual(expectedTabs[index]);
|
||||
|
||||
@ -70,8 +70,8 @@ function SmartInventory({ i18n, setBreadcrumb }) {
|
||||
{ name: i18n._(t`Access`), link: `${match.url}/access`, id: 1 },
|
||||
{ name: i18n._(t`Hosts`), link: `${match.url}/hosts`, id: 2 },
|
||||
{
|
||||
name: i18n._(t`Completed jobs`),
|
||||
link: `${match.url}/completed_jobs`,
|
||||
name: i18n._(t`Jobs`),
|
||||
link: `${match.url}/jobs`,
|
||||
id: 3,
|
||||
},
|
||||
];
|
||||
@ -150,10 +150,7 @@ function SmartInventory({ i18n, setBreadcrumb }) {
|
||||
setBreadcrumb={setBreadcrumb}
|
||||
/>
|
||||
</Route>,
|
||||
<Route
|
||||
key="completed_jobs"
|
||||
path="/inventories/smart_inventory/:id/completed_jobs"
|
||||
>
|
||||
<Route key="jobs" path="/inventories/smart_inventory/:id/jobs">
|
||||
<JobList
|
||||
defaultParams={{
|
||||
or__job__inventory: inventory.id,
|
||||
|
||||
@ -80,7 +80,10 @@ function JobDetail({ job, i18n }) {
|
||||
const jobTypes = {
|
||||
project_update: i18n._(t`Source Control Update`),
|
||||
inventory_update: i18n._(t`Inventory Sync`),
|
||||
job: i18n._(t`Playbook Run`),
|
||||
job:
|
||||
job.job_type === 'check'
|
||||
? i18n._(t`Playbook Check`)
|
||||
: i18n._(t`Playbook Run`),
|
||||
ad_hoc_command: i18n._(t`Command`),
|
||||
management_job: i18n._(t`Management Job`),
|
||||
workflow_job: i18n._(t`Workflow Job`),
|
||||
|
||||
@ -10,16 +10,15 @@ jest.mock('../../../api');
|
||||
|
||||
describe('<JobDetail />', () => {
|
||||
let wrapper;
|
||||
function assertDetail(label, value) {
|
||||
expect(wrapper.find(`Detail[label="${label}"] dt`).text()).toBe(label);
|
||||
expect(wrapper.find(`Detail[label="${label}"] dd`).text()).toBe(value);
|
||||
}
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('should display details', () => {
|
||||
function assertDetail(label, value) {
|
||||
expect(wrapper.find(`Detail[label="${label}"] dt`).text()).toBe(label);
|
||||
expect(wrapper.find(`Detail[label="${label}"] dd`).text()).toBe(value);
|
||||
}
|
||||
|
||||
wrapper = mountWithContexts(
|
||||
<JobDetail
|
||||
job={{
|
||||
@ -170,4 +169,15 @@ describe('<JobDetail />', () => {
|
||||
assertMissingDetail('Project');
|
||||
assertMissingDetail('Inventory');
|
||||
});
|
||||
test('should display Playbook Check detail', () => {
|
||||
wrapper = mountWithContexts(
|
||||
<JobDetail
|
||||
job={{
|
||||
...mockJobData,
|
||||
job_type: 'check',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
assertDetail('Job Type', 'Playbook Check');
|
||||
});
|
||||
});
|
||||
|
||||
@ -161,8 +161,8 @@ function Template({ i18n, setBreadcrumb }) {
|
||||
|
||||
tabsArray.push(
|
||||
{
|
||||
name: i18n._(t`Completed Jobs`),
|
||||
link: `${match.url}/completed_jobs`,
|
||||
name: i18n._(t`Jobs`),
|
||||
link: `${match.url}/jobs`,
|
||||
},
|
||||
{
|
||||
name: canAddAndEditSurvey ? i18n._(t`Survey`) : i18n._(t`View Survey`),
|
||||
@ -246,7 +246,7 @@ function Template({ i18n, setBreadcrumb }) {
|
||||
/>
|
||||
</Route>
|
||||
)}
|
||||
<Route path="/templates/:templateType/:id/completed_jobs">
|
||||
<Route path="/templates/:templateType/:id/jobs">
|
||||
<JobList defaultParams={{ job__job_template: template.id }} />
|
||||
</Route>
|
||||
<Route path="/templates/:templateType/:id/survey">
|
||||
|
||||
@ -45,7 +45,7 @@ function Templates({ i18n }) {
|
||||
[`${templatePath}/edit`]: i18n._(t`Edit Details`),
|
||||
[`${templatePath}/access`]: i18n._(t`Access`),
|
||||
[`${templatePath}/notifications`]: i18n._(t`Notifications`),
|
||||
[`${templatePath}/completed_jobs`]: i18n._(t`Completed Jobs`),
|
||||
[`${templatePath}/jobs`]: i18n._(t`Jobs`),
|
||||
[surveyPath]: i18n._(t`Survey`),
|
||||
[`${surveyPath}/add`]: i18n._(t`Add Question`),
|
||||
[`${surveyPath}/edit`]: i18n._(t`Edit Question`),
|
||||
|
||||
@ -142,8 +142,8 @@ function WorkflowJobTemplate({ i18n, setBreadcrumb }) {
|
||||
link: `${match.url}/visualizer`,
|
||||
},
|
||||
{
|
||||
name: i18n._(t`Completed Jobs`),
|
||||
link: `${match.url}/completed_jobs`,
|
||||
name: i18n._(t`Jobs`),
|
||||
link: `${match.url}/jobs`,
|
||||
},
|
||||
{
|
||||
name: canAddAndEditSurvey ? i18n._(t`Survey`) : i18n._(t`View Survey`),
|
||||
@ -253,7 +253,7 @@ function WorkflowJobTemplate({ i18n, setBreadcrumb }) {
|
||||
</Route>
|
||||
)}
|
||||
{template?.id && (
|
||||
<Route path="/templates/:templateType/:id/completed_jobs">
|
||||
<Route path="/templates/:templateType/:id/jobs">
|
||||
<JobList
|
||||
defaultParams={{
|
||||
workflow_job__workflow_job_template: template.id,
|
||||
|
||||
@ -154,7 +154,7 @@ function JobTemplateForm({
|
||||
|
||||
const handleProjectUpdate = useCallback(
|
||||
value => {
|
||||
setFieldValue('playbook', 0);
|
||||
setFieldValue('playbook', '');
|
||||
setFieldValue('scm_branch', '');
|
||||
setFieldValue('project', value);
|
||||
},
|
||||
@ -271,7 +271,9 @@ function JobTemplateForm({
|
||||
onBlur={() => projectHelpers.setTouched()}
|
||||
tooltip={i18n._(t`Select the project containing the playbook
|
||||
you want this job to execute.`)}
|
||||
isValid={!projectMeta.touched || !projectMeta.error}
|
||||
isValid={
|
||||
!projectMeta.touched || !projectMeta.error || projectField.value
|
||||
}
|
||||
helperTextInvalid={projectMeta.error}
|
||||
onChange={handleProjectUpdate}
|
||||
required
|
||||
|
||||
@ -58,6 +58,7 @@ function PlaybookSelect({
|
||||
placeholderText={i18n._(t`Select a playbook`)}
|
||||
isCreateable={false}
|
||||
onSelect={(event, value) => {
|
||||
setIsOpen(false);
|
||||
onChange(value);
|
||||
}}
|
||||
id="template-playbook"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user