Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dashboard builder rebased + linted #4849

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions superset/assets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,18 @@
"react-addons-css-transition-group": "^15.6.0",
"react-addons-shallow-compare": "^15.4.2",
"react-alert": "^2.3.0",
"react-bootstrap": "^0.32.0",
"react-bootstrap": "^0.31.5",
"react-bootstrap-slider": "2.0.1",
"react-bootstrap-table": "^4.0.2",
"react-color": "^2.13.8",
"react-datetime": "2.9.0",
"react-dnd": "^2.5.4",
"react-dnd-html5-backend": "^2.5.4",
"react-dom": "^15.6.2",
"react-gravatar": "^2.6.1",
"react-grid-layout": "0.16.5",
"react-map-gl": "^3.0.4",
"react-redux": "^5.0.2",
"react-resizable": "^1.3.3",
"react-search-input": "^0.11.3",
"react-select": "1.2.1",
"react-select-fast-filter-options": "^0.2.1",
"react-sortable-hoc": "^0.6.7",
Expand Down
2 changes: 1 addition & 1 deletion superset/assets/spec/javascripts/chart/Chart_spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('Chart', () => {
};
const mockedProps = {
...chart,
chartKey: 'slice_223',
id: 223,
containerId: 'slice-container-223',
datasource: {},
formData: {},
Expand Down
96 changes: 63 additions & 33 deletions superset/assets/spec/javascripts/dashboard/Dashboard_spec.jsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,68 @@
/* eslint camelcase: 0 */
import React from 'react';
import { shallow } from 'enzyme';
import { describe, it } from 'mocha';
import { expect } from 'chai';
import sinon from 'sinon';

import * as dashboardActions from '../../../src/dashboard/actions';
import * as sliceActions from '../../../src/dashboard/actions/sliceEntities';
import * as dashboardActions from '../../../src/dashboard/actions/dashboardState';
import * as chartActions from '../../../src/chart/chartAction';
import Dashboard from '../../../src/dashboard/components/Dashboard';
import { defaultFilters, dashboard, charts } from './fixtures';
import { defaultFilters, dashboardState, dashboardInfo, dashboardLayout,
charts, datasources, sliceEntities } from './fixtures';

describe('Dashboard', () => {
const mockedProps = {
actions: { ...chartActions, ...dashboardActions },
actions: { ...chartActions, ...dashboardActions, ...sliceActions },
initMessages: [],
dashboard: dashboard.dashboard,
slices: charts,
filters: dashboard.filters,
datasources: dashboard.datasources,
refresh: false,
dashboardState,
dashboardInfo,
charts,
slices: sliceEntities.slices,
datasources,
layout: dashboardLayout.present,
timeout: 60,
isStarred: false,
userId: dashboard.userId,
userId: dashboardInfo.userId,
};

it('should render', () => {
const wrapper = shallow(<Dashboard {...mockedProps} />);
expect(wrapper.find('#dashboard-container')).to.have.length(1);
expect(wrapper.instance().getAllSlices()).to.have.length(3);
expect(wrapper.instance().getAllCharts()).to.have.length(3);
});

it('should handle metadata default_filters', () => {
const wrapper = shallow(<Dashboard {...mockedProps} />);
expect(wrapper.instance().props.filters).deep.equal(defaultFilters);
expect(wrapper.instance().props.dashboardState.filters).deep.equal(defaultFilters);
});

describe('getFormDataExtra', () => {
let wrapper;
let selectedSlice;
let selectedChart;
beforeEach(() => {
wrapper = shallow(<Dashboard {...mockedProps} />);
selectedSlice = wrapper.instance().props.dashboard.slices[1];
selectedChart = charts[248];
});

it('should carry default_filters', () => {
const extraFilters = wrapper.instance().getFormDataExtra(selectedSlice).extra_filters;
const extraFilters = wrapper.instance().getFormDataExtra(selectedChart).extra_filters;
expect(extraFilters[0]).to.deep.equal({ col: 'region', op: 'in', val: [] });
expect(extraFilters[1]).to.deep.equal({ col: 'country_name', op: 'in', val: ['United States'] });
});

it('should carry updated filter', () => {
wrapper.setProps({
const newState = {
...wrapper.props('dashboardState'),
filters: {
256: { region: [] },
257: { country_name: ['France'] },
},
};
wrapper.setProps({
dashboardState: newState,
});
const extraFilters = wrapper.instance().getFormDataExtra(selectedSlice).extra_filters;
const extraFilters = wrapper.instance().getFormDataExtra(selectedChart).extra_filters;
expect(extraFilters[1]).to.deep.equal({ col: 'country_name', op: 'in', val: ['France'] });
});
});
Expand All @@ -65,7 +72,7 @@ describe('Dashboard', () => {
let spy;
beforeEach(() => {
wrapper = shallow(<Dashboard {...mockedProps} />);
spy = sinon.spy(wrapper.instance(), 'fetchSlices');
spy = sinon.spy(mockedProps.actions, 'runQuery');
});
afterEach(() => {
spy.restore();
Expand All @@ -75,13 +82,13 @@ describe('Dashboard', () => {
const filterKey = Object.keys(defaultFilters)[1];
wrapper.instance().refreshExcept(filterKey);
expect(spy.callCount).to.equal(1);
expect(spy.getCall(0).args[0].length).to.equal(1);
const slice_id = spy.getCall(0).args[0].slice_id;
expect(slice_id).to.equal(248);
});

it('should refresh all slices', () => {
wrapper.instance().refreshExcept();
expect(spy.callCount).to.equal(1);
expect(spy.getCall(0).args[0].length).to.equal(3);
expect(spy.callCount).to.equal(3);
});
});

Expand All @@ -94,7 +101,7 @@ describe('Dashboard', () => {
wrapper = shallow(<Dashboard {...mockedProps} />);
prevProp = wrapper.instance().props;
refreshExceptSpy = sinon.spy(wrapper.instance(), 'refreshExcept');
fetchSlicesStub = sinon.stub(wrapper.instance(), 'fetchSlices');
fetchSlicesStub = sinon.stub(mockedProps.actions, 'fetchCharts');
});
afterEach(() => {
fetchSlicesStub.restore();
Expand All @@ -106,77 +113,100 @@ describe('Dashboard', () => {
refreshExceptSpy.reset();
});
it('no change', () => {
wrapper.setProps({
refresh: true,
const newState = {
...wrapper.props('dashboardState'),
filters: {
256: { region: [] },
257: { country_name: ['United States'] },
},
};
wrapper.setProps({
dashboardState: newState,
});
wrapper.instance().componentDidUpdate(prevProp);
expect(refreshExceptSpy.callCount).to.equal(0);
});

it('remove filter', () => {
wrapper.setProps({
const newState = {
...wrapper.props('dashboardState'),
refresh: true,
filters: {
256: { region: [] },
},
};
wrapper.setProps({
dashboardState: newState,
});
wrapper.instance().componentDidUpdate(prevProp);
expect(refreshExceptSpy.callCount).to.equal(1);
});

it('change filter', () => {
wrapper.setProps({
const newState = {
...wrapper.props('dashboardState'),
refresh: true,
filters: {
256: { region: [] },
257: { country_name: ['Canada'] },
},
};
wrapper.setProps({
dashboardState: newState,
});
wrapper.instance().componentDidUpdate(prevProp);
expect(refreshExceptSpy.callCount).to.equal(1);
});

it('add filter', () => {
wrapper.setProps({
const newState = {
...wrapper.props('dashboardState'),
refresh: true,
filters: {
256: { region: [] },
257: { country_name: ['Canada'] },
258: { another_filter: ['new'] },
},
};
wrapper.setProps({
dashboardState: newState,
});
wrapper.instance().componentDidUpdate(prevProp);
expect(refreshExceptSpy.callCount).to.equal(1);
});
});

it('should refresh if refresh flag is true', () => {
wrapper.setProps({
const newState = {
...wrapper.props('dashboardState'),
refresh: true,
filters: {
256: { region: ['Asian'] },
},
};
wrapper.setProps({
dashboardState: newState,
});
wrapper.instance().componentDidUpdate(prevProp);
const fetchArgs = fetchSlicesStub.lastCall.args[0];
expect(fetchArgs).to.have.length(2);
expect(refreshExceptSpy.callCount).to.equal(1);
expect(refreshExceptSpy.lastCall.args[0]).to.equal('256');
});

it('should not refresh filter_immune_slices', () => {
wrapper.setProps({
const newState = {
...wrapper.props('dashboardState'),
refresh: true,
filters: {
256: { region: [] },
257: { country_name: ['Canada'] },
},
};
wrapper.setProps({
dashboardState: newState,
});
wrapper.instance().componentDidUpdate(prevProp);
const fetchArgs = fetchSlicesStub.lastCall.args[0];
expect(fetchArgs).to.have.length(1);
expect(refreshExceptSpy.callCount).to.equal(1);
expect(refreshExceptSpy.lastCall.args[0]).to.equal('257');
});
});
});
10 changes: 6 additions & 4 deletions superset/assets/spec/javascripts/dashboard/fixtures.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getInitialState } from '../../../src/dashboard/reducers';
import getInitialState from '../../../src/dashboard/reducers/getInitialState';

export const defaultFilters = {
256: { region: [] },
Expand Down Expand Up @@ -118,7 +118,6 @@ export const slice = {
slice_url: '/superset/explore/table/2/?form_data=%7B%22slice_id%22%3A%20248%7D',
};

const datasources = {};
const mockDashboardData = {
css: '',
dash_edit_perm: true,
Expand Down Expand Up @@ -152,10 +151,13 @@ const mockDashboardData = {
slices: [regionFilter, slice, countryFilter],
standalone_mode: false,
};
export const { dashboard, charts } = getInitialState({
export const {
dashboardState, dashboardInfo,
charts, datasources, sliceEntities,
dashboardLayout } = getInitialState({
common: {},
dashboard_data: mockDashboardData,
datasources,
datasources: {},
user_id: '1',
});

23 changes: 13 additions & 10 deletions superset/assets/spec/javascripts/dashboard/reducers_spec.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
import { describe, it } from 'mocha';
import { expect } from 'chai';

import { dashboard as reducers } from '../../../src/dashboard/reducers';
import * as actions from '../../../src/dashboard/actions';
import { defaultFilters, dashboard as initState } from './fixtures';
import reducers from '../../../src/dashboard/reducers/dashboardState';
import * as actions from '../../../src/dashboard/actions/dashboardState';
import { defaultFilters, dashboardState as initState } from './fixtures';

describe('Dashboard reducers', () => {
it('should initialized', () => {
expect(initState.sliceIds.size).to.equal(3);
});

it('should remove slice', () => {
const action = {
type: actions.REMOVE_SLICE,
slice: initState.dashboard.slices[1],
sliceId: 248,
};
expect(initState.dashboard.slices).to.have.length(3);

const { dashboard, filters, refresh } = reducers(initState, action);
expect(dashboard.slices).to.have.length(2);
const { sliceIds, filters, refresh } = reducers(initState, action);
expect(sliceIds.size).to.be.equal(2);
expect(filters).to.deep.equal(defaultFilters);
expect(refresh).to.equal(false);
});

it('should remove filter slice', () => {
const action = {
type: actions.REMOVE_SLICE,
slice: initState.dashboard.slices[0],
sliceId: 256,
};
const initFilters = Object.keys(initState.filters);
expect(initFilters).to.have.length(2);

const { dashboard, filters, refresh } = reducers(initState, action);
expect(dashboard.slices).to.have.length(2);
const { sliceIds, filters, refresh } = reducers(initState, action);
expect(sliceIds.size).to.equal(2);
expect(Object.keys(filters)).to.have.length(1);
expect(refresh).to.equal(true);
});
Expand Down
Loading