[RAM] Alerts table functional tests (#137857)

* first commit

* [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix'

* add triggersActionsUi as service

* use same configurationId

* add triggers action ui page object

* load infra alerts

* rollback triggers actions ui page and working test

* restore removed tests

* remove not needed fragment

* refactor test to use examples plugin

* remove import from moved resource

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Julian Gernun 2022-08-08 19:25:22 +02:00 committed by GitHub
parent f37d7e1f2c
commit 762962dcf8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 174 additions and 37 deletions

View file

@ -13,7 +13,8 @@
"data",
"alerting",
"developerExamples",
"kibanaReact"
"kibanaReact",
"cases"
],
"optionalPlugins": [],
"requiredBundles": []

View file

@ -13,6 +13,7 @@ import { AppMountParameters, CoreStart } from '@kbn/core/public';
import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';
import { TriggersActionsUiExamplePublicStartDeps } from './plugin';
import { Page } from './components/page';
@ -25,6 +26,7 @@ import { RuleTagFilterSandbox } from './components/rule_tag_filter_sandbox';
import { RuleEventLogListSandbox } from './components/rule_event_log_list_sandbox';
import { RuleStatusDropdownSandbox } from './components/rule_status_dropdown_sandbox';
import { RuleStatusFilterSandbox } from './components/rule_status_filter_sandbox';
import { AlertsTableSandbox } from './components/alerts_table_sandbox';
export interface TriggersActionsUiExampleComponentParams {
http: CoreStart['http'];
@ -114,6 +116,14 @@ const TriggersActionsUiExampleApp = ({
</Page>
)}
/>
<Route
path="/alerts_table"
render={() => (
<Page title="Alerts Table">
<AlertsTableSandbox triggersActionsUi={triggersActionsUi} />
</Page>
)}
/>
</EuiPage>
</Router>
);
@ -136,12 +146,14 @@ export const renderApp = (
actionTypeRegistry,
}}
>
<TriggersActionsUiExampleApp
basename={appBasePath}
http={http}
triggersActionsUi={deps.triggersActionsUi}
data={deps.data}
/>
<IntlProvider locale="en">
<TriggersActionsUiExampleApp
basename={appBasePath}
http={http}
triggersActionsUi={deps.triggersActionsUi}
data={deps.data}
/>
</IntlProvider>
</KibanaContextProvider>,
element
);

View file

@ -0,0 +1,37 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public';
import { AlertsTableStateProps } from '@kbn/triggers-actions-ui-plugin/public/application/sections/alerts_table/alerts_table_state';
import { AlertConsumers } from '@kbn/rule-data-utils';
interface SandboxProps {
triggersActionsUi: TriggersAndActionsUIPublicPluginStart;
}
export const AlertsTableSandbox = ({ triggersActionsUi }: SandboxProps) => {
const { getAlertsStateTable: AlertsTable, alertsTableConfigurationRegistry } = triggersActionsUi;
const alertStateProps: AlertsTableStateProps = {
id: 'observabilityCases',
configurationId: 'observabilityCases',
alertsTableConfigurationRegistry,
featureIds: [
AlertConsumers.INFRASTRUCTURE,
AlertConsumers.APM,
AlertConsumers.OBSERVABILITY,
AlertConsumers.LOGS,
],
query: {
bool: {
filter: [],
},
},
showExpandToDetails: true,
};
return <AlertsTable {...alertStateProps} />;
};

View file

@ -59,6 +59,11 @@ export const Sidebar = () => {
name: 'Rule Status Filter',
onClick: () => history.push(`/rule_status_filter`),
},
{
id: 'alerts table',
name: 'Alert Table',
onClick: () => history.push('/alerts_table'),
},
],
},
]}

View file

