From 707191bf6f10a5a8e4dcfe3d0c77adf7d12e70b3 Mon Sep 17 00:00:00 2001 From: Alec Jacobs Date: Fri, 27 May 2022 11:03:06 -0700 Subject: [PATCH] feat(plugins/pagerduty): lookup by service-id if that is available * prefer integration-key value over service-id * disable creation of incidents if integration-key is not available Signed-off-by: Alec Jacobs --- .../components/PagerDutyCard/index.test.tsx | 130 ++++++++++++++++++ .../src/components/PagerDutyCard/index.tsx | 40 ++++-- 2 files changed, 158 insertions(+), 12 deletions(-) diff --git a/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx b/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx index 2b309533ed..54b58489be 100644 --- a/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx +++ b/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx @@ -252,4 +252,134 @@ describe('PageDutyCard', () => { }); expect(getByRole('dialog')).toBeInTheDocument(); }); + + describe('when entity has the pagerduty.com/service-id annotation', () => { + it('Renders PagerDuty service information', async () => { + mockPagerDutyApi.getServiceByServiceId = jest + .fn() + .mockImplementationOnce(async () => service); + + const { getByText, queryByTestId } = render( + wrapInTestApp( + + + + + , + ), + ); + await waitFor(() => !queryByTestId('progress')); + expect(getByText('Service Directory')).toBeInTheDocument(); + expect(getByText('Create Incident')).toBeInTheDocument(); + expect(getByText('Nice! No incidents found!')).toBeInTheDocument(); + expect(getByText('Empty escalation policy')).toBeInTheDocument(); + }); + + it('Handles custom error for missing token', async () => { + mockPagerDutyApi.getServiceByServiceId = jest + .fn() + .mockRejectedValueOnce(new UnauthorizedError()); + + const { getByText, queryByTestId } = render( + wrapInTestApp( + + + + + , + ), + ); + await waitFor(() => !queryByTestId('progress')); + expect( + getByText('Missing or invalid PagerDuty Token'), + ).toBeInTheDocument(); + }); + + it('Handles custom NotFoundError', async () => { + mockPagerDutyApi.getServiceByServiceId = jest + .fn() + .mockRejectedValueOnce(new NotFoundError()); + + const { getByText, queryByTestId } = render( + wrapInTestApp( + + + + + , + ), + ); + await waitFor(() => !queryByTestId('progress')); + expect(getByText('PagerDuty Service Not Found')).toBeInTheDocument(); + }); + + it('handles general error', async () => { + mockPagerDutyApi.getServiceByServiceId = jest + .fn() + .mockRejectedValueOnce(new Error('An error occurred')); + const { getByText, queryByTestId } = render( + wrapInTestApp( + + + + + , + ), + ); + await waitFor(() => !queryByTestId('progress')); + + expect( + getByText( + 'Error encountered while fetching information. An error occurred', + ), + ).toBeInTheDocument(); + }); + + it('disables the Create Incident button', async () => { + mockPagerDutyApi.getServiceByServiceId = jest + .fn() + .mockImplementationOnce(async () => service); + + const { queryByTestId, getByTitle } = render( + wrapInTestApp( + + + + + , + ), + ); + await waitFor(() => !queryByTestId('progress')); + expect(queryByTestId('trigger-dialoger')).not.toBeInTheDocument(); + expect( + getByTitle('Must provide an integration-key to create incidents') + .className, + ).toMatch('disabled'); + }); + }); + + describe('when entity has all annotations', () => { + it('queries by integration key', async () => { + mockPagerDutyApi.getServiceByIntegrationKey = jest + .fn() + .mockImplementationOnce(async () => [service]); + mockPagerDutyApi.getServiceByServiceId = jest.fn(); + + const { getByText, queryByTestId } = render( + wrapInTestApp( + + + + + , + ), + ); + await waitFor(() => !queryByTestId('progress')); + expect(mockPagerDutyApi.getServiceByServiceId).not.toHaveBeenCalled(); + expect(getByText('Service Directory')).toBeInTheDocument(); + expect(getByText('Create Incident')).toBeInTheDocument(); + expect(getByText('Nice! No incidents found!')).toBeInTheDocument(); + expect(getByText('Empty escalation policy')).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/pagerduty/src/components/PagerDutyCard/index.tsx b/plugins/pagerduty/src/components/PagerDutyCard/index.tsx index b4b20fb25b..308d17a08d 100644 --- a/plugins/pagerduty/src/components/PagerDutyCard/index.tsx +++ b/plugins/pagerduty/src/components/PagerDutyCard/index.tsx @@ -52,7 +52,7 @@ export const isPluginApplicableToEntity = (entity: Entity) => ); export const PagerDutyCard = () => { - const { integrationKey } = usePagerdutyEntity(); + const { integrationKey, serviceId } = usePagerdutyEntity(); const api = useApi(pagerDutyApiRef); const [refreshIncidents, setRefreshIncidents] = useState(false); const [refreshChangeEvents, setRefreshChangeEvents] = @@ -77,12 +77,16 @@ export const PagerDutyCard = () => { error, } = useAsync(async () => { let service: Service; - const services = await api.getServiceByIntegrationKey( - integrationKey as string, - ); - service = services[0]; - if (!service) throw new NotFoundError(); + if (integrationKey) { + const services = await api.getServiceByIntegrationKey( + integrationKey as string, + ); + service = services[0]; + if (!service) throw new NotFoundError(); + } else { + service = await api.getServiceByServiceId(serviceId); + } return { id: service.id, @@ -128,11 +132,21 @@ export const PagerDutyCard = () => { icon: , }; + /** + * In order to create incidents using the REST API, a valid user email address must be present. + * There is no guarantee the current user entity has a valid email association, so instead just + * only allow triggering incidents when an integration key is present. + */ + const createIncidentDisabled = !integrationKey; const triggerLink: IconLinkVerticalProps = { label: 'Create Incident', onClick: showDialog, icon: , color: 'secondary', + disabled: createIncidentDisabled, + title: createIncidentDisabled + ? 'Must provide an integration-key to create incidents' + : '', }; const escalationPolicyLink: IconLinkVerticalProps = { @@ -171,12 +185,14 @@ export const PagerDutyCard = () => { - + {!createIncidentDisabled && ( + + )} ); };