Skip to content

Commit

Permalink
added integration test for view in app
Browse files Browse the repository at this point in the history
  • Loading branch information
gmmorris committed Mar 12, 2020
1 parent 0da9e64 commit 2d48a31
Show file tree
Hide file tree
Showing 15 changed files with 182 additions and 54 deletions.
26 changes: 2 additions & 24 deletions examples/alerting_example/public/alert_types/always_firing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,16 @@
import React, { Fragment } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiFieldNumber, EuiFormRow } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
import { SanitizedAlert } from '../../../../x-pack/plugins/alerting/common';
import { PluginSetupContract as AlertingSetup } from '../../../../x-pack/plugins/alerting/public';
import {
AlertTypeModel,
TriggersAndActionsUIPublicPluginSetup,
} from '../../../../x-pack/plugins/triggers_actions_ui/public';
import { AlertTypeModel } from '../../../../x-pack/plugins/triggers_actions_ui/public';
import { DEFAULT_INSTANCES_TO_GENERATE } from '../../common/constants';

export function register(
alerting: AlertingSetup,
triggersActionsUI: TriggersAndActionsUIPublicPluginSetup
) {
registerNavigation(alerting);
triggersActionsUI.alertTypeRegistry.register(getAlertType());
}

function registerNavigation(alerting: AlertingSetup) {
alerting.registerNavigation(
ALERTING_EXAMPLE_APP_ID,
'example.always-firing',
(alert: SanitizedAlert) => `/alert/${alert.id}`
);
}

interface AlwaysFiringParamsProps {
alertParams: { instances?: number };
setAlertParams: (property: string, value: any) => void;
errors: { [key: string]: string[] };
}

