[Security Solution] Fix tooltip for timeline sourcerer (#115950)

* fix tooltip for event picker

* remove unused mock

* remove unused dependency

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Angela Chuang 2021-10-25 11:16:13 +01:00 committed by GitHub
parent ed99e2466a
commit 780c43513a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 215 additions and 114 deletions

View file

@ -7,6 +7,9 @@
import React from 'react';
import { mount } from 'enzyme';
import { waitFor } from '@testing-library/react';
import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui';
import { SourcererScopeName } from '../../store/sourcerer/model';
import { Sourcerer } from './index';
import { DEFAULT_INDEX_PATTERN } from '../../../../common/constants';
@ -19,8 +22,6 @@ import {
TestProviders,
} from '../../mock';
import { createStore, State } from '../../store';
import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui';
import { waitFor } from '@testing-library/react';
const mockDispatch = jest.fn();
jest.mock('react-redux', () => {
@ -46,6 +47,7 @@ const mockOptions = [
const defaultProps = {
scope: sourcererModel.SourcererScopeName.default,
};
describe('Sourcerer component', () => {
beforeEach(() => {
jest.clearAllMocks();
@ -59,6 +61,34 @@ describe('Sourcerer component', () => {
store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage);
});
it('renders tooltip', () => {
const wrapper = mount(
<TestProviders>
<Sourcerer {...defaultProps} />
</TestProviders>
);
expect(wrapper.find('[data-test-subj="sourcerer-tooltip"]').prop('content')).toEqual(
mockOptions
.map((p) => p.label)
.sort()
.join(', ')
);
});
it('renders popover button inside tooltip', () => {
const wrapper = mount(
<TestProviders>
<Sourcerer {...defaultProps} />
</TestProviders>
);
expect(
wrapper
.find('[data-test-subj="sourcerer-tooltip"] [data-test-subj="sourcerer-trigger"]')
.exists()
).toBeTruthy();
});
// Using props callback instead of simulating clicks,
// because EuiSelectable uses a virtualized list, which isn't easily testable via test subjects
it('Mounts with all options selected', () => {

View file

@ -169,55 +169,62 @@ export const Sourcerer = React.memo<SourcererComponentProps>(({ scope: scopeId }
[isPopoverOpen, sourcererScope.selectedPatterns]
);
const buttonWithTooptip = useMemo(() => {
return tooltipContent ? (
<EuiToolTip position="top" content={tooltipContent} data-test-subj="sourcerer-tooltip">
{trigger}
</EuiToolTip>
) : (
trigger
);
}, [trigger, tooltipContent]);
return (
<EuiToolTip position="top" content={tooltipContent}>
<EuiPopover
data-test-subj="sourcerer-popover"
button={trigger}
isOpen={isPopoverOpen}
closePopover={handleClosePopOver}
display="block"
panelPaddingSize="s"
repositionOnScroll
ownFocus
>
<PopoverContent>
<EuiPopoverTitle>
<>{i18n.SELECT_INDEX_PATTERNS}</>
</EuiPopoverTitle>
<EuiSpacer size="s" />
<EuiText color="default">{i18n.INDEX_PATTERNS_SELECTION_LABEL}</EuiText>
<EuiSpacer size="xs" />
{comboBox}
<EuiSpacer size="s" />
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween">
<EuiFlexItem>
<ResetButton
aria-label={i18n.INDEX_PATTERNS_RESET}
data-test-subj="sourcerer-reset"
flush="left"
onClick={resetDataSources}
title={i18n.INDEX_PATTERNS_RESET}
>
{i18n.INDEX_PATTERNS_RESET}
</ResetButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
onClick={handleSaveIndices}
disabled={isSavingDisabled}
data-test-subj="add-index"
fill
fullWidth
size="s"
>
{i18n.SAVE_INDEX_PATTERNS}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</PopoverContent>
</EuiPopover>
</EuiToolTip>
<EuiPopover
data-test-subj="sourcerer-popover"
button={buttonWithTooptip}
isOpen={isPopoverOpen}
closePopover={handleClosePopOver}
panelPaddingSize="s"
repositionOnScroll
ownFocus
>
<PopoverContent>
<EuiPopoverTitle>
<>{i18n.SELECT_INDEX_PATTERNS}</>
</EuiPopoverTitle>
<EuiSpacer size="s" />
<EuiText color="default">{i18n.INDEX_PATTERNS_SELECTION_LABEL}</EuiText>
<EuiSpacer size="xs" />
{comboBox}
<EuiSpacer size="s" />
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween">
<EuiFlexItem>
<ResetButton
aria-label={i18n.INDEX_PATTERNS_RESET}
data-test-subj="sourcerer-reset"
flush="left"
onClick={resetDataSources}
title={i18n.INDEX_PATTERNS_RESET}
>
{i18n.INDEX_PATTERNS_RESET}
</ResetButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
onClick={handleSaveIndices}
disabled={isSavingDisabled}
data-test-subj="add-index"
fill
fullWidth
size="s"
>
{i18n.SAVE_INDEX_PATTERNS}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</PopoverContent>
</EuiPopover>
);
});
Sourcerer.displayName = 'Sourcerer';

View file

@ -5,7 +5,9 @@
* 2.0.
*/
import { fireEvent, render } from '@testing-library/react';
import { fireEvent, render, within } from '@testing-library/react';
import { EuiToolTip } from '@elastic/eui';
import React from 'react';
import { PickEventType } from './pick_events';
import {
@ -19,6 +21,14 @@ import { TimelineEventsType } from '../../../../../common';
import { createStore } from '../../../../common/store';
import { SourcererScopeName } from '../../../../common/store/sourcerer/model';
jest.mock('@elastic/eui', () => {
const actual = jest.requireActual('@elastic/eui');
return {
...actual,
EuiToolTip: jest.fn(),
};
});
describe('pick_events', () => {
const defaultProps = {
eventType: 'all' as TimelineEventsType,
@ -53,6 +63,23 @@ describe('pick_events', () => {
},
};
const store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage);
const mockTooltip = ({
tooltipContent,
children,
}: {
tooltipContent: string;
children: React.ReactElement;
}) => (
<div data-test-subj="timeline-sourcerer-tooltip">
<span>{tooltipContent}</span>
{children}
</div>
);
beforeAll(() => {
(EuiToolTip as unknown as jest.Mock).mockImplementation(mockTooltip);
});
beforeEach(() => {
jest.clearAllMocks();
jest.restoreAllMocks();
@ -68,6 +95,32 @@ describe('pick_events', () => {
initialPatterns.sort().join('')
);
});
it('renders tooltip', () => {
render(
<TestProviders>
<PickEventType {...defaultProps} />
</TestProviders>
);
expect((EuiToolTip as unknown as jest.Mock).mock.calls[0][0].content).toEqual(
initialPatterns
.filter((p) => p != null)
.sort()
.join(', ')
);
});
it('renders popover button inside tooltip', () => {
const wrapper = render(
<TestProviders>
<PickEventType {...defaultProps} />
</TestProviders>
);
const tooltip = wrapper.getByTestId('timeline-sourcerer-tooltip');
expect(within(tooltip).getByTestId('sourcerer-timeline-trigger')).toBeTruthy();
});
it('correctly filters options', () => {
const wrapper = render(
<TestProviders store={store}>

View file

@ -295,6 +295,20 @@ const PickEventTypeComponents: React.FC<PickEventTypeProps> = ({
[isPopoverOpen, sourcererScope.selectedPatterns]
);
const buttonWithTooptip = useMemo(() => {
return tooltipContent ? (
<EuiToolTip
position="top"
content={tooltipContent}
data-test-subj="timeline-sourcerer-tooltip"
>
{button}
</EuiToolTip>
) : (
button
);
}, [button, tooltipContent]);
const ButtonContent = useMemo(
() => (
<AdvancedSettings data-test-subj="advanced-settings">
@ -326,69 +340,66 @@ const PickEventTypeComponents: React.FC<PickEventTypeProps> = ({
return (
<PickEventContainer>
<EuiToolTip position="top" content={tooltipContent}>
<EuiPopover
button={button}
closePopover={closePopover}
id="popover"
isOpen={isPopoverOpen}
ownFocus
repositionOnScroll
>
<PopoverContent>
<EuiPopoverTitle>
<>{i18n.SELECT_INDEX_PATTERNS}</>
</EuiPopoverTitle>
<EuiSpacer size="s" />
{filter}
<EuiSpacer size="m" />
<EuiAccordion
id="accordion1"
forceState={showAdvanceSettings ? 'open' : 'closed'}
buttonContent={ButtonContent}
onToggle={setAdvanceSettings}
>
<>
<EuiSpacer size="s" />
{comboBox}
</>
</EuiAccordion>
{!showAdvanceSettings && (
<>
<EuiSpacer size="s" />
<ConfigHelper size="s" color="subdued">
{i18n.CONFIGURE_INDEX_PATTERNS}
</ConfigHelper>
</>
)}
<EuiSpacer size="m" />
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween">
<EuiFlexItem>
<ResetButton
aria-label={i18n.DATA_SOURCES_RESET}
data-test-subj="sourcerer-reset"
flush="left"
onClick={resetDataSources}
title={i18n.DATA_SOURCES_RESET}
>
{i18n.DATA_SOURCES_RESET}
</ResetButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
onClick={handleSaveIndices}
data-test-subj="add-index"
fill
fullWidth
size="s"
>
{i18n.SAVE_INDEX_PATTERNS}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</PopoverContent>
</EuiPopover>
</EuiToolTip>
<EuiPopover
button={buttonWithTooptip}
closePopover={closePopover}
id="popover"
isOpen={isPopoverOpen}
repositionOnScroll
>
<PopoverContent>
<EuiPopoverTitle>
<>{i18n.SELECT_INDEX_PATTERNS}</>
</EuiPopoverTitle>
<EuiSpacer size="s" />
{filter}
<EuiSpacer size="m" />
<EuiAccordion
id="accordion1"
forceState={showAdvanceSettings ? 'open' : 'closed'}
buttonContent={ButtonContent}
onToggle={setAdvanceSettings}
>
<>
<EuiSpacer size="s" />
{comboBox}
</>
</EuiAccordion>
{!showAdvanceSettings && (
<>
<EuiSpacer size="s" />
<ConfigHelper size="s" color="subdued">
{i18n.CONFIGURE_INDEX_PATTERNS}
</ConfigHelper>
</>
)}
<EuiSpacer size="m" />
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween">
<EuiFlexItem>
<ResetButton
aria-label={i18n.DATA_SOURCES_RESET}
data-test-subj="sourcerer-reset"
flush="left"
onClick={resetDataSources}
title={i18n.DATA_SOURCES_RESET}
>
{i18n.DATA_SOURCES_RESET}
</ResetButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
onClick={handleSaveIndices}
data-test-subj="add-index"
fill
fullWidth
size="s"
>
{i18n.SAVE_INDEX_PATTERNS}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</PopoverContent>
</EuiPopover>
</PickEventContainer>
);
};