This is an automated email from the ASF dual-hosted git repository. ccwilliams pushed a commit to branch chris--ajax-charts in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
commit c8b83ec7249fa3d988a94392d5660fe0fd4e5790 Author: Chris Williams <[email protected]> AuthorDate: Wed Sep 12 13:31:17 2018 -0700 [superset client][charts][tests] fix and improve chartActions_spec --- .../spec/javascripts/explore/chartActions_spec.js | 119 +++++++++++++++++---- superset/assets/src/chart/chartAction.js | 10 +- 2 files changed, 103 insertions(+), 26 deletions(-) diff --git a/superset/assets/spec/javascripts/explore/chartActions_spec.js b/superset/assets/spec/javascripts/explore/chartActions_spec.js index 6d8b009..f3bd219 100644 --- a/superset/assets/spec/javascripts/explore/chartActions_spec.js +++ b/superset/assets/spec/javascripts/explore/chartActions_spec.js @@ -1,38 +1,117 @@ import { expect } from 'chai'; +import fetchMock from 'fetch-mock'; import sinon from 'sinon'; -import $ from 'jquery'; + +import { Logger } from '../../../src/logger'; +import setupSupersetClient from '../../helpers/setupSupersetClient'; import * as exploreUtils from '../../../src/explore/exploreUtils'; import * as actions from '../../../src/chart/chartAction'; describe('chart actions', () => { + const MOCK_URL = 'mockURL'; let dispatch; let urlStub; - let ajaxStub; - let request; + let loggerStub; + + const setupDefaultFetchMock = () => { + fetchMock.post(MOCK_URL, { json: {} }, { overwriteRoutes: true }); + }; + + before(() => { + setupSupersetClient(); + setupDefaultFetchMock(); + }); + + after(fetchMock.restore); beforeEach(() => { dispatch = sinon.spy(); - urlStub = sinon.stub(exploreUtils, 'getExploreUrlAndPayload') - .callsFake(() => ({ url: 'mockURL', payload: {} })); - ajaxStub = sinon.stub($, 'ajax'); + urlStub = sinon + .stub(exploreUtils, 'getExploreUrlAndPayload') + .callsFake(() => ({ url: MOCK_URL, payload: {} })); + loggerStub = sinon.stub(Logger, 'append'); }); afterEach(() => { urlStub.restore(); - ajaxStub.restore(); - }); - - it('should handle query timeout', () => { - ajaxStub.rejects({ statusText: 'timeout' }); - request = actions.runQuery({}); - const promise = request(dispatch, sinon.stub().returns({ - explore: { - controls: [], - }, - })); - promise.then(() => { - expect(dispatch.callCount).to.equal(3); - expect(dispatch.args[0][0].type).to.equal(actions.CHART_UPDATE_TIMEOUT); + loggerStub.restore(); + fetchMock.resetHistory(); + }); + + it('should dispatch CHART_UPDATE_STARTED action before the query', (done) => { + const actionThunk = actions.runQuery({}); + actionThunk(dispatch).then(() => { + // chart update, trigger query, update form data, success + expect(dispatch.callCount).to.equal(4); + expect(fetchMock.calls(MOCK_URL)).to.have.lengthOf(1); + expect(dispatch.args[0][0].type).to.equal(actions.CHART_UPDATE_STARTED); + done(); + }); + }); + + it('should dispatch TRIGGER_QUERY action with the query', (done) => { + const actionThunk = actions.runQuery({}); + actionThunk(dispatch).then(() => { + // chart update, trigger query, update form data, success + expect(dispatch.callCount).to.equal(4); + expect(fetchMock.calls(MOCK_URL)).to.have.lengthOf(1); + expect(dispatch.args[1][0].type).to.equal(actions.TRIGGER_QUERY); + done(); + }); + }); + + it('should dispatch UPDATE_QUERY_FORM_DATA action with the query', (done) => { + const actionThunk = actions.runQuery({}); + actionThunk(dispatch).then(() => { + // chart update, trigger query, update form data, success + expect(dispatch.callCount).to.equal(4); + expect(fetchMock.calls(MOCK_URL)).to.have.lengthOf(1); + expect(dispatch.args[2][0].type).to.equal(actions.UPDATE_QUERY_FORM_DATA); + done(); + }); + }); + + it('should dispatch CHART_UPDATE_SUCCEEDED action upon success', (done) => { + const actionThunk = actions.runQuery({}); + actionThunk(dispatch).then(() => { + // chart update, trigger query, update form data, success + expect(dispatch.callCount).to.equal(4); + expect(fetchMock.calls(MOCK_URL)).to.have.lengthOf(1); + expect(dispatch.args[3][0].type).to.equal(actions.CHART_UPDATE_SUCCEEDED); + done(); + }); + }); + + it('should CHART_UPDATE_TIMEOUT action upon query timeout', (done) => { + const unresolvingPromise = new Promise(() => {}); + fetchMock.post(MOCK_URL, () => unresolvingPromise, { overwriteRoutes: true }); + + const timeoutInSec = 1 / 1000; + const actionThunk = actions.runQuery({}, false, timeoutInSec); + + actionThunk(dispatch).then(() => { + // chart update, trigger query, update form data, fail + expect(dispatch.callCount).to.equal(4); + expect(dispatch.args[3][0].type).to.equal(actions.CHART_UPDATE_TIMEOUT); + setupDefaultFetchMock(); + done(); + }); + }); + + it('should dispatch CHART_UPDATE_FAILED action upon non-timeout non-abort failure', (done) => { + fetchMock.post(MOCK_URL, { throws: { error: 'misc error' } }, { overwriteRoutes: true }); + + const timeoutInSec = 1 / 1000; + const actionThunk = actions.runQuery({}, false, timeoutInSec); + + actionThunk(dispatch).then(() => { + // chart update, trigger query, update form data, fail + expect(dispatch.callCount).to.equal(4); + const updateFailedAction = dispatch.args[3][0]; + expect(updateFailedAction.type).to.equal(actions.CHART_UPDATE_FAILED); + expect(updateFailedAction.queryResponse.error).to.equal('misc error'); + setupDefaultFetchMock(); + done(); }); }); }); diff --git a/superset/assets/src/chart/chartAction.js b/superset/assets/src/chart/chartAction.js index cb835c5..12df6a2 100644 --- a/superset/assets/src/chart/chartAction.js +++ b/superset/assets/src/chart/chartAction.js @@ -176,22 +176,20 @@ export function runQuery(formData, force = false, timeout = 60, key) { } else if (err.statusText === 'AbortError') { dispatch(chartUpdateStopped(key)); } else { - let errObject; + let errObject = err; if (err.responseJSON) { errObject = err.responseJSON; } else if (err.stack) { errObject = { - error: t('Unexpected error: ') + err.description, + error: + t('Unexpected error: ') + + (err.description || t('(no description, click to see stack trace)')), stacktrace: err.stack, }; } else if (err.responseText && err.responseText.indexOf('CSRF') >= 0) { errObject = { error: COMMON_ERR_MESSAGES.SESSION_TIMED_OUT, }; - } else { - errObject = { - error: t('Unexpected error.'), - }; } dispatch(chartUpdateFailed(errObject, key)); }
