From c568069210a55944254737587a5859cb5de1f5b3 Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Date: Mon, 28 Sep 2020 10:50:55 -0400 Subject: [PATCH 01/11] map working with sourcerer --- .../components/embeddables/embedded_map.tsx | 81 ++++++++++++++----- .../components/embeddables/selector.tsx | 35 ++++++++ 2 files changed, 95 insertions(+), 21 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/network/components/embeddables/selector.tsx diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx index 4d96c213818aa..2afcc7603072d 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx @@ -5,12 +5,16 @@ */ import { EuiLink, EuiText } from '@elastic/eui'; -import React, { useEffect, useState } from 'react'; +import deepEqual from 'fast-deep-equal'; +import React, { useEffect, useState, useMemo } from 'react'; import { createPortalNode, InPortal } from 'react-reverse-portal'; import styled, { css } from 'styled-components'; -import { ErrorEmbeddable } from '../../../../../../../src/plugins/embeddable/public'; -import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; +import { useSelector } from 'react-redux'; +import { + ErrorEmbeddable, + isErrorEmbeddable, +} from '../../../../../../../src/plugins/embeddable/public'; import { getIndexPatternTitleIdMapping } from '../../../common/hooks/api/helpers'; import { useIndexPatterns } from '../../../common/hooks/use_index_patterns'; import { Loader } from '../../../common/components/loader'; @@ -25,7 +29,9 @@ import * as i18n from './translations'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { MapEmbeddable } from '../../../../../../plugins/maps/public/embeddable'; import { Query, Filter } from '../../../../../../../src/plugins/data/public'; -import { useKibana, useUiSetting$ } from '../../../common/lib/kibana'; +import { useKibana } from '../../../common/lib/kibana'; +import { getDefaultSourcererSelector } from './selector'; +import { getLayerList } from './map_config'; interface EmbeddableMapProps { maintainRatio?: boolean; @@ -86,13 +92,17 @@ export const EmbeddedMapComponent = ({ const [embeddable, setEmbeddable] = React.useState( undefined ); - const [isLoading, setIsLoading] = useState(true); const [isError, setIsError] = useState(false); const [isIndexError, setIsIndexError] = useState(false); const [, dispatchToaster] = useStateToaster(); - const [loadingKibanaIndexPatterns, kibanaIndexPatterns] = useIndexPatterns(); - const [siemDefaultIndices] = useUiSetting$(DEFAULT_INDEX_KEY); + const defaultSourcererScopeSelector = useMemo(getDefaultSourcererSelector, []); + const { kibanaIndexPatterns, sourcererScope } = useSelector( + defaultSourcererScopeSelector, + deepEqual + ); + + const [mapIndexPatterns, setMapIndexPatterns] = useState(kibanaIndexPatterns.filter((kip) => sourcererScope.selectedPatterns.includes(kip.title))); // This portalNode provided by react-reverse-portal allows us re-parent the MapToolTip within our // own component tree instead of the embeddables (default). This is necessary to have access to @@ -102,18 +112,24 @@ export const EmbeddedMapComponent = ({ const { services } = useKibana(); + + useEffect(() => { + setMapIndexPatterns((prevMapIndexPatterns) => { + const newIndexPatterns = kibanaIndexPatterns.filter((kip) => sourcererScope.selectedPatterns.includes(kip.title)); + if (!deepEqual(newIndexPatterns, prevMapIndexPatterns)) { + return newIndexPatterns; + } + return prevMapIndexPatterns; + }) + }, [kibanaIndexPatterns, sourcererScope.selectedPatterns]) + // Initial Load useEffect useEffect(() => { let isSubscribed = true; async function setupEmbeddable() { // Ensure at least one `securitySolution:defaultIndex` kibana index pattern exists before creating embeddable - const matchingIndexPatterns = findMatchingIndexPatterns({ - kibanaIndexPatterns, - siemDefaultIndices, - }); - if (matchingIndexPatterns.length === 0 && isSubscribed) { - setIsLoading(false); + if (mapIndexPatterns.length === 0 && isSubscribed) { setIsIndexError(true); return; } @@ -122,7 +138,7 @@ export const EmbeddedMapComponent = ({ try { const embeddableObject = await createEmbeddable( filters, - getIndexPatternTitleIdMapping(matchingIndexPatterns), + mapIndexPatterns, query, startDate, endDate, @@ -139,19 +155,42 @@ export const EmbeddedMapComponent = ({ setIsError(true); } } - if (isSubscribed) { - setIsLoading(false); - } } - if (!loadingKibanaIndexPatterns) { + if (embeddable == null && sourcererScope.selectedPatterns.length > 0) { setupEmbeddable(); } + return () => { isSubscribed = false; }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [loadingKibanaIndexPatterns, kibanaIndexPatterns]); + }, [ + dispatchToaster, + endDate, + embeddable, + filters, + mapIndexPatterns, + query, + portalNode, + services.embeddable, + sourcererScope.selectedPatterns, + setQuery, + startDate, + ]); + + // update layer with new index patterns + useEffect(() => { + const setLayerList = async () => { + if (embeddable != null) { + // @ts-expect-error + await embeddable.setLayerList(getLayerList(mapIndexPatterns)); + embeddable.reload(); + } + }; + if (embeddable != null && !isErrorEmbeddable(embeddable)) { + setLayerList(); + } + }, [embeddable, mapIndexPatterns]); // queryExpression updated useEffect useEffect(() => { @@ -200,7 +239,7 @@ export const EmbeddedMapComponent = ({ {embeddable != null ? ( - ) : !isLoading && isIndexError ? ( + ) : isIndexError ? ( ) : ( diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/selector.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/selector.tsx new file mode 100644 index 0000000000000..2d0bc970f0a51 --- /dev/null +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/selector.tsx @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { State } from '../../../common/store'; +import { sourcererSelectors } from '../../../common/store/sourcerer'; +import { + KibanaIndexPatterns, + ManageScope, + SourcererScopeName, +} from '../../../common/store/sourcerer/model'; + +export interface DefaultSourcererSelector { + kibanaIndexPatterns: KibanaIndexPatterns; + sourcererScope: ManageScope; +} + +export const getDefaultSourcererSelector = () => { + const getKibanaIndexPatternsSelector = sourcererSelectors.kibanaIndexPatternsSelector(); + const getScopesSelector = sourcererSelectors.scopesSelector(); + + const mapStateToProps = (state: State): DefaultSourcererSelector => { + const kibanaIndexPatterns = getKibanaIndexPatternsSelector(state); + const scope = getScopesSelector(state)[SourcererScopeName.default]; + + return { + kibanaIndexPatterns, + sourcererScope: scope, + }; + }; + + return mapStateToProps; +}; From 813fbfe3fe9c7fc5b1395f2ea1e92cb06d7f1a36 Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Date: Mon, 28 Sep 2020 12:21:42 -0400 Subject: [PATCH 02/11] clean up --- .../network/components/embeddables/embedded_map.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx index 2afcc7603072d..d076bbf76f935 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx @@ -102,7 +102,9 @@ export const EmbeddedMapComponent = ({ deepEqual ); - const [mapIndexPatterns, setMapIndexPatterns] = useState(kibanaIndexPatterns.filter((kip) => sourcererScope.selectedPatterns.includes(kip.title))); + const [mapIndexPatterns, setMapIndexPatterns] = useState( + kibanaIndexPatterns.filter((kip) => sourcererScope.selectedPatterns.includes(kip.title)) + ); // This portalNode provided by react-reverse-portal allows us re-parent the MapToolTip within our // own component tree instead of the embeddables (default). This is necessary to have access to @@ -112,16 +114,17 @@ export const EmbeddedMapComponent = ({ const { services } = useKibana(); - useEffect(() => { setMapIndexPatterns((prevMapIndexPatterns) => { - const newIndexPatterns = kibanaIndexPatterns.filter((kip) => sourcererScope.selectedPatterns.includes(kip.title)); + const newIndexPatterns = kibanaIndexPatterns.filter((kip) => + sourcererScope.selectedPatterns.includes(kip.title) + ); if (!deepEqual(newIndexPatterns, prevMapIndexPatterns)) { return newIndexPatterns; } return prevMapIndexPatterns; - }) - }, [kibanaIndexPatterns, sourcererScope.selectedPatterns]) + }); + }, [kibanaIndexPatterns, sourcererScope.selectedPatterns]); // Initial Load useEffect useEffect(() => { From a5be5058a8fc932830a0fe580e962bca3fbf8255 Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Mon, 28 Sep 2020 18:51:59 +0100 Subject: [PATCH 03/11] fix types --- .../public/network/components/embeddables/embedded_map.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx index d076bbf76f935..5b2fa946cd354 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx @@ -15,14 +15,12 @@ import { ErrorEmbeddable, isErrorEmbeddable, } from '../../../../../../../src/plugins/embeddable/public'; -import { getIndexPatternTitleIdMapping } from '../../../common/hooks/api/helpers'; -import { useIndexPatterns } from '../../../common/hooks/use_index_patterns'; import { Loader } from '../../../common/components/loader'; import { displayErrorToast, useStateToaster } from '../../../common/components/toasters'; import { GlobalTimeArgs } from '../../../common/containers/use_global_time'; import { Embeddable } from './embeddable'; import { EmbeddableHeader } from './embeddable_header'; -import { createEmbeddable, findMatchingIndexPatterns } from './embedded_map_helpers'; +import { createEmbeddable } from './embedded_map_helpers'; import { IndexPatternsMissingPrompt } from './index_patterns_missing_prompt'; import { MapToolTip } from './map_tool_tip/map_tool_tip'; import * as i18n from './translations'; From 8dccf09555aaf1742cdfdcc1191d75ba4af87481 Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Mon, 28 Sep 2020 21:58:45 +0100 Subject: [PATCH 04/11] fix unit tests --- .../__snapshots__/embedded_map.test.tsx.snap | 149 ++++++++++++++---- .../embeddables/embedded_map.test.tsx | 18 ++- 2 files changed, 132 insertions(+), 35 deletions(-) diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/__snapshots__/embedded_map.test.tsx.snap b/x-pack/plugins/security_solution/public/network/components/embeddables/__snapshots__/embedded_map.test.tsx.snap index 456e07cf9cd15..f85eda9e11cde 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/__snapshots__/embedded_map.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/__snapshots__/embedded_map.test.tsx.snap @@ -1,34 +1,127 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`EmbeddedMapComponent renders correctly against snapshot 1`] = ` - - - + + - - Map configuration help - - - - } - > - - - - - - + + + + + + + + + `; diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx index ae0d3c2256e07..d69c7eed3215b 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx @@ -9,6 +9,8 @@ import React from 'react'; import '../../../common/mock/match_media'; import { useIndexPatterns } from '../../../common/hooks/use_index_patterns'; +import { TestProviders } from '../../../common/mock'; + import { EmbeddedMapComponent } from './embedded_map'; const mockUseIndexPatterns = useIndexPatterns as jest.Mock; @@ -26,13 +28,15 @@ describe('EmbeddedMapComponent', () => { test('renders correctly against snapshot', () => { const wrapper = shallow( - + + + ); expect(wrapper).toMatchSnapshot(); }); From 3e04c46fc547ba6082da44d66fc4137e11fc5b24 Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Tue, 29 Sep 2020 11:08:30 +0100 Subject: [PATCH 05/11] fix incorrect hight for map --- .../components/embeddables/embedded_map.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx index 5b2fa946cd354..d210b22e8f056 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx @@ -128,13 +128,6 @@ export const EmbeddedMapComponent = ({ useEffect(() => { let isSubscribed = true; async function setupEmbeddable() { - // Ensure at least one `securitySolution:defaultIndex` kibana index pattern exists before creating embeddable - - if (mapIndexPatterns.length === 0 && isSubscribed) { - setIsIndexError(true); - return; - } - // Create & set Embeddable try { const embeddableObject = await createEmbeddable( @@ -148,7 +141,14 @@ export const EmbeddedMapComponent = ({ services.embeddable ); if (isSubscribed) { + // Ensure at least one `securitySolution:defaultIndex` kibana index pattern exists before creating embeddable + if (mapIndexPatterns.length === 0) { + setIsIndexError(true); + return; + } + setEmbeddable(embeddableObject); + setIsIndexError(false); } } catch (e) { if (isSubscribed) { From 9c8885cfde20b2d1755e24e1582d82a7a43fce77 Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Tue, 29 Sep 2020 11:24:28 +0100 Subject: [PATCH 06/11] show prompt when no index exists --- .../public/network/components/embeddables/embedded_map.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx index d210b22e8f056..a96727db379d6 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx @@ -141,14 +141,13 @@ export const EmbeddedMapComponent = ({ services.embeddable ); if (isSubscribed) { - // Ensure at least one `securitySolution:defaultIndex` kibana index pattern exists before creating embeddable if (mapIndexPatterns.length === 0) { setIsIndexError(true); return; + } else { + setEmbeddable(embeddableObject); + setIsIndexError(false); } - - setEmbeddable(embeddableObject); - setIsIndexError(false); } } catch (e) { if (isSubscribed) { From 73684621e8d457b7e1deeff97a8e9549c560f85b Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Tue, 29 Sep 2020 11:32:06 +0100 Subject: [PATCH 07/11] update unit test --- .../__snapshots__/embedded_map.test.tsx.snap | 135 ++---------------- .../embeddables/embedded_map.test.tsx | 2 +- 2 files changed, 13 insertions(+), 124 deletions(-) diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/__snapshots__/embedded_map.test.tsx.snap b/x-pack/plugins/security_solution/public/network/components/embeddables/__snapshots__/embedded_map.test.tsx.snap index f85eda9e11cde..4c3cbecc7593d 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/__snapshots__/embedded_map.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/__snapshots__/embedded_map.test.tsx.snap @@ -1,127 +1,16 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`EmbeddedMapComponent renders correctly against snapshot 1`] = ` - - - - - - - - - - - - - + `; diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx index d69c7eed3215b..c42190813ea2a 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx @@ -38,6 +38,6 @@ describe('EmbeddedMapComponent', () => { /> ); - expect(wrapper).toMatchSnapshot(); + expect(wrapper.find('EmbeddedMapComponent')).toMatchSnapshot(); }); }); From 883944d98cf7cb4e9a32250707ab8b946bb0d818 Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Tue, 29 Sep 2020 12:29:01 +0100 Subject: [PATCH 08/11] fix update with no index available --- .../components/embeddables/embedded_map.tsx | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx index a96727db379d6..cd7d0846d09ef 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx @@ -100,8 +100,10 @@ export const EmbeddedMapComponent = ({ deepEqual ); + const [selectedPatterns, setSelectedPatterns] = useState(sourcererScope.selectedPatterns); + const [mapIndexPatterns, setMapIndexPatterns] = useState( - kibanaIndexPatterns.filter((kip) => sourcererScope.selectedPatterns.includes(kip.title)) + kibanaIndexPatterns.filter((kip) => selectedPatterns.includes(kip.title)) ); // This portalNode provided by react-reverse-portal allows us re-parent the MapToolTip within our @@ -122,7 +124,18 @@ export const EmbeddedMapComponent = ({ } return prevMapIndexPatterns; }); - }, [kibanaIndexPatterns, sourcererScope.selectedPatterns]); + + setSelectedPatterns((prevSelectedPatterns) => { + if ( + !deepEqual(prevSelectedPatterns, sourcererScope.selectedPatterns) && + kibanaIndexPatterns.filter((kip) => sourcererScope.selectedPatterns.includes(kip.title)) + .length === 0 + ) { + setIsIndexError(true); + } + return sourcererScope.selectedPatterns; + }); + }, [kibanaIndexPatterns, sourcererScope.selectedPatterns, setIsIndexError]); // Initial Load useEffect useEffect(() => { @@ -157,7 +170,7 @@ export const EmbeddedMapComponent = ({ } } - if (embeddable == null && sourcererScope.selectedPatterns.length > 0) { + if (embeddable == null && selectedPatterns.length > 0) { setupEmbeddable(); } @@ -173,7 +186,7 @@ export const EmbeddedMapComponent = ({ query, portalNode, services.embeddable, - sourcererScope.selectedPatterns, + selectedPatterns, setQuery, startDate, ]); @@ -237,7 +250,7 @@ export const EmbeddedMapComponent = ({ - {embeddable != null ? ( + {embeddable != null && !isIndexError ? ( ) : isIndexError ? ( From ea138798420ba15e35f4190e533a4bc053e7f585 Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Tue, 29 Sep 2020 14:00:56 +0100 Subject: [PATCH 09/11] fixup --- .../components/embeddables/embedded_map.tsx | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx index cd7d0846d09ef..359c050763c0e 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx @@ -100,10 +100,8 @@ export const EmbeddedMapComponent = ({ deepEqual ); - const [selectedPatterns, setSelectedPatterns] = useState(sourcererScope.selectedPatterns); - const [mapIndexPatterns, setMapIndexPatterns] = useState( - kibanaIndexPatterns.filter((kip) => selectedPatterns.includes(kip.title)) + kibanaIndexPatterns.filter((kip) => sourcererScope.selectedPatterns.includes(kip.title)) ); // This portalNode provided by react-reverse-portal allows us re-parent the MapToolTip within our @@ -124,18 +122,7 @@ export const EmbeddedMapComponent = ({ } return prevMapIndexPatterns; }); - - setSelectedPatterns((prevSelectedPatterns) => { - if ( - !deepEqual(prevSelectedPatterns, sourcererScope.selectedPatterns) && - kibanaIndexPatterns.filter((kip) => sourcererScope.selectedPatterns.includes(kip.title)) - .length === 0 - ) { - setIsIndexError(true); - } - return sourcererScope.selectedPatterns; - }); - }, [kibanaIndexPatterns, sourcererScope.selectedPatterns, setIsIndexError]); + }, [kibanaIndexPatterns, sourcererScope.selectedPatterns]); // Initial Load useEffect useEffect(() => { @@ -170,7 +157,7 @@ export const EmbeddedMapComponent = ({ } } - if (embeddable == null && selectedPatterns.length > 0) { + if (embeddable == null && sourcererScope.selectedPatterns.length > 0) { setupEmbeddable(); } @@ -186,7 +173,7 @@ export const EmbeddedMapComponent = ({ query, portalNode, services.embeddable, - selectedPatterns, + sourcererScope.selectedPatterns, setQuery, startDate, ]); From aaa8c2281ea1a010f02428c67d4d65b5b9a9ae6c Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Tue, 29 Sep 2020 18:57:56 +0100 Subject: [PATCH 10/11] unit test --- .../embeddables/embedded_map.test.tsx | 149 ++++++++++++++++-- .../components/embeddables/embedded_map.tsx | 11 +- 2 files changed, 145 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx index c42190813ea2a..219409b10be6c 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.test.tsx @@ -4,40 +4,169 @@ * you may not use this file except in compliance with the Elastic License. */ -import { shallow } from 'enzyme'; +import { mount, ReactWrapper, shallow } from 'enzyme'; import React from 'react'; +import * as redux from 'react-redux'; +import { act } from 'react-dom/test-utils'; import '../../../common/mock/match_media'; import { useIndexPatterns } from '../../../common/hooks/use_index_patterns'; import { TestProviders } from '../../../common/mock'; import { EmbeddedMapComponent } from './embedded_map'; +import { createEmbeddable } from './embedded_map_helpers'; const mockUseIndexPatterns = useIndexPatterns as jest.Mock; jest.mock('../../../common/hooks/use_index_patterns'); mockUseIndexPatterns.mockImplementation(() => [true, []]); jest.mock('../../../common/lib/kibana'); +jest.mock('./embedded_map_helpers', () => ({ + createEmbeddable: jest.fn(), +})); +jest.mock('../../../common/lib/kibana', () => { + return { + useKibana: jest.fn().mockReturnValue({ + services: { + embeddable: { + EmbeddablePanel: jest.fn(() =>
), + }, + docLinks: { ELASTIC_WEBSITE_URL: 'ELASTIC_WEBSITE_URL' }, + }, + }), + }; +}); + +jest.mock('./index_patterns_missing_prompt', () => { + return { + IndexPatternsMissingPrompt: jest.fn(() =>
), + }; +}); describe('EmbeddedMapComponent', () => { - let setQuery: jest.Mock; + const setQuery: jest.Mock = jest.fn(); + const mockSelector = { + kibanaIndexPatterns: [ + { id: '6f1eeb50-023d-11eb-bcb6-6ba0578012a9', title: 'filebeat-*' }, + { id: '28995490-023d-11eb-bcb6-6ba0578012a9', title: 'auditbeat-*' }, + ], + sourcererScope: { selectedPatterns: ['filebeat-*', 'packetbeat-*'] }, + }; + const mockCreateEmbeddable = { + destroyed: false, + enhancements: { dynamicActions: {} }, + getActionContext: jest.fn(), + getFilterActions: jest.fn(), + id: '70969ddc-4d01-4048-8073-4ea63d595638', + input: { + viewMode: 'view', + title: 'Source -> Destination Point-to-Point Map', + id: '70969ddc-4d01-4048-8073-4ea63d595638', + filters: Array(0), + hidePanelTitles: true, + }, + input$: {}, + isContainer: false, + output: {}, + output$: {}, + parent: undefined, + parentSubscription: undefined, + renderComplete: {}, + runtimeId: 1, + reload: jest.fn(), + setLayerList: jest.fn(), + setEventHandlers: jest.fn(), + setRenderTooltipContent: jest.fn(), + type: 'map', + updateInput: jest.fn(), + }; + const testProps = { + endDate: '2019-08-28T05:50:57.877Z', + filters: [], + query: { query: '', language: 'kuery' }, + setQuery, + startDate: '2019-08-28T05:50:47.877Z', + }; beforeEach(() => { - setQuery = jest.fn(); + setQuery.mockClear(); }); test('renders correctly against snapshot', () => { const wrapper = shallow( - + ); expect(wrapper.find('EmbeddedMapComponent')).toMatchSnapshot(); }); + + test('renders services.embeddable.EmbeddablePanel', async () => { + const spy = jest.spyOn(redux, 'useSelector'); + spy.mockReturnValue(mockSelector); + + (createEmbeddable as jest.Mock).mockResolvedValue(mockCreateEmbeddable); + + let wrapper: ReactWrapper; + await act(async () => { + wrapper = mount( + + + + ); + }); + + wrapper!.update(); + + expect(wrapper!.find('[data-test-subj="EmbeddablePanel"]').exists()).toEqual(true); + expect(wrapper!.find('[data-test-subj="IndexPatternsMissingPrompt"]').exists()).toEqual(false); + expect(wrapper!.find('[data-test-subj="loading-panel"]').exists()).toEqual(false); + }); + + test('renders IndexPatternsMissingPrompt', async () => { + const spy = jest.spyOn(redux, 'useSelector'); + spy.mockReturnValue({ + ...mockSelector, + kibanaIndexPatterns: [], + }); + + (createEmbeddable as jest.Mock).mockResolvedValue(mockCreateEmbeddable); + + let wrapper: ReactWrapper; + await act(async () => { + wrapper = mount( + + + + ); + }); + + wrapper!.update(); + + expect(wrapper!.find('[data-test-subj="EmbeddablePanel"]').exists()).toEqual(false); + expect(wrapper!.find('[data-test-subj="IndexPatternsMissingPrompt"]').exists()).toEqual(true); + expect(wrapper!.find('[data-test-subj="loading-panel"]').exists()).toEqual(false); + }); + + test('renders Loader', async () => { + const spy = jest.spyOn(redux, 'useSelector'); + spy.mockReturnValue(mockSelector); + + (createEmbeddable as jest.Mock).mockResolvedValue(null); + + let wrapper: ReactWrapper; + await act(async () => { + wrapper = mount( + + + + ); + }); + + wrapper!.update(); + + expect(wrapper!.find('[data-test-subj="EmbeddablePanel"]').exists()).toEqual(false); + expect(wrapper!.find('[data-test-subj="IndexPatternsMissingPrompt"]').exists()).toEqual(false); + expect(wrapper!.find('[data-test-subj="loading-panel"]').exists()).toEqual(true); + }); }); diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx index 359c050763c0e..7ae8aecdab606 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx @@ -118,6 +118,9 @@ export const EmbeddedMapComponent = ({ sourcererScope.selectedPatterns.includes(kip.title) ); if (!deepEqual(newIndexPatterns, prevMapIndexPatterns)) { + if (newIndexPatterns.length === 0) { + setIsError(true); + } return newIndexPatterns; } return prevMapIndexPatterns; @@ -143,7 +146,6 @@ export const EmbeddedMapComponent = ({ if (isSubscribed) { if (mapIndexPatterns.length === 0) { setIsIndexError(true); - return; } else { setEmbeddable(embeddableObject); setIsIndexError(false); @@ -156,7 +158,6 @@ export const EmbeddedMapComponent = ({ } } } - if (embeddable == null && sourcererScope.selectedPatterns.length > 0) { setupEmbeddable(); } @@ -237,10 +238,10 @@ export const EmbeddedMapComponent = ({ - {embeddable != null && !isIndexError ? ( - - ) : isIndexError ? ( + {isIndexError ? ( + ) : embeddable != null ? ( + ) : ( )} From abf1fb0e69e67c334cfa7ea041052421bf6000af Mon Sep 17 00:00:00 2001 From: Angela Chuang Date: Wed, 30 Sep 2020 11:17:42 +0100 Subject: [PATCH 11/11] add unit test --- .../components/embeddables/selector.test.tsx | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 x-pack/plugins/security_solution/public/network/components/embeddables/selector.test.tsx diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/selector.test.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/selector.test.tsx new file mode 100644 index 0000000000000..d5b105dd32798 --- /dev/null +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/selector.test.tsx @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { State } from '../../../common/store'; + +import { getDefaultSourcererSelector } from './selector'; + +jest.mock('../../../common/store/sourcerer', () => ({ + sourcererSelectors: { + kibanaIndexPatternsSelector: jest.fn().mockReturnValue(jest.fn()), + scopesSelector: jest.fn().mockReturnValue(jest.fn().mockReturnValue({ default: '' })), + }, +})); + +describe('getDefaultSourcererSelector', () => { + test('Returns correct format', () => { + const mockMapStateToProps = getDefaultSourcererSelector(); + const result = mockMapStateToProps({} as State); + expect(result).toHaveProperty('kibanaIndexPatterns'); + expect(result).toHaveProperty('sourcererScope'); + }); +});