mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Security Solution] Disable renderer hover actions in the Rules preview flyout (#141546)
## [Security Solution] Disable hover actions on renderers in the Rules preview flyout This PR addresses issue <https://github.com/elastic/kibana/issues/141026> by disabling hover actions on renderers in the _Rules preview_ flyout, per the Before and After screenshots below: ### Before  _Above: Before the fix, actions were displayed when hovering over a rendered field in the Rules preview flyout_ ### After  _Above: After the fix, actions are NOT displayed when hovering over a rendered field in the Rules preview flyout_
This commit is contained in:
parent
504d8c4c70
commit
f571f80827
2 changed files with 108 additions and 3 deletions
|
@ -5,16 +5,24 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import type { DraggableStateSnapshot, DraggingStyle } from 'react-beautiful-dnd';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
|
||||
import '../../mock/match_media';
|
||||
import { TimelineId } from '../../../../common/types';
|
||||
import { mockBrowserFields } from '../../containers/source/mock';
|
||||
import { TestProviders } from '../../mock';
|
||||
import { mockDataProviders } from '../../../timelines/components/timeline/data_providers/mock/mock_data_providers';
|
||||
import { ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID } from '../../../timelines/components/row_renderers_browser/constants';
|
||||
import { DragDropContextWrapper } from './drag_drop_context_wrapper';
|
||||
import { ConditionalPortal, DraggableWrapper, getStyle } from './draggable_wrapper';
|
||||
import {
|
||||
ConditionalPortal,
|
||||
disableHoverActions,
|
||||
DraggableWrapper,
|
||||
getStyle,
|
||||
} from './draggable_wrapper';
|
||||
import { useMountAppended } from '../../utils/use_mount_appended';
|
||||
|
||||
jest.mock('../../lib/kibana');
|
||||
|
@ -27,6 +35,26 @@ jest.mock('@elastic/eui', () => {
|
|||
};
|
||||
});
|
||||
|
||||
const timelineIdsWithHoverActions = [
|
||||
undefined,
|
||||
TimelineId.active,
|
||||
TimelineId.alternateTest,
|
||||
TimelineId.casePage,
|
||||
TimelineId.detectionsPage,
|
||||
TimelineId.detectionsRulesDetailsPage,
|
||||
TimelineId.hostsPageEvents,
|
||||
TimelineId.hostsPageSessions,
|
||||
TimelineId.kubernetesPageSessions,
|
||||
TimelineId.networkPageEvents,
|
||||
TimelineId.test,
|
||||
TimelineId.usersPageEvents,
|
||||
];
|
||||
|
||||
const timelineIdsNoHoverActions = [
|
||||
TimelineId.rulePreview,
|
||||
ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID,
|
||||
];
|
||||
|
||||
describe('DraggableWrapper', () => {
|
||||
const dataProvider = mockDataProviders[0];
|
||||
const message = 'draggable wrapper content';
|
||||
|
@ -36,6 +64,15 @@ describe('DraggableWrapper', () => {
|
|||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
const portal = document.querySelector('[data-euiportal="true"]');
|
||||
if (portal != null) {
|
||||
portal.innerHTML = '';
|
||||
}
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
describe('rendering', () => {
|
||||
test('it renders against the snapshot', () => {
|
||||
const wrapper = shallow(
|
||||
|
@ -103,6 +140,56 @@ describe('DraggableWrapper', () => {
|
|||
expect(wrapper.find('[data-test-subj="hover-actions-copy-button"]').exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
timelineIdsWithHoverActions.forEach((timelineId) => {
|
||||
test(`it renders hover actions (by default) when 'isDraggable' is false and timelineId is '${timelineId}'`, async () => {
|
||||
const isDraggable = false;
|
||||
|
||||
const { container } = render(
|
||||
<TestProviders>
|
||||
<DragDropContextWrapper browserFields={mockBrowserFields}>
|
||||
<DraggableWrapper
|
||||
dataProvider={dataProvider}
|
||||
isDraggable={isDraggable}
|
||||
render={() => message}
|
||||
timelineId={timelineId}
|
||||
/>
|
||||
</DragDropContextWrapper>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
fireEvent.mouseEnter(container.querySelector('[data-test-subj="withHoverActionsButton"]')!);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('hover-actions-copy-button')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
timelineIdsNoHoverActions.forEach((timelineId) => {
|
||||
test(`it does NOT render hover actions when 'isDraggable' is false and timelineId is '${timelineId}'`, async () => {
|
||||
const isDraggable = false;
|
||||
|
||||
const { container } = render(
|
||||
<TestProviders>
|
||||
<DragDropContextWrapper browserFields={mockBrowserFields}>
|
||||
<DraggableWrapper
|
||||
dataProvider={dataProvider}
|
||||
isDraggable={isDraggable}
|
||||
render={() => message}
|
||||
timelineId={timelineId}
|
||||
/>
|
||||
</DragDropContextWrapper>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
fireEvent.mouseEnter(container.querySelector('[data-test-subj="withHoverActionsButton"]')!);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId('hover-actions-copy-button')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('text truncation styling', () => {
|
||||
|
@ -192,4 +279,18 @@ describe('ConditionalPortal', () => {
|
|||
expect(getStyle(style, snapshot)).toHaveProperty('transitionDuration', '0.00000001s');
|
||||
});
|
||||
});
|
||||
|
||||
describe('disableHoverActions', () => {
|
||||
timelineIdsNoHoverActions.forEach((timelineId) =>
|
||||
test(`it returns true when timelineId is ${timelineId}`, () => {
|
||||
expect(disableHoverActions(timelineId)).toBe(true);
|
||||
})
|
||||
);
|
||||
|
||||
timelineIdsWithHoverActions.forEach((timelineId) =>
|
||||
test(`it returns false when timelineId is ${timelineId}`, () => {
|
||||
expect(disableHoverActions(timelineId)).toBe(false);
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,6 +18,7 @@ import { Draggable, Droppable } from 'react-beautiful-dnd';
|
|||
import { useDispatch } from 'react-redux';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { TimelineId } from '../../../../common/types';
|
||||
import { dragAndDropActions } from '../../store/drag_and_drop';
|
||||
import type { DataProvider } from '../../../timelines/components/timeline/data_providers/data_provider';
|
||||
import { ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID } from '../../../timelines/components/row_renderers_browser/constants';
|
||||
|
@ -108,6 +109,9 @@ interface Props {
|
|||
onFilterAdded?: () => void;
|
||||
}
|
||||
|
||||
export const disableHoverActions = (timelineId: string | undefined): boolean =>
|
||||
[TimelineId.rulePreview, ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID].includes(timelineId ?? '');
|
||||
|
||||
/**
|
||||
* Wraps a draggable component to handle registration / unregistration of the
|
||||
* data provider associated with the item being dropped
|
||||
|
@ -370,7 +374,7 @@ const DraggableWrapperComponent: React.FC<Props> = ({
|
|||
<WithHoverActions
|
||||
alwaysShow={showTopN || hoverActionsOwnFocus}
|
||||
closePopOverTrigger={closePopOverTrigger}
|
||||
hoverContent={hoverContent}
|
||||
hoverContent={disableHoverActions(timelineId) ? undefined : hoverContent}
|
||||
onCloseRequested={onCloseRequested}
|
||||
render={renderContent}
|
||||
/>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue