Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solutions][Timeline] Added createFrom in action to hide #98144

Merged
merged 10 commits into from
Apr 29, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,38 @@
*/

import React from 'react';
import { shallow } from 'enzyme';
import { mount, shallow } from 'enzyme';

import { QueryBarDefineRule } from './index';
import { useFormFieldMock } from '../../../../common/mock';
import {
TestProviders,
useFormFieldMock,
mockOpenTimelineQueryResults,
} from '../../../../common/mock';
import { mockHistory, Router } from '../../../../cases/components/__mock__/router';
import { useGetAllTimeline, getAllTimeline } from '../../../../timelines/containers/all';

jest.mock('../../../../common/lib/kibana');

jest.mock('../../../../timelines/containers/all', () => {
const originalModule = jest.requireActual('../../../../timelines/containers/all');
return {
...originalModule,
useGetAllTimeline: jest.fn(),
};
});

describe('QueryBarDefineRule', () => {
beforeEach(() => {
((useGetAllTimeline as unknown) as jest.Mock).mockReturnValue({
fetchAllTimeline: jest.fn(),
timelines: getAllTimeline('', mockOpenTimelineQueryResults.timeline ?? []),
loading: false,
totalCount: mockOpenTimelineQueryResults.totalCount,
refetch: jest.fn(),
});
});

it('renders correctly', () => {
const Component = () => {
const field = useFormFieldMock();
Expand All @@ -32,7 +56,36 @@ describe('QueryBarDefineRule', () => {
);
};
const wrapper = shallow(<Component />);

expect(wrapper.dive().find('[data-test-subj="query-bar-define-rule"]')).toHaveLength(1);
});

it('renders import query from saved timeline modal with no timeline action correctly', () => {
const Component = () => {
const field = useFormFieldMock();

return (
<QueryBarDefineRule
browserFields={{}}
isLoading={false}
indexPattern={{ fields: [], title: 'title' }}
onCloseTimelineSearch={jest.fn()}
openTimelineSearch={true}
dataTestSubj="query-bar-define-rule"
idAria="idAria"
field={field}
/>
);
};
const wrapper = mount(
<TestProviders>
<Router history={mockHistory}>
<Component />
</Router>
</TestProviders>
);

const firstRow = wrapper.find('[data-test-subj="timelines-table"] table tbody tr').first();
const actionsCell = firstRow.find('.euiTableRowCell').last();
expect(actionsCell.find('.euiTableCellContent').isEmptyRender()).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,10 @@ export const QueryBarDefineRule = ({
}
};

const actionTimelineToHide = useMemo<ActionTimelineToShow[]>(() => ['duplicate'], []);
const actionTimelineToHide = useMemo<ActionTimelineToShow[]>(
Copy link
Contributor

@angorayc angorayc Apr 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems doesn't change, please consider put this as a constant and move out of the component.

const actionTimelineToHide = ['duplicate', 'createFrom'];

() => ['duplicate', 'createFrom'],
[]
);

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,30 @@

import { mount, ReactWrapper } from 'enzyme';
import React from 'react';
import { waitFor } from '@testing-library/react';

import { AddTimelineButton } from './';
import { useKibana } from '../../../../common/lib/kibana';
import { TimelineId } from '../../../../../common/types/timeline';
import { mockOpenTimelineQueryResults, TestProviders } from '../../../../common/mock';
import { mockHistory, Router } from '../../../../cases/components/__mock__/router';
import { getAllTimeline, useGetAllTimeline } from '../../../containers/all';

jest.mock('../../../../common/lib/kibana', () => {
const originalModule = jest.requireActual('../../../../common/lib/kibana');
return {
...originalModule,
useKibana: jest.fn(),
useUiSetting$: jest.fn().mockReturnValue([]),
};
});

jest.mock('../../../../common/lib/kibana', () => ({
useKibana: jest.fn(),
useUiSetting$: jest.fn().mockReturnValue([]),
}));
jest.mock('../../../containers/all', () => {
const originalModule = jest.requireActual('../../../containers/all');
return {
...originalModule,
useGetAllTimeline: jest.fn(),
};
});

jest.mock('../../timeline/properties/new_template_timeline', () => ({
NewTemplateTimeline: jest.fn(() => <div data-test-subj="create-template-btn" />),
Expand All @@ -35,8 +49,7 @@ jest.mock('../../../../common/components/inspect', () => ({
InspectButtonContainer: jest.fn(({ children }) => <div>{children}</div>),
}));

// FLAKY: https://github.com/elastic/kibana/issues/96691
describe.skip('AddTimelineButton', () => {
describe('AddTimelineButton', () => {
let wrapper: ReactWrapper;
const props = {
timelineId: TimelineId.active,
Expand Down Expand Up @@ -67,24 +80,18 @@ describe.skip('AddTimelineButton', () => {
});

test('it renders create timeline btn', async () => {
await waitFor(() => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
expect(wrapper.find('[data-test-subj="create-default-btn"]').exists()).toBeTruthy();
});
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click').update();
Copy link
Contributor

@angorayc angorayc Apr 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing the tests!! Could we try putting back waitFor and just moving ...simulate(click) out of waitFor? If that works fine, let's apply this to rest of the tests in this file.

expect(wrapper.find('[data-test-subj="create-default-btn"]').exists()).toBeTruthy();
});

test('it renders create timeline template btn', async () => {
await waitFor(() => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
expect(wrapper.find('[data-test-subj="create-template-btn"]').exists()).toBeTruthy();
});
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click').update();
expect(wrapper.find('[data-test-subj="create-template-btn"]').exists()).toBeTruthy();
});

test('it renders Open timeline btn', async () => {
await waitFor(() => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
expect(wrapper.find('[data-test-subj="open-timeline-button"]').exists()).toBeTruthy();
});
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click').update();
expect(wrapper.find('[data-test-subj="open-timeline-button"]').exists()).toBeTruthy();
});
});

Expand Down Expand Up @@ -112,25 +119,71 @@ describe.skip('AddTimelineButton', () => {
expect(wrapper.find('[data-test-subj="settings-plus-in-circle"]').exists()).toBeTruthy();
});

test('it renders create timeline btn', async () => {
await waitFor(() => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
expect(wrapper.find('[data-test-subj="create-default-btn"]').exists()).toBeTruthy();
});
test('it renders create timeline btn', () => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click').update();
expect(wrapper.find('[data-test-subj="create-default-btn"]').exists()).toBeTruthy();
});

test('it renders create timeline template btn', async () => {
await waitFor(() => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
expect(wrapper.find('[data-test-subj="create-template-btn"]').exists()).toBeTruthy();
});
test('it renders create timeline template btn', () => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click').update();
expect(wrapper.find('[data-test-subj="create-template-btn"]').exists()).toBeTruthy();
});

test('it renders Open timeline btn', async () => {
await waitFor(() => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
expect(wrapper.find('[data-test-subj="open-timeline-button"]').exists()).toBeTruthy();
test('it renders Open timeline btn', () => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click').update();
expect(wrapper.find('[data-test-subj="open-timeline-button"]').exists()).toBeTruthy();
});
});

describe('open modal', () => {
beforeEach(() => {
(useKibana as jest.Mock).mockReturnValue({
services: {
application: {
getUrlForApp: jest.fn(),
capabilities: {
siem: {
crud: true,
},
},
},
},
});

((useGetAllTimeline as unknown) as jest.Mock).mockReturnValue({
fetchAllTimeline: jest.fn(),
timelines: getAllTimeline('', mockOpenTimelineQueryResults.timeline ?? []),
loading: false,
totalCount: mockOpenTimelineQueryResults.totalCount,
refetch: jest.fn(),
});

wrapper = mount(
<TestProviders>
<Router history={mockHistory}>
<AddTimelineButton {...props} />
</Router>
</TestProviders>
);
});

afterEach(() => {
(useKibana as jest.Mock).mockReset();
});

it('should render timelines table', () => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click').update();
wrapper.find('[data-test-subj="open-timeline-button"]').first().simulate('click').update();

expect(wrapper.find('[data-test-subj="timelines-table"]').exists()).toBeTruthy();
});

it('should render correct actions', () => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click').update();
wrapper.find('[data-test-subj="open-timeline-button"]').first().simulate('click').update();

expect(wrapper.find('[data-test-subj="open-duplicate"]').exists()).toBeTruthy();
expect(wrapper.find('[data-test-subj="create-from-template"]').exists()).toBeFalsy();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import React, { useCallback, useMemo, useState } from 'react';

import { OpenTimelineModalButton } from '../../open_timeline/open_timeline_modal/open_timeline_modal_button';
import { OpenTimelineModal } from '../../open_timeline/open_timeline_modal';
import { ActionTimelineToShow } from '../../open_timeline/types';
import * as i18n from '../../timeline/properties/translations';
import { NewTimeline } from '../../timeline/properties/helpers';
import { NewTemplateTimeline } from '../../timeline/properties/new_template_timeline';
Expand Down Expand Up @@ -47,6 +48,8 @@ const AddTimelineButtonComponent: React.FC<AddTimelineButtonComponentProps> = ({
[onButtonClick]
);

const actionTimelineToHide = useMemo<ActionTimelineToShow[]>(() => ['createFrom'], []);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could put this as a constant and move out of the component as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes 👍
I was thinking to do so, but I followed the same way as it was in query_bar


return (
<>
<EuiFlexItem grow={false}>
Expand Down Expand Up @@ -83,7 +86,9 @@ const AddTimelineButtonComponent: React.FC<AddTimelineButtonComponentProps> = ({
</EuiPopover>
</EuiFlexItem>

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