diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx index 9e78c9b48bf2b..771bc97ceab42 100644 --- a/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx @@ -6,17 +6,30 @@ import React from 'react'; import { render, shallow, mount } from 'enzyme'; -import { DragDrop } from './drag_drop'; -import { ChildDragDropProvider } from './providers'; +import { DragDropInternal } from './drag_drop'; +import { DragContextState } from './providers'; jest.useFakeTimers(); +function mockContext(): DragContextState { + return { + dragging: undefined, + setDragging: jest.fn(), + }; +} + describe('DragDrop', () => { test('renders if nothing is being dragged', () => { const component = render( - + Hello! - + ); expect(component).toMatchSnapshot(); @@ -24,7 +37,11 @@ describe('DragDrop', () => { test('dragover calls preventDefault if droppable is true', () => { const preventDefault = jest.fn(); - const component = shallow(Hello!); + const component = shallow( + + Hello! + + ); component.find('[data-test-subj="lnsDragDrop"]').simulate('dragover', { preventDefault }); @@ -33,7 +50,11 @@ describe('DragDrop', () => { test('dragover does not call preventDefault if droppable is false', () => { const preventDefault = jest.fn(); - const component = shallow(Hello!); + const component = shallow( + + Hello! + + ); component.find('[data-test-subj="lnsDragDrop"]').simulate('dragover', { preventDefault }); @@ -41,7 +62,7 @@ describe('DragDrop', () => { }); test('dragstart sets dragging in the context', async () => { - const setDragging = jest.fn(); + const context = mockContext(); const dataTransfer = { setData: jest.fn(), getData: jest.fn(), @@ -49,9 +70,9 @@ describe('DragDrop', () => { const value = {}; const component = mount( - - Hello! - + + Ahoy! + ); component.find('[data-test-subj="lnsDragDrop"]').simulate('dragstart', { dataTransfer }); @@ -59,22 +80,29 @@ describe('DragDrop', () => { jest.runAllTimers(); expect(dataTransfer.setData).toBeCalledWith('text', 'dragging'); - expect(setDragging).toBeCalledWith(value); + expect(context.setDragging).toBeCalledWith(value); }); test('drop resets all the things', async () => { + const context = mockContext(); const preventDefault = jest.fn(); const stopPropagation = jest.fn(); - const setDragging = jest.fn(); const onDrop = jest.fn(); const value = {}; + context.dragging = 'hola'; + const component = mount( - - - Hello! - - + + Ahoy! + ); component @@ -83,20 +111,23 @@ describe('DragDrop', () => { expect(preventDefault).toBeCalled(); expect(stopPropagation).toBeCalled(); - expect(setDragging).toBeCalledWith(undefined); + expect(context.setDragging).toBeCalledWith(undefined); expect(onDrop).toBeCalledWith('hola'); }); test('droppable is reflected in the className', () => { const component = render( - { throw x; }} droppable > Hello! - + ); expect(component).toMatchSnapshot(); diff --git a/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx index 35326a46a6820..1ac8c2c7eef40 100644 --- a/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx +++ b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx @@ -6,7 +6,7 @@ import React, { useState, useContext } from 'react'; import classNames from 'classnames'; -import { DragContext } from './providers'; +import { DragContext, DragContextState } from './providers'; type DroppableEvent = React.DragEvent; @@ -54,6 +54,13 @@ interface Props { draggable?: boolean; } +// For internal usage / test purposes only. +type InternalProps = Props & { + context: DragContextState; + isActive: boolean; + setIsActive: (isActive: boolean) => void; +}; + /** * A draggable / droppable item. Items can be both draggable and droppable at * the same time. @@ -61,14 +68,40 @@ interface Props { * @param props */ export function DragDrop(props: Props) { - const { dragging, setDragging } = useContext(DragContext); + const context = useContext(DragContext); const [state, setState] = useState({ isActive: false }); - const { className, onDrop, value, children, droppable, draggable } = props; + + return ( + setState({ isActive })} + {...props} + /> + ); +} + +/** + * For internal usage / test purposes only. + */ +export function DragDropInternal(props: InternalProps) { + const { + className, + onDrop, + value, + children, + droppable, + draggable, + context, + isActive, + setIsActive, + } = props; + const { dragging, setDragging } = context; const isDragging = draggable && value === dragging; const classes = classNames('lnsDragDrop', className, { 'lnsDragDrop-isDropTarget': droppable, - 'lnsDragDrop-isActiveDropTarget': droppable && state.isActive, + 'lnsDragDrop-isActiveDropTarget': droppable && isActive, 'lnsDragDrop-isDragging': isDragging, }); @@ -100,20 +133,20 @@ export function DragDrop(props: Props) { e.preventDefault(); // An optimization to prevent a bunch of React churn. - if (!state.isActive) { - setState({ ...state, isActive: true }); + if (!isActive) { + setIsActive(true); } }; const dragLeave = () => { - setState({ ...state, isActive: false }); + setIsActive(false); }; const drop = (e: DroppableEvent) => { e.preventDefault(); e.stopPropagation(); - setState({ ...state, isActive: false }); + setIsActive(false); setDragging(undefined); if (onDrop) { diff --git a/x-pack/plugins/lens/public/drag_drop/index.ts b/x-pack/plugins/lens/public/drag_drop/index.ts index e597bb8b6e893..24860e83c0c8b 100644 --- a/x-pack/plugins/lens/public/drag_drop/index.ts +++ b/x-pack/plugins/lens/public/drag_drop/index.ts @@ -5,4 +5,4 @@ */ export * from './providers'; -export * from './drag_drop'; +export { DragDrop } from './drag_drop';