Merge pull request #7974 from AlexSCorey/6561-WFJTDeetsNotLoad

Adds fix to load template details 

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
softwarefactory-project-zuul[bot]
2020-09-04 20:16:30 +00:00
committed by GitHub
7 changed files with 132 additions and 17 deletions

View File

@@ -24,6 +24,10 @@ class JobTemplates extends SchedulesMixin(
return this.http.post(`${this.baseUrl}${id}/launch/`, data); return this.http.post(`${this.baseUrl}${id}/launch/`, data);
} }
readTemplateOptions(id) {
return this.http.options(`${this.baseUrl}/${id}/`);
}
readLaunch(id) { readLaunch(id) {
return this.http.get(`${this.baseUrl}${id}/launch/`); return this.http.get(`${this.baseUrl}${id}/launch/`);
} }

View File

@@ -12,6 +12,10 @@ class WorkflowJobTemplates extends SchedulesMixin(NotificationsMixin(Base)) {
return this.http.get(`${this.baseUrl}${id}/webhook_key/`); return this.http.get(`${this.baseUrl}${id}/webhook_key/`);
} }
readWorkflowJobTemplateOptions(id) {
return this.http.options(`${this.baseUrl}/${id}/`);
}
updateWebhookKey(id) { updateWebhookKey(id) {
return this.http.post(`${this.baseUrl}${id}/webhook_key/`); return this.http.post(`${this.baseUrl}${id}/webhook_key/`);
} }

View File

