diff --git a/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx b/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx
index 52f3566f70c..77db226068a 100644
--- a/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx
+++ b/superset-frontend/spec/javascripts/sqllab/ResultSet_spec.jsx
@@ -45,10 +45,12 @@ const store = mockStore(initialState);
describe('ResultSet', () => {
const clearQuerySpy = sinon.spy();
const fetchQuerySpy = sinon.spy();
+ const reRunQuerySpy = sinon.spy();
const mockedProps = {
actions: {
clearQueryResults: clearQuerySpy,
fetchQueryResults: fetchQuerySpy,
+ reRunQuery: reRunQuerySpy,
},
cache: true,
query: queries[0],
@@ -83,6 +85,29 @@ describe('ResultSet', () => {
const wrapper = shallow();
expect(wrapper.find(FilterableTable)).toExist();
});
+ describe('componentDidMount', () => {
+ const propsWithError = {
+ ...mockedProps,
+ query: { ...queries[0], errorMessage: 'Your session timed out' },
+ };
+ let spy;
+ beforeEach(() => {
+ reRunQuerySpy.resetHistory();
+ spy = sinon.spy(ResultSet.prototype, 'componentDidMount');
+ });
+ afterEach(() => {
+ spy.restore();
+ });
+ it('should call reRunQuery if timed out', () => {
+ shallow();
+ expect(reRunQuerySpy.callCount).toBe(1);
+ });
+
+ it('should not call reRunQuery if no error', () => {
+ shallow();
+ expect(reRunQuerySpy.callCount).toBe(0);
+ });
+ });
describe('UNSAFE_componentWillReceiveProps', () => {
const wrapper = shallow();
let spy;
diff --git a/superset-frontend/spec/javascripts/sqllab/actions/sqlLab_spec.js b/superset-frontend/spec/javascripts/sqllab/actions/sqlLab_spec.js
index 4a83786bc9d..44e468cf57e 100644
--- a/superset-frontend/spec/javascripts/sqllab/actions/sqlLab_spec.js
+++ b/superset-frontend/spec/javascripts/sqllab/actions/sqlLab_spec.js
@@ -173,7 +173,7 @@ describe('async actions', () => {
fetchMock.get(
fetchQueryEndpoint,
- { throws: { error: 'error text' } },
+ { throws: { message: 'error text' } },
{ overwriteRoutes: true },
);
@@ -238,7 +238,7 @@ describe('async actions', () => {
fetchMock.post(
runQueryEndpoint,
- { throws: { error: 'error text' } },
+ { throws: { message: 'error text' } },
{ overwriteRoutes: true },
);
@@ -252,6 +252,29 @@ describe('async actions', () => {
});
});
+ describe('reRunQuery', () => {
+ let stub;
+ beforeEach(() => {
+ stub = sinon.stub(shortid, 'generate').returns('abcd');
+ });
+ afterEach(() => {
+ stub.restore();
+ });
+
+ it('creates new query with a new id', () => {
+ const id = 'id';
+ const state = {
+ sqlLab: {
+ tabHistory: [id],
+ queryEditors: [{ id, title: 'Dummy query editor' }],
+ },
+ };
+ const store = mockStore(state);
+ store.dispatch(actions.reRunQuery(query));
+ expect(store.getActions()[0].query.id).toEqual('abcd');
+ });
+ });
+
describe('postStopQuery', () => {
const stopQueryEndpoint = 'glob:*/superset/stop_query/*';
fetchMock.post(stopQueryEndpoint, {});
diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.js b/superset-frontend/src/SqlLab/actions/sqlLab.js
index 02a523a2348..a1bc59eafbd 100644
--- a/superset-frontend/src/SqlLab/actions/sqlLab.js
+++ b/superset-frontend/src/SqlLab/actions/sqlLab.js
@@ -352,6 +352,13 @@ export function runQuery(query) {
};
}
+export function reRunQuery(query) {
+ // run Query with a new id
+ return function (dispatch) {
+ dispatch(runQuery({ ...query, id: shortid.generate() }));
+ };
+}
+
export function validateQuery(query) {
return function (dispatch) {
dispatch(startQueryValidation(query));
diff --git a/superset-frontend/src/SqlLab/components/ResultSet.tsx b/superset-frontend/src/SqlLab/components/ResultSet.tsx
index f0c3d47de26..a33fcd1ce72 100644
--- a/superset-frontend/src/SqlLab/components/ResultSet.tsx
+++ b/superset-frontend/src/SqlLab/components/ResultSet.tsx
@@ -416,7 +416,7 @@ export default class ResultSet extends React.PureComponent<
query.errorMessage &&
query.errorMessage.indexOf('session timed out') > 0
) {
- this.props.actions.runQuery(query, true);
+ this.props.actions.reRunQuery(query);
}
}