diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/ClassificationVersionPage/ClassificationVersionPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/ClassificationVersionPage/ClassificationVersionPage.test.tsx new file mode 100644 index 00000000000..45290a8e3d0 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/pages/ClassificationVersionPage/ClassificationVersionPage.test.tsx @@ -0,0 +1,171 @@ +/* + * Copyright 2023 Collate. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { act, render, screen } from '@testing-library/react'; +import React from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import PageLayoutV1 from '../../components/PageLayoutV1/PageLayoutV1'; +import { ENTITY_PERMISSIONS } from '../../mocks/Permissions.mock'; +import { MOCK_ALL_CLASSIFICATIONS } from '../TagsPage/TagsPage.mock'; +import ClassificationVersionPage from './ClassificationVersionPage'; + +const mockParams = { + fqn: 'table', + version: '0.1', +}; + +jest.mock('react-router-dom', () => ({ + useHistory: jest.fn().mockImplementation(() => ({ + push: jest.fn(), + })), + useParams: jest.fn().mockImplementation(() => mockParams), +})); + +jest.mock( + '../../components/ClassificationDetails/ClassificationDetails', + () => ({ + ClassificationDetails: jest + .fn() + .mockImplementation(() =>
ClassificationDetails
), + }) +); + +jest.mock( + '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder', + () => { + return jest.fn().mockReturnValue(
testErrorPlaceHolder
); + } +); + +jest.mock( + '../../components/Entity/EntityVersionTimeLine/EntityVersionTimeLine', + () => { + return jest.fn().mockReturnValue(
testEntityVersionTimeLine
); + } +); + +jest.mock('../../components/Loader/Loader', () => { + return jest.fn().mockReturnValue(
Loader component
); +}); + +jest.mock('../../components/PageLayoutV1/PageLayoutV1', () => ({ + __esModule: true, + default: jest + .fn() + .mockImplementation(({ children }) =>
{children}
), +})); + +const mockGetEntityPermissionByFqn = jest + .fn() + .mockImplementation(() => Promise.resolve(ENTITY_PERMISSIONS)); + +jest.mock('../../components/PermissionProvider/PermissionProvider', () => ({ + usePermissionProvider: jest.fn().mockImplementation(() => ({ + getEntityPermissionByFqn: mockGetEntityPermissionByFqn, + })), +})); + +jest.mock('../../utils/PermissionsUtils', () => ({ + checkPermission: jest.fn().mockReturnValue(true), + DEFAULT_ENTITY_PERMISSION: { + ViewAll: true, + ViewBasic: true, + }, +})); + +jest.mock('../../rest/tagAPI', () => ({ + getClassificationByName: jest + .fn() + .mockImplementation(() => Promise.resolve(MOCK_ALL_CLASSIFICATIONS)), + getClassificationVersionData: jest + .fn() + .mockImplementation(() => Promise.resolve(MOCK_ALL_CLASSIFICATIONS)), + getClassificationVersionsList: jest + .fn() + .mockImplementation(() => Promise.resolve(MOCK_ALL_CLASSIFICATIONS)), +})); + +jest.mock('../../utils/RouterUtils', () => ({ + getClassificationVersionsPath: jest.fn(), + getClassificationDetailsPath: jest.fn(), +})); + +jest.mock('../../utils/ToastUtils', () => ({ + showErrorToast: jest.fn(), +})); + +describe('ClassificationVersionPage component', () => { + it('should render Loader', async () => { + render(, { + wrapper: MemoryRouter, + }); + + const loader = screen.getByText('Loader component'); + + expect(loader).toBeInTheDocument(); + }); + + it('should render EntityVersionTimeLine', async () => { + await act(async () => { + render(, { + wrapper: MemoryRouter, + }); + }); + + const versionData = await screen.findByTestId('version-data'); + const entityVersionTimeLine = await screen.findByText( + 'testEntityVersionTimeLine' + ); + + expect(versionData).toBeInTheDocument(); + expect(entityVersionTimeLine).toBeInTheDocument(); + }); + + it('should renders ErrorPlaceHolder with permission error', async () => { + mockGetEntityPermissionByFqn.mockResolvedValueOnce({}); + render(, { + wrapper: MemoryRouter, + }); + + const errorPlaceholder = await screen.findByText('testErrorPlaceHolder'); + + expect(errorPlaceholder).toBeInTheDocument(); + }); + + it('should renders ClassificationDetails in version view with all permissions', async () => { + await act(async () => { + render(, { + wrapper: MemoryRouter, + }); + }); + + expect(mockGetEntityPermissionByFqn).toHaveBeenCalled(); + + expect(screen.findByText('testClassificationDetails')).toBeTruthy(); + }); + + it('should render ClassificationVersionPage with PageLayoutV1 and child components', async () => { + await act(async () => { + render(, { + wrapper: MemoryRouter, + }); + }); + + expect(PageLayoutV1).toHaveBeenCalled(); + expect((PageLayoutV1 as jest.Mock).mock.calls[0][0].className).toBe( + 'version-page-container' + ); + expect((PageLayoutV1 as jest.Mock).mock.calls[0][0].pageTitle).toBe( + 'label.entity-version-detail-plural' + ); + }); +}); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/ClassificationVersionPage/ClassificationVersionPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/ClassificationVersionPage/ClassificationVersionPage.tsx index 9f105e646df..9e90bc9e860 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/ClassificationVersionPage/ClassificationVersionPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/ClassificationVersionPage/ClassificationVersionPage.tsx @@ -11,6 +11,7 @@ * limitations under the License. */ +import { AxiosError } from 'axios'; import { isEmpty, toString } from 'lodash'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -25,7 +26,6 @@ import { OperationPermission, ResourceEntity, } from '../../components/PermissionProvider/PermissionProvider.interface'; -import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants'; import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; import { Classification } from '../../generated/entity/classification/classification'; import { EntityHistory } from '../../generated/type/entityHistory'; @@ -39,11 +39,12 @@ import { getClassificationDetailsPath, getClassificationVersionsPath, } from '../../utils/RouterUtils'; +import { showErrorToast } from '../../utils/ToastUtils'; function ClassificationVersionPage() { const { t } = useTranslation(); const history = useHistory(); - const { fqn: tagCategoryName, version } = + const { fqn: classificationName, version } = useParams<{ fqn: string; version: string }>(); const { getEntityPermissionByFqn } = usePermissionProvider(); const [currentVersionData, setCurrentVersionData] = useState( @@ -60,11 +61,6 @@ function ClassificationVersionPage() { {} as EntityHistory ); - const classificationName = useMemo( - () => tagCategoryName.split(FQN_SEPARATOR_CHAR)[0], - [tagCategoryName] - ); - const viewVersionPermission = useMemo( () => classificationPermissions.ViewAll || classificationPermissions.ViewBasic, @@ -106,9 +102,10 @@ function ClassificationVersionPage() { setIsVersionDataLoading(true); if (viewVersionPermission) { const response = await getClassificationVersionData(id, version); - setCurrentVersionData(response); } + } catch (error) { + showErrorToast(error as AxiosError); } finally { setIsVersionDataLoading(false); } @@ -158,7 +155,7 @@ function ClassificationVersionPage() { return ( <> -
+
{isVersionDataLoading ? ( ) : ( diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.tsx index b6c77ffa560..fb6204d1908 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TagsPage/TagsPage.tsx @@ -117,10 +117,13 @@ const TagsPage = () => { ); const fetchCurrentClassificationPermission = async () => { + if (!currentClassification?.id) { + return; + } try { const response = await getEntityPermission( ResourceEntity.CLASSIFICATION, - currentClassification?.id as string + currentClassification?.id ); setClassificationPermissions(response); } catch (error) {