@@ -36,18 +36,23 @@ function Template({ i18n, me, setBreadcrumb }) {
request: loadTemplateAndRoles, request: loadTemplateAndRoles,
} = useRequest( } = useRequest(
useCallback(async () => { useCallback(async () => {
const [{ data }, notifAdminRes] = await Promise.all([ const [{ data }, actions, notifAdminRes] = await Promise.all([
JobTemplatesAPI.readDetail(templateId), JobTemplatesAPI.readDetail(templateId),
JobTemplatesAPI.readTemplateOptions(templateId),
OrganizationsAPI.read({ OrganizationsAPI.read({
page_size: 1, page_size: 1,
role_level: 'notification_admin_role', role_level: 'notification_admin_role',
}), }),
]); ]);
if (data.webhook_service && data?.related?.webhook_key) {
const { if (actions.data.actions.PUT) {
data: { webhook_key }, if (data.webhook_service && data?.related?.webhook_key) {
} = await JobTemplatesAPI.readWebhookKey(templateId); const {
data.webhook_key = webhook_key; data: { webhook_key },
} = await JobTemplatesAPI.readWebhookKey(templateId);
data.webhook_key = webhook_key;
}
} }
setBreadcrumb(data); setBreadcrumb(data);

View File

@@ -18,11 +18,16 @@ const mockMe = {
is_system_auditor: false, is_system_auditor: false,
}; };
describe('<Template />', () => { describe('<Template />', () => {
let wrapper;
beforeEach(() => { beforeEach(() => {
JobTemplatesAPI.readDetail.mockResolvedValue({ JobTemplatesAPI.readDetail.mockResolvedValue({
data: mockJobTemplateData, data: mockJobTemplateData,
}); });
JobTemplatesAPI.readTemplateOptions.mockResolvedValue({
data: {
actions: { PUT: true },
},
});
OrganizationsAPI.read.mockResolvedValue({ OrganizationsAPI.read.mockResolvedValue({
data: { data: {
count: 1, count: 1,
@@ -35,21 +40,33 @@ describe('<Template />', () => {
], ],
}, },
}); });
JobTemplatesAPI.readWebhookKey.mockResolvedValue({
data: {
webhook_key: 'key',
},
});
});
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
}); });
test('initially renders succesfully', async () => { test('initially renders succesfully', async () => {
await act(async () => { await act(async () => {
mountWithContexts(<Template setBreadcrumb={() => {}} me={mockMe} />); wrapper = mountWithContexts(
<Template setBreadcrumb={() => {}} me={mockMe} />
);
}); });
}); });
test('When component mounts API is called and the response is put in state', async () => { test('When component mounts API is called and the response is put in state', async () => {
await act(async () => { await act(async () => {
mountWithContexts(<Template setBreadcrumb={() => {}} me={mockMe} />); wrapper = mountWithContexts(
<Template setBreadcrumb={() => {}} me={mockMe} />
);
}); });
expect(JobTemplatesAPI.readDetail).toBeCalled(); expect(JobTemplatesAPI.readDetail).toBeCalled();
expect(OrganizationsAPI.read).toBeCalled(); expect(OrganizationsAPI.read).toBeCalled();
}); });
test('notifications tab shown for admins', async done => { test('notifications tab shown for admins', async done => {
let wrapper;
await act(async () => { await act(async () => {
wrapper = mountWithContexts( wrapper = mountWithContexts(
<Template setBreadcrumb={() => {}} me={mockMe} /> <Template setBreadcrumb={() => {}} me={mockMe} />
@@ -74,7 +91,6 @@ describe('<Template />', () => {
}, },
}); });
let wrapper;
await act(async () => { await act(async () => {
wrapper = mountWithContexts( wrapper = mountWithContexts(
<Template setBreadcrumb={() => {}} me={mockMe} /> <Template setBreadcrumb={() => {}} me={mockMe} />
@@ -93,7 +109,7 @@ describe('<Template />', () => {
const history = createMemoryHistory({ const history = createMemoryHistory({
initialEntries: ['/templates/job_template/1/foobar'], initialEntries: ['/templates/job_template/1/foobar'],
}); });
let wrapper;
await act(async () => { await act(async () => {
wrapper = mountWithContexts( wrapper = mountWithContexts(
<Template setBreadcrumb={() => {}} me={mockMe} />, <Template setBreadcrumb={() => {}} me={mockMe} />,
@@ -117,4 +133,62 @@ describe('<Template />', () => {
await waitForElement(wrapper, 'ContentError', el => el.length === 1); await waitForElement(wrapper, 'ContentError', el => el.length === 1);
}); });
test('should call to get webhook key', async () => {
const history = createMemoryHistory({
initialEntries: ['/templates/job_template/1/foobar'],
});
await act(async () => {
wrapper = mountWithContexts(
<Template setBreadcrumb={() => {}} me={mockMe} />,
{
context: {
router: {
history,
route: {
location: history.location,
match: {
params: { id: 1 },
url: '/templates/job_template/1/foobar',
path: '/templates/job_template/1/foobar',
},
},
},
},
}
);
});
expect(JobTemplatesAPI.readWebhookKey).toHaveBeenCalled();
});
test('should not call to get webhook key', async () => {
JobTemplatesAPI.readTemplateOptions.mockResolvedValueOnce({
data: {
actions: {},
},
});
const history = createMemoryHistory({
initialEntries: ['/templates/job_template/1/foobar'],
});
await act(async () => {
wrapper = mountWithContexts(
<Template setBreadcrumb={() => {}} me={mockMe} />,
{
context: {
router: {
history,
route: {
location: history.location,
match: {
params: { id: 1 },
url: '/templates/job_template/1/foobar',
path: '/templates/job_template/1/foobar',
},
},
},
},
}
);
});
expect(JobTemplatesAPI.readWebhookKey).not.toHaveBeenCalled();
});
}); });

View File

@@ -56,10 +56,20 @@ class WorkflowJobTemplate extends Component {
this.setState({ contentError: null }); this.setState({ contentError: null });
try { try {
const { data } = await WorkflowJobTemplatesAPI.readDetail(id); const [
{ data },
{
data: { actions },
},
] = await Promise.all([
WorkflowJobTemplatesAPI.readDetail(id),
WorkflowJobTemplatesAPI.readWorkflowJobTemplateOptions(id),
]);
let webhookKey; let webhookKey;
if (data?.webhook_service && data?.related?.webhook_key) { if (actions.PUT) {
webhookKey = await WorkflowJobTemplatesAPI.readWebhookKey(id); if (data?.webhook_service && data?.related?.webhook_key) {
webhookKey = await WorkflowJobTemplatesAPI.readWebhookKey(id);
}
} }
if (data?.summary_fields?.webhook_credential) { if (data?.summary_fields?.webhook_credential) {
const { const {

View File

@@ -59,6 +59,7 @@ describe('<WorkflowJobTemplate/>', () => {
}, },
}, },
}); });
WorkflowJobTemplatesAPI.readWebhookKey.mockResolvedValue({ WorkflowJobTemplatesAPI.readWebhookKey.mockResolvedValue({
data: { webhook_key: 'WebHook Key' }, data: { webhook_key: 'WebHook Key' },
}); });
@@ -74,6 +75,9 @@ describe('<WorkflowJobTemplate/>', () => {
}); });
}); });
beforeEach(() => { beforeEach(() => {
WorkflowJobTemplatesAPI.readWorkflowJobTemplateOptions.mockResolvedValue({
data: { actions: { PUT: {} } },
});
history = createMemoryHistory({ history = createMemoryHistory({
initialEntries: ['/templates/workflow_job_template/1/details'], initialEntries: ['/templates/workflow_job_template/1/details'],
}); });
@@ -95,13 +99,18 @@ describe('<WorkflowJobTemplate/>', () => {
); );
}); });
}); });
afterEach(() => {
jest.clearAllMocks();
wrapper.unmount();
});
test('calls api to get workflow job template data', async () => { test('calls api to get workflow job template data', async () => {
expect(wrapper.find('WorkflowJobTemplate').length).toBe(1); expect(wrapper.find('WorkflowJobTemplate').length).toBe(1);
expect(WorkflowJobTemplatesAPI.readDetail).toBeCalledWith('1'); expect(WorkflowJobTemplatesAPI.readDetail).toBeCalledWith('1');
wrapper.update(); wrapper.update();
await sleep(0); await sleep(0);
expect(WorkflowJobTemplatesAPI.readWebhookKey).toBeCalledWith('1'); expect(WorkflowJobTemplatesAPI.readWebhookKey).toBeCalledWith('1');
expect(WorkflowJobTemplatesAPI.readWorkflowJobTemplateOptions).toBeCalled();
expect(CredentialsAPI.readDetail).toBeCalledWith(1234567); expect(CredentialsAPI.readDetail).toBeCalledWith(1234567);
expect(OrganizationsAPI.read).toBeCalledWith({ expect(OrganizationsAPI.read).toBeCalledWith({
page_size: 1, page_size: 1,
@@ -144,4 +153,12 @@ describe('<WorkflowJobTemplate/>', () => {
tabs.forEach(t => expect(tc.prop(`aria-label=[${t}]`))); tabs.forEach(t => expect(tc.prop(`aria-label=[${t}]`)));
}); });
}); });
test('should not call for webhook key', async () => {
WorkflowJobTemplatesAPI.readWorkflowJobTemplateOptions.mockResolvedValueOnce(
{
data: { actions: {} },
}
);
expect(WorkflowJobTemplatesAPI.readWebhookKey).not.toBeCalled();
});
}); });

View File

@@ -24,7 +24,8 @@
"instance_groups": "/api/v2/job_templates/7/instance_groups/", "instance_groups": "/api/v2/job_templates/7/instance_groups/",
"slice_workflow_jobs": "/api/v2/job_templates/7/slice_workflow_jobs/", "slice_workflow_jobs": "/api/v2/job_templates/7/slice_workflow_jobs/",
"copy": "/api/v2/job_templates/7/copy/", "copy": "/api/v2/job_templates/7/copy/",
"webhook_receiver": "/api/v2/job_templates/7/github/" "webhook_receiver": "/api/v2/job_templates/7/github/",
"webhook_key": "/api/v2/job_templates/7/webhook_key/"
}, },
"summary_fields": { "summary_fields": {
"inventory": { "inventory": {