Skip to content

Commit

Permalink
[Security Solution][Timeline] refactor timeline modal open timeline b…
Browse files Browse the repository at this point in the history
…utton (#175335)
  • Loading branch information
PhilippeOberti authored Jan 24, 2024
1 parent 98cb0c2 commit 5d25406
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { InputsModelId } from '../../../../common/store/inputs/constants';
import { AddToCaseButton } from '../add_to_case_button';
import { NewTimelineAction } from './new_timeline';
import { SaveTimelineButton } from './save_timeline_button';
import { OpenTimelineAction } from './open_timeline';
import { OpenTimelineButton } from '../../modal/actions/open_timeline_button';
import { TIMELINE_TOUR_CONFIG_ANCHORS } from '../../timeline/tour/step_config';

interface TimelineActionMenuProps {
Expand Down Expand Up @@ -54,7 +54,7 @@ const TimelineActionMenuComponent = ({
<NewTimelineAction timelineId={timelineId} />
</EuiFlexItem>
<EuiFlexItem data-test-subj="open-timeline-action">
<OpenTimelineAction />
<OpenTimelineButton />
</EuiFlexItem>
<EuiFlexItem data-test-subj="inspect-timeline-action">
<InspectButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,6 @@ export const NEW_TIMELINE = i18n.translate(
}
);

export const OPEN_TIMELINE_BTN = i18n.translate(
'xpack.securitySolution.flyout.timeline.actionMenu.openTimelineBtn',
{
defaultMessage: 'Open',
}
);

export const OPEN_TIMELINE_BTN_LABEL = i18n.translate(
'xpack.securitySolution.flyout.timeline.actionMenu.openTimelineBtnLabel',
{
defaultMessage: 'Open Existing Timeline',
}
);

export const SAVE_TIMELINE_BTN = i18n.translate(
'xpack.securitySolution.flyout.timeline.actionMenu.saveTimelineBtn',
{
defaultMessage: 'Save',
}
);

export const SAVE_TIMELINE_BTN_LABEL = i18n.translate(
'xpack.securitySolution.flyout.timeline.actionMenu.saveTimelineBtnLabel',
{
defaultMessage: 'Save currently opened Timeline',
}
);

export const NEW_TEMPLATE_TIMELINE = i18n.translate(
'xpack.securitySolution.flyout.timeline.actionMenu.newTimelineTemplate',
{
Expand All @@ -66,14 +38,6 @@ export const CALL_OUT_UNAUTHORIZED_MSG = i18n.translate(
}
);

export const CALL_OUT_IMMUTABLE = i18n.translate(
'xpack.securitySolution.timeline.callOut.immutable.message.description',
{
defaultMessage:
'This prebuilt timeline template cannot be modified. To make changes, please duplicate this template and make modifications to the duplicate template.',
}
);

export const SAVE_TIMELINE = i18n.translate(
'xpack.securitySolution.timeline.saveTimeline.modal.header',
{
Expand Down Expand Up @@ -149,24 +113,10 @@ export const OPTIONAL = i18n.translate(
}
);

export const SAVE_TOUR_CLOSE = i18n.translate(
'xpack.securitySolution.timeline.flyout.saveTour.closeButton',
{
defaultMessage: 'Close',
}
);

export const TITLE = i18n.translate('xpack.securitySolution.timeline.saveTimeline.modal.title', {
defaultMessage: 'Title',
});

export const SAVE_TOUR_TITLE = i18n.translate(
'xpack.securitySolution.timeline.flyout.saveTour.title',
{
defaultMessage: 'Timeline changes now require manual saves',
}
);

export const SAVE_AS_NEW = i18n.translate(
'xpack.securitySolution.timeline.saveTimeline.modal.saveAsNew',
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* 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 { render, waitFor } from '@testing-library/react';
import React from 'react';
import { OpenTimelineButton } from './open_timeline_button';
import { TestProviders } from '../../../../common/mock/test_providers';
import { useParams } from 'react-router-dom';
import { TimelineType } from '../../../../../common/api/timeline';
import { useStartTransaction } from '../../../../common/lib/apm/use_start_transaction';
import { useSourcererDataView } from '../../../../common/containers/sourcerer';
import { useTimelineStatus } from '../../open_timeline/use_timeline_status';

jest.mock('../../../../common/lib/apm/use_start_transaction');
jest.mock('../../../../common/containers/sourcerer');
jest.mock('../../open_timeline/use_timeline_status');
jest.mock('react-redux', () => {
const origin = jest.requireActual('react-redux');
return {
...origin,
useDispatch: jest.fn(),
};
});
jest.mock('react-router-dom', () => {
const actual = jest.requireActual('react-router-dom');
return {
...actual,
useParams: jest.fn(),
};
});
jest.mock('../../../../common/lib/kibana', () => {
const actual = jest.requireActual('../../../../common/lib/kibana');
return {
...actual,
useNavigation: () => ({
navigateTo: jest.fn(),
}),
};
});

const renderOpenTimelineButton = () =>
render(
<TestProviders>
<OpenTimelineButton />
</TestProviders>
);

describe('OpenTimelineButton', () => {
it('should render the button', () => {
const { getByTestId, queryByTestId } = renderOpenTimelineButton();

expect(getByTestId('timeline-modal-open-timeline-button')).toBeInTheDocument();
expect(getByTestId('timeline-modal-open-timeline-button')).toHaveTextContent('Open');

expect(queryByTestId('open-timeline-modal')).not.toBeInTheDocument();
});

it('should open the modal after clicking on the button', async () => {
(useParams as jest.Mock).mockReturnValue({ tabName: TimelineType.template });
(useStartTransaction as jest.Mock).mockReturnValue({ startTransaction: jest.fn() });
(useSourcererDataView as jest.Mock).mockReturnValue({ dataViewId: '', selectedPatterns: [] });
(useTimelineStatus as jest.Mock).mockReturnValue({
timelineStatus: 'active',
templateTimelineFilter: null,
installPrepackagedTimelines: jest.fn(),
});

const { getByTestId } = renderOpenTimelineButton();

getByTestId('timeline-modal-open-timeline-button').click();

await waitFor(() => {
expect(getByTestId('open-timeline-modal')).toBeInTheDocument();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,28 @@ import * as i18n from './translations';

const actionTimelineToHide: ActionTimelineToShow[] = ['createFrom'];

export const OpenTimelineAction = React.memo(() => {
/**
* Renders a button that opens the `OpenTimelineModal` to allow users to select a saved timeline to open
*/
export const OpenTimelineButton = React.memo(() => {
const [showTimelineModal, setShowTimelineModal] = useState(false);
const onCloseTimelineModal = useCallback(() => setShowTimelineModal(false), []);
const onOpenTimelineModal = useCallback(() => {
setShowTimelineModal(true);
}, []);
const toggleTimelineModal = useCallback(() => setShowTimelineModal((prev) => !prev), []);

return (
<>
<EuiButtonEmpty
data-test-subj="open-timeline-button"
onClick={onOpenTimelineModal}
data-test-subj="timeline-modal-open-timeline-button"
onClick={toggleTimelineModal}
aria-label={i18n.OPEN_TIMELINE_BTN_LABEL}
>
{i18n.OPEN_TIMELINE_BTN}
</EuiButtonEmpty>

{showTimelineModal ? (
<OpenTimelineModal onClose={onCloseTimelineModal} hideActions={actionTimelineToHide} />
<OpenTimelineModal onClose={toggleTimelineModal} hideActions={actionTimelineToHide} />
) : null}
</>
);
});

OpenTimelineAction.displayName = 'OpenTimelineAction';
OpenTimelineButton.displayName = 'OpenTimelineButton';
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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 { i18n } from '@kbn/i18n';

export const OPEN_TIMELINE_BTN = i18n.translate(
'xpack.securitySolution.timeline.modal.openTimelineBtn',
{
defaultMessage: 'Open',
}
);

export const OPEN_TIMELINE_BTN_LABEL = i18n.translate(
'xpack.securitySolution.timeline.modal.openTimelineBtnLabel',
{
defaultMessage: 'Open Existing Timeline',
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const DELETE_NOTE = '[data-test-subj="delete-note"]';
export const MARKDOWN_INVESTIGATE_BUTTON =
'[data-test-subj="insight-investigate-in-timeline-button"]';

export const OPEN_TIMELINE_ICON = '[data-test-subj="open-timeline-button"]';
export const OPEN_TIMELINE_ICON = '[data-test-subj="timeline-modal-open-timeline-button"]';

export const OPEN_TIMELINE_MODAL = '[data-test-subj="open-timeline-modal"]';

Expand Down

0 comments on commit 5d25406

Please sign in to comment.