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

[SIP-4] replace explorer ajax calls with SupersetClient #5869

Merged
merged 10 commits into from
Oct 16, 2018
110 changes: 67 additions & 43 deletions superset/assets/spec/javascripts/explore/components/SaveModal_spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import thunk from 'redux-thunk';
import { shallow, mount } from 'enzyme';
import { Modal, Button, Radio } from 'react-bootstrap';
import sinon from 'sinon';
import fetchMock from 'fetch-mock';

import * as exploreUtils from '../../../../src/explore/exploreUtils';
import * as saveModalActions from '../../../../src/explore/actions/saveModalActions';
import SaveModal from '../../../../src/explore/components/SaveModal';

const $ = window.$ = require('jquery');
import setupSupersetClient from '../../../helpers/setupSupersetClient';

describe('SaveModal', () => {
const middlewares = [thunk];
Expand Down Expand Up @@ -44,9 +44,11 @@ describe('SaveModal', () => {
},
value: 'mock value',
};
const getWrapper = () => (shallow(<SaveModal {...defaultProps} />, {
context: { store },
}).dive());

const getWrapper = () =>
shallow(<SaveModal {...defaultProps} />, {
context: { store },
}).dive();

it('renders a Modal with 7 inputs and 2 buttons', () => {
const wrapper = getWrapper();
Expand Down Expand Up @@ -115,13 +117,17 @@ describe('SaveModal', () => {

describe('saveOrOverwrite', () => {
beforeEach(() => {
sinon.stub(exploreUtils, 'getExploreUrlAndPayload').callsFake(() => ({ url: 'mockURL', payload: defaultProps.form_data }));
sinon.stub(saveModalActions, 'saveSlice').callsFake(() => {
const d = $.Deferred();
d.resolve('done');
return d.promise();
});
sinon
.stub(exploreUtils, 'getExploreUrlAndPayload')
.callsFake(() => ({ url: 'mockURL', payload: defaultProps.form_data }));

sinon
.stub(saveModalActions, 'saveSlice')
.callsFake(() =>
Promise.resolve({ data: { dashboard: '/mock/', slice: { slice_url: '/mock/' } } }),
);
});

afterEach(() => {
exploreUtils.getExploreUrlAndPayload.restore();
saveModalActions.saveSlice.restore();
Expand All @@ -133,6 +139,7 @@ describe('SaveModal', () => {
const args = saveModalActions.saveSlice.getCall(0).args;
expect(args[0]).toEqual(defaultProps.form_data);
});

it('existing dashboard', () => {
const wrapper = getWrapper();
const saveToDashboardId = 100;
Expand All @@ -146,6 +153,7 @@ describe('SaveModal', () => {
const args = saveModalActions.saveSlice.getCall(0).args;
expect(args[1].save_to_dashboard_id).toBe(saveToDashboardId);
});

it('new dashboard', () => {
const wrapper = getWrapper();
const newDashboardName = 'new dashboard name';
Expand All @@ -161,52 +169,68 @@ describe('SaveModal', () => {
});
});

describe('should fetchDashboards', () => {
describe('fetchDashboards', () => {
let dispatch;
let request;
let ajaxStub;
let actionThunk;
const userID = 1;

const mockDashboardData = {
pks: ['id'],
result: [{ id: 'id', dashboard_title: 'dashboard title' }],
};

const saveEndpoint = `glob:*/dashboardasync/api/read?_flt_0_owners=${1}`;

beforeAll(() => {
setupSupersetClient();
fetchMock.get(saveEndpoint, mockDashboardData);
});

afterAll(fetchMock.restore);

beforeEach(() => {
dispatch = sinon.spy();
ajaxStub = sinon.stub($, 'ajax');
});

afterEach(() => {
ajaxStub.restore();
fetchMock.resetHistory();
});
const mockDashboardData = {
pks: ['value'],
result: [
{ dashboard_title: 'dashboard title' },
],
};

const makeRequest = () => {
request = saveModalActions.fetchDashboards(userID);
request(dispatch);
actionThunk = saveModalActions.fetchDashboards(userID);
return actionThunk(dispatch);
};

it('makes the ajax request', () => {
makeRequest();
expect(ajaxStub.callCount).toBe(1);
});
it('makes the fetch request', () => (
makeRequest().then(() => {
expect(fetchMock.calls(saveEndpoint)).toHaveLength(1);

it('calls correct url', () => {
const url = '/dashboardasync/api/read?_flt_0_owners=' + userID;
makeRequest();
expect(ajaxStub.getCall(0).args[0].url).toBe(url);
});
return Promise.resolve();
})
));

it('calls correct actions on success', () => (
makeRequest().then(() => {
expect(dispatch.callCount).toBe(1);
expect(dispatch.getCall(0).args[0].type).toBe(
saveModalActions.FETCH_DASHBOARDS_SUCCEEDED,
);

return Promise.resolve();
})
));

it('calls correct actions on error', () => {
ajaxStub.yieldsTo('error', { responseJSON: { error: 'error text' } });
makeRequest();
expect(dispatch.callCount).toBe(1);
expect(dispatch.getCall(0).args[0].type).toBe(saveModalActions.FETCH_DASHBOARDS_FAILED);
});
fetchMock.get(saveEndpoint, { throws: 'error' }, { overwriteRoutes: true });

it('calls correct actions on success', () => {
ajaxStub.yieldsTo('success', mockDashboardData);
makeRequest();
expect(dispatch.callCount).toBe(1);
expect(dispatch.getCall(0).args[0].type).toBe(saveModalActions.FETCH_DASHBOARDS_SUCCEEDED);
return makeRequest().then(() => {
expect(dispatch.callCount).toBe(1);
expect(dispatch.getCall(0).args[0].type).toBe(saveModalActions.FETCH_DASHBOARDS_FAILED);

fetchMock.get(saveEndpoint, mockDashboardData, { overwriteRoutes: true });

return Promise.resolve();
});
});
});

Expand Down
2 changes: 1 addition & 1 deletion superset/assets/src/common.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint global-require: 0, no-console: 0 */
import $ from 'jquery';
import { SupersetClient } from '@superset-ui/core';
import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only';
import { SupersetClient } from '@superset-ui/core';

import airbnb from './modules/colorSchemes/airbnb';
import categoricalSchemes from './modules/colorSchemes/categorical';
Expand Down
4 changes: 2 additions & 2 deletions superset/assets/src/components/ModalTrigger.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ export default class ModalTrigger extends React.Component {
}

close() {
this.setState({ showModal: false });
this.setState(() => ({ showModal: false }));
}

open(e) {
e.preventDefault();
this.props.beforeOpen();
this.setState({ showModal: true });
this.setState(() => ({ showModal: true }));
}
renderModal() {
return (
Expand Down
33 changes: 8 additions & 25 deletions superset/assets/src/explore/actions/exploreActions.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/* eslint camelcase: 0 */
const $ = window.$ = require('jquery');
import { SupersetClient } from '@superset-ui/core';
import { addDangerToast } from '../../messageToasts/actions';
import { t } from '../../locales';

const FAVESTAR_BASE_URL = '/superset/favstar/slice';

Expand Down Expand Up @@ -50,24 +52,6 @@ export function resetControls() {
return { type: RESET_FIELDS };
}

export function fetchDatasources() {
return function (dispatch) {
dispatch(fetchDatasourcesStarted());
const url = '/superset/datasources/';
$.ajax({
type: 'GET',
url,
success: (data) => {
dispatch(setDatasources(data));
dispatch(fetchDatasourcesSucceeded());
},
error(error) {
dispatch(fetchDatasourcesFailed(error.responseJSON.error));
},
});
};
}

export const TOGGLE_FAVE_STAR = 'TOGGLE_FAVE_STAR';
export function toggleFaveStar(isStarred) {
return { type: TOGGLE_FAVE_STAR, isStarred };
Expand All @@ -76,9 +60,8 @@ export function toggleFaveStar(isStarred) {
export const FETCH_FAVE_STAR = 'FETCH_FAVE_STAR';
export function fetchFaveStar(sliceId) {
return function (dispatch) {
const url = `${FAVESTAR_BASE_URL}/${sliceId}/count`;
$.get(url, (data) => {
if (data.count > 0) {
SupersetClient.get({ endpoint: `${FAVESTAR_BASE_URL}/${sliceId}/count` }).then(({ json }) => {
if (json.count > 0) {
dispatch(toggleFaveStar(true));
}
});
Expand All @@ -89,9 +72,9 @@ export const SAVE_FAVE_STAR = 'SAVE_FAVE_STAR';
export function saveFaveStar(sliceId, isStarred) {
return function (dispatch) {
const urlSuffix = isStarred ? 'unselect' : 'select';
const url = `${FAVESTAR_BASE_URL}/${sliceId}/${urlSuffix}/`;
$.get(url);
dispatch(toggleFaveStar(!isStarred));
SupersetClient.get({ endpoint: `${FAVESTAR_BASE_URL}/${sliceId}/${urlSuffix}/` })
.then(() => dispatch(toggleFaveStar(!isStarred)))
.catch(() => dispatch(addDangerToast(t('An error occurred while starring this chart'))));
};
}

Expand Down
49 changes: 18 additions & 31 deletions superset/assets/src/explore/actions/saveModalActions.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { SupersetClient } from '@superset-ui/core';
import { getExploreUrlAndPayload } from '../exploreUtils';

const $ = window.$ = require('jquery');

export const FETCH_DASHBOARDS_SUCCEEDED = 'FETCH_DASHBOARDS_SUCCEEDED';
export function fetchDashboardsSucceeded(choices) {
return { type: FETCH_DASHBOARDS_SUCCEEDED, choices };
Expand All @@ -13,22 +12,19 @@ export function fetchDashboardsFailed(userId) {
}

export function fetchDashboards(userId) {
return function (dispatch) {
const url = '/dashboardasync/api/read?_flt_0_owners=' + userId;
return $.ajax({
type: 'GET',
url,
success: (data) => {
const choices = [];
for (let i = 0; i < data.pks.length; i++) {
choices.push({ value: data.pks[i], label: data.result[i].dashboard_title });
}
dispatch(fetchDashboardsSucceeded(choices));
},
error: () => {
dispatch(fetchDashboardsFailed(userId));
},
});
return function fetchDashboardsThunk(dispatch) {
return SupersetClient.get({
endpoint: `/dashboardasync/api/read?_flt_0_owners=${userId}`,
})
.then(({ json }) => {
const choices = json.pks.map((id, index) => ({
value: id,
label: (json.result[index] || {}).dashboard_title,
}));

return dispatch(fetchDashboardsSucceeded(choices));
})
.catch(() => dispatch(fetchDashboardsFailed(userId)));
};
}

Expand All @@ -55,18 +51,9 @@ export function saveSlice(formData, requestParams) {
curUrl: null,
requestParams,
});
return $.ajax({
type: 'POST',
url,
data: {
form_data: JSON.stringify(payload),
},
success: ((data) => {
dispatch(saveSliceSuccess(data));
}),
error: (() => {
dispatch(saveSliceFailed());
}),
});

return SupersetClient.post({ url, postPayload: { form_data: payload } })
.then(({ json }) => dispatch(saveSliceSuccess(json)))
.catch(() => dispatch(saveSliceFailed()));
};
}
Loading