feat(plugins/pagerduty): handle empty response when querying services
* raise NotFoundError in async hook * show ServiceNotFoundError empty state when async hook errors Signed-off-by: Alec Jacobs <cajacobs5401@gmail.com>
This commit is contained in:
@@ -19,7 +19,12 @@ import { PagerDutyCard, isPluginApplicableToEntity } from '../PagerDutyCard';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-react';
|
||||
import { TestApiRegistry, wrapInTestApp } from '@backstage/test-utils';
|
||||
import { pagerDutyApiRef, UnauthorizedError, PagerDutyClient } from '../../api';
|
||||
import {
|
||||
pagerDutyApiRef,
|
||||
UnauthorizedError,
|
||||
NotFoundError,
|
||||
PagerDutyClient,
|
||||
} from '../../api';
|
||||
import { Service, User } from '../types';
|
||||
|
||||
import { alertApiRef } from '@backstage/core-plugin-api';
|
||||
@@ -166,6 +171,24 @@ describe('PageDutyCard', () => {
|
||||
expect(getByText('Missing or invalid PagerDuty Token')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Handles custom NotFoundError', async () => {
|
||||
mockPagerDutyApi.getServiceByIntegrationKey = jest
|
||||
.fn()
|
||||
.mockRejectedValueOnce(new NotFoundError());
|
||||
|
||||
const { getByText, queryByTestId } = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<EntityProvider entity={entity}>
|
||||
<PagerDutyCard />
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
await waitFor(() => !queryByTestId('progress'));
|
||||
expect(getByText('PagerDuty Service Not Found')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('handles general error', async () => {
|
||||
mockPagerDutyApi.getServiceByIntegrationKey = jest
|
||||
.fn()
|
||||
@@ -187,6 +210,25 @@ describe('PageDutyCard', () => {
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('handles empty response from getServiceByIntegrationKey', async () => {
|
||||
mockPagerDutyApi.getServiceByIntegrationKey = jest
|
||||
.fn()
|
||||
.mockImplementationOnce(async () => []);
|
||||
|
||||
const { getByText, queryByTestId } = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<EntityProvider entity={entity}>
|
||||
<PagerDutyCard />
|
||||
</EntityProvider>
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
await waitFor(() => !queryByTestId('progress'));
|
||||
expect(getByText('PagerDuty Service Not Found')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('opens the dialog when trigger button is clicked', async () => {
|
||||
mockPagerDutyApi.getServiceByIntegrationKey = jest
|
||||
.fn()
|
||||
|
||||
@@ -20,15 +20,16 @@ import { Incidents } from '../Incident';
|
||||
import { EscalationPolicy } from '../Escalation';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import { pagerDutyApiRef, UnauthorizedError } from '../../api';
|
||||
import { pagerDutyApiRef, UnauthorizedError, NotFoundError } from '../../api';
|
||||
import AlarmAddIcon from '@material-ui/icons/AlarmAdd';
|
||||
import { MissingTokenError } from '../Errors/MissingTokenError';
|
||||
import { MissingTokenError, ServiceNotFoundError } from '../Errors';
|
||||
import WebIcon from '@material-ui/icons/Web';
|
||||
import DateRangeIcon from '@material-ui/icons/DateRange';
|
||||
import { usePagerdutyEntity } from '../../hooks';
|
||||
import { PAGERDUTY_INTEGRATION_KEY, PAGERDUTY_SERVICE_ID } from '../constants';
|
||||
import { TriggerDialog } from '../TriggerDialog';
|
||||
import { ChangeEvents } from '../ChangeEvents';
|
||||
import { Service } from '../types';
|
||||
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import {
|
||||
@@ -75,29 +76,42 @@ export const PagerDutyCard = () => {
|
||||
loading,
|
||||
error,
|
||||
} = useAsync(async () => {
|
||||
let service: Service;
|
||||
const services = await api.getServiceByIntegrationKey(
|
||||
integrationKey as string,
|
||||
);
|
||||
|
||||
service = services[0];
|
||||
if (!service) throw new NotFoundError();
|
||||
|
||||
return {
|
||||
id: services[0].id,
|
||||
name: services[0].name,
|
||||
url: services[0].html_url,
|
||||
policyId: services[0].escalation_policy.id,
|
||||
policyLink: services[0].escalation_policy.html_url,
|
||||
id: service.id,
|
||||
name: service.name,
|
||||
url: service.html_url,
|
||||
policyId: service.escalation_policy.id,
|
||||
policyLink: service.escalation_policy.html_url,
|
||||
};
|
||||
});
|
||||
|
||||
if (error instanceof UnauthorizedError) {
|
||||
return <MissingTokenError />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<Alert severity="error">
|
||||
Error encountered while fetching information. {error.message}
|
||||
</Alert>
|
||||
);
|
||||
let errorNode: ReactNode;
|
||||
|
||||
switch (error.constructor) {
|
||||
case UnauthorizedError:
|
||||
errorNode = <MissingTokenError />;
|
||||
break;
|
||||
case NotFoundError:
|
||||
errorNode = <ServiceNotFoundError />;
|
||||
break;
|
||||
default:
|
||||
errorNode = (
|
||||
<Alert severity="error">
|
||||
Error encountered while fetching information. {error.message}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
return <BasicCard>{errorNode}</BasicCard>;
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
|
||||
Reference in New Issue
Block a user