feat: support new errors payload in SQL Lab (#10243)

This commit is contained in:
Erik Ritter 2020-07-06 09:49:32 -07:00 committed by GitHub
parent 2314aad450
commit 9a5195ab85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 92 additions and 18 deletions

View File

@ -19,12 +19,20 @@
import React from 'react';
import { shallow } from 'enzyme';
import sinon from 'sinon';
import { Alert, ProgressBar } from 'react-bootstrap';
import FilterableTable from 'src/components/FilterableTable/FilterableTable';
import ExploreResultsButton from 'src/SqlLab/components/ExploreResultsButton';
import ResultSet from 'src/SqlLab/components/ResultSet';
import { queries, stoppedQuery, runningQuery, cachedQuery } from './fixtures';
import ErrorMessageWithStackTrace from 'src/components/ErrorMessage/ErrorMessageWithStackTrace';
import {
cachedQuery,
failedQueryWithErrorMessage,
failedQueryWithErrors,
queries,
runningQuery,
stoppedQuery,
} from './fixtures';
describe('ResultSet', () => {
const clearQuerySpy = sinon.spy();
@ -42,6 +50,14 @@ describe('ResultSet', () => {
const stoppedQueryProps = { ...mockedProps, query: stoppedQuery };
const runningQueryProps = { ...mockedProps, query: runningQuery };
const cachedQueryProps = { ...mockedProps, query: cachedQuery };
const failedQueryWithErrorMessageProps = {
...mockedProps,
query: failedQueryWithErrorMessage,
};
const failedQueryWithErrorsProps = {
...mockedProps,
query: failedQueryWithErrors,
};
const newProps = {
query: {
cached: false,
@ -117,5 +133,15 @@ describe('ResultSet', () => {
const wrapper = shallow(<ResultSet {...runningQueryProps} />);
expect(wrapper.find(ProgressBar)).toHaveLength(1);
});
it('should render a failed query with an error message', () => {
const wrapper = shallow(
<ResultSet {...failedQueryWithErrorMessageProps} />,
);
expect(wrapper.find(ErrorMessageWithStackTrace)).toHaveLength(1);
});
it('should render a failed query with an errors object', () => {
const wrapper = shallow(<ResultSet {...failedQueryWithErrorsProps} />);
expect(wrapper.find(ErrorMessageWithStackTrace)).toHaveLength(1);
});
});
});

View File

@ -389,6 +389,50 @@ export const stoppedQuery = {
tab: 'Untitled Query 2',
tempTable: '',
};
export const failedQueryWithErrorMessage = {
dbId: 1,
cached: false,
ctas: false,
errorMessage: 'Something went wrong',
id: 'ryhMUZCGb',
progress: 0,
results: [],
runAsync: false,
schema: 'main',
sql: 'SELECT ...',
sqlEditorId: 'rJaf5u9WZ',
startDttm: 1497400851936,
state: 'failed',
tab: 'Untitled Query 2',
tempTable: '',
};
export const failedQueryWithErrors = {
dbId: 1,
cached: false,
ctas: false,
errors: [
{
message: 'Something went wrong',
error_type: 'TEST_ERROR',
level: 'error',
extra: null,
},
],
id: 'ryhMUZCGb',
progress: 0,
results: [],
runAsync: false,
schema: 'main',
sql: 'SELECT ...',
sqlEditorId: 'rJaf5u9WZ',
startDttm: 1497400851936,
state: 'failed',
tab: 'Untitled Query 2',
tempTable: '',
};
export const runningQuery = {
dbId: 1,
cached: false,

View File

@ -271,7 +271,7 @@ export function querySuccess(query, results) {
};
}
export function queryFailed(query, msg, link) {
export function queryFailed(query, msg, link, errors) {
return function (dispatch) {
const sync =
!query.isDataPreview &&
@ -283,7 +283,7 @@ export function queryFailed(query, msg, link) {
: Promise.resolve();
return sync
.then(() => dispatch({ type: QUERY_FAILED, query, msg, link }))
.then(() => dispatch({ type: QUERY_FAILED, query, msg, link, errors }))
.catch(() =>
dispatch(
addDangerToast(
@ -332,7 +332,9 @@ export function fetchQueryResults(query, displayLimit) {
error.statusText ||
t('Failed at retrieving results');
return dispatch(queryFailed(query, message, error.link));
return dispatch(
queryFailed(query, message, error.link, error.errors),
);
}),
);
};
@ -376,7 +378,7 @@ export function runQuery(query) {
if (message.includes('CSRF token')) {
message = t(COMMON_ERR_MESSAGES.SESSION_TIMED_OUT);
}
dispatch(queryFailed(query, message, error.link));
dispatch(queryFailed(query, message, error.link, error.errors));
}),
);
};

View File

@ -21,6 +21,7 @@ import { Alert, Button, ButtonGroup, ProgressBar } from 'react-bootstrap';
import shortid from 'shortid';
import { t } from '@superset-ui/translation';
import ErrorMessageWithStackTrace from 'src/components/ErrorMessage/ErrorMessageWithStackTrace';
import Loading from '../../components/Loading';
import ExploreCtasResultsButton from './ExploreCtasResultsButton';
import ExploreResultsButton from './ExploreResultsButton';
@ -215,15 +216,11 @@ export default class ResultSet extends React.PureComponent<
return <Alert bsStyle="warning">Query was stopped</Alert>;
} else if (query.state === 'failed') {
return (
<Alert bsStyle="danger">
{query.errorMessage}
{query.link && (
<a href={query.link} target="_blank" rel="noopener noreferrer">
{' '}
{t('(Request Access)')}{' '}
</a>
)}
</Alert>
<ErrorMessageWithStackTrace
error={query.errors?.[0]}
message={query.errorMessage || undefined}
link={query.link}
/>
);
} else if (query.state === 'success' && query.ctas) {
const { tempSchema, tempTable } = query;

View File

@ -343,6 +343,7 @@ export default function sqlLabReducer(state = {}, action) {
}
const alts = {
state: 'failed',
errors: action.errors,
errorMessage: action.msg,
endDttm: now(),
link: action.link,

View File

@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
import { CtasEnum } from './actions/sqlLab';
import { SupersetError } from 'src/components/ErrorMessage/types';
import { CtasEnum } from 'src/SqlLab/actions/sqlLab';
export type Column = {
name: string;
@ -27,6 +28,7 @@ export type Query = {
ctas: boolean;
ctas_method?: keyof typeof CtasEnum;
dbId: number;
errors?: SupersetError[];
errorMessage: string | null;
extra: {
progress: string | null;

View File

@ -19,13 +19,15 @@
import React, { useState } from 'react';
// @ts-ignore
import { Alert, Collapse } from 'react-bootstrap';
import { t } from '@superset-ui/translation';
import getErrorMessageComponentRegistry from './getErrorMessageComponentRegistry';
import { SupersetError } from './types';
type Props = {
error?: SupersetError;
link?: string;
message: string;
message?: string;
stackTrace?: string;
};
@ -54,7 +56,7 @@ export default function ErrorMessageWithStackTrace({
bsStyle="warning"
onClick={() => setShowStackTrace(!showStackTrace)}
>
{message}
{message || t('An error occurred.')}
{link && (
<a href={link} target="_blank" rel="noopener noreferrer">
(Request Access)