diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_flyout.test.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_flyout.test.tsx index fd8f286a9d8f6d..5f06e4ec447873 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_flyout.test.tsx +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_flyout.test.tsx @@ -29,12 +29,18 @@ import { ContactCardEmbeddable } from '../../../../test_samples/embeddables/cont import { ContainerInput } from '../../../../containers'; import { mountWithIntl as mount } from 'test_utils/enzyme_helpers'; import { ReactWrapper } from 'enzyme'; - +import { coreMock } from '../../../../../../../../core/public/mocks'; // @ts-ignore import { findTestSubject } from '@elastic/eui/lib/test'; -// eslint-disable-next-line -import { coreMock } from '../../../../../../../../core/public/mocks'; +function DummySavedObjectFinder(props: { children: React.ReactNode }) { + return ( +
+
Hello World
+ {props.children} +
+ ) as JSX.Element; +} test('createNewEmbeddable() add embeddable to container', async () => { const core = coreMock.createStart(); @@ -101,14 +107,14 @@ test('selecting embeddable in "Create new ..." list calls createNewEmbeddable()' }; const container = new HelloWorldContainer(input, { getEmbeddableFactory } as any); const onClose = jest.fn(); - const component = mount( + const component = mount( new Set([contactCardEmbeddableFactory]).values()} notifications={core.notifications} - SavedObjectFinder={() => null} + SavedObjectFinder={props => } /> ) as ReactWrapper; diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_flyout.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_flyout.tsx index 4f2ae7ab19bcb3..815394ebd97e05 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_flyout.tsx +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/add_panel_flyout.tsx @@ -18,24 +18,21 @@ */ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import React from 'react'; +import React, { ReactElement } from 'react'; import { CoreSetup } from 'src/core/public'; import { - EuiButton, EuiContextMenuItem, - EuiContextMenuPanel, EuiFlyout, EuiFlyoutBody, - EuiFlyoutFooter, EuiFlyoutHeader, - EuiPopover, EuiTitle, } from '@elastic/eui'; import { IContainer } from '../../../../containers'; import { EmbeddableFactoryNotFoundError } from '../../../../errors'; import { GetEmbeddableFactories, GetEmbeddableFactory } from '../../../../types'; +import { SavedObjectFinderCreateNew } from './saved_object_finder_create_new'; interface Props { onClose: () => void; @@ -107,15 +104,7 @@ export class AddPanelFlyout extends React.Component { this.showToast(name); }; - private toggleCreateMenu = () => { - this.setState(prevState => ({ isCreateMenuOpen: !prevState.isCreateMenuOpen })); - }; - - private closeCreateMenu = () => { - this.setState({ isCreateMenuOpen: false }); - }; - - private getCreateMenuItems() { + private getCreateMenuItems(): ReactElement[] { return [...this.props.getAllFactories()] .filter(factory => factory.isEditable() && !factory.isContainerType && factory.canCreateNew()) .map(factory => ( @@ -145,7 +134,9 @@ export class AddPanelFlyout extends React.Component { noItemsMessage={i18n.translate('embeddableApi.addPanel.noMatchingObjectsMessage', { defaultMessage: 'No matching objects found.', })} - /> + > + + ); return ( @@ -158,30 +149,6 @@ export class AddPanelFlyout extends React.Component { {savedObjectsFinder} - - - - - } - isOpen={this.state.isCreateMenuOpen} - closePopover={this.closeCreateMenu} - panelPaddingSize="none" - anchorPosition="upLeft" - > - - - ); } diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/saved_object_finder_create_new.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/saved_object_finder_create_new.tsx new file mode 100644 index 00000000000000..ac39eacab287f2 --- /dev/null +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/saved_object_finder_create_new.tsx @@ -0,0 +1,62 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React, { ReactElement, useState } from 'react'; +import { EuiButton } from '@elastic/eui'; +import { EuiContextMenuPanel } from '@elastic/eui'; +import { EuiPopover } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + +interface Props { + menuItems: ReactElement[]; +} + +export function SavedObjectFinderCreateNew({ menuItems }: Props) { + const [isCreateMenuOpen, setCreateMenuOpen] = useState(false); + const toggleCreateMenu = () => { + setCreateMenuOpen(!isCreateMenuOpen); + }; + const closeCreateMenu = () => { + setCreateMenuOpen(false); + }; + return ( + + + + } + isOpen={isCreateMenuOpen} + closePopover={closeCreateMenu} + panelPaddingSize="none" + anchorPosition="downRight" + > + + + ); +} diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/tests/saved_object_finder_create_new.test.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/tests/saved_object_finder_create_new.test.tsx new file mode 100644 index 00000000000000..6275dbd4eaa45f --- /dev/null +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/add_panel/tests/saved_object_finder_create_new.test.tsx @@ -0,0 +1,91 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React from 'react'; +import { SavedObjectFinderCreateNew } from '../saved_object_finder_create_new'; +import { shallow } from 'enzyme'; +import { EuiButton, EuiContextMenuItem, EuiContextMenuPanel, EuiPopover } from '@elastic/eui'; +import { mountWithIntl } from 'test_utils/enzyme_helpers'; + +describe('SavedObjectFinderCreateNew', () => { + test('renders correctly with no items', () => { + const wrapper = shallow(); + expect(wrapper.find(EuiPopover).length).toEqual(1); + const menuPanel = wrapper.find(EuiContextMenuPanel); + expect(menuPanel.length).toEqual(1); + const panelItems = menuPanel.prop('items'); + if (panelItems) { + expect(panelItems.length).toEqual(0); + } else { + fail('Expect paneltems to be defined'); + } + }); + + test('renders correctly with items', () => { + const items = []; + const onClick = jest.fn(); + for (let i = 0; i < 3; i++) { + items.push( + {`item${i + 1}`} + ); + } + + const wrapper = shallow(); + expect(wrapper.find(EuiPopover).length).toEqual(1); + const menuPanel = wrapper.find(EuiContextMenuPanel); + expect(menuPanel.length).toEqual(1); + const paneltems = menuPanel.prop('items'); + if (paneltems) { + expect(paneltems.length).toEqual(3); + expect(paneltems[0].key).toEqual('1'); + expect(paneltems[1].key).toEqual('2'); + expect(paneltems[2].key).toEqual('3'); + } else { + fail('Expect paneltems to be defined'); + } + }); + + test('clicking the button opens/closes the popover', () => { + const items = []; + const onClick = jest.fn(); + for (let i = 0; i < 3; i++) { + items.push( + {`item${i + 1}`} + ); + } + + const component = mountWithIntl(); + let popover = component.find(EuiPopover); + expect(popover.prop('isOpen')).toBe(false); + const button = component.find(EuiButton); + button.simulate('click'); + popover = component.find(EuiPopover); + expect(popover.prop('isOpen')).toBe(true); + button.simulate('click'); + popover = component.find(EuiPopover); + expect(popover.prop('isOpen')).toBe(false); + }); +}); diff --git a/src/plugins/saved_objects/public/finder/saved_object_finder.test.tsx b/src/plugins/saved_objects/public/finder/saved_object_finder.test.tsx index 97ac25dca8cf11..90212fbe83c10b 100644 --- a/src/plugins/saved_objects/public/finder/saved_object_finder.test.tsx +++ b/src/plugins/saved_objects/public/finder/saved_object_finder.test.tsx @@ -695,4 +695,34 @@ describe('SavedObjectsFinder', () => { expect(wrapper.containsMatchingElement()).toBe(false); }); }); + + it('should render with children', async () => { + const core = coreMock.createStart(); + ((core.savedObjects.client.find as any) as jest.SpyInstance).mockImplementation(() => + Promise.resolve({ savedObjects: [doc, doc2] }) + ); + core.uiSettings.get.mockImplementation(() => 10); + + const wrapper = shallow( + 'search', + }, + { + type: 'vis', + name: 'Vis', + getIconForSavedObject: () => 'visLine', + }, + ]} + > + + + ); + expect(wrapper.exists('#testChildButton')).toBe(true); + }); }); diff --git a/src/plugins/saved_objects/public/finder/saved_object_finder.tsx b/src/plugins/saved_objects/public/finder/saved_object_finder.tsx index 0658ed64df84c2..b503392c9827fa 100644 --- a/src/plugins/saved_objects/public/finder/saved_object_finder.tsx +++ b/src/plugins/saved_objects/public/finder/saved_object_finder.tsx @@ -438,6 +438,7 @@ class SavedObjectFinderUi extends React.Component< )} + {this.props.children ? {this.props.children} : null} ); }