diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx
index 0320daa2ec338..ac254714adbb7 100644
--- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx
@@ -45,9 +45,9 @@ jest.mock('./utils', () => ({
getCustomChartData: jest.fn().mockReturnValue(true),
}));
-const mockUseVisualizationResponse = jest.fn(() => [
- { aggregations: [{ buckets: [{ key: '1234' }] }], hits: { total: 999 } },
-]);
+const mockUseVisualizationResponse = jest.fn(() => ({
+ responses: [{ aggregations: [{ buckets: [{ key: '1234' }] }], hits: { total: 999 } }],
+}));
jest.mock('../visualization_actions/use_visualization_response', () => ({
useVisualizationResponse: () => mockUseVisualizationResponse(),
}));
@@ -345,9 +345,9 @@ describe('Matrix Histogram Component', () => {
});
test('it should render 0 as subtitle when buckets are empty', () => {
- mockUseVisualizationResponse.mockReturnValue([
- { aggregations: [{ buckets: [] }], hits: { total: 999 } },
- ]);
+ mockUseVisualizationResponse.mockReturnValue({
+ responses: [{ aggregations: [{ buckets: [] }], hits: { total: 999 } }],
+ });
mockUseMatrix.mockReturnValue([
false,
{
diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/__mocks__/use_actions.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/__mocks__/use_actions.ts
new file mode 100644
index 0000000000000..9f5f46fb67f68
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/__mocks__/use_actions.ts
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+export const VISUALIZATION_CONTEXT_MENU_TRIGGER = 'VISUALIZATION_CONTEXT_MENU_TRIGGER';
+export const DEFAULT_ACTIONS = [
+ 'inspect',
+ 'addToNewCase',
+ 'addToExistingCase',
+ 'saveToLibrary',
+ 'openInLens',
+];
+export const MOCK_ACTIONS = [
+ {
+ id: 'inspect',
+ getDisplayName: () => 'Inspect',
+ getIconType: () => 'inspect',
+ type: 'actionButton',
+ order: 4,
+ isCompatible: () => true,
+ execute: jest.fn(),
+ },
+ {
+ id: 'addToNewCase',
+ getDisplayName: () => 'Add to new case',
+ getIconType: () => 'casesApp',
+ type: 'actionButton',
+ order: 3,
+ isCompatible: () => true,
+ execute: jest.fn(),
+ },
+ {
+ id: 'addToExistingCase',
+ getDisplayName: () => 'Add to existing case',
+ getIconType: () => 'casesApp',
+ type: 'actionButton',
+ order: 2,
+ isCompatible: () => true,
+ execute: jest.fn(),
+ },
+ {
+ id: 'saveToLibrary',
+ getDisplayName: () => 'Added to library',
+ getIconType: () => 'save',
+ type: 'actionButton',
+ order: 1,
+ isCompatible: () => true,
+ execute: jest.fn(),
+ },
+ {
+ id: 'openInLens',
+ getDisplayName: () => 'Open in Lens',
+ getIconType: () => 'visArea',
+ type: 'actionButton',
+ order: 0,
+ isCompatible: () => true,
+ execute: jest.fn(),
+ },
+];
+export const useActions = jest.fn().mockReturnValue(MOCK_ACTIONS);
diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/actions.test.tsx b/x-pack/plugins/security_solution/public/common/components/visualization_actions/actions.test.tsx
index 924b1158593a7..b3fd18989991c 100644
--- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/actions.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/actions.test.tsx
@@ -5,66 +5,36 @@
* 2.0.
*/
import React from 'react';
-import { fireEvent, render, screen } from '@testing-library/react';
-import type { Action } from '@kbn/ui-actions-plugin/public';
+import { EuiContextMenu } from '@elastic/eui';
+
+import { fireEvent, render, waitFor } from '@testing-library/react';
import { getDnsTopDomainsLensAttributes } from './lens_attributes/network/dns_top_domains';
import { VisualizationActions } from './actions';
-import {
- createSecuritySolutionStorageMock,
- kibanaObservable,
- mockGlobalState,
- SUB_PLUGINS_REDUCER,
- TestProviders,
-} from '../../mock';
-import type { State } from '../../store';
-import { createStore } from '../../store';
-import type { UpdateQueryParams } from '../../store/inputs/helpers';
-import { upsertQuery } from '../../store/inputs/helpers';
-import { cloneDeep } from 'lodash';
-import { useKibana } from '../../lib/kibana/kibana_react';
-import { CASES_FEATURE_ID } from '../../../../common/constants';
-import { mockCasesContract } from '@kbn/cases-plugin/public/mocks';
-import { allCasesCapabilities, allCasesPermissions } from '../../../cases_test_utils';
-import { InputsModelId } from '../../store/inputs/constants';
+import { TestProviders } from '../../mock';
+
import type { VisualizationActionsProps } from './types';
import * as useLensAttributesModule from './use_lens_attributes';
import { SourcererScopeName } from '../../store/sourcerer/model';
-jest.mock('react-router-dom', () => {
- const actual = jest.requireActual('react-router-dom');
+jest.mock('./use_actions');
+
+jest.mock('../inspect/use_inspect', () => {
return {
- ...actual,
- useLocation: jest.fn(() => {
- return { pathname: 'network' };
- }),
+ useInspect: jest.fn().mockReturnValue({}),
};
});
-jest.mock('../../lib/kibana/kibana_react');
-jest.mock('../../utils/route/use_route_spy', () => {
+
+jest.mock('@elastic/eui', () => {
+ const original = jest.requireActual('@elastic/eui');
return {
- useRouteSpy: jest.fn(() => [{ pageName: 'network', detailName: '', tabName: 'dns' }]),
+ ...original,
+ EuiContextMenu: jest.fn().mockReturnValue(
),
};
});
describe('VisualizationActions', () => {
- const refetch = jest.fn();
- const state: State = mockGlobalState;
- const { storage } = createSecuritySolutionStorageMock();
- const newQuery: UpdateQueryParams = {
- inputId: InputsModelId.global,
- id: 'networkDnsHistogramQuery',
- inspect: {
- dsl: ['mockDsl'],
- response: ['mockResponse'],
- },
- loading: false,
- refetch,
- state: state.inputs,
- };
const spyUseLensAttributes = jest.spyOn(useLensAttributesModule, 'useLensAttributes');
-
- let store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage);
const props: VisualizationActionsProps = {
getLensAttributes: getDnsTopDomainsLensAttributes,
queryId: 'networkDnsHistogramQuery',
@@ -76,64 +46,15 @@ describe('VisualizationActions', () => {
extraOptions: { dnsIsPtrIncluded: true },
stackByField: 'dns.question.registered_domain',
};
- const mockNavigateToPrefilledEditor = jest.fn();
- const mockGetCreateCaseFlyoutOpen = jest.fn();
- const mockGetAllCasesSelectorModalOpen = jest.fn();
+ const mockContextMenu = EuiContextMenu as unknown as jest.Mock;
beforeEach(() => {
jest.clearAllMocks();
- const cases = mockCasesContract();
- cases.helpers.getUICapabilities.mockReturnValue(allCasesPermissions());
-
- (useKibana as jest.Mock).mockReturnValue({
- services: {
- lens: {
- canUseEditor: jest.fn(() => true),
- navigateToPrefilledEditor: mockNavigateToPrefilledEditor,
- },
- cases: {
- ...mockCasesContract(),
- hooks: {
- useCasesAddToExistingCaseModal: jest
- .fn()
- .mockReturnValue({ open: mockGetAllCasesSelectorModalOpen }),
- useCasesAddToNewCaseFlyout: jest
- .fn()
- .mockReturnValue({ open: mockGetCreateCaseFlyoutOpen }),
- },
- helpers: { canUseCases: jest.fn().mockReturnValue(allCasesPermissions()) },
- },
- application: {
- capabilities: { [CASES_FEATURE_ID]: allCasesCapabilities() },
- getUrlForApp: jest.fn(),
- navigateToApp: jest.fn(),
- },
- notifications: {
- toasts: {
- addError: jest.fn(),
- addSuccess: jest.fn(),
- addWarning: jest.fn(),
- remove: jest.fn(),
- },
- },
- http: jest.fn(),
- data: {
- search: jest.fn(),
- },
- storage: {
- set: jest.fn(),
- },
- theme: {},
- },
- });
- const myState = cloneDeep(state);
- myState.inputs = upsertQuery(newQuery);
- store = createStore(myState, SUB_PLUGINS_REDUCER, kibanaObservable, storage);
});
test('Should generate attributes', () => {
render(
-
+
);
@@ -150,161 +71,38 @@ describe('VisualizationActions', () => {
);
});
- test('Should render VisualizationActions button', () => {
- const { container } = render(
-
-
-
- );
- expect(
- container.querySelector(`[data-test-subj="stat-networkDnsHistogramQuery"]`)
- ).toBeInTheDocument();
- });
-
- test('Should render Open in Lens button', () => {
- const { container } = render(
-
-
-
- );
- fireEvent.click(container.querySelector(`[data-test-subj="stat-networkDnsHistogramQuery"]`)!);
-
- expect(screen.getByText('Open in Lens')).toBeInTheDocument();
- expect(screen.getByText('Open in Lens')).not.toBeDisabled();
- });
-
- test('Should call NavigateToPrefilledEditor when Open in Lens', () => {
- const { container } = render(
-
-
-
- );
- fireEvent.click(container.querySelector(`[data-test-subj="stat-networkDnsHistogramQuery"]`)!);
-
- fireEvent.click(screen.getByText('Open in Lens'));
- expect(mockNavigateToPrefilledEditor.mock.calls[0][0].timeRange).toEqual(props.timerange);
- expect(mockNavigateToPrefilledEditor.mock.calls[0][0].attributes.title).toEqual('');
- expect(mockNavigateToPrefilledEditor.mock.calls[0][0].attributes.references).toEqual([
- {
- id: 'security-solution',
- name: 'indexpattern-datasource-layer-b1c3efc6-c886-4fba-978f-3b6bb5e7948a',
- type: 'index-pattern',
- },
- ]);
- expect(mockNavigateToPrefilledEditor.mock.calls[0][1].openInNewTab).toEqual(true);
- });
-
- test('Should render Inspect button', () => {
- const { container } = render(
-
-
-
- );
- fireEvent.click(container.querySelector(`[data-test-subj="stat-networkDnsHistogramQuery"]`)!);
-
- expect(screen.getByText('Inspect')).toBeInTheDocument();
- expect(screen.getByText('Inspect')).not.toBeDisabled();
- });
-
- test('Should render Inspect Modal after clicking the inspect button', () => {
- const { baseElement, container } = render(
-
-
-
- );
- fireEvent.click(container.querySelector(`[data-test-subj="stat-networkDnsHistogramQuery"]`)!);
-
- expect(screen.getByText('Inspect')).toBeInTheDocument();
- fireEvent.click(screen.getByText('Inspect'));
- expect(
- baseElement.querySelector('[data-test-subj="modal-inspect-euiModal"]')
- ).toBeInTheDocument();
- });
-
- test('Should render Add to new case button', () => {
- const { container } = render(
-
-
-
- );
- fireEvent.click(container.querySelector(`[data-test-subj="stat-networkDnsHistogramQuery"]`)!);
-
- expect(screen.getByText('Add to new case')).toBeInTheDocument();
- expect(screen.getByText('Add to new case')).not.toBeDisabled();
- });
-
- test('Should render Add to new case modal after clicking on Add to new case button', () => {
- const { container } = render(
-
-
-
- );
- fireEvent.click(container.querySelector(`[data-test-subj="stat-networkDnsHistogramQuery"]`)!);
- fireEvent.click(screen.getByText('Add to new case'));
-
- expect(mockGetCreateCaseFlyoutOpen).toBeCalled();
- });
-
- test('Should render Add to existing case button', () => {
- const { container } = render(
-
+ test('Should render VisualizationActions button', async () => {
+ const { queryByTestId } = render(
+
);
- fireEvent.click(container.querySelector(`[data-test-subj="stat-networkDnsHistogramQuery"]`)!);
- expect(screen.getByText('Add to existing case')).toBeInTheDocument();
- expect(screen.getByText('Add to existing case')).not.toBeDisabled();
+ await waitFor(() => {
+ expect(queryByTestId(`stat-networkDnsHistogramQuery`)).toBeInTheDocument();
+ });
});
- test('Should render Add to existing case modal after clicking on Add to existing case button', () => {
- const { container } = render(
-
+ test('renders context menu', async () => {
+ const { getByTestId } = render(
+
);
- fireEvent.click(container.querySelector(`[data-test-subj="stat-networkDnsHistogramQuery"]`)!);
- fireEvent.click(screen.getByText('Add to existing case'));
-
- expect(mockGetAllCasesSelectorModalOpen).toBeCalled();
- });
- test('Should not render default actions when withDefaultActions = false', () => {
- const testProps = { ...props, withDefaultActions: false };
- render(
-
-
-
- );
+ await waitFor(() => {
+ expect(getByTestId(`stat-networkDnsHistogramQuery`)).toBeInTheDocument();
+ });
- expect(
- screen.queryByTestId(`[data-test-subj="stat-networkDnsHistogramQuery"]`)
- ).not.toBeInTheDocument();
- expect(screen.queryByText('Inspect')).not.toBeInTheDocument();
- expect(screen.queryByText('Add to new case')).not.toBeInTheDocument();
- expect(screen.queryByText('Add to existing case')).not.toBeInTheDocument();
- expect(screen.queryByText('Open in Lens')).not.toBeInTheDocument();
- });
+ fireEvent.click(getByTestId(`stat-networkDnsHistogramQuery`));
- test('Should render extra actions when extraAction is provided', () => {
- const testProps = {
- ...props,
- extraActions: [
- {
- getIconType: () => 'reset',
- id: 'resetField',
- execute: jest.fn(),
- getDisplayName: () => 'Reset Field',
- } as unknown as Action