function getAlertType(): AlertTypeModel {
export function getAlertType(): AlertTypeModel {
return {
id: 'example.always-firing',
name: 'Always Fires',
Expand Down
17 changes: 3 additions & 14 deletions examples/alerting_example/public/alert_types/astros.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,9 @@ import { flatten } from 'lodash';
import { ALERTING_EXAMPLE_APP_ID, Craft, Operator } from '../../common/constants';
import { SanitizedAlert } from '../../../../x-pack/plugins/alerting/common';
import { PluginSetupContract as AlertingSetup } from '../../../../x-pack/plugins/alerting/public';
import {
AlertTypeModel,
TriggersAndActionsUIPublicPluginSetup,
} from '../../../../x-pack/plugins/triggers_actions_ui/public';

export function register(
alerting: AlertingSetup,
triggersActionsUI: TriggersAndActionsUIPublicPluginSetup
) {
registerNavigation(alerting);
triggersActionsUI.alertTypeRegistry.register(getAlertType());
}
import { AlertTypeModel } from '../../../../x-pack/plugins/triggers_actions_ui/public';

function registerNavigation(alerting: AlertingSetup) {
export function registerNavigation(alerting: AlertingSetup) {
alerting.registerNavigation(
ALERTING_EXAMPLE_APP_ID,
'example.people-in-space',
Expand All @@ -65,7 +54,7 @@ function isValueInEnum(enumeratin: Record<string, any>, value: any): boolean {
return !!Object.values(enumeratin).find(enumVal => enumVal === value);
}

function getAlertType(): AlertTypeModel {
export function getAlertType(): AlertTypeModel {
return {
id: 'example.people-in-space',
name: 'People Are In Space Right Now',
Expand Down
33 changes: 33 additions & 0 deletions examples/alerting_example/public/alert_types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { registerNavigation as registerPeopleInSpaceNavigation } from './astros';
import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
import { SanitizedAlert } from '../../../../x-pack/plugins/alerting/common';
import { PluginSetupContract as AlertingSetup } from '../../../../x-pack/plugins/alerting/public';

export function registerNavigation(alerting: AlertingSetup) {
// register default navigation
alerting.registerDefaultNavigation(
ALERTING_EXAMPLE_APP_ID,
(alert: SanitizedAlert) => `/alert/${alert.id}`
);

registerPeopleInSpaceNavigation(alerting);
}
2 changes: 0 additions & 2 deletions examples/alerting_example/public/components/view_alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ import {
EuiDescriptionListDescription,
EuiCodeBlock,
EuiSpacer,
EuiFlexGroup,
EuiPanel,
} from '@elastic/eui';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import { CoreStart } from 'kibana/public';
Expand Down
18 changes: 10 additions & 8 deletions examples/alerting_example/public/components/view_astros_alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,16 @@ export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => {
</EuiFlexItem>
<EuiFlexItem>
<EuiDescriptionList compressed>
{Object.entries(alertState.alertInstances ?? {}).map(([instance, { state }]) => (
<Fragment>
<EuiDescriptionListTitle>{instance}</EuiDescriptionListTitle>
<EuiDescriptionListDescription>
{hasCraft(state) ? state.craft : 'Unknown Craft'}
</EuiDescriptionListDescription>
</Fragment>
))}
{Object.entries(alertState.alertInstances ?? {}).map(
([instance, { state }], index) => (
<Fragment key={index}>
<EuiDescriptionListTitle>{instance}</EuiDescriptionListTitle>
<EuiDescriptionListDescription>
{hasCraft(state) ? state.craft : 'Unknown Craft'}
</EuiDescriptionListDescription>
</Fragment>
)
)}
</EuiDescriptionList>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
11 changes: 7 additions & 4 deletions examples/alerting_example/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import { PluginSetupContract as AlertingSetup } from '../../../x-pack/plugins/al
import { ChartsPluginStart } from '../../../src/plugins/charts/public';
import { TriggersAndActionsUIPublicPluginSetup } from '../../../x-pack/plugins/triggers_actions_ui/public';
import { DataPublicPluginStart } from '../../../src/plugins/data/public';
import { register as registerAlwaysFiringAlert } from './alert_types/always_firing';
import { register as registerPeopleInSpaceAlert } from './alert_types/astros';
import { getAlertType as getAlwaysFiringAlertType } from './alert_types/always_firing';
import { getAlertType as getPeopleInSpaceAlertType } from './alert_types/astros';
import { registerNavigation } from './alert_types';

export type Setup = void;
export type Start = void;
Expand Down Expand Up @@ -58,8 +59,10 @@ export class AlertingExamplePlugin implements Plugin<Setup, Start, AlertingExamp
},
});

registerAlwaysFiringAlert(alerting, triggers_actions_ui);
registerPeopleInSpaceAlert(alerting, triggers_actions_ui);
triggers_actions_ui.alertTypeRegistry.register(getAlwaysFiringAlertType());
triggers_actions_ui.alertTypeRegistry.register(getPeopleInSpaceAlertType());

registerNavigation(alerting);
}

public start() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ type Schema = PublicMethodsOf<AlertNavigationRegistry>;
const createAlertNavigationRegistryMock = () => {
const mocked: jest.Mocked<Schema> = {
has: jest.fn(),
hasDefaultHandler: jest.fn(),
hasTypedHandler: jest.fn(),
register: jest.fn(),
registerDefault: jest.fn(),
get: jest.fn(),
};
return mocked;
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/alerting/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type Start = jest.Mocked<ReturnType<AlertingPublicPlugin['start']>>;

const createSetupContract = (): Setup => ({
registerNavigation: jest.fn(),
registerDefaultNavigation: jest.fn(),
});

const createStartContract = (): Start => ({
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/alerting/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export class AlertingPublicPlugin implements Plugin<PluginSetupContract, PluginS
getNavigation: async (alertId: Alert['id']) => {
const alert = await loadAlert({ http: core.http, alertId });
const alertType = await loadAlertType({ http: core.http, id: alert.alertTypeId });

if (this.alertNavigationRegistry!.has(alert.consumer, alertType)) {
const navigationHandler = this.alertNavigationRegistry!.get(alert.consumer, alertType);
const state = navigationHandler(alert, alertType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const ViewInApp: React.FunctionComponent<ViewInAppProps> = ({ alert }) =>

return (
<EuiButtonEmpty
data-test-subj="alertDetails-viewInApp"
isLoading={alertNavigation === null}
disabled={!hasNavigation(alertNavigation)}
iconType="popout"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,34 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
});
});

describe('View In App', function() {
const testRunUuid = uuid.v4();
before(async () => {
await pageObjects.common.navigateToApp('triggersActions');
});

it('renders the alert details view in app button', async () => {
const alert = await alerting.alerts.createNoOp(`test-alert-${testRunUuid}`);

// refresh to see alert
await browser.refresh();

await pageObjects.header.waitUntilLoadingHasFinished();

// Verify content
await testSubjects.existOrFail('alertsList');

// click on first alert
await pageObjects.triggersActionsUI.clickOnAlertInAlertsList(alert.name);

expect(await pageObjects.alertDetailsUI.isViewInAppEnabled()).to.be(true);

await pageObjects.alertDetailsUI.clickViewInAppEnabled();

expect(await pageObjects.alertDetailsUI.getNoOpAppTitle()).to.be(`View Alert ${alert.id}`);
});
});

describe('Alert Instances', function() {
const testRunUuid = uuid.v4();
let alert: any;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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.
*/

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route, RouteComponentProps } from 'react-router-dom';
import { EuiPage, EuiText } from '@elastic/eui';
import { AppMountParameters, CoreStart } from '../../../../../../../src/core/public';

export interface AlertingExampleComponentParams {
basename: string;
}

const AlertingExampleApp = (deps: AlertingExampleComponentParams) => {
const { basename } = deps;
return (
<Router basename={basename}>
<EuiPage>
<Route
path={`/alert/:id`}
render={(props: RouteComponentProps<{ id: string }>) => {
return (
<EuiText data-test-subj="noop-title">
<h2>View Alert {props.match.params.id}</h2>
</EuiText>
);
}}
/>
</EuiPage>
</Router>
);
};

export const renderApp = (
core: CoreStart,
deps: any,
{ appBasePath, element }: AppMountParameters
) => {
ReactDOM.render(<AlertingExampleApp basename={appBasePath} {...deps} />, element);

return () => ReactDOM.unmountComponentAtNode(element);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { Plugin, CoreSetup } from 'kibana/public';
import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public';
import { PluginSetupContract as AlertingSetup } from '../../../../../../plugins/alerting/public';
import { AlertType, SanitizedAlert } from '../../../../../../plugins/alerting/common';

Expand All @@ -18,10 +18,20 @@ export interface AlertingExamplePublicSetupDeps {
export class AlertingFixturePlugin implements Plugin<Setup, Start, AlertingExamplePublicSetupDeps> {
public setup(core: CoreSetup, { alerting }: AlertingExamplePublicSetupDeps) {
alerting.registerNavigation(
'consumer.noop',
'consumer-noop',
'test.noop',
(alert: SanitizedAlert, alertType: AlertType) => `/alert/${alert.id}`
);

core.application.register({
id: 'consumer-noop',
title: 'No Op App',
async mount(params: AppMountParameters) {
const [coreStart, depsStart] = await core.getStartServices();
const { renderApp } = await import('./application');
return renderApp(coreStart, depsStart, params);
},
});
}

public start() {}
Expand Down
11 changes: 11 additions & 0 deletions x-pack/test/functional_with_es_ssl/page_objects/alert_details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,16 @@ export function AlertDetailsPageProvider({ getService }: FtrProviderContext) {
const nextButton = await testSubjects.find(`pagination-button-next`);
nextButton.click();
},
async isViewInAppEnabled() {
const viewInAppButton = await testSubjects.find(`alertDetails-viewInApp`);
return (await viewInAppButton.getAttribute('disabled')) !== 'disabled';
},
async clickViewInAppEnabled() {
const viewInAppButton = await testSubjects.find(`alertDetails-viewInApp`);
viewInAppButton.click();
},
async getNoOpAppTitle() {
return await testSubjects.getVisibleText('noop-title');
},
};
}
25 changes: 25 additions & 0 deletions x-pack/test/functional_with_es_ssl/services/alerting/alerts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,31 @@ export class Alerts {
});
}

public async createNoOp(name: string) {
this.log.debug(`creating alert ${name}`);

const { data: alert, status, statusText } = await this.axios.post(`/api/alert`, {
enabled: true,
name,
tags: ['foo'],
alertTypeId: 'test.noop',
consumer: 'consumer-noop',
schedule: { interval: '1m' },
throttle: '1m',
actions: [],
params: {},
});
if (status !== 200) {
throw new Error(
`Expected status code of 200, received ${status} ${statusText}: ${util.inspect(alert)}`
);
}

this.log.debug(`created alert ${alert.id}`);

return alert;
}

public async createAlwaysFiringWithActions(
name: string,
actions: Array<{
Expand Down

0 comments on commit 2d48a31

Please sign in to comment.