Skip to content

Commit

Permalink
Create PageHeader comp again
Browse files Browse the repository at this point in the history
  • Loading branch information
CoenWarmer committed Sep 30, 2022
1 parent 5fdd100 commit bfb6b58
Show file tree
Hide file tree
Showing 23 changed files with 570 additions and 440 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
5 changes: 1 addition & 4 deletions x-pack/plugins/observability/public/config/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@
* 2.0.
*/

const APP_BASE = '/app/observability';
export const ALERT_PAGE_LINK = `${APP_BASE}/alerts`;
export const ALERT_PAGE_LINK = '/app/observability/alerts';
export const RULES_PAGE_LINK = `${ALERT_PAGE_LINK}/rules`;
export const CASES_PAGE_LINK = `${APP_BASE}/cases`;
export const CASES_CREATE_NEW_PAGE_LINK = `${CASES_PAGE_LINK}/create`;

export const paths = {
observability: {
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,102 @@
/*
* 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();
});

const mockViewInExternalApp = jest.fn();

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',
},
],
});
});
});

it('should show a connector action if passed an externalConnector prop', async () => {
const { findByRole, getByTestId } = render(
<HeaderActions
alert={alertWithTags}
externalConnector={{ name: 'foo', onViewInExternalApp: mockViewInExternalApp }}
/>
);

fireEvent.click(await findByRole('button', { name: 'Actions' }));
const button = getByTestId('view-in-external-app-button');
expect(button).toBeTruthy();

fireEvent.click(button);

expect(mockViewInExternalApp).toBeCalledTimes(1);
});
});
Loading

0 comments on commit bfb6b58

Please sign in to comment.