Update job template detail unit tests

This commit is contained in:
Marliana Lara
2020-01-23 13:59:20 -05:00
parent 6efa751157
commit afc1f85668
3 changed files with 128 additions and 139 deletions

View File

@@ -1,161 +1,141 @@
import React from 'react'; import React from 'react';
import { act } from 'react-dom/test-utils';
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers'; import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
import JobTemplateDetail, { _JobTemplateDetail } from './JobTemplateDetail'; import JobTemplateDetail from './JobTemplateDetail';
import { JobTemplatesAPI } from '@api'; import { JobTemplatesAPI } from '@api';
import mockTemplate from '../shared/data.job_template.json';
jest.mock('@api'); jest.mock('@api');
const mockInstanceGroups = {
count: 5,
data: {
results: [{ id: 1, name: 'IG1' }, { id: 2, name: 'IG2' }],
},
};
describe('<JobTemplateDetail />', () => { describe('<JobTemplateDetail />', () => {
const template = { let wrapper;
forks: 1,
host_config_key: 'ssh',
name: 'Temp 1',
job_type: 'run',
inventory: 1,
limit: '1',
project: 7,
playbook: '',
id: 1,
verbosity: 1,
summary_fields: {
user_capabilities: { edit: true },
created_by: { id: 1, username: 'Joe' },
modified_by: { id: 1, username: 'Joe' },
credentials: [
{ id: 1, kind: 'ssh', name: 'Credential 1' },
{ id: 2, kind: 'awx', name: 'Credential 2' },
],
inventory: { name: 'Inventory' },
project: { name: 'Project' },
},
created: '2020-04-25T01:23:45.678901Z',
modified: '2020-04-25T01:23:45.678901Z',
};
const mockInstanceGroups = { beforeEach(async () => {
count: 5,
data: {
results: [{ id: 1, name: 'IG1' }, { id: 2, name: 'IG2' }],
},
};
const readInstanceGroups = jest.spyOn(
_JobTemplateDetail.prototype,
'readInstanceGroups'
);
beforeEach(() => {
JobTemplatesAPI.readInstanceGroups.mockResolvedValue(mockInstanceGroups); JobTemplatesAPI.readInstanceGroups.mockResolvedValue(mockInstanceGroups);
await act(async () => {
wrapper = mountWithContexts(
<JobTemplateDetail template={mockTemplate} />
);
});
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
}); });
afterEach(() => { afterEach(() => {
jest.clearAllMocks(); jest.clearAllMocks();
}); });
test('Can load with missing summary fields', async () => { test('should render successfully with missing summary fields', async () => {
const mockTemplate = { ...template }; await act(async () => {
mockTemplate.summary_fields = { user_capabilities: {} }; wrapper = mountWithContexts(
<JobTemplateDetail
const wrapper = mountWithContexts( template={{
<JobTemplateDetail template={mockTemplate} /> ...mockTemplate,
); become_enabled: true,
summary_fields: { user_capabilities: {} },
}}
/>
);
});
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
await waitForElement( await waitForElement(
wrapper, wrapper,
'Detail[label="Description"]', 'Detail[label="Name"]',
el => el.length === 1 el => el.length === 1
); );
}); });
test('When component mounts API is called to get instance groups', async done => { test('should request instance groups from api', async () => {
const wrapper = mountWithContexts(
<JobTemplateDetail template={template} />
);
await waitForElement(
wrapper,
'JobTemplateDetail',
el => el.state('hasContentLoading') === true
);
expect(readInstanceGroups).toHaveBeenCalled();
await waitForElement(
wrapper,
'JobTemplateDetail',
el => el.state('hasContentLoading') === false
);
expect(JobTemplatesAPI.readInstanceGroups).toHaveBeenCalledTimes(1); expect(JobTemplatesAPI.readInstanceGroups).toHaveBeenCalledTimes(1);
done();
}); });
test('Edit button is absent when user does not have edit privilege', async done => { test('should hide edit button for users without edit permission', async () => {
const regularUser = { JobTemplatesAPI.readInstanceGroups.mockResolvedValue({ data: {} });
forks: 1, await act(async () => {
host_config_key: 'ssh', wrapper = mountWithContexts(
name: 'Temp 1', <JobTemplateDetail
job_tags: 'cookies,pizza', template={{
job_type: 'run', ...mockTemplate,
inventory: 1, diff_mode: true,
limit: '1', host_config_key: 'key',
project: 7, summary_fields: { user_capabilities: { edit: false } },
playbook: '', }}
id: 1, />
verbosity: 0, );
created_by: 'Alex',
skip_tags: 'coffe,tea',
summary_fields: {
user_capabilities: { edit: false },
created_by: { id: 1, username: 'Joe' },
modified_by: { id: 1, username: 'Joe' },
inventory: { name: 'Inventory' },
project: { name: 'Project' },
labels: { count: 1, results: [{ name: 'Label', id: 1 }] },
},
created: '2020-04-25T01:23:45.678901Z',
modified: '2020-04-25T01:23:45.678901Z',
};
const wrapper = mountWithContexts(
<JobTemplateDetail template={regularUser} />
);
const jobTemplateDetail = wrapper.find('JobTemplateDetail');
const editButton = jobTemplateDetail.find('button[aria-label="Edit"]');
jobTemplateDetail.setState({
instanceGroups: mockInstanceGroups,
hasContentLoading: false,
contentError: false,
}); });
expect(editButton.length).toBe(0); expect(wrapper.find('button[aria-label="Edit"]').length).toBe(0);
done();
}); });
test('should render CredentialChip', () => { test('should render credential chips', () => {
template.summary_fields.credentials = [{ id: 1, name: 'cred', kind: null }]; const chips = wrapper.find('CredentialChip');
const wrapper = mountWithContexts( expect(chips).toHaveLength(2);
<JobTemplateDetail template={template} /> chips.forEach((chip, id) => {
); expect(chip.prop('credential')).toEqual(
wrapper.find('JobTemplateDetail').setState({ mockTemplate.summary_fields.credentials[id]
instanceGroups: mockInstanceGroups, );
hasContentLoading: false,
contentError: false,
}); });
const chip = wrapper.find('CredentialChip');
expect(chip).toHaveLength(1);
expect(chip.prop('credential')).toEqual(
template.summary_fields.credentials[0]
);
}); });
test('should render SCM_Branch', async () => { test('should render SCM_Branch', async () => {
const mockTemplate = { ...template };
mockTemplate.scm_branch = 'Foo branch';
const wrapper = mountWithContexts(
<JobTemplateDetail template={mockTemplate} />
);
await waitForElement(
wrapper,
'JobTemplateDetail',
el => el.state('hasContentLoading') === false
);
const SCMBranch = wrapper.find('Detail[label="SCM Branch"]'); const SCMBranch = wrapper.find('Detail[label="SCM Branch"]');
expect(SCMBranch.prop('value')).toBe('Foo branch'); expect(SCMBranch.prop('value')).toBe('Foo branch');
}); });
test('should show content error for failed instance group fetch', async () => {
JobTemplatesAPI.readInstanceGroups.mockImplementationOnce(() =>
Promise.reject(new Error())
);
await act(async () => {
wrapper = mountWithContexts(
<JobTemplateDetail
template={{
...mockTemplate,
allow_simultaneous: true,
ask_inventory_on_launch: true,
summary_fields: {
inventory: {
kind: 'smart',
},
},
}}
/>
);
});
await waitForElement(wrapper, 'ContentError', el => el.length === 1);
});
test('expected api calls are made for delete', async () => {
await act(async () => {
wrapper.find('DeleteButton').invoke('onConfirm')();
});
expect(JobTemplatesAPI.destroy).toHaveBeenCalledTimes(1);
});
test('Error dialog shown for failed deletion', async () => {
JobTemplatesAPI.destroy.mockImplementationOnce(() =>
Promise.reject(new Error())
);
await act(async () => {
wrapper.find('DeleteButton').invoke('onConfirm')();
});
await waitForElement(
wrapper,
'Modal[title="Error!"]',
el => el.length === 1
);
await act(async () => {
wrapper.find('Modal[title="Error!"]').invoke('onClose')();
});
await waitForElement(
wrapper,
'Modal[title="Error!"]',
el => el.length === 0
);
});
}); });

