Minor: fixed testSuite dependency on table entity object (#16147)

* Minor: fixed testSuite dependency on table entity object

* fixed failing unit
 test case
This commit is contained in:
Shailesh Parmar 2024-05-07 22:19:24 +05:30 committed by GitHub
parent b3e0470882
commit 1acf7d92d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 166 additions and 74 deletions

View File

@ -43,6 +43,7 @@ import { useFqn } from '../../../hooks/useFqn';
import { import {
createExecutableTestSuite, createExecutableTestSuite,
createTestCase, createTestCase,
getTestSuiteByName,
} from '../../../rest/testAPI'; } from '../../../rest/testAPI';
import { import {
getEntityBreadcrumbs, getEntityBreadcrumbs,
@ -133,8 +134,19 @@ const AddDataQualityTestV1: React.FC<AddDataQualityTestProps> = ({
return response; return response;
}; };
const fetchTestSuiteByFqn = async (fqn: string) => {
try {
const response = await getTestSuiteByName(fqn);
setTestSuiteData(response);
} catch (error) {
setTestSuiteData(undefined);
}
};
useEffect(() => { useEffect(() => {
setTestSuiteData(table.testSuite); if (table.testSuite?.fullyQualifiedName) {
fetchTestSuiteByFqn(table.testSuite.fullyQualifiedName);
}
}, [table.testSuite]); }, [table.testSuite]);
const handleFormSubmit = async (data: CreateTestCase) => { const handleFormSubmit = async (data: CreateTestCase) => {

View File

@ -36,9 +36,8 @@ import {
SORT_ORDER, SORT_ORDER,
} from '../../../../enums/common.enum'; } from '../../../../enums/common.enum';
import { EntityTabs, EntityType } from '../../../../enums/entity.enum'; import { EntityTabs, EntityType } from '../../../../enums/entity.enum';
import { TestSummary } from '../../../../generated/entity/data/table';
import { EntityReference } from '../../../../generated/entity/type'; import { EntityReference } from '../../../../generated/entity/type';
import { TestSuite } from '../../../../generated/tests/testCase'; import { TestSuite, TestSummary } from '../../../../generated/tests/testCase';
import { usePaging } from '../../../../hooks/paging/usePaging'; import { usePaging } from '../../../../hooks/paging/usePaging';
import { DataQualityPageTabs } from '../../../../pages/DataQuality/DataQualityPage.interface'; import { DataQualityPageTabs } from '../../../../pages/DataQuality/DataQualityPage.interface';
import { import {

View File

@ -94,9 +94,10 @@ const ColumnProfileTable = () => {
dateRangeObject, dateRangeObject,
onDateRangeChange, onDateRangeChange,
table, table,
testCaseSummary,
} = useTableProfiler(); } = useTableProfiler();
const testCaseCounts = useMemo( const testCaseCounts = useMemo(
() => table?.testSuite?.summary?.columnTestSummary ?? [], () => testCaseSummary?.columnTestSummary ?? [],
[table] [table]
); );
const isLoading = isTestsLoading || isProfilerDataLoading; const isLoading = isTestsLoading || isProfilerDataLoading;

View File

@ -53,6 +53,7 @@ export const QualityTab = () => {
isTableDeleted, isTableDeleted,
testCasePaging, testCasePaging,
table, table,
testCaseSummary,
} = useTableProfiler(); } = useTableProfiler();
const { const {
@ -248,9 +249,7 @@ export const QualityTab = () => {
</Row> </Row>
</Col> </Col>
<Col span={24}> <Col span={24}>
<SummaryPanel <SummaryPanel testSummary={testCaseSummary ?? INITIAL_TEST_SUMMARY} />
testSummary={testSuite?.summary ?? INITIAL_TEST_SUMMARY}
/>
</Col> </Col>
<Col span={24}> <Col span={24}>
<Tabs items={tabs} /> <Tabs items={tabs} />

View File

@ -24,13 +24,14 @@ import {
TableProfile, TableProfile,
TableProfilerConfig, TableProfilerConfig,
} from '../../../../generated/entity/data/table'; } from '../../../../generated/entity/data/table';
import { TestCase } from '../../../../generated/tests/testCase'; import { TestCase, TestSummary } from '../../../../generated/tests/testCase';
import { UsePagingInterface } from '../../../../hooks/paging/usePaging'; import { UsePagingInterface } from '../../../../hooks/paging/usePaging';
import { ListTestCaseParams } from '../../../../rest/testAPI'; import { ListTestCaseParams } from '../../../../rest/testAPI';
export interface TableProfilerProps { export interface TableProfilerProps {
permissions: OperationPermission; permissions: OperationPermission;
table?: Table; table?: Table;
testCaseSummary?: TestSummary;
} }
export interface TableProfilerProviderProps extends TableProfilerProps { export interface TableProfilerProviderProps extends TableProfilerProps {
@ -39,6 +40,7 @@ export interface TableProfilerProviderProps extends TableProfilerProps {
export interface TableProfilerContextInterface { export interface TableProfilerContextInterface {
isTableDeleted?: boolean; isTableDeleted?: boolean;
testCaseSummary?: TestSummary;
permissions: OperationPermission; permissions: OperationPermission;
isTestsLoading: boolean; isTestsLoading: boolean;
isProfilerDataLoading: boolean; isProfilerDataLoading: boolean;

View File

@ -59,6 +59,7 @@ export const TableProfilerProvider = ({
children, children,
permissions, permissions,
table, table,
testCaseSummary,
}: TableProfilerProviderProps) => { }: TableProfilerProviderProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { fqn: datasetFQN } = useFqn(); const { fqn: datasetFQN } = useFqn();
@ -272,6 +273,7 @@ export const TableProfilerProvider = ({
dateRangeObject, dateRangeObject,
testCasePaging, testCasePaging,
table, table,
testCaseSummary,
}; };
}, [ }, [
isTestsLoading, isTestsLoading,
@ -286,6 +288,7 @@ export const TableProfilerProvider = ({
dateRangeObject, dateRangeObject,
testCasePaging, testCasePaging,
table, table,
testCaseSummary,
]); ]);
return ( return (

View File

@ -25,6 +25,7 @@ const SchemaTab: FunctionComponent<Props> = ({
hasTagEditAccess, hasTagEditAccess,
onThreadLinkSelect, onThreadLinkSelect,
isReadOnly = false, isReadOnly = false,
testCaseSummary,
}: Props) => { }: Props) => {
const [searchText, setSearchText] = useState(''); const [searchText, setSearchText] = useState('');
@ -51,6 +52,7 @@ const SchemaTab: FunctionComponent<Props> = ({
isReadOnly={isReadOnly} isReadOnly={isReadOnly}
searchText={lowerCase(searchText)} searchText={lowerCase(searchText)}
table={table} table={table}
testCaseSummary={testCaseSummary}
onThreadLinkSelect={onThreadLinkSelect} onThreadLinkSelect={onThreadLinkSelect}
onUpdate={onUpdate} onUpdate={onUpdate}
/> />

View File

@ -13,6 +13,7 @@
import { ThreadType } from '../../../generated/api/feed/createThread'; import { ThreadType } from '../../../generated/api/feed/createThread';
import { Table } from '../../../generated/entity/data/table'; import { Table } from '../../../generated/entity/data/table';
import { TestSummary } from '../../../generated/tests/testCase';
export type Props = { export type Props = {
table?: Table; table?: Table;
@ -21,4 +22,5 @@ export type Props = {
isReadOnly?: boolean; isReadOnly?: boolean;
onThreadLinkSelect: (value: string, threadType?: ThreadType) => void; onThreadLinkSelect: (value: string, threadType?: ThreadType) => void;
onUpdate: (columns: Table['columns']) => Promise<void>; onUpdate: (columns: Table['columns']) => Promise<void>;
testCaseSummary?: TestSummary;
}; };

View File

@ -85,17 +85,18 @@ const SchemaTable = ({
isReadOnly = false, isReadOnly = false,
onThreadLinkSelect, onThreadLinkSelect,
table, table,
testCaseSummary,
}: SchemaTableProps) => { }: SchemaTableProps) => {
const { theme } = useApplicationStore(); const { theme } = useApplicationStore();
const { t } = useTranslation(); const { t } = useTranslation();
const { testCaseCounts, tableColumns, joins, tableConstraints } = useMemo( const { testCaseCounts, tableColumns, joins, tableConstraints } = useMemo(
() => ({ () => ({
testCaseCounts: table?.testSuite?.summary?.columnTestSummary ?? [], testCaseCounts: testCaseSummary?.columnTestSummary ?? [],
tableColumns: table?.columns ?? [], tableColumns: table?.columns ?? [],
joins: table?.joins?.columnJoins ?? [], joins: table?.joins?.columnJoins ?? [],
tableConstraints: table?.tableConstraints, tableConstraints: table?.tableConstraints,
}), }),
[table] [table, testCaseSummary]
); );
const [searchedColumns, setSearchedColumns] = useState<Column[]>([]); const [searchedColumns, setSearchedColumns] = useState<Column[]>([]);

View File

@ -14,6 +14,7 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { ThreadType } from '../../../generated/api/feed/createThread'; import { ThreadType } from '../../../generated/api/feed/createThread';
import { Column, Table } from '../../../generated/entity/data/table'; import { Column, Table } from '../../../generated/entity/data/table';
import { TestSummary } from '../../../generated/tests/testCase';
export interface SchemaTableProps { export interface SchemaTableProps {
hasDescriptionEditAccess: boolean; hasDescriptionEditAccess: boolean;
@ -23,6 +24,7 @@ export interface SchemaTableProps {
onUpdate: (columns: Column[]) => Promise<void>; onUpdate: (columns: Column[]) => Promise<void>;
onThreadLinkSelect: (value: string, threadType?: ThreadType) => void; onThreadLinkSelect: (value: string, threadType?: ThreadType) => void;
table?: Table; table?: Table;
testCaseSummary?: TestSummary;
} }
export type TableCellRendered<T, K extends keyof T> = ( export type TableCellRendered<T, K extends keyof T> = (

View File

@ -12,14 +12,12 @@
*/ */
import { Button } from 'antd'; import { Button } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import { isEmpty } from 'lodash';
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import { Handle, HandleProps, HandleType, Position } from 'reactflow'; import { Handle, HandleProps, HandleType, Position } from 'reactflow';
import { ReactComponent as MinusIcon } from '../../../assets/svg/control-minus.svg'; import { ReactComponent as MinusIcon } from '../../../assets/svg/control-minus.svg';
import { ReactComponent as PlusIcon } from '../../../assets/svg/plus-outlined.svg'; import { ReactComponent as PlusIcon } from '../../../assets/svg/plus-outlined.svg';
import { EntityLineageNodeType } from '../../../enums/entity.enum'; import { EntityLineageNodeType } from '../../../enums/entity.enum';
import { Column, TestSuite } from '../../../generated/entity/data/table'; import { Column } from '../../../generated/entity/data/table';
import { formTwoDigitNumber } from '../../../utils/CommonUtils';
import { encodeLineageHandles } from '../../../utils/EntityLineageUtils'; import { encodeLineageHandles } from '../../../utils/EntityLineageUtils';
import { getEntityName } from '../../../utils/EntityUtils'; import { getEntityName } from '../../../utils/EntityUtils';
import { getConstraintIcon } from '../../../utils/TableUtils'; import { getConstraintIcon } from '../../../utils/TableUtils';
@ -118,32 +116,6 @@ export const getCollapseHandle = (
); );
}; };
export const getTestSuiteSummary = (testSuite?: TestSuite) => {
if (isEmpty(testSuite)) {
return null;
}
return (
<div className="d-flex justify-end">
<div className="profiler-item green" data-testid="test-passed">
<div className="font-medium" data-testid="test-passed-value">
{formTwoDigitNumber(testSuite?.summary?.success ?? 0)}
</div>
</div>
<div className="profiler-item amber" data-testid="test-aborted">
<div className="font-medium" data-testid="test-aborted-value">
{formTwoDigitNumber(testSuite?.summary?.aborted ?? 0)}
</div>
</div>
<div className="profiler-item red" data-testid="test-failed">
<div className="font-medium" data-testid="test-failed-value">
{formTwoDigitNumber(testSuite?.summary?.failed ?? 0)}
</div>
</div>
</div>
);
};
export const getColumnContent = ( export const getColumnContent = (
column: Column, column: Column,
isColumnTraced: boolean, isColumnTraced: boolean,

View File

@ -24,7 +24,8 @@ import { Column, Table } from '../../../../generated/entity/data/table';
import { getEntityChildrenAndLabel } from '../../../../utils/EntityLineageUtils'; import { getEntityChildrenAndLabel } from '../../../../utils/EntityLineageUtils';
import { getEntityName } from '../../../../utils/EntityUtils'; import { getEntityName } from '../../../../utils/EntityUtils';
import { getEntityIcon } from '../../../../utils/TableUtils'; import { getEntityIcon } from '../../../../utils/TableUtils';
import { getColumnContent, getTestSuiteSummary } from '../CustomNode.utils'; import { getColumnContent } from '../CustomNode.utils';
import TestSuiteSummaryWidget from '../TestSuiteSummaryWidget/TestSuiteSummaryWidget.component';
import { EntityChildren, NodeChildrenProps } from './NodeChildren.interface'; import { EntityChildren, NodeChildrenProps } from './NodeChildren.interface';
const NodeChildren = ({ node, isConnectable }: NodeChildrenProps) => { const NodeChildren = ({ node, isConnectable }: NodeChildrenProps) => {
@ -163,9 +164,9 @@ const NodeChildren = ({ node, isConnectable }: NodeChildrenProps) => {
</Button> </Button>
)} )}
</div> </div>
{showDataQuality && {showDataQuality && entityType === EntityType.TABLE && (
entityType === EntityType.TABLE && <TestSuiteSummaryWidget testSuite={(node as Table).testSuite} />
getTestSuiteSummary((node as Table).testSuite)} )}
</div> </div>
{showColumns && isExpanded && ( {showColumns && isExpanded && (

View File

@ -0,0 +1,76 @@
/*
* Copyright 2024 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 { Skeleton } from 'antd';
import { isUndefined } from 'lodash';
import React, { useEffect, useState } from 'react';
import {
EntityReference,
TestSummary,
} from '../../../../generated/tests/testCase';
import { getTestCaseExecutionSummary } from '../../../../rest/testAPI';
import { formTwoDigitNumber } from '../../../../utils/CommonUtils';
const TestSuiteSummaryWidget = ({
testSuite,
}: {
testSuite?: EntityReference;
}) => {
const [summary, setSummary] = useState<TestSummary>();
const [isLoading, setIsLoading] = useState(true);
const fetchTestSuiteSummary = async (testSuite: EntityReference) => {
setIsLoading(true);
try {
const response = await getTestCaseExecutionSummary(testSuite.id);
setSummary(response);
} catch (error) {
setSummary(undefined);
} finally {
setIsLoading(false);
}
};
useEffect(() => {
if (testSuite && isUndefined(summary)) {
fetchTestSuiteSummary(testSuite);
} else {
setIsLoading(false);
}
}, [testSuite]);
if (isLoading) {
return <Skeleton.Input active />;
}
return (
<div className="d-flex justify-end">
<div className="profiler-item green" data-testid="test-passed">
<div className="font-medium" data-testid="test-passed-value">
{formTwoDigitNumber(summary?.success ?? 0)}
</div>
</div>
<div className="profiler-item amber" data-testid="test-aborted">
<div className="font-medium" data-testid="test-aborted-value">
{formTwoDigitNumber(summary?.aborted ?? 0)}
</div>
</div>
<div className="profiler-item red" data-testid="test-failed">
<div className="font-medium" data-testid="test-failed-value">
{formTwoDigitNumber(summary?.failed ?? 0)}
</div>
</div>
</div>
);
};
export default TestSuiteSummaryWidget;

View File

@ -31,11 +31,10 @@ import {
} from '../../../../context/PermissionProvider/PermissionProvider.interface'; } from '../../../../context/PermissionProvider/PermissionProvider.interface';
import { SummaryEntityType } from '../../../../enums/EntitySummary.enum'; import { SummaryEntityType } from '../../../../enums/EntitySummary.enum';
import { ExplorePageTabs } from '../../../../enums/Explore.enum'; import { ExplorePageTabs } from '../../../../enums/Explore.enum';
import { Table, TestSummary } from '../../../../generated/entity/data/table'; import { Table } from '../../../../generated/entity/data/table';
import { import { TestSummary } from '../../../../generated/tests/testCase';
getLatestTableProfileByFqn, import { getLatestTableProfileByFqn } from '../../../../rest/tableAPI';
getTableDetailsByFQN, import { getTestCaseExecutionSummary } from '../../../../rest/testAPI';
} from '../../../../rest/tableAPI';
import { formTwoDigitNumber } from '../../../../utils/CommonUtils'; import { formTwoDigitNumber } from '../../../../utils/CommonUtils';
import { import {
getFormattedEntityData, getFormattedEntityData,
@ -88,18 +87,17 @@ function TableSummary({
const isTableDeleted = useMemo(() => tableDetails.deleted, [tableDetails]); const isTableDeleted = useMemo(() => tableDetails.deleted, [tableDetails]);
const fetchAllTests = async () => { const fetchAllTests = async () => {
if (tableDetails?.testSuite?.id) {
try { try {
const res = await getTableDetailsByFQN( const res = await getTestCaseExecutionSummary(
tableDetails.fullyQualifiedName ?? '', tableDetails.testSuite.id
{ fields: 'testSuite' }
); );
if (res?.testSuite?.summary) { setTestSuiteSummary(res);
setTestSuiteSummary(res?.testSuite?.summary);
}
} catch (error) { } catch (error) {
// Error // Error
} }
}
}; };
const fetchProfilerData = useCallback(async () => { const fetchProfilerData = useCallback(async () => {

View File

@ -14,11 +14,8 @@
import { act, render, screen } from '@testing-library/react'; import { act, render, screen } from '@testing-library/react';
import React from 'react'; import React from 'react';
import { MemoryRouter } from 'react-router-dom'; import { MemoryRouter } from 'react-router-dom';
import { MOCK_TABLE } from '../../../../mocks/TableData.mock'; import { getLatestTableProfileByFqn } from '../../../../rest/tableAPI';
import { import { getTestCaseExecutionSummary } from '../../../../rest/testAPI';
getLatestTableProfileByFqn,
getTableDetailsByFQN,
} from '../../../../rest/tableAPI';
import { DRAWER_NAVIGATION_OPTIONS } from '../../../../utils/EntityUtils'; import { DRAWER_NAVIGATION_OPTIONS } from '../../../../utils/EntityUtils';
import { mockTableEntityDetails } from '../mocks/TableSummary.mock'; import { mockTableEntityDetails } from '../mocks/TableSummary.mock';
import TableSummary from './TableSummary.component'; import TableSummary from './TableSummary.component';
@ -43,9 +40,13 @@ jest.mock('../../../../rest/tableAPI', () => ({
getLatestTableProfileByFqn: jest getLatestTableProfileByFqn: jest
.fn() .fn()
.mockImplementation(() => mockTableEntityDetails), .mockImplementation(() => mockTableEntityDetails),
getTableDetailsByFQN: jest }));
.fn() jest.mock('../../../../rest/testAPI', () => ({
.mockImplementation(() => Promise.resolve(MOCK_TABLE)), getTestCaseExecutionSummary: jest.fn().mockImplementation(() => ({
success: 0,
failed: 0,
aborted: 0,
})),
})); }));
jest.mock('../SummaryList/SummaryList.component', () => jest.mock('../SummaryList/SummaryList.component', () =>
@ -195,16 +196,11 @@ describe('TableSummary component tests', () => {
profile: { rowCount: 30, timestamp: 38478857 }, profile: { rowCount: 30, timestamp: 38478857 },
}) })
); );
(getTableDetailsByFQN as jest.Mock).mockImplementationOnce(() => (getTestCaseExecutionSummary as jest.Mock).mockImplementationOnce(() =>
Promise.resolve({ Promise.resolve({
...MOCK_TABLE,
testSuite: {
summary: {
success: 3, success: 3,
failed: 1, failed: 1,
aborted: 1, aborted: 1,
},
},
}) })
); );
await act(async () => { await act(async () => {

View File

@ -121,4 +121,9 @@ export const mockTableEntityDetails: Table = {
href: 'http://localhost:8585/api/v1/databases/78a58be0-26a9-4ac8-b515-067db85bbb41', href: 'http://localhost:8585/api/v1/databases/78a58be0-26a9-4ac8-b515-067db85bbb41',
}, },
followers: [], followers: [],
testSuite: {
id: 'id',
name: 'dim.api/client',
type: 'testSuite',
},
}; };

View File

@ -71,6 +71,7 @@ import {
} from '../../generated/entity/data/table'; } from '../../generated/entity/data/table';
import { Suggestion } from '../../generated/entity/feed/suggestion'; import { Suggestion } from '../../generated/entity/feed/suggestion';
import { ThreadType } from '../../generated/entity/feed/thread'; import { ThreadType } from '../../generated/entity/feed/thread';
import { TestSummary } from '../../generated/tests/testCase';
import { TagLabel } from '../../generated/type/tagLabel'; import { TagLabel } from '../../generated/type/tagLabel';
import { useApplicationStore } from '../../hooks/useApplicationStore'; import { useApplicationStore } from '../../hooks/useApplicationStore';
import { useFqn } from '../../hooks/useFqn'; import { useFqn } from '../../hooks/useFqn';
@ -86,6 +87,7 @@ import {
restoreTable, restoreTable,
updateTablesVotes, updateTablesVotes,
} from '../../rest/tableAPI'; } from '../../rest/tableAPI';
import { getTestCaseExecutionSummary } from '../../rest/testAPI';
import { import {
addToRecentViewed, addToRecentViewed,
getFeedCounts, getFeedCounts,
@ -130,6 +132,7 @@ const TableDetailsPageV1: React.FC = () => {
const [tablePermissions, setTablePermissions] = useState<OperationPermission>( const [tablePermissions, setTablePermissions] = useState<OperationPermission>(
DEFAULT_ENTITY_PERMISSION DEFAULT_ENTITY_PERMISSION
); );
const [testCaseSummary, setTestCaseSummary] = useState<TestSummary>();
const extraDropdownContent = entityUtilClassBase.getManageExtraOptions( const extraDropdownContent = entityUtilClassBase.getManageExtraOptions(
EntityType.TABLE, EntityType.TABLE,
@ -190,6 +193,21 @@ const TableDetailsPageV1: React.FC = () => {
} }
}, [tableFqn, viewUsagePermission]); }, [tableFqn, viewUsagePermission]);
const fetchTestCaseSummary = async () => {
if (isUndefined(tableDetails?.testSuite?.id)) {
return;
}
try {
const response = await getTestCaseExecutionSummary(
tableDetails?.testSuite?.id
);
setTestCaseSummary(response);
} catch (error) {
setTestCaseSummary(undefined);
}
};
const fetchQueryCount = async () => { const fetchQueryCount = async () => {
if (!tableDetails?.id) { if (!tableDetails?.id) {
return; return;
@ -549,6 +567,7 @@ const TableDetailsPageV1: React.FC = () => {
hasTagEditAccess={editTagsPermission} hasTagEditAccess={editTagsPermission}
isReadOnly={deleted} isReadOnly={deleted}
table={tableDetails} table={tableDetails}
testCaseSummary={testCaseSummary}
onThreadLinkSelect={onThreadLinkSelect} onThreadLinkSelect={onThreadLinkSelect}
onUpdate={onColumnsUpdate} onUpdate={onColumnsUpdate}
/> />
@ -690,6 +709,7 @@ const TableDetailsPageV1: React.FC = () => {
<TableProfiler <TableProfiler
permissions={tablePermissions} permissions={tablePermissions}
table={tableDetails} table={tableDetails}
testCaseSummary={testCaseSummary}
/> />
), ),
}, },
@ -987,6 +1007,7 @@ const TableDetailsPageV1: React.FC = () => {
useEffect(() => { useEffect(() => {
if (tableDetails) { if (tableDetails) {
fetchQueryCount(); fetchQueryCount();
fetchTestCaseSummary();
} }
}, [tableDetails?.fullyQualifiedName]); }, [tableDetails?.fullyQualifiedName]);