mirror of
https://github.com/apache/superset.git
synced 2026-08-04 04:52:32 +00:00
fix(charts): properly parse error responses in StatefulChart (#37130)
(cherry picked from commit 23b91d22ef)
This commit is contained in:
@@ -471,3 +471,95 @@ test('should handle chartId changes', async () => {
|
||||
expect(mockChartClient.loadFormData).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
test('should display error message when HTTP request fails with Response object', async () => {
|
||||
const errorBody = JSON.stringify({ message: 'Error: division by zero' });
|
||||
const mockResponse = new Response(errorBody, {
|
||||
status: 400,
|
||||
statusText: 'Bad Request',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
mockChartClient.client.post.mockRejectedValue(mockResponse);
|
||||
|
||||
const onError = jest.fn();
|
||||
const { findByText } = render(
|
||||
<StatefulChart
|
||||
formData={mockFormData}
|
||||
chartType="test_chart"
|
||||
onError={onError}
|
||||
/>,
|
||||
);
|
||||
|
||||
const errorElement = await findByText(/Error: division by zero/i);
|
||||
expect(errorElement).toBeInTheDocument();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onError).toHaveBeenCalledTimes(1);
|
||||
expect(onError).toHaveBeenCalledWith(expect.any(Error));
|
||||
expect(onError.mock.calls[0][0].message).toBe('Error: division by zero');
|
||||
});
|
||||
});
|
||||
|
||||
test('should display error message when HTTP request fails with errors array', async () => {
|
||||
const errorBody = JSON.stringify({
|
||||
errors: [
|
||||
{
|
||||
message: 'Query failed: column "invalid_col" does not exist',
|
||||
error_type: 'COLUMN_DOES_NOT_EXIST_ERROR',
|
||||
},
|
||||
],
|
||||
});
|
||||
const mockResponse = new Response(errorBody, {
|
||||
status: 422,
|
||||
statusText: 'Unprocessable Entity',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
mockChartClient.client.post.mockRejectedValue(mockResponse);
|
||||
|
||||
const { findByText } = render(
|
||||
<StatefulChart formData={mockFormData} chartType="test_chart" />,
|
||||
);
|
||||
|
||||
const errorElement = await findByText(
|
||||
/Query failed: column "invalid_col" does not exist/i,
|
||||
);
|
||||
expect(errorElement).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should display generic error message for network failures', async () => {
|
||||
const networkError = new TypeError('Failed to fetch');
|
||||
mockChartClient.client.post.mockRejectedValue(networkError);
|
||||
|
||||
const { findByText } = render(
|
||||
<StatefulChart formData={mockFormData} chartType="test_chart" />,
|
||||
);
|
||||
|
||||
const errorElement = await findByText(/Network error/i);
|
||||
expect(errorElement).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should pass error to custom errorComponent when provided', async () => {
|
||||
const errorBody = JSON.stringify({ message: 'Custom error message' });
|
||||
const mockResponse = new Response(errorBody, {
|
||||
status: 400,
|
||||
statusText: 'Bad Request',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
mockChartClient.client.post.mockRejectedValue(mockResponse);
|
||||
|
||||
const CustomErrorComponent = ({ error }: { error: Error }) => (
|
||||
<div data-test="custom-error">Custom: {error.message}</div>
|
||||
);
|
||||
|
||||
const { findByTestId } = render(
|
||||
<StatefulChart
|
||||
formData={mockFormData}
|
||||
chartType="test_chart"
|
||||
errorComponent={CustomErrorComponent}
|
||||
/>,
|
||||
);
|
||||
|
||||
const customError = await findByTestId('custom-error');
|
||||
expect(customError).toBeInTheDocument();
|
||||
expect(customError).toHaveTextContent('Custom: Custom error message');
|
||||
});
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
SupersetClientInterface,
|
||||
buildQueryContext,
|
||||
RequestConfig,
|
||||
getClientErrorObject,
|
||||
} from '../..';
|
||||
import { Loading } from '../../components/Loading';
|
||||
import ChartClient from '../clients/ChartClient';
|
||||
@@ -279,11 +280,17 @@ export default function StatefulChart(props: StatefulChartProps) {
|
||||
}
|
||||
} catch (err) {
|
||||
// Ignore abort errors
|
||||
if (err.name === 'AbortError') {
|
||||
if ((err as Error).name === 'AbortError') {
|
||||
return;
|
||||
}
|
||||
|
||||
const errorObj = err as Error;
|
||||
const parsedError = await getClientErrorObject(
|
||||
err as Parameters<typeof getClientErrorObject>[0],
|
||||
);
|
||||
const errorMessage =
|
||||
parsedError.error || parsedError.message || 'An error occurred';
|
||||
|
||||
const errorObj = new Error(errorMessage);
|
||||
setStatus('error');
|
||||
setError(errorObj);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user