View File

@@ -1,4 +1 @@
import JobTemplateDetail from './JobTemplateDetail'; export { default } from './JobTemplateDetail';
export { JobTemplateDetail as _JobTemplateDetail };
export default JobTemplateDetail;

View File

@@ -101,9 +101,14 @@
"copy": true "copy": true
}, },
"labels": { "labels": {
"count": 0, "count": 1,
"results": [] "results": [
}, {
"id": 91,
"name": "L_91o2"
}
]
},
"survey": { "survey": {
"title": "", "title": "",
"description": "" "description": ""
@@ -117,7 +122,14 @@
} }
], ],
"extra_credentials": [], "extra_credentials": [],
"credentials": [] "credentials": [
{
"id": 1, "kind": "ssh" , "name": "Credential 1"
},
{
"id": 2, "kind": "awx" , "name": "Credential 2"
}
]
}, },
"created": "2019-09-30T16:18:34.564820Z", "created": "2019-09-30T16:18:34.564820Z",
"modified": "2019-10-01T14:47:31.818431Z", "modified": "2019-10-01T14:47:31.818431Z",
@@ -127,17 +139,17 @@
"inventory": 1, "inventory": 1,
"project": 6, "project": 6,
"playbook": "ping.yml", "playbook": "ping.yml",
"scm_branch": "", "scm_branch": "Foo branch",
"forks": 0, "forks": 0,
"limit": "", "limit": "",
"verbosity": 0, "verbosity": 0,
"extra_vars": "", "extra_vars": "",
"job_tags": "", "job_tags": "T_100,T_200",
"force_handlers": false, "force_handlers": false,
"skip_tags": "", "skip_tags": "S_100,S_200",
"start_at_task": "", "start_at_task": "",
"timeout": 0, "timeout": 0,
"use_fact_cache": false, "use_fact_cache": true,
"last_job_run": "2019-10-01T14:34:35.142483Z", "last_job_run": "2019-10-01T14:34:35.142483Z",
"last_job_failed": false, "last_job_failed": false,
"next_job_run": null, "next_job_run": null,