Skip to content

Commit

Permalink
Always call resolve (#114670) (#114913)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisronline authored Oct 13, 2021
1 parent 0686bac commit a1b45d4
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 116 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,6 @@ import { spacesPluginMock } from '../../../../../../spaces/public/mocks';
import { useKibana } from '../../../../common/lib/kibana';
jest.mock('../../../../common/lib/kibana');

class NotFoundError extends Error {
public readonly body: {
statusCode: number;
name: string;
} = {
statusCode: 404,
name: 'Not found',
};

constructor(message: string | undefined) {
super(message);
}
}

describe('alert_details_route', () => {
beforeEach(() => {
jest.clearAllMocks();
Expand All @@ -58,29 +44,22 @@ describe('alert_details_route', () => {
it('redirects to another page if fetched rule is an aliasMatch', async () => {
await setup();
const rule = mockRule();
const { loadAlert, resolveRule } = mockApis();
const { resolveRule } = mockApis();

loadAlert.mockImplementationOnce(async () => {
throw new NotFoundError('OMG');
});
resolveRule.mockImplementationOnce(async () => ({
...rule,
id: 'new_id',
outcome: 'aliasMatch',
alias_target_id: rule.id,
}));
const wrapper = mountWithIntl(
<AlertDetailsRoute
{...mockRouterProps(rule)}
{...{ ...mockApis(), loadAlert, resolveRule }}
/>
<AlertDetailsRoute {...mockRouterProps(rule)} {...{ ...mockApis(), resolveRule }} />
);
await act(async () => {
await nextTick();
wrapper.update();
});

expect(loadAlert).toHaveBeenCalledWith(rule.id);
expect(resolveRule).toHaveBeenCalledWith(rule.id);
expect((spacesMock as any).ui.redirectLegacyUrl).toHaveBeenCalledWith(
`insightsAndAlerting/triggersActions/rule/new_id`,
Expand All @@ -96,11 +75,8 @@ describe('alert_details_route', () => {
name: 'type name',
authorizedConsumers: ['consumer'],
};
const { loadAlert, loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { loadAlertTypes, loadActionTypes, resolveRule } = mockApis();

loadAlert.mockImplementationOnce(async () => {
throw new NotFoundError('OMG');
});
loadAlertTypes.mockImplementationOnce(async () => [ruleType]);
loadActionTypes.mockImplementation(async () => []);
resolveRule.mockImplementationOnce(async () => ({
Expand All @@ -112,15 +88,14 @@ describe('alert_details_route', () => {
const wrapper = mountWithIntl(
<AlertDetailsRoute
{...mockRouterProps(rule)}
{...{ ...mockApis(), loadAlert, loadAlertTypes, loadActionTypes, resolveRule }}
{...{ ...mockApis(), loadAlertTypes, loadActionTypes, resolveRule }}
/>
);
await act(async () => {
await nextTick();
wrapper.update();
});

expect(loadAlert).toHaveBeenCalledWith(rule.id);
expect(resolveRule).toHaveBeenCalledWith(rule.id);
expect((spacesMock as any).ui.components.getLegacyUrlConflict).toHaveBeenCalledWith({
currentObjectId: 'new_id',
Expand All @@ -138,18 +113,17 @@ describe('getRuleData useEffect handler', () => {

it('fetches rule', async () => {
const rule = mockRule();
const { loadAlert, loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { setAlert, setAlertType, setActionTypes } = mockStateSetter();

loadAlert.mockImplementationOnce(async () => rule);
resolveRule.mockImplementationOnce(async () => rule);

const toastNotifications = {
addDanger: jest.fn(),
} as unknown as ToastsApi;

await getRuleData(
rule.id,
loadAlert,
loadAlertTypes,
resolveRule,
loadActionTypes,
Expand All @@ -159,8 +133,7 @@ describe('getRuleData useEffect handler', () => {
toastNotifications
);

expect(loadAlert).toHaveBeenCalledWith(rule.id);
expect(resolveRule).not.toHaveBeenCalled();
expect(resolveRule).toHaveBeenCalledWith(rule.id);
expect(setAlert).toHaveBeenCalledWith(rule);
});

Expand All @@ -184,10 +157,10 @@ describe('getRuleData useEffect handler', () => {
id: rule.alertTypeId,
name: 'type name',
};
const { loadAlert, loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { setAlert, setAlertType, setActionTypes } = mockStateSetter();

loadAlert.mockImplementation(async () => rule);
resolveRule.mockImplementation(async () => rule);
loadAlertTypes.mockImplementation(async () => [ruleType]);
loadActionTypes.mockImplementation(async () => [connectorType]);

Expand All @@ -197,7 +170,6 @@ describe('getRuleData useEffect handler', () => {

await getRuleData(
rule.id,
loadAlert,
loadAlertTypes,
resolveRule,
loadActionTypes,
Expand All @@ -209,58 +181,13 @@ describe('getRuleData useEffect handler', () => {

expect(loadAlertTypes).toHaveBeenCalledTimes(1);
expect(loadActionTypes).toHaveBeenCalledTimes(1);
expect(resolveRule).not.toHaveBeenCalled();
expect(resolveRule).toHaveBeenCalled();

expect(setAlert).toHaveBeenCalledWith(rule);
expect(setAlertType).toHaveBeenCalledWith(ruleType);
expect(setActionTypes).toHaveBeenCalledWith([connectorType]);
});

it('fetches rule using resolve if initial GET results in a 404 error', async () => {
const connectorType = {
id: '.server-log',
name: 'Server log',
enabled: true,
};
const rule = mockRule({
actions: [
{
group: '',
id: uuid.v4(),
actionTypeId: connectorType.id,
params: {},
},
],
});

const { loadAlert, loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { setAlert, setAlertType, setActionTypes } = mockStateSetter();

loadAlert.mockImplementationOnce(async () => {
throw new NotFoundError('OMG');
});
resolveRule.mockImplementationOnce(async () => rule);

const toastNotifications = {
addDanger: jest.fn(),
} as unknown as ToastsApi;
await getRuleData(
rule.id,
loadAlert,
loadAlertTypes,
resolveRule,
loadActionTypes,
setAlert,
setAlertType,
setActionTypes,
toastNotifications
);

expect(loadAlert).toHaveBeenCalledWith(rule.id);
expect(resolveRule).toHaveBeenCalledWith(rule.id);
expect(setAlert).toHaveBeenCalledWith(rule);
});

it('displays an error if fetching the rule results in a non-404 error', async () => {
const connectorType = {
id: '.server-log',
Expand All @@ -278,10 +205,10 @@ describe('getRuleData useEffect handler', () => {
],
});

const { loadAlert, loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { setAlert, setAlertType, setActionTypes } = mockStateSetter();

loadAlert.mockImplementation(async () => {
resolveRule.mockImplementation(async () => {
throw new Error('OMG');
});

Expand All @@ -290,7 +217,6 @@ describe('getRuleData useEffect handler', () => {
} as unknown as ToastsApi;
await getRuleData(
rule.id,
loadAlert,
loadAlertTypes,
resolveRule,
loadActionTypes,
Expand Down Expand Up @@ -322,10 +248,10 @@ describe('getRuleData useEffect handler', () => {
],
});

const { loadAlert, loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { setAlert, setAlertType, setActionTypes } = mockStateSetter();

loadAlert.mockImplementation(async () => rule);
resolveRule.mockImplementation(async () => rule);

loadAlertTypes.mockImplementation(async () => {
throw new Error('OMG no rule type');
Expand All @@ -337,7 +263,6 @@ describe('getRuleData useEffect handler', () => {
} as unknown as ToastsApi;
await getRuleData(
rule.id,
loadAlert,
loadAlertTypes,
resolveRule,
loadActionTypes,
Expand Down Expand Up @@ -373,10 +298,10 @@ describe('getRuleData useEffect handler', () => {
name: 'type name',
};

const { loadAlert, loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { setAlert, setAlertType, setActionTypes } = mockStateSetter();

loadAlert.mockImplementation(async () => rule);
resolveRule.mockImplementation(async () => rule);

loadAlertTypes.mockImplementation(async () => [ruleType]);
loadActionTypes.mockImplementation(async () => {
Expand All @@ -388,7 +313,6 @@ describe('getRuleData useEffect handler', () => {
} as unknown as ToastsApi;
await getRuleData(
rule.id,
loadAlert,
loadAlertTypes,
resolveRule,
loadActionTypes,
Expand Down Expand Up @@ -425,10 +349,10 @@ describe('getRuleData useEffect handler', () => {
name: 'type name',
};

const { loadAlert, loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { setAlert, setAlertType, setActionTypes } = mockStateSetter();

loadAlert.mockImplementation(async () => rule);
resolveRule.mockImplementation(async () => rule);
loadAlertTypes.mockImplementation(async () => [ruleType]);
loadActionTypes.mockImplementation(async () => [connectorType]);

Expand All @@ -437,7 +361,6 @@ describe('getRuleData useEffect handler', () => {
} as unknown as ToastsApi;
await getRuleData(
rule.id,
loadAlert,
loadAlertTypes,
resolveRule,
loadActionTypes,
Expand Down Expand Up @@ -485,10 +408,10 @@ describe('getRuleData useEffect handler', () => {
name: 'type name',
};

const { loadAlert, loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { loadAlertTypes, loadActionTypes, resolveRule } = mockApis();
const { setAlert, setAlertType, setActionTypes } = mockStateSetter();

loadAlert.mockImplementation(async () => rule);
resolveRule.mockImplementation(async () => rule);
loadAlertTypes.mockImplementation(async () => [ruleType]);
loadActionTypes.mockImplementation(async () => [availableConnectorType]);

Expand All @@ -497,7 +420,6 @@ describe('getRuleData useEffect handler', () => {
} as unknown as ToastsApi;
await getRuleData(
rule.id,
loadAlert,
loadAlertTypes,
resolveRule,
loadActionTypes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import React, { useState, useEffect } from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { ToastsApi } from 'kibana/public';
import { EuiSpacer } from '@elastic/eui';
import { Alert, AlertType, ActionType, ResolvedRule } from '../../../../types';
import { AlertType, ActionType, ResolvedRule } from '../../../../types';
import { AlertDetailsWithApi as AlertDetails } from './alert_details';
import { throwIfAbsent, throwIfIsntContained } from '../../../lib/value_validators';
import {
Expand All @@ -28,13 +28,12 @@ type AlertDetailsRouteProps = RouteComponentProps<{
ruleId: string;
}> &
Pick<ActionApis, 'loadActionTypes'> &
Pick<AlertApis, 'loadAlert' | 'loadAlertTypes' | 'resolveRule'>;
Pick<AlertApis, 'loadAlertTypes' | 'resolveRule'>;

export const AlertDetailsRoute: React.FunctionComponent<AlertDetailsRouteProps> = ({
match: {
params: { ruleId },
},
loadAlert,
loadAlertTypes,
loadActionTypes,
resolveRule,
Expand All @@ -47,14 +46,13 @@ export const AlertDetailsRoute: React.FunctionComponent<AlertDetailsRouteProps>

const { basePath } = http;

const [alert, setAlert] = useState<Alert | ResolvedRule | null>(null);
const [alert, setAlert] = useState<ResolvedRule | null>(null);
const [alertType, setAlertType] = useState<AlertType | null>(null);
const [actionTypes, setActionTypes] = useState<ActionType[] | null>(null);
const [refreshToken, requestRefresh] = React.useState<number>();
useEffect(() => {
getRuleData(
ruleId,
loadAlert,
loadAlertTypes,
resolveRule,
loadActionTypes,
Expand All @@ -63,7 +61,7 @@ export const AlertDetailsRoute: React.FunctionComponent<AlertDetailsRouteProps>
setActionTypes,
toasts
);
}, [ruleId, http, loadActionTypes, loadAlert, loadAlertTypes, resolveRule, toasts, refreshToken]);
}, [ruleId, http, loadActionTypes, loadAlertTypes, resolveRule, toasts, refreshToken]);

useEffect(() => {
if (alert) {
Expand Down Expand Up @@ -128,26 +126,16 @@ export const AlertDetailsRoute: React.FunctionComponent<AlertDetailsRouteProps>

export async function getRuleData(
ruleId: string,
loadAlert: AlertApis['loadAlert'],
loadAlertTypes: AlertApis['loadAlertTypes'],
resolveRule: AlertApis['resolveRule'],
loadActionTypes: ActionApis['loadActionTypes'],
setAlert: React.Dispatch<React.SetStateAction<Alert | ResolvedRule | null>>,
setAlert: React.Dispatch<React.SetStateAction<ResolvedRule | null>>,
setAlertType: React.Dispatch<React.SetStateAction<AlertType | null>>,
setActionTypes: React.Dispatch<React.SetStateAction<ActionType[] | null>>,
toasts: Pick<ToastsApi, 'addDanger'>
) {
try {
let loadedRule: Alert | ResolvedRule;
try {
loadedRule = await loadAlert(ruleId);
} catch (err) {
// Try resolving this rule id if the error is a 404, otherwise re-throw
if (err?.body?.statusCode !== 404) {
throw err;
}
loadedRule = await resolveRule(ruleId);
}
const loadedRule: ResolvedRule = await resolveRule(ruleId);
setAlert(loadedRule);

const [loadedAlertType, loadedActionTypes] = await Promise.all<AlertType, ActionType[]>([
Expand Down

0 comments on commit a1b45d4

Please sign in to comment.