diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/error-with-placeholder/ErrorPlaceHolderIngestion.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/error-with-placeholder/ErrorPlaceHolderIngestion.test.tsx index 6215c05e810..fb335817514 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/error-with-placeholder/ErrorPlaceHolderIngestion.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/error-with-placeholder/ErrorPlaceHolderIngestion.test.tsx @@ -11,14 +11,21 @@ * limitations under the License. */ -import { getByTestId, render } from '@testing-library/react'; +import { + getByTestId, + render, + screen, + waitForElementToBeRemoved, +} from '@testing-library/react'; import React from 'react'; import ErrorPlaceHolderIngestion from './ErrorPlaceHolderIngestion'; describe('Test Error placeholder ingestion Component', () => { - it('Component should render', () => { + it('Component should render', async () => { const { container } = render(); + await waitForElementToBeRemoved(() => screen.getByTestId('loader')); + expect(getByTestId(container, 'error-steps')).toBeInTheDocument(); }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/error-with-placeholder/ErrorPlaceHolderIngestion.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/error-with-placeholder/ErrorPlaceHolderIngestion.tsx index 1989ee591c6..fba775c86f9 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/error-with-placeholder/ErrorPlaceHolderIngestion.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/error-with-placeholder/ErrorPlaceHolderIngestion.tsx @@ -13,6 +13,7 @@ import { Card, Space, Typography } from 'antd'; import { ReactComponent as IconCollateSupport } from 'assets/svg/ic-collate-support.svg'; +import Loader from 'components/Loader/Loader'; import { AIRFLOW_DOCS } from 'constants/docs.constants'; import { PIPELINE_SERVICE_PLATFORM } from 'constants/Services.constant'; import { useAirflowStatus } from 'hooks/useAirflowStatus'; @@ -21,7 +22,7 @@ import React from 'react'; import AirflowMessageBanner from '../AirflowMessageBanner/AirflowMessageBanner'; const ErrorPlaceHolderIngestion = () => { - const { platform } = useAirflowStatus(); + const { platform, isFetchingStatus } = useAirflowStatus(); const isAirflowPlatform = platform === PIPELINE_SERVICE_PLATFORM; @@ -68,7 +69,7 @@ const ErrorPlaceHolderIngestion = () => { return (
- {airflowSetupGuide()} + {isFetchingStatus ? : airflowSetupGuide()}
); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/success-screen/SuccessScreen.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/success-screen/SuccessScreen.test.tsx index 63bcab44bd3..b8b55792f59 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/success-screen/SuccessScreen.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/success-screen/SuccessScreen.test.tsx @@ -11,96 +11,141 @@ * limitations under the License. */ -import { findByTestId, queryByTestId, render } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import { PIPELINE_SERVICE_PLATFORM } from 'constants/Services.constant'; +import { useAirflowStatus } from 'hooks/useAirflowStatus'; import React from 'react'; import { FormSubmitType } from '../../../enums/form.enum'; -import { useAirflowStatus } from '../../../hooks/useAirflowStatus'; -import SuccessScreen from './SuccessScreen'; +import SuccessScreen, { SuccessScreenProps } from './SuccessScreen'; jest.mock('../../../hooks/useAirflowStatus', () => ({ useAirflowStatus: jest.fn().mockImplementation(() => ({ isAirflowAvailable: true, fetchAirflowStatus: jest.fn(), isFetchingStatus: false, + platform: PIPELINE_SERVICE_PLATFORM, })), })); +const mockViewService = jest.fn(); +const mockDeployService = jest.fn(); +const mockIngestService = jest.fn(); + +const mockProps: SuccessScreenProps = { + name: 'newService', + suffix: 'suffix', + successMessage: 'this is success message', + showIngestionButton: true, + showDeployButton: true, + state: FormSubmitType.ADD, + viewServiceText: 'View New Service', + handleViewServiceClick: mockViewService, + handleDeployClick: mockDeployService, + handleIngestionClick: mockIngestService, +}; + describe('Test SuccessScreen component', () => { it('SuccessScreen component should render', async () => { - const { container } = render( - title} - /> - ); + render(); - const succsessScreenContainer = await findByTestId( - container, + const successScreenContainer = await screen.findByTestId( 'success-screen-container' ); - const successIcon = await findByTestId(container, 'success-icon'); - const successLine = await findByTestId(container, 'success-line'); - const viewServiceBtn = await findByTestId(container, 'view-service-button'); - const addIngestionBtn = await findByTestId( - container, - 'add-ingestion-button' - ); - const statusMsg = queryByTestId(container, 'airflow-status-msg'); - const airflowDoc = queryByTestId(container, 'airflow-doc-link'); - const statusCheck = queryByTestId(container, 'airflow-status-check'); + const successIcon = await screen.findByTestId('success-icon'); + const successLine = await screen.findByTestId('success-line'); + const viewServiceBtn = await screen.findByTestId('view-service-button'); + const addIngestionBtn = await screen.findByTestId('add-ingestion-button'); + const deployButton = await screen.findByTestId('deploy-ingestion-button'); + + const statusMsg = screen.queryByTestId('airflow-platform-message'); + + expect(successScreenContainer).toBeInTheDocument(); - expect(succsessScreenContainer).toBeInTheDocument(); expect(successIcon).toBeInTheDocument(); expect(successLine).toBeInTheDocument(); + expect(viewServiceBtn).toBeInTheDocument(); expect(addIngestionBtn).toBeInTheDocument(); + expect(deployButton).toBeInTheDocument(); + expect(statusMsg).not.toBeInTheDocument(); - expect(airflowDoc).not.toBeInTheDocument(); - expect(statusCheck).not.toBeInTheDocument(); }); - it('SuccessScreen component should render with airflow helper text', async () => { - (useAirflowStatus as jest.Mock).mockImplementation(() => ({ + it('Should Render airflow message if pipeline service client is not available and platform is airflow', () => { + (useAirflowStatus as jest.Mock).mockImplementationOnce(() => ({ isAirflowAvailable: false, fetchAirflowStatus: jest.fn(), isFetchingStatus: false, + platform: PIPELINE_SERVICE_PLATFORM, })); + render(); - const { container } = render( - title} - /> + const airflowPlatformMessage = screen.getByTestId( + 'airflow-platform-message' ); - const succsessScreenContainer = await findByTestId( - container, - 'success-screen-container' - ); - const successIcon = await findByTestId(container, 'success-icon'); - const successLine = await findByTestId(container, 'success-line'); - const viewServiceBtn = await findByTestId(container, 'view-service-button'); - const addIngestionBtn = await findByTestId( - container, - 'add-ingestion-button' - ); - const statusMsg = await findByTestId(container, 'airflow-status-msg'); - const airflowDoc = await findByTestId(container, 'airflow-doc-link'); - const statusCheck = await findByTestId(container, 'airflow-status-check'); + expect(airflowPlatformMessage).toBeInTheDocument(); - expect(succsessScreenContainer).toBeInTheDocument(); - expect(successIcon).toBeInTheDocument(); - expect(successLine).toBeInTheDocument(); - expect(viewServiceBtn).toBeInTheDocument(); - expect(addIngestionBtn).toBeInTheDocument(); - expect(statusMsg).toBeInTheDocument(); - expect(airflowDoc).toBeInTheDocument(); - expect(statusCheck).toBeInTheDocument(); + expect( + screen.getByText('message.manage-airflow-api-failed') + ).toBeInTheDocument(); + + expect( + screen.getByText('message.airflow-guide-message') + ).toBeInTheDocument(); + + expect( + screen.getByText('label.install-airflow-api >>') + ).toBeInTheDocument(); + }); + + it('Should Render pipeline scheduler message if pipeline service client is not available and platform is argo', () => { + (useAirflowStatus as jest.Mock).mockImplementationOnce(() => ({ + isAirflowAvailable: false, + fetchAirflowStatus: jest.fn(), + isFetchingStatus: false, + platform: 'Argo', + })); + render(); + + const argoPlatformMessage = screen.getByTestId('argo-platform-message'); + + expect(argoPlatformMessage).toBeInTheDocument(); + + expect( + screen.getByText('message.pipeline-scheduler-message') + ).toBeInTheDocument(); + + expect(screen.getByTestId('collate-support')).toBeInTheDocument(); + }); + + it('Should not render any message if pipeline service client is available with any platform', () => { + (useAirflowStatus as jest.Mock).mockImplementationOnce(() => ({ + isAirflowAvailable: true, + fetchAirflowStatus: jest.fn(), + isFetchingStatus: false, + platform: PIPELINE_SERVICE_PLATFORM, + })); + render(); + const airflowPlatformMessage = screen.queryByTestId( + 'airflow-platform-message' + ); + + const argoPlatformMessage = screen.queryByTestId('argo-platform-message'); + + expect(airflowPlatformMessage).not.toBeInTheDocument(); + expect(argoPlatformMessage).not.toBeInTheDocument(); + }); + + it('Should render the loader if status is fetching', () => { + (useAirflowStatus as jest.Mock).mockImplementationOnce(() => ({ + isAirflowAvailable: false, + fetchAirflowStatus: jest.fn(), + isFetchingStatus: true, + platform: PIPELINE_SERVICE_PLATFORM, + })); + render(); + + expect(screen.getByTestId('loader')).toBeInTheDocument(); }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/success-screen/SuccessScreen.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/success-screen/SuccessScreen.tsx index ce298f8302e..f95a4ca2332 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/success-screen/SuccessScreen.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/success-screen/SuccessScreen.tsx @@ -11,22 +11,23 @@ * limitations under the License. */ -import { Button, Typography } from 'antd'; -import classNames from 'classnames'; +import { Button, Card, Space, Typography } from 'antd'; +import { ReactComponent as IconCollateSupport } from 'assets/svg/ic-collate-support.svg'; +import { ReactComponent as IconSuccessBadge } from 'assets/svg/success-badge.svg'; +import Loader from 'components/Loader/Loader'; import { AIRFLOW_DOCS } from 'constants/docs.constants'; +import { PIPELINE_SERVICE_PLATFORM } from 'constants/Services.constant'; import { isUndefined } from 'lodash'; -import React from 'react'; +import React, { ReactNode, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { Transi18next } from 'utils/CommonUtils'; import { FormSubmitType } from '../../../enums/form.enum'; import { useAirflowStatus } from '../../../hooks/useAirflowStatus'; -import SVGIcons, { Icons } from '../../../utils/SvgUtils'; -import Loader from '../../Loader/Loader'; +import AirflowMessageBanner from '../AirflowMessageBanner/AirflowMessageBanner'; -type SuccessScreenProps = { +export type SuccessScreenProps = { name: string; suffix?: string; - successMessage?: JSX.Element; + successMessage?: ReactNode; showIngestionButton: boolean; showDeployButton?: boolean; state: FormSubmitType; @@ -41,7 +42,6 @@ const SuccessScreen = ({ suffix, showIngestionButton, showDeployButton = false, - handleIngestionClick, handleViewServiceClick, handleDeployClick, @@ -49,111 +49,86 @@ const SuccessScreen = ({ viewServiceText, }: SuccessScreenProps) => { const { t } = useTranslation(); - const { isAirflowAvailable, fetchAirflowStatus, isFetchingStatus } = - useAirflowStatus(); + const { isAirflowAvailable, platform, isFetchingStatus } = useAirflowStatus(); - const getAirflowStatusIcon = () => { - let icon; - if (isFetchingStatus) { - icon = ; - } else if (isAirflowAvailable) { - icon = ( - - ); - } else { - icon = ( - - ); - } + const isAirflowPlatform = useMemo( + () => platform === PIPELINE_SERVICE_PLATFORM, + [platform] + ); - return icon; - }; + const messageElement = useMemo( + () => + isAirflowPlatform ? ( +
+
+
+ {t('message.manage-airflow-api-failed')} +
+ +

+ {t('message.airflow-guide-message')} +

+
+ +

+ + {`${t('label.install-airflow-api')} >>`} + +

+
+ ) : ( + + + {t('message.pipeline-scheduler-message')} + + ), + [isAirflowPlatform] + ); return (
-
-
- -
- - {isUndefined(successMessage) ? ( - - - {`"${name || 'demo_mysql'}"`} + + + + + {isUndefined(successMessage) ? ( + + + {`"${name || 'demo_mysql'}"`} + + {suffix && {suffix}} + {t('message.has-been-created-successfully')} - {suffix && {suffix}} - {t('message.has-been-created-successfully')} - - ) : ( - successMessage - )} - -
- - {!isAirflowAvailable && ( -
-
-
-
{getAirflowStatusIcon()}
-
- {isAirflowAvailable - ? t('message.manage-airflow-api') - : t('message.manage-airflow-api-failed')} -
-
- {!isUndefined(fetchAirflowStatus) && ( -
- -
+ ) : ( + successMessage )} -
- {!isAirflowAvailable && ( - - } - values={{ - text: t('label.documentation-lowercase'), - }} - /> - )} -
+ + + + {!isAirflowAvailable && ( + <> + + + {isFetchingStatus ? : <>{messageElement}} + + )} -
+