diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/TableProfiler/TableProfiler.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/TableProfiler/TableProfiler.interface.ts index 6b2d3d10dcf..ea3f7c92a44 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/TableProfiler/TableProfiler.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/TableProfiler/TableProfiler.interface.ts @@ -30,7 +30,6 @@ import { TestLevel } from '../../../DataQuality/AddDataQualityTest/components/Te export interface TableProfilerProps { permissions: OperationPermission; table?: Table; - testCaseSummary?: TestSummary; } export interface TableProfilerProviderProps extends TableProfilerProps { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/TableProfiler/TableProfilerProvider.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/TableProfiler/TableProfilerProvider.tsx index 3a04ed5a3b2..7ef5ddd7a12 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/TableProfiler/TableProfilerProvider.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/TableProfiler/TableProfilerProvider.tsx @@ -33,7 +33,7 @@ import { useTourProvider } from '../../../../context/TourProvider/TourProvider'; import { TabSpecificField } from '../../../../enums/entity.enum'; import { Table } from '../../../../generated/entity/data/table'; import { ProfileSampleType } from '../../../../generated/metadataIngestion/databaseServiceProfilerPipeline'; -import { TestCase } from '../../../../generated/tests/testCase'; +import { TestCase, TestSummary } from '../../../../generated/tests/testCase'; import { Include } from '../../../../generated/type/include'; import { usePaging } from '../../../../hooks/paging/usePaging'; import useCustomLocation from '../../../../hooks/useCustomLocation/useCustomLocation'; @@ -44,6 +44,7 @@ import { } from '../../../../rest/tableAPI'; import { getListTestCaseBySearch, + getTestCaseExecutionSummary, ListTestCaseParamsBySearch, } from '../../../../rest/testAPI'; import { bytesToSize } from '../../../../utils/StringsUtils'; @@ -68,7 +69,6 @@ export const TableProfilerProvider = ({ children, permissions, table: tableEntity, - testCaseSummary, }: TableProfilerProviderProps) => { const { t } = useTranslation(); const { fqn: datasetFQN } = useFqn(); @@ -88,6 +88,7 @@ export const TableProfilerProvider = ({ const [isTestCaseDrawerOpen, setIsTestCaseDrawerOpen] = useState(false); const [testLevel, setTestLevel] = useState(); const [table, setTable] = useState(tableEntity); + const [testCaseSummary, setTestCaseSummary] = useState(); const isTableDeleted = useMemo(() => table?.deleted, [table]); @@ -309,6 +310,22 @@ export const TableProfilerProvider = ({ } }, [viewTest, isTourOpen, activeTab, testCasePaging.pageSize]); + const fetchTestCaseSummary = useCallback(async () => { + if (isUndefined(table?.testSuite?.id)) { + return; + } + try { + const response = await getTestCaseExecutionSummary(table.testSuite.id); + setTestCaseSummary(response); + } catch (error) { + setTestCaseSummary(undefined); + } + }, [table?.testSuite?.id]); + + useEffect(() => { + fetchTestCaseSummary(); + }, []); + const tableProfilerPropsData: TableProfilerContextInterface = useMemo(() => { return { isTestsLoading, diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx index f57eecddfca..268fd8239e3 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx @@ -59,7 +59,7 @@ import { } from '../../generated/entity/feed/suggestion'; import { Operation } from '../../generated/entity/policies/accessControl/resourcePermission'; import { PageType } from '../../generated/system/ui/page'; -import { TestSummary } from '../../generated/tests/testCase'; +import { TestCaseStatus } from '../../generated/tests/testCase'; import { TagLabel } from '../../generated/type/tagLabel'; import LimitWrapper from '../../hoc/LimitWrapper'; import { useApplicationStore } from '../../hooks/useApplicationStore'; @@ -68,6 +68,7 @@ import { useFqn } from '../../hooks/useFqn'; import { useSub } from '../../hooks/usePubSub'; import { FeedCounts } from '../../interface/feed.interface'; import { getContractByEntityId } from '../../rest/contractAPI'; +import { fetchTestCaseResultByTestSuiteId } from '../../rest/dataQualityDashboardAPI'; import { getDataQualityLineage } from '../../rest/lineageAPI'; import { getQueriesList } from '../../rest/queryAPI'; import { @@ -78,7 +79,6 @@ import { restoreTable, updateTablesVotes, } from '../../rest/tableAPI'; -import { getTestCaseExecutionSummary } from '../../rest/testAPI'; import { addToRecentViewed, getFeedCounts, @@ -133,7 +133,6 @@ const TableDetailsPageV1: React.FC = () => { const [tablePermissions, setTablePermissions] = useState( DEFAULT_ENTITY_PERMISSION ); - const [testCaseSummary, setTestCaseSummary] = useState(); const [dqFailureCount, setDqFailureCount] = useState(0); const { customizedPage, isLoading } = useCustomPages(PageType.Table); const [isTabExpanded, setIsTabExpanded] = useState(false); @@ -233,7 +232,7 @@ const TableDetailsPageV1: React.FC = () => { } }, [tableFqn, viewUsagePermission]); - const fetchDQFailureCount = async () => { + const fetchDQUpstreamFailureCount = async () => { if (!tableClassBase.getAlertEnableStatus()) { setDqFailureCount(0); } @@ -253,34 +252,38 @@ const TableDetailsPageV1: React.FC = () => { } }; - const fetchTestCaseSummary = async () => { + const getTestCaseFailureCount = async () => { try { - if (isUndefined(tableDetails?.testSuite?.id)) { - setTestCaseSummary(undefined); - await fetchDQFailureCount(); + if (!tableClassBase.getAlertEnableStatus()) { + setDqFailureCount(0); return; } - const response = await getTestCaseExecutionSummary( - tableDetails?.testSuite?.id - ); - setTestCaseSummary(response); + if (isUndefined(tableDetails?.testSuite?.id)) { + await fetchDQUpstreamFailureCount(); - const failureCount = - response.columnTestSummary?.reduce((acc, curr) => { - return acc + (curr.failed ?? 0); - }, response.failed ?? 0) ?? - response.failed ?? - 0; + return; + } + + const testSuiteId = tableDetails?.testSuite?.id; + + const { data } = await fetchTestCaseResultByTestSuiteId( + testSuiteId, + TestCaseStatus.Failed + ); + const failureCount = data.reduce( + (acc, curr) => acc + parseInt(curr.document_count ?? '0'), + 0 + ); if (failureCount === 0) { - await fetchDQFailureCount(); + await fetchDQUpstreamFailureCount(); } else { setDqFailureCount(failureCount); } } catch { - setTestCaseSummary(undefined); + setDqFailureCount(0); } }; @@ -551,7 +554,6 @@ const TableDetailsPageV1: React.FC = () => { viewProfilerPermission, editLineagePermission, fetchTableDetails, - testCaseSummary, isViewTableType, labelMap: tabLabelMap, }); @@ -581,7 +583,6 @@ const TableDetailsPageV1: React.FC = () => { viewProfilerPermission, editLineagePermission, fetchTableDetails, - testCaseSummary, isViewTableType, ]); @@ -787,7 +788,7 @@ const TableDetailsPageV1: React.FC = () => { useEffect(() => { if (tableDetails) { fetchQueryCount(); - fetchTestCaseSummary(); + getTestCaseFailureCount(); } }, [tableDetails?.fullyQualifiedName]); diff --git a/openmetadata-ui/src/main/resources/ui/src/rest/dataQualityDashboardAPI.ts b/openmetadata-ui/src/main/resources/ui/src/rest/dataQualityDashboardAPI.ts index 2522ba17eef..e04e75bbf20 100644 --- a/openmetadata-ui/src/main/resources/ui/src/rest/dataQualityDashboardAPI.ts +++ b/openmetadata-ui/src/main/resources/ui/src/rest/dataQualityDashboardAPI.ts @@ -20,7 +20,7 @@ import { buildMustEsFilterForOwner, buildMustEsFilterForTags, } from '../utils/DataQuality/DataQualityUtils'; -import { getDataQualityReport } from './testAPI'; +import { DataQualityReportParamsType, getDataQualityReport } from './testAPI'; export const fetchEntityCoveredWithDQ = ( filters?: DataQualityDashboardChartFilters, @@ -274,3 +274,59 @@ export const fetchTestCaseStatusMetricsByDays = ( 'bucketName=byDay:aggType=date_histogram:field=timestamp&calendar_interval=day,bucketName=newIncidents:aggType=cardinality:field=testCase.fullyQualifiedName', }); }; + +export const fetchTestCaseResultByTestSuiteId = ( + testSuiteId: string, + status?: TestCaseStatus +) => { + const params: DataQualityReportParamsType = { + q: JSON.stringify({ + query: { + bool: { + must: [ + { + bool: { + should: [ + { + nested: { + path: 'testSuites', + query: { + term: { + 'testSuites.id': testSuiteId, + }, + }, + }, + }, + { + term: { + 'testSuite.id': testSuiteId, + }, + }, + ], + }, + }, + { + term: { + deleted: false, + }, + }, + ...(status + ? [ + { + term: { + 'testCaseResult.testCaseStatus': status, + }, + }, + ] + : []), + ], + }, + }, + }), + aggregationQuery: + 'bucketName=entityLinks:aggType=terms:field=entityLink.nonNormalized,bucketName=status_counts:aggType=terms:field=testCaseResult.testCaseStatus', + index: 'testCase', + }; + + return getDataQualityReport(params); +}; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TableClassBase.ts b/openmetadata-ui/src/main/resources/ui/src/utils/TableClassBase.ts index a0c36701fbc..d6be7380f89 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/TableClassBase.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TableClassBase.ts @@ -25,7 +25,6 @@ import { DetailPageWidgetKeys } from '../enums/CustomizeDetailPage.enum'; import { EntityTabs } from '../enums/entity.enum'; import { Table } from '../generated/entity/data/table'; import { Tab } from '../generated/system/ui/uiCustomization'; -import { TestSummary } from '../generated/tests/testCase'; import { FeedCounts } from '../interface/feed.interface'; import { WidgetConfig } from '../pages/CustomizablePage/CustomizablePage.interface'; import i18n from './i18next/LocalUtil'; @@ -49,7 +48,6 @@ export interface TableDetailPageTabProps { editCustomAttributePermission: boolean; deleted?: boolean; tableDetails?: Table; - testCaseSummary?: TestSummary; getEntityFeedCount: () => void; fetchTableDetails: () => Promise; handleFeedCount: (data: FeedCounts) => void; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx index 081086acd3e..be98a45897f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx @@ -766,7 +766,6 @@ export const getTableDetailPageBaseTabs = ({ viewQueriesPermission, editLineagePermission, fetchTableDetails, - testCaseSummary, isViewTableType, labelMap, }: TableDetailPageTabProps): TabProps[] => { @@ -881,11 +880,7 @@ export const getTableDetailPageBaseTabs = ({ ), key: EntityTabs.PROFILER, children: ( - + ), }, {