feat: update dataset editor modal (#10347)

This commit is contained in:
Lily Kuang
2020-07-28 15:53:20 -07:00
committed by GitHub
parent e89e60df76
commit 39fad8575c
12 changed files with 541 additions and 510 deletions

View File

@@ -17,17 +17,23 @@
* under the License.
*/
import React from 'react';
import { mount } from 'enzyme';
import { Modal } from 'react-bootstrap';
import configureStore from 'redux-mock-store';
import { shallow } from 'enzyme';
import fetchMock from 'fetch-mock';
import thunk from 'redux-thunk';
import sinon from 'sinon';
import { supersetTheme, ThemeProvider } from '@superset-ui/style';
import { act } from 'react-dom/test-utils';
import ChangeDatasourceModal from 'src/datasource/ChangeDatasourceModal';
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
import mockDatasource from '../../fixtures/mockDatasource';
const props = {
const mockStore = configureStore([thunk]);
const store = mockStore({});
const mockedProps = {
addDangerToast: () => {},
onDatasourceSave: sinon.spy(),
onChange: () => {},
@@ -37,62 +43,53 @@ const props = {
const datasource = mockDatasource['7__table'];
const datasourceData = {
id: datasource.name,
id: datasource.id,
type: datasource.type,
uid: datasource.id,
};
const DATASOURCES_ENDPOINT = 'glob:*/superset/datasources/';
const DATASOURCE_ENDPOINT = `glob:*/datasource/get/${datasourceData.type}/${datasourceData.id}`;
const DATASOURCES_PAYLOAD = { json: 'data' };
const DATASOURCE_PAYLOAD = { new: 'data' };
fetchMock.get(DATASOURCES_ENDPOINT, [mockDatasource['7__table']]);
fetchMock.get(DATASOURCE_ENDPOINT, DATASOURCE_PAYLOAD);
async function mountAndWait(props = mockedProps) {
const mounted = mount(<ChangeDatasourceModal {...props} />, {
context: { store },
wrappingComponent: ThemeProvider,
wrappingComponentProps: { theme: supersetTheme },
});
await waitForComponentToPaint(mounted);
return mounted;
}
describe('ChangeDatasourceModal', () => {
const mockStore = configureStore([thunk]);
const store = mockStore({});
fetchMock.get(DATASOURCES_ENDPOINT, DATASOURCES_PAYLOAD);
let wrapper;
let el;
let inst;
beforeEach(() => {
el = <ChangeDatasourceModal {...props} />;
wrapper = shallow(el, { context: { store } }).dive();
inst = wrapper.instance();
beforeEach(async () => {
wrapper = await mountAndWait();
});
it('is valid', () => {
expect(React.isValidElement(el)).toBe(true);
it('renders', () => {
expect(wrapper.find(ChangeDatasourceModal)).toHaveLength(1);
});
it('renders a Modal', () => {
expect(wrapper.find(Modal)).toHaveLength(1);
});
it('fetches datasources', () => {
return new Promise(done => {
inst.onEnterModal();
setTimeout(() => {
expect(fetchMock.calls(DATASOURCES_ENDPOINT)).toHaveLength(1);
fetchMock.reset();
done();
}, 0);
});
it('fetches datasources', async () => {
expect(fetchMock.calls(/superset\/datasources/)).toHaveLength(3);
});
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);
it('changes the datasource', async () => {
act(() => {
wrapper.find('.datasource-link').at(0).props().onClick(datasourceData);
});
await waitForComponentToPaint(wrapper);
expect(fetchMock.calls(/datasource\/get\/table\/7/)).toHaveLength(1);
});
});

View File

@@ -17,66 +17,80 @@
* under the License.
*/
import React from 'react';
import { act } from 'react-dom/test-utils';
import { Modal } from 'react-bootstrap';
import configureStore from 'redux-mock-store';
import { shallow } from 'enzyme';
import { mount } from 'enzyme';
import fetchMock from 'fetch-mock';
import thunk from 'redux-thunk';
import sinon from 'sinon';
import { supersetTheme, ThemeProvider } from '@superset-ui/style';
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
import DatasourceModal from 'src/datasource/DatasourceModal';
import DatasourceEditor from 'src/datasource/DatasourceEditor';
import mockDatasource from '../../fixtures/mockDatasource';
const props = {
datasource: mockDatasource['7__table'],
const mockStore = configureStore([thunk]);
const store = mockStore({});
const datasource = mockDatasource['7__table'];
const SAVE_ENDPOINT = 'glob:*/api/v1/dataset/7';
const SAVE_PAYLOAD = { new: 'data' };
const mockedProps = {
datasource,
addSuccessToast: () => {},
addDangerToast: () => {},
onChange: () => {},
show: true,
onHide: () => {},
show: true,
onDatasourceSave: sinon.spy(),
};
const SAVE_ENDPOINT = 'glob:*/datasource/save/';
const SAVE_PAYLOAD = { new: 'data' };
async function mountAndWait(props = mockedProps) {
const mounted = mount(<DatasourceModal {...props} />, {
context: { store },
wrappingComponent: ThemeProvider,
wrappingComponentProps: { theme: supersetTheme },
});
await waitForComponentToPaint(mounted);
return mounted;
}
describe('DatasourceModal', () => {
const mockStore = configureStore([thunk]);
const store = mockStore({});
fetchMock.post(SAVE_ENDPOINT, SAVE_PAYLOAD);
const callsP = fetchMock.put(SAVE_ENDPOINT, SAVE_PAYLOAD);
let wrapper;
let el;
let inst;
beforeEach(() => {
el = <DatasourceModal {...props} />;
wrapper = shallow(el, { context: { store } }).dive();
inst = wrapper.instance();
beforeEach(async () => {
wrapper = await mountAndWait();
});
it('is valid', () => {
expect(React.isValidElement(el)).toBe(true);
it('renders', () => {
expect(wrapper.find(DatasourceModal)).toHaveLength(1);
});
it('renders a Modal', () => {
expect(wrapper.find(Modal)).toHaveLength(1);
expect(wrapper.find(Modal)).toHaveLength(2);
});
it('renders a DatasourceEditor', () => {
expect(wrapper.find(DatasourceEditor)).toHaveLength(1);
});
it('saves on confirm', () => {
return new Promise(done => {
inst.onConfirmSave();
setTimeout(() => {
expect(fetchMock.calls(SAVE_ENDPOINT)).toHaveLength(1);
expect(props.onDatasourceSave.getCall(0).args[0]).toEqual(SAVE_PAYLOAD);
fetchMock.reset();
done();
}, 0);
it('saves on confirm', async () => {
act(() => {
wrapper.find('[className="m-r-5"]').props().onClick();
});
await waitForComponentToPaint(wrapper);
act(() => {
const okButton = wrapper.find('[className="btn btn-sm btn-primary"]');
okButton.simulate('click');
});
await waitForComponentToPaint(wrapper);
expect(callsP._calls).toHaveLength(2); /* eslint no-underscore-dangle: 0 */
});
});