Skip to content

Commit

Permalink
Merge branch 'main' into fix/142123
Browse files Browse the repository at this point in the history
  • Loading branch information
dej611 authored Oct 4, 2022
2 parents 6c70c07 + 10884e6 commit ab56cd2
Show file tree
Hide file tree
Showing 40 changed files with 895 additions and 150 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const CaseViewAlerts = ({ caseData }: CaseViewAlertsProps) => {
}),
[caseData.comments]
);

const alertRegistrationContexts = useMemo(
() => getRegistrationContextFromAlerts(caseData.comments),
[caseData.comments]
Expand Down
6 changes: 5 additions & 1 deletion x-pack/plugins/cases/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@ const uiMock: jest.Mocked<CasesUiStart['ui']> = {
getRecentCases: jest.fn(),
};

export const openAddToExistingCaseModalMock = jest.fn();

const hooksMock: jest.Mocked<CasesUiStart['hooks']> = {
getUseCasesAddToNewCaseFlyout: jest.fn(),
getUseCasesAddToExistingCaseModal: jest.fn(),
getUseCasesAddToExistingCaseModal: jest.fn().mockImplementation(() => ({
open: openAddToExistingCaseModalMock,
})),
};

const helpersMock: jest.Mocked<CasesUiStart['helpers']> = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ interface AlertDetailParams {

export const useFetchAlertDetail = (id: string): [boolean, TopAlert | null] => {
const { observabilityRuleTypeRegistry } = usePluginContext();

const params = useMemo(
() => ({ id, ruleType: observabilityRuleTypeRegistry }),
[id, observabilityRuleTypeRegistry]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,58 @@

import React from 'react';
import * as useUiSettingHook from '@kbn/kibana-react-plugin/public/ui_settings/use_ui_setting';
import { useParams } from 'react-router-dom';
import { Chance } from 'chance';
import { waitFor } from '@testing-library/react';
import { casesPluginMock } from '@kbn/cases-plugin/public/mocks';
import { triggersActionsUiMock } from '@kbn/triggers-actions-ui-plugin/public/mocks';

import { render } from '../../../utils/test_helper';
import { useKibana } from '../../../utils/kibana_react';
import { kibanaStartMock } from '../../../utils/kibana_react.mock';
import { useFetchAlertDetail } from '../../../hooks/use_fetch_alert_detail';
import { AlertDetails } from './alert_details';
import { Chance } from 'chance';
import { useParams } from 'react-router-dom';
import { useBreadcrumbs } from '../../../hooks/use_breadcrumbs';
import { AlertDetails } from './alert_details';
import { ConfigSchema } from '../../../plugin';
import { alert, alertWithNoData } from '../mock/alert';
import { waitFor } from '@testing-library/react';

jest.mock('../../../hooks/use_fetch_alert_detail');
jest.mock('../../../hooks/use_breadcrumbs');
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: jest.fn(),
}));

jest.mock('../../../utils/kibana_react');

const useKibanaMock = useKibana as jest.Mock;

const mockKibana = () => {
useKibanaMock.mockReturnValue({
services: {
...kibanaStartMock.startContract(),
cases: casesPluginMock.createStartContract(),
http: {
basePath: {
prepend: jest.fn(),
},
},
triggersActionsUi: triggersActionsUiMock.createStart(),
},
});
};

jest.mock('../../../hooks/use_fetch_alert_detail');
jest.mock('../../../hooks/use_breadcrumbs');
jest.mock('../../../hooks/use_get_user_cases_permissions', () => ({
useGetUserCasesPermissions: () => ({
all: true,
create: true,
delete: true,
push: true,
read: true,
update: true,
}),
}));

const useFetchAlertDetailMock = useFetchAlertDetail as jest.Mock;
const useParamsMock = useParams as jest.Mock;
const useBreadcrumbsMock = useBreadcrumbs as jest.Mock;
Expand All @@ -49,16 +84,20 @@ describe('Alert details', () => {
jest.clearAllMocks();
useParamsMock.mockReturnValue(params);
useBreadcrumbsMock.mockReturnValue([]);
mockKibana();
});

it('should show alert summary', async () => {
it('should show the alert detail page with all necessary components', async () => {
useFetchAlertDetailMock.mockReturnValue([false, alert]);

const alertDetails = render(<AlertDetails />, config);

expect(alertDetails.queryByTestId('alertDetails')).toBeTruthy();
await waitFor(() => expect(alertDetails.queryByTestId('centerJustifiedSpinner')).toBeFalsy());

expect(alertDetails.queryByTestId('alertDetails')).toBeTruthy();
expect(alertDetails.queryByTestId('alertDetailsError')).toBeFalsy();
expect(alertDetails.queryByTestId('page-title-container')).toBeTruthy();
expect(alertDetails.queryByTestId('alert-summary-container')).toBeTruthy();
});

it('should show error loading the alert details', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,36 @@ import React from 'react';
import { i18n } from '@kbn/i18n';
import { useParams } from 'react-router-dom';
import { EuiEmptyPrompt, EuiPanel } from '@elastic/eui';

import { useKibana } from '../../../utils/kibana_react';
import { ObservabilityAppServices } from '../../../application/types';
import { usePluginContext } from '../../../hooks/use_plugin_context';
import { useBreadcrumbs } from '../../../hooks/use_breadcrumbs';
import { paths } from '../../../config/paths';
import { AlertDetailsPathParams } from '../types';
import { useFetchAlertDetail } from '../../../hooks/use_fetch_alert_detail';

import { AlertSummary, HeaderActions, PageTitle } from '.';
import { CenterJustifiedSpinner } from '../../rule_details/components/center_justified_spinner';
import { AlertSummary } from '.';
import PageNotFound from '../../404';
import { useFetchAlertDetail } from '../../../hooks/use_fetch_alert_detail';

import { ObservabilityAppServices } from '../../../application/types';
import { AlertDetailsPathParams } from '../types';
import { observabilityFeatureId } from '../../../../common';
import { paths } from '../../../config/paths';

export function AlertDetails() {
const { http } = useKibana<ObservabilityAppServices>().services;
const {
http,
cases: {
helpers: { canUseCases },
ui: { getCasesContext },
},
} = useKibana<ObservabilityAppServices>().services;
const { ObservabilityPageTemplate, config } = usePluginContext();
const { alertId } = useParams<AlertDetailsPathParams>();
const [isLoading, alert] = useFetchAlertDetail(alertId);

const CasesContext = getCasesContext();
const userCasesPermissions = canUseCases();

useBreadcrumbs([
{
href: http.basePath.prepend(paths.observability.alerts),
Expand Down Expand Up @@ -69,7 +82,22 @@ export function AlertDetails() {
);

return (
<ObservabilityPageTemplate data-test-subj="alertDetails">
<ObservabilityPageTemplate
pageHeader={{
pageTitle: <PageTitle title={alert?.reason} active={Boolean(alert?.active)} />,
rightSideItems: [
<CasesContext
owner={[observabilityFeatureId]}
permissions={userCasesPermissions}
features={{ alerts: { sync: false } }}
>
<HeaderActions alert={alert} />
</CasesContext>,
],
bottomBorder: false,
}}
data-test-subj="alertDetails"
>
<AlertSummary alert={alert} />
</ObservabilityPageTemplate>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export function AlertSummary({ alert }: AlertSummaryProps) {
const tags = alert?.fields[ALERT_RULE_TAGS];

return (
<>
<div data-test-subj="alert-summary-container">
<EuiFlexGroup>
<EuiFlexItem>
<EuiTitle size="xxs">
Expand Down Expand Up @@ -161,6 +161,6 @@ export function AlertSummary({ alert }: AlertSummaryProps) {
</div>
</EuiFlexItem>
</EuiFlexGroup>
</>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* 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 { fireEvent } from '@testing-library/react';
import { triggersActionsUiMock } from '@kbn/triggers-actions-ui-plugin/public/mocks';
import { casesPluginMock, openAddToExistingCaseModalMock } from '@kbn/cases-plugin/public/mocks';

import { render } from '../../../utils/test_helper';
import { useKibana } from '../../../utils/kibana_react';
import { kibanaStartMock } from '../../../utils/kibana_react.mock';
import { alertWithTags, mockAlertUuid } from '../mock/alert';

import { HeaderActions } from './header_actions';

jest.mock('../../../utils/kibana_react');

const useKibanaMock = useKibana as jest.Mock;

const mockKibana = () => {
useKibanaMock.mockReturnValue({
services: {
...kibanaStartMock.startContract(),
triggersActionsUi: triggersActionsUiMock.createStart(),
cases: casesPluginMock.createStartContract(),
},
});
};

const ruleId = '123';
const ruleName = '456';

jest.mock('../../../hooks/use_fetch_rule', () => {
return {
useFetchRule: () => ({
reloadRule: jest.fn(),
rule: {
id: ruleId,
name: ruleName,
},
}),
};
});

describe('Header Actions', () => {
beforeEach(() => {
jest.clearAllMocks();
mockKibana();
});

it('should display an actions button', () => {
const { queryByTestId } = render(<HeaderActions alert={alertWithTags} />);
expect(queryByTestId('alert-details-header-actions-menu-button')).toBeTruthy();
});

describe('when clicking the actions button', () => {
it('should offer an "add to case" button which opens the add to case modal', async () => {
const { getByTestId, findByRole } = render(<HeaderActions alert={alertWithTags} />);

fireEvent.click(await findByRole('button', { name: 'Actions' }));

fireEvent.click(getByTestId('add-to-case-button'));

expect(openAddToExistingCaseModalMock).toBeCalledWith({
attachments: [
{
alertId: mockAlertUuid,
index: '.internal.alerts-observability.metrics.alerts-*',
rule: {
id: ruleId,
name: ruleName,
},
type: 'alert',
},
],
});
});
});
});
Loading

0 comments on commit ab56cd2

Please sign in to comment.