Skip to content

Commit

Permalink
feat(viz): add query mode switch to table chart (apache#10113)
Browse files Browse the repository at this point in the history
1, Replace table chart rendering from jquery.DataTables to react-table: apache-superset/superset-ui#623
2. Rearrange the control panel, replace GROUP BY and NOT GROUP BY with a "Query Mode" switch: apache-superset/superset-ui#609
  • Loading branch information
ktmud authored and auxten committed Nov 20, 2020
1 parent 5b187b4 commit 1f19156
Show file tree
Hide file tree
Showing 34 changed files with 8,746 additions and 12,431 deletions.
Expand Up @@ -61,7 +61,7 @@ describe('Dashboard filter', () => {
expect(nodes).to.have.length(9);
});

cy.get('.Select__control input[type=text]').first().blur();
cy.get('.Select__control input[type=text]').first().focus().blur();

// should hide the filter indicator
cy.get('.filter-indicator')
Expand Down
20,123 changes: 8,183 additions & 11,940 deletions superset-frontend/package-lock.json

Large diffs are not rendered by default.

29 changes: 15 additions & 14 deletions superset-frontend/package.json
Expand Up @@ -61,14 +61,14 @@
"@emotion/core": "^10.0.28",
"@superset-ui/chart": "^0.14.1",
"@superset-ui/chart-composition": "^0.14.1",
"@superset-ui/color": "^0.14.1",
"@superset-ui/color": "^0.14.2",
"@superset-ui/connection": "^0.14.0",
"@superset-ui/chart-controls": "^0.14.1",
"@superset-ui/chart-controls": "^0.14.2",
"@superset-ui/core": "^0.14.0",
"@superset-ui/dimension": "^0.14.0",
"@superset-ui/legacy-plugin-chart-calendar": "^0.14.1",
"@superset-ui/legacy-plugin-chart-chord": "^0.14.1",
"@superset-ui/legacy-plugin-chart-country-map": "^0.14.1",
"@superset-ui/legacy-plugin-chart-country-map": "^0.14.2",
"@superset-ui/legacy-plugin-chart-event-flow": "^0.14.1",
"@superset-ui/legacy-plugin-chart-force-directed": "^0.14.1",
"@superset-ui/legacy-plugin-chart-heatmap": "^0.14.1",
Expand All @@ -85,7 +85,7 @@
"@superset-ui/legacy-plugin-chart-sankey": "^0.14.1",
"@superset-ui/legacy-plugin-chart-sankey-loop": "^0.14.1",
"@superset-ui/legacy-plugin-chart-sunburst": "^0.14.1",
"@superset-ui/legacy-plugin-chart-table": "^0.14.1",
"@superset-ui/plugin-chart-table": "^0.14.2",
"@superset-ui/legacy-plugin-chart-treemap": "^0.14.1",
"@superset-ui/legacy-plugin-chart-world-map": "^0.14.1",
"@superset-ui/legacy-preset-chart-big-number": "^0.14.1",
Expand All @@ -96,7 +96,7 @@
"@superset-ui/preset-chart-xy": "^0.14.1",
"@superset-ui/query": "^0.14.1",
"@superset-ui/style": "^0.14.0",
"@superset-ui/superset-ui": "^0.14.1",
"@superset-ui/superset-ui": "^0.14.2",
"@superset-ui/time-format": "^0.14.1",
"@superset-ui/translation": "^0.14.0",
"@superset-ui/validator": "^0.14.1",
Expand All @@ -110,6 +110,7 @@
"@types/redux-localstorage": "^1.0.8",
"@types/rison": "0.0.6",
"@vx/responsive": "^0.0.195",
"memoize-one": "^5.1.1",
"abortcontroller-polyfill": "^1.1.9",
"aphrodite": "^2.3.1",
"array-move": "^2.2.1",
Expand Down Expand Up @@ -166,7 +167,7 @@
"react-split": "^2.0.4",
"react-sticky": "^6.0.2",
"react-syntax-highlighter": "^7.0.4",
"react-table": "^7.0.4",
"react-table": "^7.2.1",
"react-transition-group": "^2.5.3",
"react-ultimate-pagination": "^1.2.0",
"react-virtualized": "9.19.1",
Expand All @@ -178,7 +179,7 @@
"redux-localstorage": "^0.4.1",
"redux-thunk": "^2.1.0",
"redux-undo": "^1.0.0-beta9-9-7",
"regenerator-runtime": "^0.13.3",
"regenerator-runtime": "^0.13.5",
"rison": "^0.1.1",
"shortid": "^2.2.6",
"urijs": "^1.18.10",
Expand All @@ -202,19 +203,19 @@
"@svgr/webpack": "^5.4.0",
"@types/classnames": "^2.2.9",
"@types/dom-to-image": "^2.6.0",
"@types/jest": "^25.1.4",
"@types/jest": "^26.0.3",
"@types/jquery": "^3.3.32",
"@types/react": "^16.9.38",
"@types/react-dom": "^16.9.8",
"@types/react-json-tree": "^0.6.11",
"@types/react-redux": "^7.1.7",
"@types/react-table": "^7.0.2",
"@types/react-table": "^7.0.19",
"@types/react-ultimate-pagination": "^1.2.0",
"@types/yargs": "12 - 15",
"@typescript-eslint/eslint-plugin": "^2.20.0",
"@typescript-eslint/parser": "^2.20.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^25.1.0",
"babel-jest": "^26.1.0",
"babel-loader": "^8.0.6",
"babel-plugin-dynamic-import-node": "^2.3.0",
"babel-plugin-emotion": "^10.0.29",
Expand All @@ -233,7 +234,7 @@
"eslint-import-resolver-webpack": "^0.10.1",
"eslint-plugin-cypress": "^2.0.1",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jest": "^21.24.1",
"eslint-plugin-jest": "^23.17.1",
"eslint-plugin-jsx-a11y": "^5.1.1",
"eslint-plugin-no-only-tests": "^2.0.1",
"eslint-plugin-prettier": "^3.1.3",
Expand All @@ -244,8 +245,8 @@
"fork-ts-checker-webpack-plugin": "^0.4.9",
"ignore-styles": "^5.0.1",
"imports-loader": "^0.7.1",
"jest": "^25.1.0",
"jsdom": "9.12.0",
"jest": "^26.1.0",
"jsdom": "^16.2.2",
"less": "^3.9.0",
"less-loader": "^5.0.0",
"mini-css-extract-plugin": "^0.4.0",
Expand All @@ -261,7 +262,7 @@
"terser-webpack-plugin": "^1.1.0",
"thread-loader": "^1.2.0",
"transform-loader": "^0.2.3",
"ts-jest": "^25.4.0",
"ts-jest": "^26.1.1",
"ts-loader": "^6.2.1",
"typescript": "^3.8.3",
"url-loader": "^1.0.1",
Expand Down
27 changes: 0 additions & 27 deletions superset-frontend/spec/helpers/shim.js
Expand Up @@ -20,7 +20,6 @@
import 'core-js/stable';
import 'regenerator-runtime/runtime';
import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only';
import jsdom from 'jsdom';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { configure as configureTranslation } from '@superset-ui/translation';
Expand All @@ -31,39 +30,13 @@ configure({ adapter: new Adapter() });

const exposedProperties = ['window', 'navigator', 'document'];

global.jsdom = jsdom.jsdom;
global.document = global.jsdom('<!doctype html><html><body></body></html>');
global.window = document.defaultView;
global.HTMLElement = window.HTMLElement;

Object.keys(document.defaultView).forEach(property => {
if (typeof global[property] === 'undefined') {
exposedProperties.push(property);
global[property] = document.defaultView[property];
}
});

global.navigator = {
userAgent: 'node.js',
platform: 'linux',
appName: 'Netscape',
};

// Fix `Option is not defined`
// https://stackoverflow.com/questions/39501589/jsdom-option-is-not-defined-when-running-my-mocha-test
global.Option = window.Option;

// Configuration copied from https://github.com/sinonjs/sinon/issues/657
// allowing for sinon.fakeServer to work

global.window = global.document.defaultView;
global.XMLHttpRequest = global.window.XMLHttpRequest;

global.sinon = require('sinon');

global.sinon.useFakeXMLHttpRequest();

global.window.XMLHttpRequest = global.XMLHttpRequest;
global.window.location = { href: 'about:blank' };
global.window.performance = { now: () => new Date().getTime() };
global.$ = require('jquery')(global.window);
Expand Down
86 changes: 47 additions & 39 deletions superset-frontend/spec/javascripts/components/AsyncSelect_spec.jsx
Expand Up @@ -62,53 +62,61 @@ describe('AsyncSelect', () => {
});

describe('auto select', () => {
it('should not call onChange if autoSelect=false', done => {
expect.assertions(2);
it('should not call onChange if autoSelect=false', () => {
return new Promise(done => {
expect.assertions(2);

const onChangeSpy = jest.fn();
shallow(<AsyncSelect {...mockedProps} onChange={onChangeSpy} />);
const onChangeSpy = jest.fn();
shallow(<AsyncSelect {...mockedProps} onChange={onChangeSpy} />);

setTimeout(() => {
expect(fetchMock.calls(dataGlob)).toHaveLength(1);
expect(onChangeSpy.mock.calls).toHaveLength(0);
done();
setTimeout(() => {
expect(fetchMock.calls(dataGlob)).toHaveLength(1);
expect(onChangeSpy.mock.calls).toHaveLength(0);
done();
});
});
});

it('should auto select the first option if autoSelect=true', done => {
expect.assertions(3);

const onChangeSpy = jest.fn();
const wrapper = shallow(
<AsyncSelect {...mockedProps} onChange={onChangeSpy} autoSelect />,
);

setTimeout(() => {
expect(fetchMock.calls(dataGlob)).toHaveLength(1);
expect(onChangeSpy.mock.calls).toHaveLength(1);
expect(onChangeSpy).toBeCalledWith(wrapper.instance().state.options[0]);
done();
it('should auto select the first option if autoSelect=true', () => {
return new Promise(done => {
expect.assertions(3);

const onChangeSpy = jest.fn();
const wrapper = shallow(
<AsyncSelect {...mockedProps} onChange={onChangeSpy} autoSelect />,
);

setTimeout(() => {
expect(fetchMock.calls(dataGlob)).toHaveLength(1);
expect(onChangeSpy.mock.calls).toHaveLength(1);
expect(onChangeSpy).toBeCalledWith(
wrapper.instance().state.options[0],
);
done();
});
});
});

it('should not auto select when value prop is set and autoSelect=true', done => {
expect.assertions(3);

const onChangeSpy = jest.fn();
const wrapper = shallow(
<AsyncSelect
{...mockedProps}
value={2}
onChange={onChangeSpy}
autoSelect
/>,
);

setTimeout(() => {
expect(fetchMock.calls(dataGlob)).toHaveLength(1);
expect(onChangeSpy.mock.calls).toHaveLength(0);
expect(wrapper.find(Select)).toHaveLength(1);
done();
it('should not auto select when value prop is set and autoSelect=true', () => {
return new Promise(done => {
expect.assertions(3);

const onChangeSpy = jest.fn();
const wrapper = shallow(
<AsyncSelect
{...mockedProps}
value={2}
onChange={onChangeSpy}
autoSelect
/>,
);

setTimeout(() => {
expect(fetchMock.calls(dataGlob)).toHaveLength(1);
expect(onChangeSpy.mock.calls).toHaveLength(0);
expect(wrapper.find(Select)).toHaveLength(1);
done();
});
});
});

Expand Down
Expand Up @@ -30,7 +30,7 @@ import Pagination from 'src/components/Pagination';
import { areArraysShallowEqual } from 'src/reduxUtils';
import { supersetTheme, ThemeProvider } from '@superset-ui/style';

export function makeMockLocation(query) {
function makeMockLocation(query) {
const queryStr = encodeURIComponent(query);
return {
protocol: 'http:',
Expand Down Expand Up @@ -292,16 +292,14 @@ Array [
...mockedProps,
filters: [...mockedProps.filters, { id: 'some_column' }],
};
try {
expect(() => {
shallow(<ListView {...props} />, {
wrappingComponent: ThemeProvider,
wrappingComponentProps: { theme: supersetTheme },
});
} catch (e) {
expect(e).toMatchInlineSnapshot(
`[ListViewError: Invalid filter config, some_column is not present in columns]`,
);
}
}).toThrowErrorMatchingInlineSnapshot(
'"Invalid filter config, some_column is not present in columns"',
);
});
});

Expand Down
Expand Up @@ -176,7 +176,7 @@ describe('TableSelector', () => {
});

// Test needs to be fixed: Github issue #7768
xit('should dispatch a danger toast on error', () => {
it.skip('should dispatch a danger toast on error', () => {
fetchMock.get(
FETCH_TABLES_GLOB,
{ throws: 'error' },
Expand Down Expand Up @@ -218,7 +218,7 @@ describe('TableSelector', () => {
});

// Test needs to be fixed: Github issue #7768
xit('should dispatch a danger toast on error', () => {
it.skip('should dispatch a danger toast on error', () => {
const handleErrors = sinon.stub();
expect(handleErrors.callCount).toBe(0);
wrapper.setProps({ handleErrors });
Expand Down
Expand Up @@ -70,25 +70,29 @@ describe('ChangeDatasourceModal', () => {
expect(wrapper.find(Modal)).toHaveLength(1);
});

it('fetches datasources', done => {
inst.onEnterModal();
setTimeout(() => {
expect(fetchMock.calls(DATASOURCES_ENDPOINT)).toHaveLength(1);
fetchMock.reset();
done();
}, 0);
it('fetches datasources', () => {
return new Promise(done => {
inst.onEnterModal();
setTimeout(() => {
expect(fetchMock.calls(DATASOURCES_ENDPOINT)).toHaveLength(1);
fetchMock.reset();
done();
}, 0);
});
});

it('changes the datasource', done => {
fetchMock.get(DATASOURCE_ENDPOINT, DATASOURCE_PAYLOAD);
inst.selectDatasource(datasourceData);
setTimeout(() => {
expect(fetchMock.calls(DATASOURCE_ENDPOINT)).toHaveLength(1);
expect(props.onDatasourceSave.getCall(0).args[0]).toEqual(
DATASOURCE_PAYLOAD,
);
fetchMock.reset();
done();
}, 0);
it('changes the datasource', () => {
return new Promise(done => {
fetchMock.get(DATASOURCE_ENDPOINT, DATASOURCE_PAYLOAD);
inst.selectDatasource(datasourceData);
setTimeout(() => {
expect(fetchMock.calls(DATASOURCE_ENDPOINT)).toHaveLength(1);
expect(props.onDatasourceSave.getCall(0).args[0]).toEqual(
DATASOURCE_PAYLOAD,
);
fetchMock.reset();
done();
}, 0);
});
});
});
Expand Up @@ -70,17 +70,19 @@ describe('DatasourceEditor', () => {
expect(wrapper.find(Tabs)).toHaveLength(1);
});

it('makes an async request', done => {
wrapper.setState({ activeTabKey: 2 });
const syncButton = wrapper.find('.sync-from-source');
expect(syncButton).toHaveLength(1);
syncButton.simulate('click');
it('makes an async request', () => {
return new Promise(done => {
wrapper.setState({ activeTabKey: 2 });
const syncButton = wrapper.find('.sync-from-source');
expect(syncButton).toHaveLength(1);
syncButton.simulate('click');

setTimeout(() => {
expect(fetchMock.calls(DATASOURCE_ENDPOINT)).toHaveLength(1);
fetchMock.reset();
done();
}, 0);
setTimeout(() => {
expect(fetchMock.calls(DATASOURCE_ENDPOINT)).toHaveLength(1);
fetchMock.reset();
done();
}, 0);
});
});

it('merges columns', () => {
Expand Down

0 comments on commit 1f19156

Please sign in to comment.