mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-31 09:25:40 +00:00
Update test connection modal to include error messages (#20248)
* update test connection modal to include error messages * update test * update as per comments * updated component * fix the error message and improve the code with unit test * minor improvement * fix the unit test and some improvement --------- Co-authored-by: Ashish Gupta <ashish@getcollate.io>
This commit is contained in:
parent
269d9b66d3
commit
07ac8fa5eb
@ -18,7 +18,7 @@ export interface InlineAlertProps {
|
||||
alertClassName?: string;
|
||||
type?: InlineAlertType;
|
||||
heading: string;
|
||||
description: ReactNode;
|
||||
description?: ReactNode;
|
||||
subDescription?: ReactNode;
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
@ -43,6 +43,14 @@ describe('InlineAlert', () => {
|
||||
expect(screen.getByText('Test Description')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not render description when it is not provided', () => {
|
||||
render(<InlineAlert {...mockProps} description={undefined} />);
|
||||
|
||||
expect(
|
||||
screen.queryByTestId('inline-alert-description')
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle show more/less functionality when subDescription is provided', () => {
|
||||
const subDescription = 'Additional details here';
|
||||
render(<InlineAlert {...mockProps} subDescription={subDescription} />);
|
||||
|
||||
@ -102,19 +102,25 @@ function InlineAlert({
|
||||
<Typography.Text className="font-semibold text-sm">
|
||||
{heading}
|
||||
</Typography.Text>
|
||||
<Typography.Paragraph className="m-b-0 text-sm">
|
||||
{description}
|
||||
</Typography.Paragraph>
|
||||
{description && (
|
||||
<Typography.Paragraph
|
||||
className="m-b-0 text-sm"
|
||||
data-testid="inline-alert-description">
|
||||
{description}
|
||||
</Typography.Paragraph>
|
||||
)}
|
||||
|
||||
{subDescription && showMore && (
|
||||
<Typography.Paragraph className="m-b-0 text-sm">
|
||||
<Typography.Paragraph
|
||||
className="m-b-0 text-sm"
|
||||
data-testid="inline-alert-sub-description">
|
||||
{subDescription}
|
||||
</Typography.Paragraph>
|
||||
)}
|
||||
|
||||
{subDescription && (
|
||||
<Button
|
||||
className="text-xs p-0 m-0 w-fit-content"
|
||||
className="text-xs p-0 m-0 w-fit-content h-auto"
|
||||
data-testid={`read-${showMore ? 'less' : 'more'}-button`}
|
||||
type="link"
|
||||
onClick={handleToggleShowMore}>
|
||||
|
||||
@ -58,7 +58,7 @@ import {
|
||||
getTestConnectionName,
|
||||
shouldTestConnection,
|
||||
} from '../../../utils/ServiceUtils';
|
||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||
import { getErrorText } from '../../../utils/StringsUtils';
|
||||
import Loader from '../Loader/Loader';
|
||||
import './test-connection.style.less';
|
||||
import { TestConnectionProps, TestStatus } from './TestConnection.interface';
|
||||
@ -86,6 +86,11 @@ const TestConnection: FC<TestConnectionProps> = ({
|
||||
TEST_CONNECTION_INITIAL_MESSAGE
|
||||
);
|
||||
|
||||
const [errorMessage, setErrorMessage] = useState<{
|
||||
description?: string;
|
||||
subDescription?: string;
|
||||
}>();
|
||||
|
||||
const [testConnectionStep, setTestConnectionStep] = useState<
|
||||
TestConnectionStep[]
|
||||
>([]);
|
||||
@ -346,7 +351,18 @@ const TestConnection: FC<TestConnectionProps> = ({
|
||||
setIsTestingConnection(false);
|
||||
setMessage(TEST_CONNECTION_FAILURE_MESSAGE);
|
||||
setTestStatus(StatusType.Failed);
|
||||
showErrorToast(error as AxiosError);
|
||||
if ((error as AxiosError)?.status === 500) {
|
||||
setErrorMessage({
|
||||
description: t('server.unexpected-response'),
|
||||
});
|
||||
} else {
|
||||
setErrorMessage({
|
||||
subDescription: getErrorText(
|
||||
error as AxiosError,
|
||||
t('server.unexpected-error')
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
// delete the workflow if there is an exception
|
||||
const workflowId = currentWorkflowRef.current?.id;
|
||||
@ -373,6 +389,10 @@ const TestConnection: FC<TestConnectionProps> = ({
|
||||
setDialogOpen(false);
|
||||
};
|
||||
|
||||
const handleCloseErrorMessage = () => {
|
||||
setErrorMessage(undefined);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
currentWorkflowRef.current = currentWorkflow; // update ref with latest value of currentWorkflow state variable
|
||||
}, [currentWorkflow]);
|
||||
@ -478,6 +498,8 @@ const TestConnection: FC<TestConnectionProps> = ({
|
||||
</Button>
|
||||
)}
|
||||
<TestConnectionModal
|
||||
errorMessage={errorMessage}
|
||||
handleCloseErrorMessage={handleCloseErrorMessage}
|
||||
isConnectionTimeout={isConnectionTimeout}
|
||||
isOpen={dialogOpen}
|
||||
isTestingConnection={isTestingConnection}
|
||||
|
||||
@ -14,6 +14,11 @@ import { act, fireEvent, render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import React from 'react';
|
||||
import TestConnectionModal from './TestConnectionModal';
|
||||
|
||||
jest.mock('../../InlineAlert/InlineAlert', () => {
|
||||
return jest.fn().mockReturnValue(<p>InlineAlert</p>);
|
||||
});
|
||||
|
||||
const onCancelMock = jest.fn();
|
||||
const onConfirmMock = jest.fn();
|
||||
|
||||
@ -36,115 +41,55 @@ const testConnectionStepResult = [
|
||||
];
|
||||
|
||||
const mockOnTestConnection = jest.fn();
|
||||
const mockHandleCloseErrorMessage = jest.fn();
|
||||
|
||||
const isConnectionTimeout = false;
|
||||
const commonProps = {
|
||||
isOpen: true,
|
||||
isConnectionTimeout: false,
|
||||
isTestingConnection: false,
|
||||
progress: 10,
|
||||
testConnectionStep,
|
||||
testConnectionStepResult,
|
||||
onCancel: onCancelMock,
|
||||
onConfirm: onConfirmMock,
|
||||
onTestConnection: mockOnTestConnection,
|
||||
handleCloseErrorMessage: mockHandleCloseErrorMessage,
|
||||
};
|
||||
|
||||
describe('TestConnectionModal', () => {
|
||||
it('Should render the modal title', () => {
|
||||
render(
|
||||
<TestConnectionModal
|
||||
isOpen
|
||||
isConnectionTimeout={isConnectionTimeout}
|
||||
isTestingConnection={false}
|
||||
progress={10}
|
||||
testConnectionStep={testConnectionStep}
|
||||
testConnectionStepResult={testConnectionStepResult}
|
||||
onCancel={onCancelMock}
|
||||
onConfirm={onConfirmMock}
|
||||
onTestConnection={mockOnTestConnection}
|
||||
/>
|
||||
);
|
||||
render(<TestConnectionModal {...commonProps} />);
|
||||
|
||||
expect(screen.getByText('label.connection-status')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render the steps and their results', () => {
|
||||
render(
|
||||
<TestConnectionModal
|
||||
isOpen
|
||||
isConnectionTimeout={isConnectionTimeout}
|
||||
isTestingConnection={false}
|
||||
progress={10}
|
||||
testConnectionStep={testConnectionStep}
|
||||
testConnectionStepResult={testConnectionStepResult}
|
||||
onCancel={onCancelMock}
|
||||
onConfirm={onConfirmMock}
|
||||
onTestConnection={mockOnTestConnection}
|
||||
/>
|
||||
);
|
||||
render(<TestConnectionModal {...commonProps} />);
|
||||
|
||||
expect(screen.getByText('Step 1')).toBeInTheDocument();
|
||||
expect(screen.getByText('Step 2')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render the success icon for a passing step', () => {
|
||||
render(
|
||||
<TestConnectionModal
|
||||
isOpen
|
||||
isConnectionTimeout={isConnectionTimeout}
|
||||
isTestingConnection={false}
|
||||
progress={10}
|
||||
testConnectionStep={testConnectionStep}
|
||||
testConnectionStepResult={testConnectionStepResult}
|
||||
onCancel={onCancelMock}
|
||||
onConfirm={onConfirmMock}
|
||||
onTestConnection={mockOnTestConnection}
|
||||
/>
|
||||
);
|
||||
render(<TestConnectionModal {...commonProps} />);
|
||||
|
||||
expect(screen.getByTestId('success-badge')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render the fail icon for a failing step', () => {
|
||||
render(
|
||||
<TestConnectionModal
|
||||
isOpen
|
||||
isConnectionTimeout={isConnectionTimeout}
|
||||
isTestingConnection={false}
|
||||
progress={10}
|
||||
testConnectionStep={testConnectionStep}
|
||||
testConnectionStepResult={testConnectionStepResult}
|
||||
onCancel={onCancelMock}
|
||||
onConfirm={onConfirmMock}
|
||||
onTestConnection={mockOnTestConnection}
|
||||
/>
|
||||
);
|
||||
render(<TestConnectionModal {...commonProps} />);
|
||||
|
||||
expect(screen.getByTestId('fail-badge')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should render the awaiting status for a step being tested', () => {
|
||||
render(
|
||||
<TestConnectionModal
|
||||
isOpen
|
||||
isTestingConnection
|
||||
isConnectionTimeout={isConnectionTimeout}
|
||||
progress={10}
|
||||
testConnectionStep={testConnectionStep}
|
||||
testConnectionStepResult={testConnectionStepResult}
|
||||
onCancel={onCancelMock}
|
||||
onConfirm={onConfirmMock}
|
||||
onTestConnection={mockOnTestConnection}
|
||||
/>
|
||||
);
|
||||
render(<TestConnectionModal {...commonProps} isTestingConnection />);
|
||||
|
||||
expect(screen.getAllByText('label.awaiting-status...')).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('Should call onCancel when the cancel button is clicked', () => {
|
||||
render(
|
||||
<TestConnectionModal
|
||||
isOpen
|
||||
isConnectionTimeout={isConnectionTimeout}
|
||||
isTestingConnection={false}
|
||||
progress={10}
|
||||
testConnectionStep={testConnectionStep}
|
||||
testConnectionStepResult={testConnectionStepResult}
|
||||
onCancel={onCancelMock}
|
||||
onConfirm={onConfirmMock}
|
||||
onTestConnection={mockOnTestConnection}
|
||||
/>
|
||||
);
|
||||
render(<TestConnectionModal {...commonProps} />);
|
||||
const cancelButton = screen.getByText('Cancel');
|
||||
|
||||
fireEvent.click(cancelButton);
|
||||
@ -153,19 +98,7 @@ describe('TestConnectionModal', () => {
|
||||
});
|
||||
|
||||
it('Should call onConfirm when the confirm button is clicked', () => {
|
||||
render(
|
||||
<TestConnectionModal
|
||||
isOpen
|
||||
isConnectionTimeout={isConnectionTimeout}
|
||||
isTestingConnection={false}
|
||||
progress={10}
|
||||
testConnectionStep={testConnectionStep}
|
||||
testConnectionStepResult={testConnectionStepResult}
|
||||
onCancel={onCancelMock}
|
||||
onConfirm={onConfirmMock}
|
||||
onTestConnection={mockOnTestConnection}
|
||||
/>
|
||||
);
|
||||
render(<TestConnectionModal {...commonProps} />);
|
||||
const okButton = screen.getByText('OK');
|
||||
|
||||
fireEvent.click(okButton);
|
||||
@ -174,19 +107,7 @@ describe('TestConnectionModal', () => {
|
||||
});
|
||||
|
||||
it('Should render the progress bar with proper value', () => {
|
||||
render(
|
||||
<TestConnectionModal
|
||||
isOpen
|
||||
isConnectionTimeout={isConnectionTimeout}
|
||||
isTestingConnection={false}
|
||||
progress={90}
|
||||
testConnectionStep={testConnectionStep}
|
||||
testConnectionStepResult={testConnectionStepResult}
|
||||
onCancel={onCancelMock}
|
||||
onConfirm={onConfirmMock}
|
||||
onTestConnection={mockOnTestConnection}
|
||||
/>
|
||||
);
|
||||
render(<TestConnectionModal {...commonProps} progress={90} />);
|
||||
const progressBarValue = screen.getByTestId('progress-bar-value');
|
||||
|
||||
expect(progressBarValue).toBeInTheDocument();
|
||||
@ -196,17 +117,7 @@ describe('TestConnectionModal', () => {
|
||||
|
||||
it('Should render the timeout widget if "isConnectionTimeout" is true', () => {
|
||||
render(
|
||||
<TestConnectionModal
|
||||
isConnectionTimeout
|
||||
isOpen
|
||||
isTestingConnection={false}
|
||||
progress={90}
|
||||
testConnectionStep={testConnectionStep}
|
||||
testConnectionStepResult={testConnectionStepResult}
|
||||
onCancel={onCancelMock}
|
||||
onConfirm={onConfirmMock}
|
||||
onTestConnection={mockOnTestConnection}
|
||||
/>
|
||||
<TestConnectionModal {...commonProps} isConnectionTimeout progress={90} />
|
||||
);
|
||||
|
||||
expect(
|
||||
@ -216,17 +127,7 @@ describe('TestConnectionModal', () => {
|
||||
|
||||
it('Try again button should work', async () => {
|
||||
render(
|
||||
<TestConnectionModal
|
||||
isConnectionTimeout
|
||||
isOpen
|
||||
isTestingConnection={false}
|
||||
progress={90}
|
||||
testConnectionStep={testConnectionStep}
|
||||
testConnectionStepResult={testConnectionStepResult}
|
||||
onCancel={onCancelMock}
|
||||
onConfirm={onConfirmMock}
|
||||
onTestConnection={mockOnTestConnection}
|
||||
/>
|
||||
<TestConnectionModal {...commonProps} isConnectionTimeout progress={90} />
|
||||
);
|
||||
|
||||
const tryAgainButton = screen.getByTestId('try-again-button');
|
||||
@ -239,4 +140,28 @@ describe('TestConnectionModal', () => {
|
||||
|
||||
expect(mockOnTestConnection).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not show error message component if error message is not passed', async () => {
|
||||
render(<TestConnectionModal {...commonProps} />);
|
||||
|
||||
const errorComponent = screen.queryByText('InlineAlert');
|
||||
|
||||
expect(errorComponent).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show error message component if error message is passed', async () => {
|
||||
render(
|
||||
<TestConnectionModal
|
||||
{...commonProps}
|
||||
errorMessage={{
|
||||
description: 'Error description',
|
||||
subDescription: 'Error sub description',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const errorComponent = screen.getByText('InlineAlert');
|
||||
|
||||
expect(errorComponent).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@ -22,8 +22,10 @@ import React, { FC } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReactComponent as IconTimeOut } from '../../../../assets/svg/ic-time-out.svg';
|
||||
import { ReactComponent as IconTimeOutButton } from '../../../../assets/svg/ic-timeout-button.svg';
|
||||
import { TEST_CONNECTION_FAILURE_MESSAGE } from '../../../../constants/Services.constant';
|
||||
import { TestConnectionStepResult } from '../../../../generated/entity/automations/workflow';
|
||||
import { TestConnectionStep } from '../../../../generated/entity/services/connections/testConnectionDefinition';
|
||||
import InlineAlert from '../../InlineAlert/InlineAlert';
|
||||
import ConnectionStepCard from '../ConnectionStepCard/ConnectionStepCard';
|
||||
import './test-connection-modal.less';
|
||||
interface TestConnectionModalProps {
|
||||
@ -36,6 +38,11 @@ interface TestConnectionModalProps {
|
||||
onCancel: () => void;
|
||||
onConfirm: () => void;
|
||||
onTestConnection: () => void;
|
||||
errorMessage?: {
|
||||
description?: string;
|
||||
subDescription?: string;
|
||||
};
|
||||
handleCloseErrorMessage: () => void;
|
||||
}
|
||||
|
||||
const TestConnectionModal: FC<TestConnectionModalProps> = ({
|
||||
@ -48,6 +55,8 @@ const TestConnectionModal: FC<TestConnectionModalProps> = ({
|
||||
onCancel,
|
||||
isConnectionTimeout,
|
||||
onTestConnection,
|
||||
errorMessage,
|
||||
handleCloseErrorMessage,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@ -77,6 +86,15 @@ const TestConnectionModal: FC<TestConnectionModalProps> = ({
|
||||
className="p-x-md w-full overflow-hidden"
|
||||
direction="vertical"
|
||||
size={16}>
|
||||
{errorMessage && (
|
||||
<InlineAlert
|
||||
heading={TEST_CONNECTION_FAILURE_MESSAGE}
|
||||
{...errorMessage}
|
||||
type="error"
|
||||
onClose={handleCloseErrorMessage}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Progress
|
||||
className="test-connection-progress-bar"
|
||||
format={getProgressFormat}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user