mirror of
https://github.com/apache/superset.git
synced 2026-04-19 08:04:53 +00:00
feat(dashboard): Let users download full CSV of a table (#15046)
* - Convert SliceHeader to TSX in progress - Add menu option to download full CSV. Probably will change it * Add Download Full CSV feature, and tests * Added more tests, more TS fixes * Added feature flag * Update @superset-ui package versions * Update @superset-ui packages versions * use backend config instead of hardcoding number of rows * Update tests * front end test fix * Lint fixes and test fixes
This commit is contained in:
@@ -36,6 +36,7 @@ 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 'spec/javascripts/sqllab/fixtures';
|
||||
import { nativeFiltersInfo } from '../../fixtures/mockNativeFilters';
|
||||
|
||||
describe('ChartHolder', () => {
|
||||
@@ -61,6 +62,7 @@ describe('ChartHolder', () => {
|
||||
|
||||
function setup(overrideProps) {
|
||||
const mockStore = getMockStore({
|
||||
...initialState,
|
||||
sliceEntities: sliceEntitiesForChart,
|
||||
});
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ 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, {
|
||||
@@ -38,6 +38,7 @@ describe('Chart', () => {
|
||||
updateSliceName() {},
|
||||
|
||||
// from redux
|
||||
maxRows: 666,
|
||||
chart: chartQueries[queryId],
|
||||
formData: chartQueries[queryId].formData,
|
||||
datasource: mockDatasource[sliceEntities.slices[queryId].datasource],
|
||||
@@ -59,6 +60,8 @@ describe('Chart', () => {
|
||||
unsetFocusedFilterField() {},
|
||||
addSuccessToast() {},
|
||||
addDangerToast() {},
|
||||
exportCSV() {},
|
||||
exportFullCSV() {},
|
||||
componentId: 'test',
|
||||
dashboardId: 111,
|
||||
editMode: false,
|
||||
@@ -86,7 +89,6 @@ describe('Chart', () => {
|
||||
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();
|
||||
});
|
||||
@@ -104,4 +106,30 @@ describe('Chart', () => {
|
||||
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: 'results',
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -34,8 +34,9 @@ import IconButton from 'src/dashboard/components/IconButton';
|
||||
import ResizableContainer from 'src/dashboard/components/resizable/ResizableContainer';
|
||||
import WithPopoverMenu from 'src/dashboard/components/menu/WithPopoverMenu';
|
||||
|
||||
import { mockStore } from 'spec/fixtures/mockStore';
|
||||
import { getMockStore } from 'spec/fixtures/mockStore';
|
||||
import { dashboardLayout as mockLayout } from 'spec/fixtures/mockDashboardLayout';
|
||||
import { initialState } from 'spec/javascripts/sqllab/fixtures';
|
||||
|
||||
describe('Column', () => {
|
||||
const columnWithoutChildren = {
|
||||
@@ -65,6 +66,9 @@ describe('Column', () => {
|
||||
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}>
|
||||
|
||||
@@ -34,8 +34,9 @@ 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 { mockStore } from 'spec/fixtures/mockStore';
|
||||
import { getMockStore } from 'spec/fixtures/mockStore';
|
||||
import { dashboardLayout as mockLayout } from 'spec/fixtures/mockDashboardLayout';
|
||||
import { initialState } from 'spec/javascripts/sqllab/fixtures';
|
||||
|
||||
describe('Row', () => {
|
||||
const rowWithoutChildren = { ...mockLayout.present.ROW_ID, children: [] };
|
||||
@@ -61,6 +62,9 @@ describe('Row', () => {
|
||||
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}>
|
||||
|
||||
@@ -31,7 +31,8 @@ import Tab, {
|
||||
RENDER_TAB_CONTENT,
|
||||
} from 'src/dashboard/components/gridComponents/Tab';
|
||||
import { dashboardLayoutWithTabs } from 'spec/fixtures/mockDashboardLayout';
|
||||
import { mockStoreWithTabs } from 'spec/fixtures/mockStore';
|
||||
import { getMockStore } from 'spec/fixtures/mockStore';
|
||||
import { initialState } from 'spec/javascripts/sqllab/fixtures';
|
||||
|
||||
describe('Tabs', () => {
|
||||
const props = {
|
||||
@@ -62,8 +63,13 @@ describe('Tabs', () => {
|
||||
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={mockStoreWithTabs}>
|
||||
<Provider store={mockStore}>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<Tab {...props} {...overrideProps} />
|
||||
</DndProvider>
|
||||
|
||||
@@ -35,8 +35,9 @@ 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 { mockStoreWithTabs } from 'spec/fixtures/mockStore';
|
||||
import { getMockStore } from 'spec/fixtures/mockStore';
|
||||
import { nativeFilters } from 'spec/fixtures/mockNativeFilters';
|
||||
import { initialState } from 'spec/javascripts/sqllab/fixtures';
|
||||
|
||||
describe('Tabs', () => {
|
||||
fetchMock.post('glob:*/r/shortner/', {});
|
||||
@@ -68,8 +69,13 @@ describe('Tabs', () => {
|
||||
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={mockStoreWithTabs}>
|
||||
<Provider store={mockStore}>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<Tabs {...props} {...overrideProps} />
|
||||
</DndProvider>
|
||||
|
||||
Reference in New Issue
Block a user