@ -5,15 +5,30 @@
* 2.0.
*/
import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '@kbn/core/public';
import React from 'react';
import {
Plugin,
CoreSetup,
AppMountParameters,
AppNavLinkStatus,
CoreStart,
} from '@kbn/core/public';
import { PluginSetupContract as AlertingSetup } from '@kbn/alerting-plugin/public';
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
import { get } from 'lodash';
import {
TriggersAndActionsUIPublicPluginSetup,
TriggersAndActionsUIPublicPluginStart,
} from '@kbn/triggers-actions-ui-plugin/public';
import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry';
import {
AlertsTableConfigurationRegistry,
AlertsTableFlyoutBaseProps,
AlertTableFlyoutComponent,
} from '@kbn/triggers-actions-ui-plugin/public/types';
import { SortCombinations } from '@elastic/elasticsearch/lib/api/types';
import { EuiDataGridColumn } from '@elastic/eui';
export interface TriggersActionsUiExamplePublicSetupDeps {
alerting: AlertingSetup;
@ -40,7 +55,12 @@ export class TriggersActionsUiExamplePlugin
id: 'triggersActionsUiExample',
title: 'Triggers Actions UI Example',
navLinkStatus: AppNavLinkStatus.hidden,
async mount(params: AppMountParameters) {
// category set as cases expects the label to exist
category: {
id: 'fakeId',
label: 'fakeLabel',
},
mount: async (params: AppMountParameters) => {
const [coreStart, devStart] = await core.getStartServices();
const { renderApp } = await import('./application');
return renderApp(coreStart, devStart, params);
@ -54,6 +74,81 @@ export class TriggersActionsUiExamplePlugin
'Sandbox for shared reusable alerting components (triggers actions UI shareable components)',
});
}
public start() {}
public start(
coreStart: CoreStart,
{ triggersActionsUi }: TriggersActionsUiExamplePublicStartDeps
) {
const {
alertsTableConfigurationRegistry,
}: { alertsTableConfigurationRegistry: TypeRegistry<AlertsTableConfigurationRegistry> } =
triggersActionsUi;
const columns: EuiDataGridColumn[] = [
{
id: 'event.action',
displayAsText: 'Alert status',
initialWidth: 150,
},
{
id: '@timestamp',
displayAsText: 'Last updated',
initialWidth: 250,
},
{
id: 'kibana.alert.duration.us',
displayAsText: 'Duration',
initialWidth: 150,
},
{
id: 'kibana.alert.reason',
displayAsText: 'Reason',
},
];
const FlyoutBody: AlertTableFlyoutComponent = ({ alert }: AlertsTableFlyoutBaseProps) => (
<ul>
{columns.map((column) => (
<li data-test-subj={`alertsFlyout${column.displayAsText}`} key={column.id}>
{get(alert as any, column.id, [])[0]}
</li>
))}
</ul>
);
const FlyoutHeader: AlertTableFlyoutComponent = ({ alert }: AlertsTableFlyoutBaseProps) => {
const { 'kibana.alert.rule.name': name } = alert;
return <div data-test-subj="alertsFlyoutName">{name}</div>;
};
const useInternalFlyout = () => ({
body: FlyoutBody,
header: FlyoutHeader,
footer: null,
});
const sort: SortCombinations[] = [
{
'event.action': {
order: 'asc',
},
},
];
const config: AlertsTableConfigurationRegistry = {
id: 'observabilityCases',
casesFeatureId: 'observabilityCases',
columns,
useInternalFlyout,
getRenderCellValue: () => (props: any) => {
const value = props.data.find((d: any) => d.field === props.columnId)?.value ?? [];
return <>{value.length ? value.join() : '--'}</>;
},
sort,
};
alertsTableConfigurationRegistry.register(config);
}
public stop() {}
}

View file

@ -6,35 +6,36 @@
*/
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../ftr_provider_context';
import { FtrProviderContext } from '../../../../test/functional/ftr_provider_context';
export default ({ getPageObjects, getService }: FtrProviderContext) => {
// eslint-disable-next-line import/no-default-export
export default function ({ getPageObjects, getService }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const browser = getService('browser');
const PageObjects = getPageObjects(['common', 'triggersActionsUI', 'header']);
const PageObjects = getPageObjects(['common', 'header']);
const retry = getService('retry');
const esArchiver = getService('esArchiver');
const find = getService('find');
describe.skip('Alerts table', function () {
describe('Alerts table', function () {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts');
});
after(async () => {
await esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts');
});
beforeEach(async () => {
await PageObjects.common.navigateToApp('triggersActionsUiExample/alerts_table');
await waitTableIsLoaded();
});
afterEach(async () => {
await browser.clearLocalStorage();
});
it('should load the table', async () => {
await PageObjects.common.navigateToUrlWithBrowserHistory('triggersActions', '/alerts');
const headingText = await PageObjects.triggersActionsUI.getSectionHeadingText();
expect(headingText).to.be('Rules and Connectors');
await waitTableIsLoaded();
const rows = await getRows();
expect(rows.length).to.be(10);
expect(rows[0].status).to.be('active');
@ -46,12 +47,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
});
it('should sort properly', async () => {
await PageObjects.common.navigateToUrlWithBrowserHistory('triggersActions', '/alerts');
const headingText = await PageObjects.triggersActionsUI.getSectionHeadingText();
expect(headingText).to.be('Rules and Connectors');
await waitTableIsLoaded();
await find.clickDisplayedByCssSelector(
'[data-test-subj="dataGridHeaderCell-event.action"] .euiDataGridHeaderCell__button'
);
@ -72,12 +67,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
});
it('should paginate properly', async () => {
await PageObjects.common.navigateToUrlWithBrowserHistory('triggersActions', '/alerts');
const headingText = await PageObjects.triggersActionsUI.getSectionHeadingText();
expect(headingText).to.be('Rules and Connectors');
await waitTableIsLoaded();
await testSubjects.click('pagination-button-1');
await waitTableIsLoaded();
@ -93,8 +82,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
});
it('should open a flyout and paginate through the flyout', async () => {
await PageObjects.common.navigateToUrlWithBrowserHistory('triggersActions', '/alerts');
await waitTableIsLoaded();
await testSubjects.click('expandColumnCellOpenFlyoutButton-0');
await waitFlyoutOpen();
await waitFlyoutIsLoaded();
@ -174,4 +161,4 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
return rows;
}
});
};
}

View file

@ -15,5 +15,6 @@ export default ({ loadTestFile, getService }: FtrProviderContext) => {
loadTestFile(require.resolve('./rule_tag_badge'));
loadTestFile(require.resolve('./rule_event_log_list'));
loadTestFile(require.resolve('./rules_list'));
loadTestFile(require.resolve('./alerts_table'));
});
};

View file

@ -14,6 +14,5 @@ export default ({ loadTestFile, getService }: FtrProviderContext) => {
loadTestFile(require.resolve('./alert_create_flyout'));
loadTestFile(require.resolve('./details'));
loadTestFile(require.resolve('./connectors'));
loadTestFile(require.resolve('./alerts_table'));
});
};