Skip to content

Commit

Permalink
[Monitoring][Alerting] Added core features to Kibana services UPDATED (
Browse files Browse the repository at this point in the history
…#85074)

* added core features to kibana services

* Added test for alert form

* Added mocking of legacy shims and actions

* Fixed typing

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
igoristic and kibanamachine authored Dec 7, 2020
1 parent 4a44804 commit d19b558
Show file tree
Hide file tree
Showing 4 changed files with 277 additions and 9 deletions.
270 changes: 270 additions & 0 deletions x-pack/plugins/monitoring/public/alerts/alert_form.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

/**
* Prevent any breaking changes to context requirement from breaking the alert form/actions
*/

import React, { Fragment, lazy } from 'react';
import { mountWithIntl, nextTick } from '@kbn/test/jest';
import { ReactWrapper, mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
import { coreMock } from 'src/core/public/mocks';
import { actionTypeRegistryMock } from '../../../triggers_actions_ui/public/application/action_type_registry.mock';
import { alertTypeRegistryMock } from '../../../triggers_actions_ui/public/application/alert_type_registry.mock';
import { ValidationResult, Alert } from '../../../triggers_actions_ui/public/types';
import { AlertForm } from '../../../triggers_actions_ui/public/application/sections/alert_form/alert_form';
import ActionForm from '../../../triggers_actions_ui/public/application/sections/action_connector_form/action_form';
import { AlertsContextProvider } from '../../../triggers_actions_ui/public/application/context/alerts_context';
import { Legacy } from '../legacy_shims';
import { I18nProvider } from '@kbn/i18n/react';
import { createKibanaReactContext } from '../../../../../src/plugins/kibana_react/public';

interface AlertAction {
group: string;
id: string;
actionTypeId: string;
params: unknown;
}

jest.mock('../../../triggers_actions_ui/public/application/lib/action_connector_api', () => ({
loadAllActions: jest.fn(),
loadActionTypes: jest.fn(),
}));

jest.mock('../../../triggers_actions_ui/public/application/lib/alert_api', () => ({
loadAlertTypes: jest.fn(),
}));

const initLegacyShims = () => {
const triggersActionsUi = {
actionTypeRegistry: actionTypeRegistryMock.create(),
alertTypeRegistry: alertTypeRegistryMock.create(),
};
const data = { query: { timefilter: { timefilter: {} } } } as any;
const ngInjector = {} as angular.auto.IInjectorService;
Legacy.init(
{
core: coreMock.createStart(),
data,
isCloud: false,
triggersActionsUi,
usageCollection: {},
} as any,
ngInjector
);
};

const ALERTS_FEATURE_ID = 'alerts';
const validationMethod = (): ValidationResult => ({ errors: {} });
const actionTypeRegistry = actionTypeRegistryMock.create();
const alertTypeRegistry = alertTypeRegistryMock.create();

describe('alert_form', () => {
beforeEach(() => {
initLegacyShims();
jest.resetAllMocks();
});

const alertType = {
id: 'alert-type',
iconClass: 'test',
name: 'test-alert',
description: 'Testing',
documentationUrl: 'https://...',
validate: validationMethod,
alertParamsExpression: () => <Fragment />,
requiresAppContext: false,
};

const mockedActionParamsFields = lazy(async () => ({
default() {
return <Fragment />;
},
}));

const actionType = {
id: 'alert-action-type',
iconClass: '',
selectMessage: '',
validateConnector: validationMethod,
validateParams: validationMethod,
actionConnectorFields: null,
actionParamsFields: mockedActionParamsFields,
};

describe('alert_form edit alert', () => {
let wrapper: ReactWrapper<any>;

beforeEach(async () => {
const coreStart = coreMock.createStart();
alertTypeRegistry.list.mockReturnValue([alertType]);
alertTypeRegistry.get.mockReturnValue(alertType);
alertTypeRegistry.has.mockReturnValue(true);
actionTypeRegistry.list.mockReturnValue([actionType]);
actionTypeRegistry.has.mockReturnValue(true);
actionTypeRegistry.get.mockReturnValue(actionType);

const monitoringDependencies = {
toastNotifications: coreStart.notifications.toasts,
...Legacy.shims.kibanaServices,
actionTypeRegistry,
alertTypeRegistry,
} as any;

const initialAlert = ({
name: 'test',
alertTypeId: alertType.id,
params: {},
consumer: ALERTS_FEATURE_ID,
schedule: {
interval: '1m',
},
actions: [],
tags: [],
muteAll: false,
enabled: false,
mutedInstanceIds: [],
} as unknown) as Alert;

wrapper = mountWithIntl(
<AlertsContextProvider
value={{
...monitoringDependencies,
}}
>
<AlertForm
alert={initialAlert}
dispatch={() => {}}
errors={{ name: [], interval: [] }}
operation="create"
/>
</AlertsContextProvider>
);

await act(async () => {
await nextTick();
wrapper.update();
});
});

it('renders alert name', async () => {
const alertNameField = wrapper.find('[data-test-subj="alertNameInput"]');
expect(alertNameField.exists()).toBeTruthy();
expect(alertNameField.first().prop('value')).toBe('test');
});

it('renders registered selected alert type', async () => {
const alertTypeSelectOptions = wrapper.find('[data-test-subj="selectedAlertTypeTitle"]');
expect(alertTypeSelectOptions.exists()).toBeTruthy();
});

it('should update throttle value', async () => {
const newThrottle = 17;
const throttleField = wrapper.find('[data-test-subj="throttleInput"]');
expect(throttleField.exists()).toBeTruthy();
throttleField.at(1).simulate('change', { target: { value: newThrottle.toString() } });
const throttleFieldAfterUpdate = wrapper.find('[data-test-subj="throttleInput"]');
expect(throttleFieldAfterUpdate.at(1).prop('value')).toEqual(newThrottle);
});
});

describe('alert_form > action_form', () => {
describe('action_form in alert', () => {
async function setup() {
initLegacyShims();
const { loadAllActions } = jest.requireMock(
'../../../triggers_actions_ui/public/application/lib/action_connector_api'
);
loadAllActions.mockResolvedValueOnce([
{
secrets: {},
id: 'test',
actionTypeId: actionType.id,
name: 'Test connector',
config: {},
isPreconfigured: false,
},
]);

actionTypeRegistry.list.mockReturnValue([actionType]);
actionTypeRegistry.has.mockReturnValue(true);
actionTypeRegistry.get.mockReturnValue(actionType);

const initialAlert = ({
name: 'test',
alertTypeId: alertType.id,
params: {},
consumer: ALERTS_FEATURE_ID,
schedule: {
interval: '1m',
},
actions: [
{
group: 'default',
id: 'test',
actionTypeId: actionType.id,
params: {
message: '',
},
},
],
tags: [],
muteAll: false,
enabled: false,
mutedInstanceIds: [],
} as unknown) as Alert;

const KibanaReactContext = createKibanaReactContext(Legacy.shims.kibanaServices);

const actionWrapper = mount(
<I18nProvider>
<KibanaReactContext.Provider>
<ActionForm
actions={initialAlert.actions}
defaultActionGroupId={'default'}
setActionIdByIndex={(id: string, index: number) => {
initialAlert.actions[index].id = id;
}}
setActions={(_updatedActions: AlertAction[]) => {}}
setActionParamsProperty={(key: string, value: any, index: number) =>
(initialAlert.actions[index] = { ...initialAlert.actions[index], [key]: value })
}
actionTypeRegistry={actionTypeRegistry}
actionTypes={[
{
id: actionType.id,
name: 'Test',
enabled: true,
enabledInConfig: true,
enabledInLicense: true,
minimumLicenseRequired: 'basic',
},
]}
/>
</KibanaReactContext.Provider>
</I18nProvider>
);

// Wait for active space to resolve before requesting the component to update
await act(async () => {
await nextTick();
actionWrapper.update();
});

return actionWrapper;
}

it('renders available action cards', async () => {
const wrapperTwo = await setup();
const actionOption = wrapperTwo.find(
`[data-test-subj="${actionType.id}-ActionTypeSelectOption"]`
);
expect(actionOption.exists()).toBeTruthy();
});
});
});
});
5 changes: 5 additions & 0 deletions x-pack/plugins/monitoring/public/legacy_shims.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export interface IShims {
isCloud: boolean;
triggersActionsUi: TriggersAndActionsUIPublicPluginSetup;
usageCollection: UsageCollectionSetup;
kibanaServices: CoreStart & { usageCollection: UsageCollectionSetup };
}

export class Legacy {
Expand Down Expand Up @@ -123,6 +124,10 @@ export class Legacy {
isCloud,
triggersActionsUi,
usageCollection,
kibanaServices: {
...core,
usageCollection,
},
};
}

Expand Down
6 changes: 1 addition & 5 deletions x-pack/plugins/monitoring/public/lib/setup_mode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,10 @@ export const setSetupModeMenuItem = () => {

const globalState = angularState.injector.get('globalState');
const enabled = !globalState.inSetupMode;

const services = {
usageCollection: Legacy.shims.usageCollection,
};
const I18nContext = Legacy.shims.I18nContext;

render(
<KibanaContextProvider services={services}>
<KibanaContextProvider services={Legacy.shims.kibanaServices}>
<I18nContext>
<SetupModeEnterButton enabled={enabled} toggleSetupMode={toggleSetupMode} />
</I18nContext>
Expand Down
5 changes: 1 addition & 4 deletions x-pack/plugins/monitoring/public/views/base_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,9 @@ export class MonitoringViewBaseController {
console.warn(`"#${this.reactNodeId}" element has not been added to the DOM yet`);
return;
}
const services = {
usageCollection: Legacy.shims.usageCollection,
};
const I18nContext = Legacy.shims.I18nContext;
const wrappedComponent = (
<KibanaContextProvider services={services}>
<KibanaContextProvider services={Legacy.shims.kibanaServices}>
<I18nContext>
{!this._isDataInitialized ? (
<PageLoading pageViewTitle={trackPageView ? this.telemetryPageViewTitle : null} />
Expand Down

0 comments on commit d19b558

Please sign in to comment.