mirror of
https://github.com/apache/superset.git
synced 2026-04-18 23:55:00 +00:00
[superset-client] replace misc ajax calls (#6135)
* [superset-client][misc] replace ajax calls in DashboardTable, TableLoader, utils, common * [superset-client][misc] replace ajax calls in AsyncSelect, HeaderActions, Deck.gl * [superset-client][misc] fix tests * [superset-client] remove unneeded functional setState calls * [superset-client] make welcome a redux app for toasts * [superset-client] make Profile a redux app for toasts * [superset-client] TableLoader don't pass toast props to dom nodes * tweak deckgl Multi syntax
This commit is contained in:
@@ -1,14 +1,22 @@
|
||||
import React from 'react';
|
||||
import Select from 'react-select';
|
||||
import { shallow } from 'enzyme';
|
||||
import sinon from 'sinon';
|
||||
import fetchMock from 'fetch-mock';
|
||||
|
||||
import AsyncSelect from '../../../src/components/AsyncSelect';
|
||||
|
||||
describe('AsyncSelect', () => {
|
||||
afterAll(fetchMock.reset);
|
||||
afterEach(fetchMock.resetHistory);
|
||||
|
||||
const dataEndpoint = '/chart/api/read';
|
||||
const dataGlob = 'glob:*/chart/api/read';
|
||||
fetchMock.get(dataGlob, []);
|
||||
fetchMock.resetHistory();
|
||||
|
||||
const mockedProps = {
|
||||
dataEndpoint: '/chart/api/read',
|
||||
onChange: sinon.spy(),
|
||||
dataEndpoint,
|
||||
onChange: () => {},
|
||||
placeholder: 'Select...',
|
||||
mutator: () => [
|
||||
{ value: 1, label: 'main' },
|
||||
@@ -16,6 +24,7 @@ describe('AsyncSelect', () => {
|
||||
],
|
||||
valueRenderer: opt => opt.label,
|
||||
};
|
||||
|
||||
it('is valid element', () => {
|
||||
expect(
|
||||
React.isValidElement(<AsyncSelect {...mockedProps} />),
|
||||
@@ -30,52 +39,81 @@ describe('AsyncSelect', () => {
|
||||
});
|
||||
|
||||
it('calls onChange on select change', () => {
|
||||
const onChangeSpy = jest.fn();
|
||||
const wrapper = shallow(
|
||||
<AsyncSelect {...mockedProps} />,
|
||||
<AsyncSelect {...mockedProps} onChange={onChangeSpy} />,
|
||||
);
|
||||
|
||||
wrapper.find(Select).simulate('change', { value: 1 });
|
||||
expect(mockedProps.onChange).toHaveProperty('callCount', 1);
|
||||
expect(onChangeSpy.mock.calls).toHaveLength(1);
|
||||
});
|
||||
|
||||
describe('auto select', () => {
|
||||
let server;
|
||||
beforeEach(() => {
|
||||
server = sinon.fakeServer.create();
|
||||
server.respondWith([
|
||||
200, { 'Content-Type': 'application/json' }, JSON.stringify({}),
|
||||
]);
|
||||
});
|
||||
afterEach(() => {
|
||||
server.restore();
|
||||
});
|
||||
it('should be off by default', () => {
|
||||
const wrapper = shallow(
|
||||
<AsyncSelect {...mockedProps} />,
|
||||
);
|
||||
wrapper.instance().fetchOptions();
|
||||
const spy = sinon.spy(wrapper.instance(), 'onChange');
|
||||
expect(spy.callCount).toBe(0);
|
||||
});
|
||||
it('should auto select first option', () => {
|
||||
const wrapper = shallow(
|
||||
<AsyncSelect {...mockedProps} autoSelect />,
|
||||
);
|
||||
const spy = sinon.spy(wrapper.instance(), 'onChange');
|
||||
server.respond();
|
||||
it('should not call onChange if autoSelect=false', (done) => {
|
||||
expect.assertions(2);
|
||||
|
||||
expect(spy.callCount).toBe(1);
|
||||
expect(spy.calledWith(wrapper.instance().state.options[0])).toBe(true);
|
||||
});
|
||||
it('should not auto select when value prop is set', () => {
|
||||
const wrapper = shallow(
|
||||
<AsyncSelect {...mockedProps} value={2} autoSelect />,
|
||||
const onChangeSpy = jest.fn();
|
||||
shallow(
|
||||
<AsyncSelect {...mockedProps} onChange={onChangeSpy} />,
|
||||
);
|
||||
const spy = sinon.spy(wrapper.instance(), 'onChange');
|
||||
wrapper.instance().fetchOptions();
|
||||
server.respond();
|
||||
|
||||
expect(spy.callCount).toBe(0);
|
||||
expect(wrapper.find(Select)).toHaveLength(1);
|
||||
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 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 call onAsyncError if there is an error fetching options', (done) => {
|
||||
expect.assertions(3);
|
||||
|
||||
const errorEndpoint = 'async/error/';
|
||||
const errorGlob = 'glob:*async/error/';
|
||||
fetchMock.get(errorGlob, { throws: 'error' });
|
||||
|
||||
const onAsyncError = jest.fn();
|
||||
shallow(
|
||||
<AsyncSelect {...mockedProps} dataEndpoint={errorEndpoint} onAsyncError={onAsyncError} />,
|
||||
);
|
||||
|
||||
setTimeout(() => {
|
||||
expect(fetchMock.calls(errorGlob)).toHaveLength(1);
|
||||
expect(onAsyncError.mock.calls).toHaveLength(1);
|
||||
expect(onAsyncError).toBeCalledWith('error');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Col, Row, Tab } from 'react-bootstrap';
|
||||
import { mount } from 'enzyme';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { user } from './fixtures';
|
||||
import App from '../../../src/profile/components/App';
|
||||
@@ -14,13 +14,15 @@ describe('App', () => {
|
||||
React.isValidElement(<App {...mockedProps} />),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('renders 2 Col', () => {
|
||||
const wrapper = mount(<App {...mockedProps} />);
|
||||
const wrapper = shallow(<App {...mockedProps} />);
|
||||
expect(wrapper.find(Row)).toHaveLength(1);
|
||||
expect(wrapper.find(Col)).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('renders 4 Tabs', () => {
|
||||
const wrapper = mount(<App {...mockedProps} />);
|
||||
const wrapper = shallow(<App {...mockedProps} />);
|
||||
expect(wrapper.find(Tab)).toHaveLength(4);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { shallow } from 'enzyme';
|
||||
import thunk from 'redux-thunk';
|
||||
import configureStore from 'redux-mock-store';
|
||||
|
||||
import { user } from './fixtures';
|
||||
import CreatedContent from '../../../src/profile/components/CreatedContent';
|
||||
import TableLoader from '../../../src/components/TableLoader';
|
||||
|
||||
// store needed for withToasts(TableLoader)
|
||||
const mockStore = configureStore([thunk]);
|
||||
const store = mockStore({});
|
||||
|
||||
describe('CreatedContent', () => {
|
||||
const mockedProps = {
|
||||
user,
|
||||
};
|
||||
it('is valid', () => {
|
||||
expect(
|
||||
React.isValidElement(<CreatedContent {...mockedProps} />),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('renders 2 TableLoader', () => {
|
||||
const wrapper = mount(<CreatedContent {...mockedProps} />);
|
||||
const wrapper = shallow(<CreatedContent {...mockedProps} />, { context: { store } });
|
||||
expect(wrapper.find(TableLoader)).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('renders 2 titles', () => {
|
||||
const wrapper = mount(<CreatedContent {...mockedProps} />);
|
||||
const wrapper = shallow(<CreatedContent {...mockedProps} />, { context: { store } });
|
||||
expect(wrapper.find('h3')).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { shallow } from 'enzyme';
|
||||
import thunk from 'redux-thunk';
|
||||
import configureStore from 'redux-mock-store';
|
||||
|
||||
import { user } from './fixtures';
|
||||
import Favorites from '../../../src/profile/components/Favorites';
|
||||
import TableLoader from '../../../src/components/TableLoader';
|
||||
|
||||
// store needed for withToasts(TableLoader)
|
||||
const mockStore = configureStore([thunk]);
|
||||
const store = mockStore({});
|
||||
|
||||
describe('Favorites', () => {
|
||||
const mockedProps = {
|
||||
user,
|
||||
};
|
||||
it('is valid', () => {
|
||||
expect(
|
||||
React.isValidElement(<Favorites {...mockedProps} />),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('renders 2 TableLoader', () => {
|
||||
const wrapper = mount(<Favorites {...mockedProps} />);
|
||||
const wrapper = shallow(<Favorites {...mockedProps} />, { context: { store } });
|
||||
expect(wrapper.find(TableLoader)).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('renders 2 titles', () => {
|
||||
const wrapper = mount(<Favorites {...mockedProps} />);
|
||||
const wrapper = shallow(<Favorites {...mockedProps} />, { context: { store } });
|
||||
expect(wrapper.find('h3')).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { user } from './fixtures';
|
||||
import RecentActivity from '../../../src/profile/components/RecentActivity';
|
||||
import TableLoader from '../../../src/components/TableLoader';
|
||||
|
||||
|
||||
describe('RecentActivity', () => {
|
||||
const mockedProps = {
|
||||
user,
|
||||
@@ -15,8 +14,9 @@ describe('RecentActivity', () => {
|
||||
React.isValidElement(<RecentActivity {...mockedProps} />),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('renders a TableLoader', () => {
|
||||
const wrapper = mount(<RecentActivity {...mockedProps} />);
|
||||
const wrapper = shallow(<RecentActivity {...mockedProps} />);
|
||||
expect(wrapper.find(TableLoader)).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,30 +1,47 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import sinon from 'sinon';
|
||||
import thunk from 'redux-thunk';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import { Table } from 'reactable';
|
||||
|
||||
import DashboardTable from '../../../src/welcome/DashboardTable';
|
||||
import Loading from '../../../src/components/Loading';
|
||||
|
||||
const $ = window.$ = require('jquery');
|
||||
// store needed for withToasts(TableLoader)
|
||||
const mockStore = configureStore([thunk]);
|
||||
const store = mockStore({});
|
||||
|
||||
const dashboardsEndpoint = 'glob:*/dashboardasync/api/read*';
|
||||
const mockDashboards = [
|
||||
{ id: 1, url: 'url', dashboard_title: 'title' },
|
||||
];
|
||||
|
||||
fetchMock.get(dashboardsEndpoint, { result: mockDashboards });
|
||||
|
||||
function setup() {
|
||||
// use mount because data fetching is triggered on mount
|
||||
return mount(<DashboardTable />, { context: { store } });
|
||||
}
|
||||
|
||||
describe('DashboardTable', () => {
|
||||
const mockedProps = {};
|
||||
let stub;
|
||||
beforeEach(() => {
|
||||
stub = sinon.stub($, 'getJSON');
|
||||
});
|
||||
afterEach(() => {
|
||||
stub.restore();
|
||||
afterEach(fetchMock.resetHistory);
|
||||
|
||||
it('renders a Loading initially', () => {
|
||||
const wrapper = setup();
|
||||
expect(wrapper.find(Loading)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('is valid', () => {
|
||||
expect(
|
||||
React.isValidElement(<DashboardTable {...mockedProps} />),
|
||||
).toBe(true);
|
||||
});
|
||||
it('renders', () => {
|
||||
const wrapper = mount(<DashboardTable {...mockedProps} />);
|
||||
expect(stub.callCount).toBe(1);
|
||||
expect(wrapper.find('img')).toHaveLength(1);
|
||||
it('fetches dashboards and renders a Table', (done) => {
|
||||
const wrapper = setup();
|
||||
|
||||
setTimeout(() => {
|
||||
expect(fetchMock.calls(dashboardsEndpoint)).toHaveLength(1);
|
||||
// there's a delay between response and updating state, so manually set it
|
||||
// rather than adding a timeout which could introduce flakiness
|
||||
wrapper.setState({ dashaboards: mockDashboards });
|
||||
expect(wrapper.find(Table)).toHaveLength(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user