diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.test.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.test.tsx index a697153d697..411937d6992 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.test.tsx @@ -11,10 +11,15 @@ * limitations under the License. */ import { render } from '@testing-library/react'; +import { startCase } from 'lodash'; import React from 'react'; -import { getEntityDetailsPath } from '../constants/constants'; +import { + getEntityDetailsPath, + getServiceDetailsPath, +} from '../constants/constants'; import { EntityTabs, EntityType } from '../enums/entity.enum'; import { ExplorePageTabs } from '../enums/Explore.enum'; +import { ServiceCategory } from '../enums/service.enum'; import { TestSuite } from '../generated/tests/testCase'; import { MOCK_CHART_DATA } from '../mocks/Chart.mock'; import { MOCK_TABLE, MOCK_TIER_DATA } from '../mocks/TableData.mock'; @@ -22,6 +27,7 @@ import { columnSorter, getBreadcrumbForTestSuite, getColumnSorter, + getEntityBreadcrumbs, getEntityLinkFromType, getEntityOverview, highlightEntityNameAndDescription, @@ -32,11 +38,19 @@ import { entityWithoutNameAndDescHighlight, highlightedEntityDescription, highlightedEntityDisplayName, + mockDatabaseUrl, + mockEntityForDatabase, + mockEntityForDatabaseSchema, mockHighlightedResult, mockHighlights, mockSearchText, + mockServiceUrl, + mockSettingUrl, mockText, + mockUrl, } from './mocks/EntityUtils.mock'; +import { getSettingPath } from './RouterUtils'; +import { getServiceRouteFromServiceType } from './ServiceUtils'; jest.mock('../constants/constants', () => ({ getEntityDetailsPath: jest.fn(), @@ -46,6 +60,16 @@ jest.mock('../constants/constants', () => ({ jest.mock('./RouterUtils', () => ({ getDataQualityPagePath: jest.fn(), getDomainPath: jest.fn(), + getSettingPath: jest.fn(), +})); + +jest.mock('./ServiceUtils', () => ({ + getServiceRouteFromServiceType: jest.fn(), +})); + +jest.mock('../constants/constants', () => ({ + getServiceDetailsPath: jest.fn(), + getEntityDetailsPath: jest.fn(), })); describe('EntityUtils unit tests', () => { @@ -355,4 +379,79 @@ describe('EntityUtils unit tests', () => { } ); }); + + describe('getEntityBreadcrumbs', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should return breadcrumbs for EntityType.DATABASE', () => { + (getServiceRouteFromServiceType as jest.Mock).mockReturnValue(mockUrl); + (getSettingPath as jest.Mock).mockReturnValue(mockSettingUrl); + (getServiceDetailsPath as jest.Mock).mockReturnValue( + '/service/databaseServices/mysql_sample' + ); + (getEntityDetailsPath as jest.Mock).mockReturnValue('/database/default'); + + const result = getEntityBreadcrumbs( + mockEntityForDatabase, + EntityType.DATABASE + ); + + expect(result).toEqual([ + { + name: startCase(ServiceCategory.DATABASE_SERVICES), + url: mockSettingUrl, + }, + { name: 'mysql_sample', url: '/service/databaseServices/mysql_sample' }, + { + name: 'default', + url: '/database/default', + }, + ]); + + expect(getServiceRouteFromServiceType).toHaveBeenCalledWith( + ServiceCategory.DATABASE_SERVICES + ); + }); + + it('should return breadcrumbs for EntityType.DATABASE_SCHEMA', () => { + (getSettingPath as jest.Mock).mockReturnValue(mockSettingUrl); + (getServiceDetailsPath as jest.Mock).mockReturnValue(mockServiceUrl); + (getEntityDetailsPath as jest.Mock).mockReturnValue(mockDatabaseUrl); + + const result = getEntityBreadcrumbs( + mockEntityForDatabaseSchema, + EntityType.DATABASE_SCHEMA + ); + + expect(result).toEqual([ + { + name: startCase(ServiceCategory.DATABASE_SERVICES), + url: mockSettingUrl, + }, + { + name: 'sample_data', + url: mockServiceUrl, + }, + { + name: 'ecommerce_db', + url: mockDatabaseUrl, + }, + { + name: 'shopify', + url: '/entity/MockDatabase', + }, + ]); + + expect(getServiceDetailsPath).toHaveBeenCalledWith( + 'sample_data', + ServiceCategory.DATABASE_SERVICES + ); + expect(getEntityDetailsPath).toHaveBeenCalledWith( + EntityType.DATABASE, + 'sample_data.ecommerce_db' + ); + }); + }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx index e73b0652fb6..d5fe8c99e42 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx @@ -1897,6 +1897,13 @@ export const getEntityBreadcrumbs = ( ), }, ...getBreadcrumbForEntitiesWithServiceOnly(entity as Database), + { + name: entity.name, + url: getEntityLinkFromType( + entity.fullyQualifiedName ?? '', + (entity as SourceType).entityType as EntityType + ), + }, ]; case EntityType.DATABASE_SCHEMA: @@ -1927,6 +1934,13 @@ export const getEntityBreadcrumbs = ( (entity as DatabaseSchema).database?.fullyQualifiedName ?? '' ), }, + { + name: entity.name, + url: getEntityLinkFromType( + entity.fullyQualifiedName ?? '', + (entity as SourceType).entityType as EntityType + ), + }, ]; case EntityType.DATABASE_SERVICE: diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/mocks/EntityUtils.mock.ts b/openmetadata-ui/src/main/resources/ui/src/utils/mocks/EntityUtils.mock.ts index 842e91f513d..0cac1707077 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/mocks/EntityUtils.mock.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/mocks/EntityUtils.mock.ts @@ -144,3 +144,50 @@ export const mockSearchText = 'test'; export const mockHighlightedResult = 'This is a test description to verify highlightText method.'; + +export const mockEntityForDatabase = { + id: '127463-8374', + name: 'default', + fullyQualifiedName: 'mysql_sample.default', + service: { + deleted: false, + displayName: 'mysql_sample', + fullyQualifiedName: 'mysql_sample', + id: '48a1a33a-71f9-4eca-9257-4fe3f919d20b', + name: 'mysql_sample', + type: 'databaseService', + }, + serviceType: 'Mysql', + entityType: 'database', +}; + +export const mockEntityForDatabaseSchema = { + id: '996c254d-1646-4d50-8457-10ec10de6bd8', + name: 'shopify', + fullyQualifiedName: 'sample_data.ecommerce_db.shopify', + service: { + deleted: false, + displayName: 'sample_data', + fullyQualifiedName: 'sample_data', + id: '166e3e84-dc2e-4c4e-bc4b-fe94d1a29bc7', + name: 'sample_data', + type: 'databaseService', + }, + serviceType: 'BigQuery', + database: { + deleted: false, + description: + 'This mock database contains schemas related to shopify sales and orders with related dimension tables.', + displayName: 'ecommerce_db', + fullyQualifiedName: 'sample_data.ecommerce_db', + id: 'ba923994-a1e3-429b-a7ff-ffae33101255', + name: 'ecommerce_db', + type: 'database', + }, + entityType: 'databaseSchema', +}; + +export const mockUrl = '/services/mockDatabase'; +export const mockSettingUrl = '/settings/services/database-services'; +export const mockServiceUrl = '/services/mockService'; +export const mockDatabaseUrl = '/entity/MockDatabase';