diff --git a/x-pack/plugins/observability/public/hooks/use_get_filtered_rule_types.ts b/x-pack/plugins/observability/public/hooks/use_get_filtered_rule_types.ts
new file mode 100644
index 0000000000000..d72118182ed65
--- /dev/null
+++ b/x-pack/plugins/observability/public/hooks/use_get_filtered_rule_types.ts
@@ -0,0 +1,15 @@
+/*
+ * 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 { useMemo } from 'react';
+import { usePluginContext } from './use_plugin_context';
+
+export function useGetFilteredRuleTypes() {
+ const { observabilityRuleTypeRegistry } = usePluginContext();
+
+ return useMemo(() => observabilityRuleTypeRegistry.list(), [observabilityRuleTypeRegistry]);
+}
diff --git a/x-pack/plugins/observability/public/observability_public_plugins_start.mock.ts b/x-pack/plugins/observability/public/observability_public_plugins_start.mock.tsx
similarity index 50%
rename from x-pack/plugins/observability/public/observability_public_plugins_start.mock.ts
rename to x-pack/plugins/observability/public/observability_public_plugins_start.mock.tsx
index 31aa38cb2fd49..6ccca21b37907 100644
--- a/x-pack/plugins/observability/public/observability_public_plugins_start.mock.ts
+++ b/x-pack/plugins/observability/public/observability_public_plugins_start.mock.tsx
@@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-
+import React from 'react';
import { mockCasesContract } from '@kbn/cases-plugin/public/mocks';
const embeddableStartMock = {
@@ -26,13 +26,39 @@ const embeddableStartMock = {
const triggersActionsUiStartMock = {
createStart() {
return {
- getAddAlertFlyout: jest.fn(),
- getAlertsSearchBar: jest.fn(),
- getRuleStatusDropdown: jest.fn(),
- getRuleTagBadge: jest.fn(),
- getRuleStatusFilter: jest.fn(),
- getRuleTagFilter: jest.fn(),
- getRulesList: jest.fn(),
+ getAddAlertFlyout: jest.fn(() => (
+
mocked component
+ )),
+ getAlertsSearchBar: jest.fn(() => (
+ mocked component
+ )),
+ getAlertsStateTable: jest.fn(() => (
+ mocked component
+ )),
+ getEditAlertFlyout: jest.fn(() => (
+ mocked component
+ )),
+ getRuleAlertsSummary: jest.fn(() => (
+ mocked component
+ )),
+ getRuleDefinition: jest.fn(() => (
+ mocked component
+ )),
+ getRuleEventLogList: jest.fn(() => (
+ mocked component
+ )),
+ getRuleStatusDropdown: jest.fn(() => (
+ mocked component
+ )),
+ getRuleStatusPanel: jest.fn(() => (
+ mocked component
+ )),
+ getRuleTagBadge: jest.fn(() => mocked component
),
+ getRuleStatusFilter: jest.fn(() => (
+ mocked component
+ )),
+ getRuleTagFilter: jest.fn(() => mocked component
),
+ getRulesList: jest.fn(() => mocked component
),
ruleTypeRegistry: {
has: jest.fn(),
register: jest.fn(),
diff --git a/x-pack/plugins/observability/public/pages/rules/index.test.tsx b/x-pack/plugins/observability/public/pages/rules/index.test.tsx
index 5c1a66246cd53..fafa723c1aa1b 100644
--- a/x-pack/plugins/observability/public/pages/rules/index.test.tsx
+++ b/x-pack/plugins/observability/public/pages/rules/index.test.tsx
@@ -6,11 +6,9 @@
*/
import React from 'react';
-import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers';
-import { act } from 'react-dom/test-utils';
-import { ReactWrapper } from 'enzyme';
+import { render } from '@testing-library/react';
import { CoreStart } from '@kbn/core/public';
-import { ConfigSchema, ObservabilityPublicPluginsStart } from '../../plugin';
+import { ObservabilityPublicPluginsStart } from '../../plugin';
import { RulesPage } from '.';
import { kibanaStartMock } from '../../utils/kibana_react.mock';
import * as pluginContext from '../../hooks/use_plugin_context';
@@ -34,20 +32,18 @@ jest.mock('@kbn/triggers-actions-ui-plugin/public', () => ({
useLoadRuleTypes: jest.fn(),
}));
-const config = {
- unsafe: {
- alertDetails: {
- apm: { enabled: false },
- logs: { enabled: false },
- metrics: { enabled: false },
- uptime: { enabled: false },
- },
- },
-} as ConfigSchema;
-
jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({
appMountParameters: {} as AppMountParameters,
- config,
+ config: {
+ unsafe: {
+ alertDetails: {
+ apm: { enabled: false },
+ logs: { enabled: false },
+ metrics: { enabled: false },
+ uptime: { enabled: false },
+ },
+ },
+ },
observabilityRuleTypeRegistry: createObservabilityRuleTypeRegistryMock(),
ObservabilityPageTemplate: KibanaPageTemplate,
kibanaFeatures: [],
@@ -58,9 +54,8 @@ jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({
const { useLoadRuleTypes } = jest.requireMock('@kbn/triggers-actions-ui-plugin/public');
describe('RulesPage with all capabilities', () => {
- let wrapper: ReactWrapper;
async function setup() {
- const mockedRuleTypeIndex = new Map(
+ const ruleTypeIndex = new Map(
Object.entries({
'1': {
enabledInLicense: true,
@@ -79,6 +74,7 @@ describe('RulesPage with all capabilities', () => {
},
})
);
+
const ruleTypes = [
{
id: 'test_rule_type',
@@ -96,51 +92,34 @@ describe('RulesPage with all capabilities', () => {
ruleTaskTimeout: '1m',
},
];
+
useLoadRuleTypes.mockReturnValue({
ruleTypes,
- ruleTypeIndex: mockedRuleTypeIndex,
- });
- wrapper = mountWithIntl();
- await act(async () => {
- await nextTick();
- wrapper.update();
+ ruleTypeIndex,
});
+
+ return render();
}
- it('renders table of rules', async () => {
- await setup();
- const getRulesList = mockUseKibanaReturnValue.services.triggersActionsUi.getRulesList;
- expect(getRulesList).toHaveBeenCalled();
- expect(getRulesList).toHaveBeenCalledWith(
- expect.objectContaining({
- showActionFilter: false,
- showCreateRuleButton: false,
- ruleDetailsRoute: 'alerts/rules/:ruleId',
- filteredRuleTypes: ['ruleType1', 'ruleType2'],
- rulesListKey: 'observability_rulesListColumns',
- visibleColumns: [
- 'ruleName',
- 'ruleExecutionStatusLastDate',
- 'ruleSnoozeNotify',
- 'ruleExecutionStatus',
- 'ruleExecutionState',
- ],
- })
- );
+ it('should render a page template', async () => {
+ const wrapper = await setup();
+ expect(wrapper.getByTestId('rulesPage')).toBeInTheDocument();
});
- it('renders a create rule button that is not disabled', async () => {
- await setup();
- expect(wrapper.find('[data-test-subj="createRuleButton"]').hostNodes().prop('disabled')).toBe(
- false
- );
+ it('should render a RuleList ', async () => {
+ const wrapper = await setup();
+ expect(wrapper.getByTestId('rules-list')).toBeInTheDocument();
+ });
+
+ it('renders a create rule button which is not disabled', async () => {
+ const wrapper = await setup();
+ expect(wrapper.getByTestId('createRuleButton')).not.toBeDisabled();
});
});
describe('RulesPage with show only capability', () => {
- let wrapper: ReactWrapper;
async function setup() {
- const mockedRuleTypeIndex = new Map(
+ const ruleTypeIndex = new Map(
Object.entries({
'1': {
enabledInLicense: true,
@@ -159,6 +138,7 @@ describe('RulesPage with show only capability', () => {
},
})
);
+
const ruleTypes = [
{
id: 'test_rule_type',
@@ -176,16 +156,13 @@ describe('RulesPage with show only capability', () => {
ruleTaskTimeout: '1m',
},
];
- useLoadRuleTypes.mockReturnValue({ ruleTypes, ruleTypeIndex: mockedRuleTypeIndex });
+ useLoadRuleTypes.mockReturnValue({ ruleTypes, ruleTypeIndex });
- wrapper = mountWithIntl();
+ return render();
}
- it('renders a create rule button that is disabled', async () => {
- await setup();
-
- expect(wrapper.find('[data-test-subj="createRuleButton"]').hostNodes().prop('disabled')).toBe(
- true
- );
+ it('renders a create rule button which is not disabled', async () => {
+ const wrapper = await setup();
+ expect(wrapper.getByTestId('createRuleButton')).toBeDisabled();
});
});
diff --git a/x-pack/plugins/observability/public/pages/rules/index.tsx b/x-pack/plugins/observability/public/pages/rules/index.tsx
index 7051aa68d944f..166e62b06d261 100644
--- a/x-pack/plugins/observability/public/pages/rules/index.tsx
+++ b/x-pack/plugins/observability/public/pages/rules/index.tsx
@@ -5,19 +5,19 @@
* 2.0.
*/
-import React, { useState, useMemo } from 'react';
+import React, { useState } from 'react';
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { useLoadRuleTypes } from '@kbn/triggers-actions-ui-plugin/public';
-import type { RulesListVisibleColumns } from '@kbn/triggers-actions-ui-plugin/public';
import { ALERTS_FEATURE_ID } from '@kbn/alerting-plugin/common';
+import type { RulesListVisibleColumns } from '@kbn/triggers-actions-ui-plugin/public';
-import { usePluginContext } from '../../hooks/use_plugin_context';
import { Provider, rulesPageStateContainer, useRulesPageStateContainer } from './state_container';
-
-import { useBreadcrumbs } from '../../hooks/use_breadcrumbs';
import { useKibana } from '../../utils/kibana_react';
+import { usePluginContext } from '../../hooks/use_plugin_context';
+import { useBreadcrumbs } from '../../hooks/use_breadcrumbs';
+import { useGetFilteredRuleTypes } from '../../hooks/use_get_filtered_rule_types';
import { RULES_PAGE_TITLE, RULES_BREADCRUMB_TEXT } from './translations';
const RULES_LIST_COLUMNS_KEY = 'observability_rulesListColumns';
@@ -30,22 +30,23 @@ const RULES_LIST_COLUMNS: RulesListVisibleColumns[] = [
];
function RulesPage() {
- const { ObservabilityPageTemplate, observabilityRuleTypeRegistry } = usePluginContext();
- const { http, docLinks, triggersActionsUi } = useKibana().services;
-
- const documentationLink = docLinks.links.observability.createAlerts;
-
- const filteredRuleTypes = useMemo(
- () => observabilityRuleTypeRegistry.list(),
- [observabilityRuleTypeRegistry]
- );
+ const { ObservabilityPageTemplate } = usePluginContext();
+ const {
+ http,
+ docLinks,
+ triggersActionsUi: { getAddAlertFlyout: AddAlertFlyout, getRulesList: RuleList },
+ } = useKibana().services;
const { status, setStatus, lastResponse, setLastResponse } = useRulesPageStateContainer();
- const [createRuleFlyoutVisibility, setCreateRuleFlyoutVisibility] = useState(false);
- const [refresh, setRefresh] = useState(new Date());
+
+ const filteredRuleTypes = useGetFilteredRuleTypes();
const { ruleTypes } = useLoadRuleTypes({
filteredRuleTypes,
});
+
+ const [addRuleFlyoutVisibility, setAddRuleFlyoutVisibility] = useState(false);
+ const [refresh, setRefresh] = useState(new Date());
+
const authorizedRuleTypes = [...ruleTypes.values()];
const authorizedToCreateAnyRules = authorizedRuleTypes.some(
@@ -64,54 +65,6 @@ function RulesPage() {
},
]);
- const CreateRuleFlyout = useMemo(
- () =>
- triggersActionsUi.getAddAlertFlyout({
- consumer: ALERTS_FEATURE_ID,
- onClose: () => {
- setCreateRuleFlyoutVisibility(false);
- },
- onSave: () => {
- setRefresh(new Date());
- return Promise.resolve();
- },
- filteredRuleTypes,
- }),
- // eslint-disable-next-line react-hooks/exhaustive-deps
- [filteredRuleTypes]
- );
-
- const getRulesTable = useMemo(() => {
- return (
- <>
-
-
- {triggersActionsUi.getRulesList({
- filteredRuleTypes,
- showActionFilter: false,
- showCreateRuleButton: false,
- ruleDetailsRoute: 'alerts/rules/:ruleId',
- statusFilter: status,
- onStatusFilterChange: setStatus,
- lastResponseFilter: lastResponse,
- onLastResponseFilterChange: setLastResponse,
- refresh,
- rulesListKey: RULES_LIST_COLUMNS_KEY,
- visibleColumns: RULES_LIST_COLUMNS,
- })}
-
-
- >
- );
- }, [
- triggersActionsUi,
- filteredRuleTypes,
- status,
- setStatus,
- lastResponse,
- setLastResponse,
- refresh,
- ]);
return (
setCreateRuleFlyoutVisibility(true)}
+ onClick={() => setAddRuleFlyoutVisibility(true)}
>
,
,
],
}}
+ data-test-subj="rulesPage"
>
- {getRulesTable}
- {createRuleFlyoutVisibility && CreateRuleFlyout}
+
+
+
+
+
+
+ {addRuleFlyoutVisibility && (
+ {
+ setAddRuleFlyoutVisibility(false);
+ }}
+ onSave={() => {
+ setRefresh(new Date());
+ return Promise.resolve();
+ }}
+ />
+ )}
);
}