chore: Moves spec files to the src folder - iteration 8 (#17899)

* chore: Moves spec files to the src folder - iteration 8

* Fixes tests
This commit is contained in:
Michael S. Molina
2022-01-07 09:25:45 -03:00
committed by GitHub
parent aa91662ec8
commit e6ef7da758
18 changed files with 2 additions and 2 deletions

View File

@@ -1,103 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { shallow, mount } from 'enzyme';
import sinon from 'sinon';
import newComponentFactory from 'src/dashboard/util/newComponentFactory';
import { CHART_TYPE, ROW_TYPE } from 'src/dashboard/util/componentTypes';
import { UnwrappedDragDroppable as DragDroppable } from 'src/dashboard/components/dnd/DragDroppable';
describe('DragDroppable', () => {
const props = {
component: newComponentFactory(CHART_TYPE),
parentComponent: newComponentFactory(ROW_TYPE),
editMode: false,
depth: 1,
index: 0,
isDragging: false,
isDraggingOver: false,
isDraggingOverShallow: false,
droppableRef() {},
dragSourceRef() {},
dragPreviewRef() {},
};
function setup(overrideProps, shouldMount = false) {
const method = shouldMount ? mount : shallow;
const wrapper = method(<DragDroppable {...props} {...overrideProps} />);
return wrapper;
}
it('should render a div with class dragdroppable', () => {
const wrapper = setup();
expect(wrapper.find('.dragdroppable')).toExist();
});
it('should add class dragdroppable--dragging when dragging', () => {
const wrapper = setup({ isDragging: true });
expect(wrapper.find('.dragdroppable')).toExist();
});
it('should call its child function', () => {
const childrenSpy = sinon.spy();
setup({ children: childrenSpy });
expect(childrenSpy.callCount).toBe(1);
});
it('should call its child function with "dragSourceRef" if editMode=true', () => {
const children = sinon.spy();
const dragSourceRef = () => {};
setup({ children, editMode: false, dragSourceRef });
setup({ children, editMode: true, dragSourceRef });
expect(children.getCall(0).args[0].dragSourceRef).toBeUndefined();
expect(children.getCall(1).args[0].dragSourceRef).toBe(dragSourceRef);
});
it('should call its child function with "dropIndicatorProps" dependent on editMode, isDraggingOver, state.dropIndicator is set', () => {
const children = sinon.spy();
const wrapper = setup({ children, editMode: false, isDraggingOver: false });
wrapper.setState({ dropIndicator: 'nonsense' });
wrapper.setProps({ ...props, editMode: true, isDraggingOver: true });
expect(children.callCount).toBe(3); // initial + setState + setProps
expect(children.getCall(0).args[0].dropIndicatorProps).toBeUndefined();
expect(children.getCall(2).args[0].dropIndicatorProps).toEqual({
className: 'drop-indicator',
});
});
it('should call props.dragPreviewRef and props.droppableRef on mount', () => {
const dragPreviewRef = sinon.spy();
const droppableRef = sinon.spy();
setup({ dragPreviewRef, droppableRef }, true);
expect(dragPreviewRef.callCount).toBe(1);
expect(droppableRef.callCount).toBe(1);
});
it('should set this.mounted dependent on life cycle', () => {
const wrapper = setup({}, true);
const instance = wrapper.instance();
expect(instance.mounted).toBe(true);
wrapper.unmount();
expect(instance.mounted).toBe(false);
});
});

View File

@@ -1,143 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { Provider } from 'react-redux';
import React from 'react';
import { mount } from 'enzyme';
import sinon from 'sinon';
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import Chart from 'src/dashboard/containers/Chart';
import ChartHolderConnected from 'src/dashboard/components/gridComponents/ChartHolder';
import DeleteComponentButton from 'src/dashboard/components/DeleteComponentButton';
import DragDroppable from 'src/dashboard/components/dnd/DragDroppable';
import HoverMenu from 'src/dashboard/components/menu/HoverMenu';
import ResizableContainer from 'src/dashboard/components/resizable/ResizableContainer';
import { getMockStore } from 'spec/fixtures/mockStore';
import { sliceId } from 'spec/fixtures/mockChartQueries';
import dashboardInfo from 'spec/fixtures/mockDashboardInfo';
import { dashboardLayout as mockLayout } from 'spec/fixtures/mockDashboardLayout';
import { sliceEntitiesForChart } from 'spec/fixtures/mockSliceEntities';
import { initialState } from 'src/SqlLab/fixtures';
import { nativeFiltersInfo } from '../../fixtures/mockNativeFilters';
describe('ChartHolder', () => {
const props = {
id: String(sliceId),
dashboardId: dashboardInfo.id,
parentId: 'ROW_ID',
component: mockLayout.present.CHART_ID,
depth: 2,
parentComponent: mockLayout.present.ROW_ID,
index: 0,
editMode: false,
availableColumnCount: 12,
columnWidth: 50,
onResizeStart() {},
onResize() {},
onResizeStop() {},
handleComponentDrop() {},
updateComponents() {},
deleteComponent() {},
nativeFilters: nativeFiltersInfo.filters,
};
function setup(overrideProps) {
const mockStore = getMockStore({
...initialState,
sliceEntities: sliceEntitiesForChart,
});
// We have to wrap provide DragDropContext for the underlying DragDroppable
// otherwise we cannot assert on DragDroppable children
const wrapper = mount(
<Provider store={mockStore}>
<DndProvider backend={HTML5Backend}>
<ChartHolderConnected {...props} {...overrideProps} />
</DndProvider>
</Provider>,
{
wrappingComponent: ThemeProvider,
wrappingComponentProps: { theme: supersetTheme },
},
);
return wrapper;
}
it('should render a DragDroppable', () => {
const wrapper = setup();
expect(wrapper.find(DragDroppable)).toExist();
});
it('should render a ResizableContainer', () => {
const wrapper = setup();
expect(wrapper.find(ResizableContainer)).toExist();
});
it('should only have an adjustableWidth if its parent is a Row', () => {
let wrapper = setup();
expect(wrapper.find(ResizableContainer).prop('adjustableWidth')).toBe(true);
wrapper = setup({ ...props, parentComponent: mockLayout.present.CHART_ID });
expect(wrapper.find(ResizableContainer).prop('adjustableWidth')).toBe(
false,
);
});
it('should pass correct props to ResizableContainer', () => {
const wrapper = setup();
const resizableProps = wrapper.find(ResizableContainer).props();
expect(resizableProps.widthStep).toBe(props.columnWidth);
expect(resizableProps.widthMultiple).toBe(props.component.meta.width);
expect(resizableProps.heightMultiple).toBe(props.component.meta.height);
expect(resizableProps.maxWidthMultiple).toBe(
props.component.meta.width + props.availableColumnCount,
);
});
it('should render a div with class "dashboard-component-chart-holder"', () => {
const wrapper = setup();
expect(wrapper.find('.dashboard-component-chart-holder')).toExist();
});
it('should render a Chart', () => {
const wrapper = setup();
expect(wrapper.find(Chart)).toExist();
});
it('should render a HoverMenu with DeleteComponentButton in editMode', () => {
let wrapper = setup();
expect(wrapper.find(HoverMenu)).not.toExist();
expect(wrapper.find(DeleteComponentButton)).not.toExist();
// we cannot set props on the Divider because of the WithDragDropContext wrapper
wrapper = setup({ editMode: true });
expect(wrapper.find(HoverMenu)).toExist();
expect(wrapper.find(DeleteComponentButton)).toExist();
});
it('should call deleteComponent when deleted', () => {
const deleteComponent = sinon.spy();
const wrapper = setup({ editMode: true, deleteComponent });
wrapper.find(DeleteComponentButton).simulate('click');
expect(deleteComponent.callCount).toBe(1);
});
});

View File

@@ -1,135 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { shallow } from 'enzyme';
import sinon from 'sinon';
import Chart from 'src/dashboard/components/gridComponents/Chart';
import SliceHeader from 'src/dashboard/components/SliceHeader';
import ChartContainer from 'src/chart/ChartContainer';
import * as exploreUtils from 'src/explore/exploreUtils';
import { sliceEntitiesForChart as sliceEntities } from 'spec/fixtures/mockSliceEntities';
import mockDatasource from 'spec/fixtures/mockDatasource';
import chartQueries, {
sliceId as queryId,
} from 'spec/fixtures/mockChartQueries';
describe('Chart', () => {
const props = {
id: queryId,
width: 100,
height: 100,
updateSliceName() {},
// from redux
maxRows: 666,
chart: chartQueries[queryId],
formData: chartQueries[queryId].formData,
datasource: mockDatasource[sliceEntities.slices[queryId].datasource],
slice: {
...sliceEntities.slices[queryId],
description_markeddown: 'markdown',
owners: [],
},
sliceName: sliceEntities.slices[queryId].slice_name,
timeout: 60,
filters: {},
refreshChart() {},
toggleExpandSlice() {},
addFilter() {},
logEvent() {},
handleToggleFullSize() {},
changeFilter() {},
setFocusedFilterField() {},
unsetFocusedFilterField() {},
addSuccessToast() {},
addDangerToast() {},
exportCSV() {},
exportFullCSV() {},
componentId: 'test',
dashboardId: 111,
editMode: false,
isExpanded: false,
supersetCanExplore: false,
supersetCanCSV: false,
sliceCanEdit: false,
};
function setup(overrideProps) {
const wrapper = shallow(<Chart {...props} {...overrideProps} />);
return wrapper;
}
it('should render a SliceHeader', () => {
const wrapper = setup();
expect(wrapper.find(SliceHeader)).toExist();
});
it('should render a ChartContainer', () => {
const wrapper = setup();
expect(wrapper.find(ChartContainer)).toExist();
});
it('should render a description if it has one and isExpanded=true', () => {
const wrapper = setup();
expect(wrapper.find('.slice_description')).not.toExist();
wrapper.setProps({ ...props, isExpanded: true });
expect(wrapper.find('.slice_description')).toExist();
});
it('should call refreshChart when SliceHeader calls forceRefresh', () => {
const refreshChart = sinon.spy();
const wrapper = setup({ refreshChart });
wrapper.instance().forceRefresh();
expect(refreshChart.callCount).toBe(1);
});
it('should call changeFilter when ChartContainer calls changeFilter', () => {
const changeFilter = sinon.spy();
const wrapper = setup({ changeFilter });
wrapper.instance().changeFilter();
expect(changeFilter.callCount).toBe(1);
});
it('should call exportChart when exportCSV is clicked', () => {
const stubbedExportCSV = sinon
.stub(exploreUtils, 'exportChart')
.returns(() => {});
const wrapper = setup();
wrapper.instance().exportCSV(props.slice.sliceId);
expect(stubbedExportCSV.calledOnce).toBe(true);
expect(stubbedExportCSV.lastCall.args[0]).toEqual(
expect.objectContaining({
formData: expect.anything(),
resultType: 'full',
resultFormat: 'csv',
}),
);
exploreUtils.exportChart.restore();
});
it('should call exportChart with row_limit props.maxRows when exportFullCSV is clicked', () => {
const stubbedExportCSV = sinon
.stub(exploreUtils, 'exportChart')
.returns(() => {});
const wrapper = setup();
wrapper.instance().exportFullCSV(props.slice.sliceId);
expect(stubbedExportCSV.calledOnce).toBe(true);
expect(stubbedExportCSV.lastCall.args[0].formData.row_limit).toEqual(666);
exploreUtils.exportChart.restore();
});
});

View File

@@ -1,170 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { Provider } from 'react-redux';
import React from 'react';
import { mount } from 'enzyme';
import sinon from 'sinon';
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import BackgroundStyleDropdown from 'src/dashboard/components/menu/BackgroundStyleDropdown';
import Column from 'src/dashboard/components/gridComponents/Column';
import DashboardComponent from 'src/dashboard/containers/DashboardComponent';
import DeleteComponentButton from 'src/dashboard/components/DeleteComponentButton';
import DragDroppable from 'src/dashboard/components/dnd/DragDroppable';
import HoverMenu from 'src/dashboard/components/menu/HoverMenu';
import IconButton from 'src/dashboard/components/IconButton';
import ResizableContainer from 'src/dashboard/components/resizable/ResizableContainer';
import WithPopoverMenu from 'src/dashboard/components/menu/WithPopoverMenu';
import { getMockStore } from 'spec/fixtures/mockStore';
import { dashboardLayout as mockLayout } from 'spec/fixtures/mockDashboardLayout';
import { initialState } from 'src/SqlLab/fixtures';
describe('Column', () => {
const columnWithoutChildren = {
...mockLayout.present.COLUMN_ID,
children: [],
};
const props = {
id: 'COLUMN_ID',
parentId: 'ROW_ID',
component: mockLayout.present.COLUMN_ID,
parentComponent: mockLayout.present.ROW_ID,
index: 0,
depth: 2,
editMode: false,
availableColumnCount: 12,
minColumnWidth: 2,
columnWidth: 50,
occupiedColumnCount: 6,
onResizeStart() {},
onResize() {},
onResizeStop() {},
handleComponentDrop() {},
deleteComponent() {},
updateComponents() {},
};
function setup(overrideProps) {
// We have to wrap provide DragDropContext for the underlying DragDroppable
// otherwise we cannot assert on DragDroppable children
const mockStore = getMockStore({
...initialState,
});
const wrapper = mount(
<Provider store={mockStore}>
<DndProvider backend={HTML5Backend}>
<Column {...props} {...overrideProps} />
</DndProvider>
</Provider>,
{
wrappingComponent: ThemeProvider,
wrappingComponentProps: { theme: supersetTheme },
},
);
return wrapper;
}
it('should render a DragDroppable', () => {
// don't count child DragDroppables
const wrapper = setup({ component: columnWithoutChildren });
expect(wrapper.find(DragDroppable)).toExist();
});
it('should render a WithPopoverMenu', () => {
// don't count child DragDroppables
const wrapper = setup({ component: columnWithoutChildren });
expect(wrapper.find(WithPopoverMenu)).toExist();
});
it('should render a ResizableContainer', () => {
// don't count child DragDroppables
const wrapper = setup({ component: columnWithoutChildren });
expect(wrapper.find(ResizableContainer)).toExist();
});
it('should render a HoverMenu in editMode', () => {
let wrapper = setup({ component: columnWithoutChildren });
expect(wrapper.find(HoverMenu)).not.toExist();
// we cannot set props on the Row because of the WithDragDropContext wrapper
wrapper = setup({ component: columnWithoutChildren, editMode: true });
expect(wrapper.find(HoverMenu)).toExist();
});
it('should render a DeleteComponentButton in editMode', () => {
let wrapper = setup({ component: columnWithoutChildren });
expect(wrapper.find(DeleteComponentButton)).not.toExist();
// we cannot set props on the Row because of the WithDragDropContext wrapper
wrapper = setup({ component: columnWithoutChildren, editMode: true });
expect(wrapper.find(DeleteComponentButton)).toExist();
});
it('should render a BackgroundStyleDropdown when focused', () => {
let wrapper = setup({ component: columnWithoutChildren });
expect(wrapper.find(BackgroundStyleDropdown)).not.toExist();
// we cannot set props on the Row because of the WithDragDropContext wrapper
wrapper = setup({ component: columnWithoutChildren, editMode: true });
wrapper
.find(IconButton)
.at(1) // first one is delete button
.simulate('click');
expect(wrapper.find(BackgroundStyleDropdown)).toExist();
});
it('should call deleteComponent when deleted', () => {
const deleteComponent = sinon.spy();
const wrapper = setup({ editMode: true, deleteComponent });
wrapper.find(DeleteComponentButton).simulate('click');
expect(deleteComponent.callCount).toBe(1);
});
it('should pass its own width as availableColumnCount to children', () => {
const wrapper = setup();
const dashboardComponent = wrapper.find(DashboardComponent).first();
expect(dashboardComponent.props().availableColumnCount).toBe(
props.component.meta.width,
);
});
it('should pass appropriate dimensions to ResizableContainer', () => {
const wrapper = setup({ component: columnWithoutChildren });
const columnWidth = columnWithoutChildren.meta.width;
const resizableProps = wrapper.find(ResizableContainer).props();
expect(resizableProps.adjustableWidth).toBe(true);
expect(resizableProps.adjustableHeight).toBe(false);
expect(resizableProps.widthStep).toBe(props.columnWidth);
expect(resizableProps.widthMultiple).toBe(columnWidth);
expect(resizableProps.minWidthMultiple).toBe(props.minColumnWidth);
expect(resizableProps.maxWidthMultiple).toBe(
props.availableColumnCount + columnWidth,
);
});
it('should increment the depth of its children', () => {
const wrapper = setup();
const dashboardComponent = wrapper.find(DashboardComponent);
expect(dashboardComponent.props().depth).toBe(props.depth + 1);
});
});

View File

@@ -1,86 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { styledMount as mount } from 'spec/helpers/theming';
import sinon from 'sinon';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import DeleteComponentButton from 'src/dashboard/components/DeleteComponentButton';
import HoverMenu from 'src/dashboard/components/menu/HoverMenu';
import DragDroppable from 'src/dashboard/components/dnd/DragDroppable';
import Divider from 'src/dashboard/components/gridComponents/Divider';
import newComponentFactory from 'src/dashboard/util/newComponentFactory';
import {
DIVIDER_TYPE,
DASHBOARD_GRID_TYPE,
} from 'src/dashboard/util/componentTypes';
describe('Divider', () => {
const props = {
id: 'id',
parentId: 'parentId',
component: newComponentFactory(DIVIDER_TYPE),
depth: 1,
parentComponent: newComponentFactory(DASHBOARD_GRID_TYPE),
index: 0,
editMode: false,
handleComponentDrop() {},
deleteComponent() {},
};
function setup(overrideProps) {
// We have to wrap provide DragDropContext for the underlying DragDroppable
// otherwise we cannot assert on DragDroppable children
const wrapper = mount(
<DndProvider backend={HTML5Backend}>
<Divider {...props} {...overrideProps} />
</DndProvider>,
);
return wrapper;
}
it('should render a DragDroppable', () => {
const wrapper = setup();
expect(wrapper.find(DragDroppable)).toExist();
});
it('should render a div with class "dashboard-component-divider"', () => {
const wrapper = setup();
expect(wrapper.find('.dashboard-component-divider')).toExist();
});
it('should render a HoverMenu with DeleteComponentButton in editMode', () => {
let wrapper = setup();
expect(wrapper.find(HoverMenu)).not.toExist();
expect(wrapper.find(DeleteComponentButton)).not.toExist();
// we cannot set props on the Divider because of the WithDragDropContext wrapper
wrapper = setup({ editMode: true });
expect(wrapper.find(HoverMenu)).toExist();
expect(wrapper.find(DeleteComponentButton)).toExist();
});
it('should call deleteComponent when deleted', () => {
const deleteComponent = sinon.spy();
const wrapper = setup({ editMode: true, deleteComponent });
wrapper.find(DeleteComponentButton).simulate('click');
expect(deleteComponent.callCount).toBe(1);
});
});

View File

@@ -1,122 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { Provider } from 'react-redux';
import { styledMount as mount } from 'spec/helpers/theming';
import sinon from 'sinon';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import DeleteComponentButton from 'src/dashboard/components/DeleteComponentButton';
import EditableTitle from 'src/components/EditableTitle';
import HoverMenu from 'src/dashboard/components/menu/HoverMenu';
import WithPopoverMenu from 'src/dashboard/components/menu/WithPopoverMenu';
import DragDroppable from 'src/dashboard/components/dnd/DragDroppable';
import Header from 'src/dashboard/components/gridComponents/Header';
import newComponentFactory from 'src/dashboard/util/newComponentFactory';
import {
HEADER_TYPE,
DASHBOARD_GRID_TYPE,
} from 'src/dashboard/util/componentTypes';
import { mockStoreWithTabs } from 'spec/fixtures/mockStore';
describe('Header', () => {
const props = {
id: 'id',
parentId: 'parentId',
component: newComponentFactory(HEADER_TYPE),
depth: 1,
parentComponent: newComponentFactory(DASHBOARD_GRID_TYPE),
index: 0,
editMode: false,
filters: {},
handleComponentDrop() {},
deleteComponent() {},
updateComponents() {},
};
function setup(overrideProps) {
// We have to wrap provide DragDropContext for the underlying DragDroppable
// otherwise we cannot assert on DragDroppable children
const wrapper = mount(
<Provider store={mockStoreWithTabs}>
<DndProvider backend={HTML5Backend}>
<Header {...props} {...overrideProps} />
</DndProvider>
</Provider>,
);
return wrapper;
}
it('should render a DragDroppable', () => {
const wrapper = setup();
expect(wrapper.find(DragDroppable)).toExist();
});
it('should render a WithPopoverMenu', () => {
const wrapper = setup();
expect(wrapper.find(WithPopoverMenu)).toExist();
});
it('should render a HoverMenu in editMode', () => {
let wrapper = setup();
expect(wrapper.find(HoverMenu)).not.toExist();
// we cannot set props on the Header because of the WithDragDropContext wrapper
wrapper = setup({ editMode: true });
expect(wrapper.find(HoverMenu)).toExist();
});
it('should render an EditableTitle with meta.text', () => {
const wrapper = setup();
expect(wrapper.find(EditableTitle)).toExist();
expect(wrapper.find('.editable-title')).toHaveText(
props.component.meta.text,
);
});
it('should call updateComponents when EditableTitle changes', () => {
const updateComponents = sinon.spy();
const wrapper = setup({ editMode: true, updateComponents });
wrapper.find(EditableTitle).prop('onSaveTitle')('New title');
const headerId = props.component.id;
expect(updateComponents.callCount).toBe(1);
expect(updateComponents.getCall(0).args[0][headerId].meta.text).toBe(
'New title',
);
});
it('should render a DeleteComponentButton when focused in editMode', () => {
const wrapper = setup({ editMode: true });
wrapper.find(WithPopoverMenu).simulate('click'); // focus
expect(wrapper.find(DeleteComponentButton)).toExist();
});
it('should call deleteComponent when deleted', () => {
const deleteComponent = sinon.spy();
const wrapper = setup({ editMode: true, deleteComponent });
wrapper.find(WithPopoverMenu).simulate('click'); // focus
wrapper.find(DeleteComponentButton).simulate('click');
expect(deleteComponent.callCount).toBe(1);
});
});

View File

@@ -1,181 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { Provider } from 'react-redux';
import React from 'react';
import { styledMount as mount } from 'spec/helpers/theming';
import sinon from 'sinon';
import ReactMarkdown from 'react-markdown';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { act } from 'react-dom/test-utils';
import { MarkdownEditor } from 'src/components/AsyncAceEditor';
import MarkdownConnected from 'src/dashboard/components/gridComponents/Markdown';
import MarkdownModeDropdown from 'src/dashboard/components/menu/MarkdownModeDropdown';
import DeleteComponentButton from 'src/dashboard/components/DeleteComponentButton';
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
import DragDroppable from 'src/dashboard/components/dnd/DragDroppable';
import WithPopoverMenu from 'src/dashboard/components/menu/WithPopoverMenu';
import ResizableContainer from 'src/dashboard/components/resizable/ResizableContainer';
import { mockStore } from 'spec/fixtures/mockStore';
import { dashboardLayout as mockLayout } from 'spec/fixtures/mockDashboardLayout';
describe('Markdown', () => {
const props = {
id: 'id',
parentId: 'parentId',
component: mockLayout.present.MARKDOWN_ID,
depth: 2,
parentComponent: mockLayout.present.ROW_ID,
index: 0,
editMode: false,
availableColumnCount: 12,
columnWidth: 50,
redoLength: 0,
undoLength: 0,
onResizeStart() {},
onResize() {},
onResizeStop() {},
handleComponentDrop() {},
updateComponents() {},
deleteComponent() {},
logEvent() {},
addDangerToast() {},
};
function setup(overrideProps) {
// We have to wrap provide DragDropContext for the underlying DragDroppable
// otherwise we cannot assert on DragDroppable children
const wrapper = mount(
<Provider store={mockStore}>
<DndProvider backend={HTML5Backend}>
<MarkdownConnected {...props} {...overrideProps} />
</DndProvider>
</Provider>,
);
return wrapper;
}
it('should render a DragDroppable', () => {
const wrapper = setup();
expect(wrapper.find(DragDroppable)).toExist();
});
it('should render a WithPopoverMenu', () => {
const wrapper = setup();
expect(wrapper.find(WithPopoverMenu)).toExist();
});
it('should render a ResizableContainer', () => {
const wrapper = setup();
expect(wrapper.find(ResizableContainer)).toExist();
});
it('should only have an adjustableWidth if its parent is a Row', () => {
let wrapper = setup();
expect(wrapper.find(ResizableContainer).prop('adjustableWidth')).toBe(true);
wrapper = setup({ ...props, parentComponent: mockLayout.present.CHART_ID });
expect(wrapper.find(ResizableContainer).prop('adjustableWidth')).toBe(
false,
);
});
it('should pass correct props to ResizableContainer', () => {
const wrapper = setup();
const resizableProps = wrapper.find(ResizableContainer).props();
expect(resizableProps.widthStep).toBe(props.columnWidth);
expect(resizableProps.widthMultiple).toBe(props.component.meta.width);
expect(resizableProps.heightMultiple).toBe(props.component.meta.height);
expect(resizableProps.maxWidthMultiple).toBe(
props.component.meta.width + props.availableColumnCount,
);
});
it('should render an Markdown when NOT focused', () => {
const wrapper = setup();
expect(wrapper.find(MarkdownEditor)).not.toExist();
expect(wrapper.find(ReactMarkdown)).toExist();
});
it('should render an AceEditor when focused and editMode=true and editorMode=edit', async () => {
const wrapper = setup({ editMode: true });
expect(wrapper.find(MarkdownEditor)).not.toExist();
expect(wrapper.find(ReactMarkdown)).toExist();
act(() => {
wrapper.find(WithPopoverMenu).simulate('click'); // focus + edit
});
await waitForComponentToPaint(wrapper);
expect(wrapper.find(MarkdownEditor)).toExist();
expect(wrapper.find(ReactMarkdown)).not.toExist();
});
it('should render a ReactMarkdown when focused and editMode=true and editorMode=preview', () => {
const wrapper = setup({ editMode: true });
wrapper.find(WithPopoverMenu).simulate('click'); // focus + edit
expect(wrapper.find(MarkdownEditor)).toExist();
expect(wrapper.find(ReactMarkdown)).not.toExist();
// we can't call setState on Markdown bc it's not the root component, so call
// the mode dropdown onchange instead
const dropdown = wrapper.find(MarkdownModeDropdown);
dropdown.prop('onChange')('preview');
wrapper.update();
expect(wrapper.find(ReactMarkdown)).toExist();
expect(wrapper.find(MarkdownEditor)).not.toExist();
});
it('should call updateComponents when editMode changes from edit => preview, and there are markdownSource changes', () => {
const updateComponents = sinon.spy();
const wrapper = setup({ editMode: true, updateComponents });
wrapper.find(WithPopoverMenu).simulate('click'); // focus + edit
// we can't call setState on Markdown bc it's not the root component, so call
// the mode dropdown onchange instead
const dropdown = wrapper.find(MarkdownModeDropdown);
dropdown.prop('onChange')('preview');
expect(updateComponents.callCount).toBe(0);
dropdown.prop('onChange')('edit');
// because we can't call setState on Markdown, change it through the editor
// then go back to preview mode to invoke updateComponents
const editor = wrapper.find(MarkdownEditor);
editor.prop('onChange')('new markdown!');
dropdown.prop('onChange')('preview');
expect(updateComponents.callCount).toBe(1);
});
it('should render a DeleteComponentButton when focused in editMode', () => {
const wrapper = setup({ editMode: true });
wrapper.find(WithPopoverMenu).simulate('click'); // focus
expect(wrapper.find(DeleteComponentButton)).toExist();
});
it('should call deleteComponent when deleted', () => {
const deleteComponent = sinon.spy();
const wrapper = setup({ editMode: true, deleteComponent });
wrapper.find(WithPopoverMenu).simulate('click'); // focus
wrapper.find(DeleteComponentButton).simulate('click');
expect(deleteComponent.callCount).toBe(1);
});
});

View File

@@ -1,146 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { Provider } from 'react-redux';
import React from 'react';
import { mount } from 'enzyme';
import sinon from 'sinon';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import BackgroundStyleDropdown from 'src/dashboard/components/menu/BackgroundStyleDropdown';
import DashboardComponent from 'src/dashboard/containers/DashboardComponent';
import DeleteComponentButton from 'src/dashboard/components/DeleteComponentButton';
import DragDroppable from 'src/dashboard/components/dnd/DragDroppable';
import HoverMenu from 'src/dashboard/components/menu/HoverMenu';
import IconButton from 'src/dashboard/components/IconButton';
import Row from 'src/dashboard/components/gridComponents/Row';
import WithPopoverMenu from 'src/dashboard/components/menu/WithPopoverMenu';
import { DASHBOARD_GRID_ID } from 'src/dashboard/util/constants';
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
import { getMockStore } from 'spec/fixtures/mockStore';
import { dashboardLayout as mockLayout } from 'spec/fixtures/mockDashboardLayout';
import { initialState } from 'src/SqlLab/fixtures';
describe('Row', () => {
const rowWithoutChildren = { ...mockLayout.present.ROW_ID, children: [] };
const props = {
id: 'ROW_ID',
parentId: DASHBOARD_GRID_ID,
component: mockLayout.present.ROW_ID,
parentComponent: mockLayout.present[DASHBOARD_GRID_ID],
index: 0,
depth: 2,
editMode: false,
availableColumnCount: 12,
columnWidth: 50,
occupiedColumnCount: 6,
onResizeStart() {},
onResize() {},
onResizeStop() {},
handleComponentDrop() {},
deleteComponent() {},
updateComponents() {},
};
function setup(overrideProps) {
// We have to wrap provide DragDropContext for the underlying DragDroppable
// otherwise we cannot assert on DragDroppable children
const mockStore = getMockStore({
...initialState,
});
const wrapper = mount(
<Provider store={mockStore}>
<DndProvider backend={HTML5Backend}>
<Row {...props} {...overrideProps} />
</DndProvider>
</Provider>,
{
wrappingComponent: ThemeProvider,
wrappingComponentProps: { theme: supersetTheme },
},
);
return wrapper;
}
it('should render a DragDroppable', () => {
// don't count child DragDroppables
const wrapper = setup({ component: rowWithoutChildren });
expect(wrapper.find(DragDroppable)).toExist();
});
it('should render a WithPopoverMenu', () => {
// don't count child DragDroppables
const wrapper = setup({ component: rowWithoutChildren });
expect(wrapper.find(WithPopoverMenu)).toExist();
});
it('should render a HoverMenu in editMode', () => {
let wrapper = setup({ component: rowWithoutChildren });
expect(wrapper.find(HoverMenu)).not.toExist();
// we cannot set props on the Row because of the WithDragDropContext wrapper
wrapper = setup({ component: rowWithoutChildren, editMode: true });
expect(wrapper.find(HoverMenu)).toExist();
});
it('should render a DeleteComponentButton in editMode', () => {
let wrapper = setup({ component: rowWithoutChildren });
expect(wrapper.find(DeleteComponentButton)).not.toExist();
// we cannot set props on the Row because of the WithDragDropContext wrapper
wrapper = setup({ component: rowWithoutChildren, editMode: true });
expect(wrapper.find(DeleteComponentButton)).toExist();
});
it('should render a BackgroundStyleDropdown when focused', () => {
let wrapper = setup({ component: rowWithoutChildren });
expect(wrapper.find(BackgroundStyleDropdown)).not.toExist();
// we cannot set props on the Row because of the WithDragDropContext wrapper
wrapper = setup({ component: rowWithoutChildren, editMode: true });
wrapper
.find(IconButton)
.at(1) // first one is delete button
.simulate('click');
expect(wrapper.find(BackgroundStyleDropdown)).toExist();
});
it('should call deleteComponent when deleted', () => {
const deleteComponent = sinon.spy();
const wrapper = setup({ editMode: true, deleteComponent });
wrapper.find(DeleteComponentButton).simulate('click');
expect(deleteComponent.callCount).toBe(1);
});
it('should pass appropriate availableColumnCount to children', () => {
const wrapper = setup();
const dashboardComponent = wrapper.find(DashboardComponent).first();
expect(dashboardComponent.props().availableColumnCount).toBe(
props.availableColumnCount - props.occupiedColumnCount,
);
});
it('should increment the depth of its children', () => {
const wrapper = setup();
const dashboardComponent = wrapper.find(DashboardComponent).first();
expect(dashboardComponent.props().depth).toBe(props.depth + 1);
});
});

View File

@@ -1,115 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { Provider } from 'react-redux';
import React from 'react';
import { styledMount as mount } from 'spec/helpers/theming';
import sinon from 'sinon';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import DashboardComponent from 'src/dashboard/containers/DashboardComponent';
import DragDroppable from 'src/dashboard/components/dnd/DragDroppable';
import EditableTitle from 'src/components/EditableTitle';
import Tab, {
RENDER_TAB,
RENDER_TAB_CONTENT,
} from 'src/dashboard/components/gridComponents/Tab';
import { dashboardLayoutWithTabs } from 'spec/fixtures/mockDashboardLayout';
import { getMockStore } from 'spec/fixtures/mockStore';
import { initialState } from 'src/SqlLab/fixtures';
describe('Tabs', () => {
const props = {
id: 'TAB_ID',
parentId: 'TABS_ID',
component: dashboardLayoutWithTabs.present.TAB_ID,
parentComponent: dashboardLayoutWithTabs.present.TABS_ID,
index: 0,
depth: 1,
editMode: false,
renderType: RENDER_TAB,
filters: {},
setDirectPathToChild: jest.fn(),
onDropOnTab() {},
onDeleteTab() {},
availableColumnCount: 12,
columnWidth: 50,
onResizeStart() {},
onResize() {},
onResizeStop() {},
createComponent() {},
handleComponentDrop() {},
onChangeTab() {},
deleteComponent() {},
updateComponents() {},
};
function setup(overrideProps) {
// We have to wrap provide DragDropContext for the underlying DragDroppable
// otherwise we cannot assert on DragDroppable children
const mockStore = getMockStore({
...initialState,
dashboardLayout: dashboardLayoutWithTabs,
dashboardFilters: {},
});
const wrapper = mount(
<Provider store={mockStore}>
<DndProvider backend={HTML5Backend}>
<Tab {...props} {...overrideProps} />
</DndProvider>
</Provider>,
);
return wrapper;
}
describe('renderType=RENDER_TAB', () => {
it('should render a DragDroppable', () => {
const wrapper = setup();
expect(wrapper.find(DragDroppable)).toExist();
});
it('should render an EditableTitle with meta.text', () => {
const wrapper = setup();
const title = wrapper.find(EditableTitle);
expect(title).toHaveLength(1);
expect(title.find('.editable-title')).toHaveText(
props.component.meta.defaultText,
);
});
it('should call updateComponents when EditableTitle changes', () => {
const updateComponents = sinon.spy();
const wrapper = setup({ editMode: true, updateComponents });
wrapper.find(EditableTitle).prop('onSaveTitle')('New title');
expect(updateComponents.callCount).toBe(1);
expect(updateComponents.getCall(0).args[0].TAB_ID.meta.text).toBe(
'New title',
);
});
});
describe('renderType=RENDER_TAB_CONTENT', () => {
it('should render a DashboardComponent', () => {
const wrapper = setup({ renderType: RENDER_TAB_CONTENT });
// We expect 2 because this Tab has a Row child and the row has a Chart
expect(wrapper.find(DashboardComponent)).toHaveLength(2);
});
});
});

View File

@@ -1,205 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { Provider } from 'react-redux';
import React from 'react';
import { shallow } from 'enzyme';
import sinon from 'sinon';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { LineEditableTabs } from 'src/components/Tabs';
import { Modal } from 'src/common/components';
import fetchMock from 'fetch-mock';
import { styledMount as mount } from 'spec/helpers/theming';
import DashboardComponent from 'src/dashboard/containers/DashboardComponent';
import DeleteComponentButton from 'src/dashboard/components/DeleteComponentButton';
import HoverMenu from 'src/dashboard/components/menu/HoverMenu';
import DragDroppable from 'src/dashboard/components/dnd/DragDroppable';
import { Tabs } from 'src/dashboard/components/gridComponents/Tabs';
import { DASHBOARD_ROOT_ID } from 'src/dashboard/util/constants';
import emptyDashboardLayout from 'src/dashboard/fixtures/emptyDashboardLayout';
import { dashboardLayoutWithTabs } from 'spec/fixtures/mockDashboardLayout';
import { getMockStore } from 'spec/fixtures/mockStore';
import { nativeFilters } from 'spec/fixtures/mockNativeFilters';
import { initialState } from 'src/SqlLab/fixtures';
describe('Tabs', () => {
fetchMock.post('glob:*/r/shortner/', {});
const props = {
id: 'TABS_ID',
parentId: DASHBOARD_ROOT_ID,
component: dashboardLayoutWithTabs.present.TABS_ID,
parentComponent: dashboardLayoutWithTabs.present[DASHBOARD_ROOT_ID],
index: 0,
depth: 1,
renderTabContent: true,
editMode: false,
availableColumnCount: 12,
columnWidth: 50,
onResizeStart() {},
onResize() {},
onResizeStop() {},
createComponent() {},
handleComponentDrop() {},
onChangeTab() {},
deleteComponent() {},
updateComponents() {},
logEvent() {},
dashboardLayout: emptyDashboardLayout,
nativeFilters: nativeFilters.filters,
};
const mockStore = getMockStore({
...initialState,
dashboardLayout: dashboardLayoutWithTabs,
dashboardFilters: {},
});
function setup(overrideProps) {
// We have to wrap provide DragDropContext for the underlying DragDroppable
// otherwise we cannot assert on DragDroppable children
const wrapper = mount(
<Provider store={mockStore}>
<DndProvider backend={HTML5Backend}>
<Tabs {...props} {...overrideProps} />
</DndProvider>
</Provider>,
);
return wrapper;
}
it('should render a DragDroppable', () => {
// test just Tabs with no children DragDroppables
const wrapper = setup({ component: { ...props.component, children: [] } });
expect(wrapper.find(DragDroppable)).toExist();
});
it('should render non-editable tabs', () => {
const wrapper = setup();
expect(wrapper.find(LineEditableTabs)).toExist();
expect(wrapper.find('.ant-tabs-nav-add').exists()).toBeFalsy();
});
it('should render a tab pane for each child', () => {
const wrapper = setup();
expect(wrapper.find(LineEditableTabs.TabPane)).toHaveLength(
props.component.children.length,
);
});
it('should render editable tabs in editMode', () => {
const wrapper = setup({ editMode: true });
expect(wrapper.find(LineEditableTabs)).toExist();
expect(wrapper.find('.ant-tabs-nav-add')).toExist();
});
it('should render a DashboardComponent for each child', () => {
// note: this does not test Tab content
const wrapper = setup({ renderTabContent: false });
expect(wrapper.find(DashboardComponent)).toHaveLength(
props.component.children.length,
);
});
it('should call createComponent if the (+) tab is clicked', () => {
const createComponent = sinon.spy();
const wrapper = setup({ editMode: true, createComponent });
wrapper
.find('[data-test="dashboard-component-tabs"] .ant-tabs-nav-add')
.last()
.simulate('click');
expect(createComponent.callCount).toBe(1);
});
it('should call onChangeTab when a tab is clicked', () => {
const onChangeTab = sinon.spy();
const wrapper = setup({ editMode: true, onChangeTab });
wrapper
.find('[data-test="dashboard-component-tabs"] .ant-tabs-tab')
.at(1) // will not call if it is already selected
.simulate('click');
expect(onChangeTab.callCount).toBe(1);
});
it('should not call onChangeTab when anchor link is clicked', () => {
const onChangeTab = sinon.spy();
const wrapper = setup({ editMode: true, onChangeTab });
wrapper
.find(
'[data-test="dashboard-component-tabs"] .ant-tabs-tab [role="button"]',
)
.at(1) // will not call if it is already selected
.simulate('click');
expect(onChangeTab.callCount).toBe(0);
});
it('should render a HoverMenu in editMode', () => {
let wrapper = setup();
expect(wrapper.find(HoverMenu)).not.toExist();
wrapper = setup({ editMode: true });
expect(wrapper.find(HoverMenu)).toExist();
});
it('should render a DeleteComponentButton in editMode', () => {
let wrapper = setup();
expect(wrapper.find(DeleteComponentButton)).not.toExist();
wrapper = setup({ editMode: true });
expect(wrapper.find(DeleteComponentButton)).toExist();
});
it('should call deleteComponent when deleted', () => {
const deleteComponent = sinon.spy();
const wrapper = setup({ editMode: true, deleteComponent });
wrapper.find(DeleteComponentButton).simulate('click');
expect(deleteComponent.callCount).toBe(1);
});
it('should direct display direct-link tab', () => {
let wrapper = shallow(<Tabs {...props} />);
// default show first tab child
expect(wrapper.state('tabIndex')).toBe(0);
// display child in directPathToChild list
const directPathToChild =
dashboardLayoutWithTabs.present.ROW_ID2.parents.slice();
const directLinkProps = {
...props,
directPathToChild,
};
wrapper = shallow(<Tabs {...directLinkProps} />);
expect(wrapper.state('tabIndex')).toBe(1);
});
it('should render Modal when clicked remove tab button', () => {
const deleteComponent = sinon.spy();
const modalMock = jest.spyOn(Modal, 'confirm');
const wrapper = setup({ editMode: true, deleteComponent });
wrapper.find('.ant-tabs-tab-remove').at(0).simulate('click');
expect(modalMock.mock.calls).toHaveLength(1);
expect(deleteComponent.callCount).toBe(0);
});
});

View File

@@ -1,84 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { mount } from 'enzyme';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import DragDroppable from 'src/dashboard/components/dnd/DragDroppable';
import DraggableNewComponent from 'src/dashboard/components/gridComponents/new/DraggableNewComponent';
import { NEW_COMPONENTS_SOURCE_ID } from 'src/dashboard/util/constants';
import {
NEW_COMPONENT_SOURCE_TYPE,
CHART_TYPE,
} from 'src/dashboard/util/componentTypes';
describe('DraggableNewComponent', () => {
const props = {
id: 'id',
type: CHART_TYPE,
label: 'label!',
className: 'a_class',
};
function setup(overrideProps) {
// We have to wrap provide DragDropContext for the underlying DragDroppable
// otherwise we cannot assert on DragDroppable children
const wrapper = mount(
<DndProvider backend={HTML5Backend}>
<DraggableNewComponent {...props} {...overrideProps} />
</DndProvider>,
);
return wrapper;
}
it('should render a DragDroppable', () => {
const wrapper = setup();
expect(wrapper.find(DragDroppable)).toExist();
});
it('should pass component={ type, id } to DragDroppable', () => {
const wrapper = setup();
const dragdroppable = wrapper.find(DragDroppable);
expect(dragdroppable.prop('component')).toEqual({
id: props.id,
type: props.type,
});
});
it('should pass appropriate parent source and id to DragDroppable', () => {
const wrapper = setup();
const dragdroppable = wrapper.find(DragDroppable);
expect(dragdroppable.prop('parentComponent')).toEqual({
id: NEW_COMPONENTS_SOURCE_ID,
type: NEW_COMPONENT_SOURCE_TYPE,
});
});
it('should render the passed label', () => {
const wrapper = setup();
expect(wrapper.find('.new-component').text()).toBe(props.label);
});
it('should add the passed className', () => {
const wrapper = setup();
const className = `.new-component-placeholder.${props.className}`;
expect(wrapper.find(className)).toExist();
});
});

View File

@@ -1,45 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { shallow } from 'enzyme';
import DraggableNewComponent from 'src/dashboard/components/gridComponents/new/DraggableNewComponent';
import NewColumn from 'src/dashboard/components/gridComponents/new/NewColumn';
import { NEW_COLUMN_ID } from 'src/dashboard/util/constants';
import { COLUMN_TYPE } from 'src/dashboard/util/componentTypes';
describe('NewColumn', () => {
function setup() {
return shallow(<NewColumn />);
}
it('should render a DraggableNewComponent', () => {
const wrapper = setup();
expect(wrapper.find(DraggableNewComponent)).toExist();
});
it('should set appropriate type and id', () => {
const wrapper = setup();
expect(wrapper.find(DraggableNewComponent).props()).toMatchObject({
type: COLUMN_TYPE,
id: NEW_COLUMN_ID,
});
});
});

View File

@@ -1,45 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { shallow } from 'enzyme';
import DraggableNewComponent from 'src/dashboard/components/gridComponents/new/DraggableNewComponent';
import NewDivider from 'src/dashboard/components/gridComponents/new/NewDivider';
import { NEW_DIVIDER_ID } from 'src/dashboard/util/constants';
import { DIVIDER_TYPE } from 'src/dashboard/util/componentTypes';
describe('NewDivider', () => {
function setup() {
return shallow(<NewDivider />);
}
it('should render a DraggableNewComponent', () => {
const wrapper = setup();
expect(wrapper.find(DraggableNewComponent)).toExist();
});
it('should set appropriate type and id', () => {
const wrapper = setup();
expect(wrapper.find(DraggableNewComponent).props()).toMatchObject({
type: DIVIDER_TYPE,
id: NEW_DIVIDER_ID,
});
});
});

View File

@@ -1,45 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { shallow } from 'enzyme';
import DraggableNewComponent from 'src/dashboard/components/gridComponents/new/DraggableNewComponent';
import NewHeader from 'src/dashboard/components/gridComponents/new/NewHeader';
import { NEW_HEADER_ID } from 'src/dashboard/util/constants';
import { HEADER_TYPE } from 'src/dashboard/util/componentTypes';
describe('NewHeader', () => {
function setup() {
return shallow(<NewHeader />);
}
it('should render a DraggableNewComponent', () => {
const wrapper = setup();
expect(wrapper.find(DraggableNewComponent)).toExist();
});
it('should set appropriate type and id', () => {
const wrapper = setup();
expect(wrapper.find(DraggableNewComponent).props()).toMatchObject({
type: HEADER_TYPE,
id: NEW_HEADER_ID,
});
});
});

View File

@@ -1,45 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { shallow } from 'enzyme';
import DraggableNewComponent from 'src/dashboard/components/gridComponents/new/DraggableNewComponent';
import NewRow from 'src/dashboard/components/gridComponents/new/NewRow';
import { NEW_ROW_ID } from 'src/dashboard/util/constants';
import { ROW_TYPE } from 'src/dashboard/util/componentTypes';
describe('NewRow', () => {
function setup() {
return shallow(<NewRow />);
}
it('should render a DraggableNewComponent', () => {
const wrapper = setup();
expect(wrapper.find(DraggableNewComponent)).toExist();
});
it('should set appropriate type and id', () => {
const wrapper = setup();
expect(wrapper.find(DraggableNewComponent).props()).toMatchObject({
type: ROW_TYPE,
id: NEW_ROW_ID,
});
});
});

View File

@@ -1,45 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 { shallow } from 'enzyme';
import DraggableNewComponent from 'src/dashboard/components/gridComponents/new/DraggableNewComponent';
import NewTabs from 'src/dashboard/components/gridComponents/new/NewTabs';
import { NEW_TABS_ID } from 'src/dashboard/util/constants';
import { TABS_TYPE } from 'src/dashboard/util/componentTypes';
describe('NewTabs', () => {
function setup() {
return shallow(<NewTabs />);
}
it('should render a DraggableNewComponent', () => {
const wrapper = setup();
expect(wrapper.find(DraggableNewComponent)).toExist();
});
it('should set appropriate type and id', () => {
const wrapper = setup();
expect(wrapper.find(DraggableNewComponent).props()).toMatchObject({
type: TABS_TYPE,
id: NEW_TABS_ID,
});
});
});