Skip to content

Commit c43294a

Browse files
feat: extract ObservabilityRouterClassBase for extensible data quality and observability routing (#27212)
* Feat: supporting PR for data observability * test: add unit tests for ObservabilityRouterClassBase functionality * refactor: format navigation path calls for better readability * addressing comment * fix: ensure correct typing for description table object in ObservabilityAlertsPage * refactor: replace getDataQualityPagePath with observabilityRouterClassBase methods across multiple components * refactor: format getDataQualityPagePath calls for better readability * refactor: simplify getDataQualityPagePath mock implementation in tests * refactor: streamline getDataQualityPagePath calls for improved readability * refactor: improve readability of navigation path calls in Data Quality components * fixed unit test * feat(observability): implement ObservabilityRouterClassBase for alert navigation and data quality paths * refactor: format code for better readability in AlertDetailsPage, BulkEntityImportPage, and TestSuiteDetailsPage * refactor: update navigation and path handling in AlertDetailsPage and ObservabilityRouterClassBase * refactor(test): improve readability of assertions in DataAssetsCoveragePieChartWidget test
1 parent 8676a9f commit c43294a

14 files changed

Lines changed: 281 additions & 57 deletions

File tree

openmetadata-ui/src/main/resources/ui/src/components/DataQuality/ChartWidgets/DataAssetsCoveragePieChartWidget/DataAssetsCoveragePieChartWidget.component.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
fetchTotalEntityCount,
2626
} from '../../../../rest/dataQualityDashboardAPI';
2727
import { getPieChartLabel } from '../../../../utils/DataQuality/DataQualityUtils';
28-
import { getDataQualityPagePath } from '../../../../utils/RouterUtils';
28+
import observabilityRouterClassBase from '../../../../utils/ObservabilityRouterClassBase';
2929
import type { CustomPieChartData } from '../../../Visualisations/Chart/Chart.interface';
3030
import CustomPieChart from '../../../Visualisations/Chart/CustomPieChart.component';
3131
import { PieChartWidgetCommonProps } from '../../DataQuality.interface';
@@ -47,7 +47,11 @@ const DataAssetsCoveragePieChartWidget = ({
4747
const handleSegmentClick = useCallback(
4848
(_entry: CustomPieChartData, index: number) => {
4949
if (index === 0) {
50-
navigate(getDataQualityPagePath(DataQualityPageTabs.TEST_SUITES));
50+
navigate(
51+
observabilityRouterClassBase.getDataQualityPagePath(
52+
DataQualityPageTabs.TEST_SUITES
53+
)
54+
);
5155
} else if (index === 1) {
5256
navigate(ROUTES.EXPLORE);
5357
}

openmetadata-ui/src/main/resources/ui/src/components/DataQuality/ChartWidgets/DataAssetsCoveragePieChartWidget/DataAssetsCoveragePieChartWidget.test.tsx

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
* See the License for the specific language governing permissions and
1111
* limitations under the License.
1212
*/
13-
import { act, render, screen } from '@testing-library/react';
13+
import { render, screen } from '@testing-library/react';
14+
import { act } from 'react';
1415
import {
1516
fetchEntityCoveredWithDQ,
1617
fetchTotalEntityCount,
@@ -35,8 +36,11 @@ jest.mock('../../../../rest/dataQualityDashboardAPI', () => ({
3536
fetchTotalEntityCount: jest.fn().mockResolvedValue({ data: [] }),
3637
}));
3738

38-
jest.mock('../../../../utils/RouterUtils', () => ({
39-
getDataQualityPagePath: jest.fn((tab: string) => `/data-quality/${tab}`),
39+
jest.mock('../../../../utils/ObservabilityRouterClassBase', () => ({
40+
__esModule: true,
41+
default: {
42+
getDataQualityPagePath: jest.fn((tab: string) => `/data-quality/${tab}`),
43+
},
4044
}));
4145

4246
jest.mock('../../../Visualisations/Chart/CustomPieChart.component', () =>
@@ -45,7 +49,7 @@ jest.mock('../../../Visualisations/Chart/CustomPieChart.component', () =>
4549
.mockImplementation(
4650
(props: { onSegmentClick?: (e: unknown, i: number) => void }) => (
4751
<div>
48-
CustomPieChart.component
52+
<p>CustomPieChart.component</p>
4953
<button
5054
data-testid="segment-covered"
5155
onClick={() =>
@@ -107,9 +111,6 @@ describe('DataAssetsCoveragePieChartWidget', () => {
107111
});
108112

109113
it('should pass onSegmentClick to CustomPieChart and navigate to Test Suites on Covered click', async () => {
110-
const { getDataQualityPagePath } = jest.requireMock(
111-
'../../../../utils/RouterUtils'
112-
) as { getDataQualityPagePath: jest.Mock };
113114
const mockNavigate = (
114115
jest.requireMock('react-router-dom') as {
115116
__getMockNavigate: () => jest.Mock;
@@ -134,7 +135,13 @@ describe('DataAssetsCoveragePieChartWidget', () => {
134135
segmentCovered.click();
135136
});
136137

137-
expect(getDataQualityPagePath).toHaveBeenCalledWith('test-suites');
138+
const { default: observabilityRouterMock } = jest.requireMock(
139+
'../../../../utils/ObservabilityRouterClassBase'
140+
) as { default: { getDataQualityPagePath: jest.Mock } };
141+
142+
expect(observabilityRouterMock.getDataQualityPagePath).toHaveBeenCalledWith(
143+
'test-suites'
144+
);
138145
expect(mockNavigate).toHaveBeenCalledWith('/data-quality/test-suites');
139146
});
140147

openmetadata-ui/src/main/resources/ui/src/components/DataQuality/ChartWidgets/StatusByDimensionCardWidget/StatusByDimensionCardWidget.component.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
getDimensionIcon,
2727
transformToTestCaseStatusByDimension,
2828
} from '../../../../utils/DataQuality/DataQualityUtils';
29-
import { getDataQualityPagePath } from '../../../../utils/RouterUtils';
29+
import observabilityRouterClassBase from '../../../../utils/ObservabilityRouterClassBase';
3030
import { PieChartWidgetCommonProps } from '../../DataQuality.interface';
3131
import StatusByDimensionWidget from '../StatusCardWidget/StatusCardWidget.component';
3232
import './status-by-dimension-card-widget.less';
@@ -81,7 +81,9 @@ const StatusByDimensionCardWidget = ({
8181
isLoading={isDqByDimensionLoading}
8282
key={dimension.title}
8383
redirectPath={{
84-
pathname: getDataQualityPagePath(DataQualityPageTabs.TEST_CASES),
84+
pathname: observabilityRouterClassBase.getDataQualityPagePath(
85+
DataQualityPageTabs.TEST_CASES
86+
),
8587
search: QueryString.stringify({
8688
dataQualityDimension: dimension.title,
8789
}),

openmetadata-ui/src/main/resources/ui/src/components/DataQuality/DataQualityDashboard/DataQualityDashboard.component.tsx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ import {
5757
getStartOfDayInMillis,
5858
} from '../../../utils/date-time/DateTimeUtils';
5959
import { getEntityName } from '../../../utils/EntityUtils';
60-
import { getDataQualityPagePath } from '../../../utils/RouterUtils';
60+
import observabilityRouterClassBase from '../../../utils/ObservabilityRouterClassBase';
6161
import DataAssetsCoveragePieChartWidget from '../ChartWidgets/DataAssetsCoveragePieChartWidget/DataAssetsCoveragePieChartWidget.component';
6262
import EntityHealthStatusPieChartWidget from '../ChartWidgets/EntityHealthStatusPieChartWidget/EntityHealthStatusPieChartWidget.component';
6363
import IncidentTimeChartWidget from '../ChartWidgets/IncidentTimeChartWidget/IncidentTimeChartWidget.component';
@@ -797,9 +797,10 @@ const DataQualityDashboard = ({
797797
chartFilter={defaultFilters}
798798
name="success"
799799
redirectPath={{
800-
pathname: getDataQualityPagePath(
801-
DataQualityPageTabs.TEST_CASES
802-
),
800+
pathname:
801+
observabilityRouterClassBase.getDataQualityPagePath(
802+
DataQualityPageTabs.TEST_CASES
803+
),
803804
search: QueryString.stringify({
804805
testCaseStatus: TestCaseStatus.Success,
805806
}),
@@ -814,9 +815,10 @@ const DataQualityDashboard = ({
814815
chartFilter={defaultFilters}
815816
name="aborted"
816817
redirectPath={{
817-
pathname: getDataQualityPagePath(
818-
DataQualityPageTabs.TEST_CASES
819-
),
818+
pathname:
819+
observabilityRouterClassBase.getDataQualityPagePath(
820+
DataQualityPageTabs.TEST_CASES
821+
),
820822
search: QueryString.stringify({
821823
testCaseStatus: TestCaseStatus.Aborted,
822824
}),
@@ -831,9 +833,10 @@ const DataQualityDashboard = ({
831833
chartFilter={defaultFilters}
832834
name="failed"
833835
redirectPath={{
834-
pathname: getDataQualityPagePath(
835-
DataQualityPageTabs.TEST_CASES
836-
),
836+
pathname:
837+
observabilityRouterClassBase.getDataQualityPagePath(
838+
DataQualityPageTabs.TEST_CASES
839+
),
837840
search: QueryString.stringify({
838841
testCaseStatus: TestCaseStatus.Failed,
839842
}),

openmetadata-ui/src/main/resources/ui/src/components/DataQuality/TestCases/TestCases.component.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ import {
6868
import { getTestCaseFiltersValue } from '../../../utils/DataQuality/DataQualityUtils';
6969
import { getEntityName } from '../../../utils/EntityUtils';
7070
import { getPopupContainer } from '../../../utils/formUtils';
71+
import observabilityRouterClassBase from '../../../utils/ObservabilityRouterClassBase';
7172
import {
7273
checkPermission,
7374
getPrioritizedViewPermission,
7475
} from '../../../utils/PermissionsUtils';
75-
import { getDataQualityPagePath } from '../../../utils/RouterUtils';
7676
import tagClassBase from '../../../utils/TagClassBase';
7777
import { ExtraTestCaseDropdownOptions } from '../../../utils/TestCaseUtils';
7878
import { showErrorToast } from '../../../utils/ToastUtils';
@@ -738,7 +738,9 @@ export const TestCases = () => {
738738
breadcrumbData={[
739739
{
740740
name: t('label.data-quality'),
741-
url: getDataQualityPagePath(DataQualityPageTabs.TEST_CASES),
741+
url: observabilityRouterClassBase.getDataQualityPagePath(
742+
DataQualityPageTabs.TEST_CASES
743+
),
742744
},
743745
]}
744746
enableBulkActions={Boolean(testSuitePermission?.Create)}

openmetadata-ui/src/main/resources/ui/src/components/DataQuality/TestSuite/TestSuiteList/TestSuites.component.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ import {
5757
} from '../../../../rest/testAPI';
5858
import { getEntityName } from '../../../../utils/EntityUtils';
5959
import { getPopupContainer } from '../../../../utils/formUtils';
60+
import observabilityRouterClassBase from '../../../../utils/ObservabilityRouterClassBase';
6061
import { getPrioritizedViewPermission } from '../../../../utils/PermissionsUtils';
6162
import {
62-
getDataQualityPagePath,
6363
getEntityDetailsPath,
6464
getTestSuitePath,
6565
} from '../../../../utils/RouterUtils';
@@ -269,7 +269,12 @@ export const TestSuites = () => {
269269
};
270270

271271
const handleSubTabChange = (e: RadioChangeEvent) => {
272-
navigate(getDataQualityPagePath(tab, e.target.value as DataQualitySubTabs));
272+
navigate(
273+
observabilityRouterClassBase.getDataQualityPagePath(
274+
tab,
275+
e.target.value as DataQualitySubTabs
276+
)
277+
);
273278
};
274279

275280
const customPaginationProps = useMemo(

openmetadata-ui/src/main/resources/ui/src/pages/AlertDetailsPage/AlertDetailsPage.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,11 @@ import {
6161
} from '../../rest/observabilityAPI';
6262
import { getAlertExtraInfo } from '../../utils/Alerts/AlertsUtil';
6363
import { getEntityName } from '../../utils/EntityUtils';
64+
import observabilityRouterClassBase from '../../utils/ObservabilityRouterClassBase';
6465
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
6566
import {
6667
getNotificationAlertDetailsPath,
6768
getNotificationAlertsEditPath,
68-
getObservabilityAlertDetailsPath,
69-
getObservabilityAlertsEditPath,
7069
getSettingPath,
7170
} from '../../utils/RouterUtils';
7271
import searchClassBase from '../../utils/SearchClassBase';
@@ -209,15 +208,15 @@ function AlertDetailsPage({
209208
isNotificationAlert
210209
? navigate(ROUTES.NOTIFICATION_ALERT_LIST)
211210
: navigate(ROUTES.OBSERVABILITY_ALERTS);
212-
}, [history]);
211+
}, [navigate, isNotificationAlert]);
213212

214213
const handleAlertEdit = useCallback(async () => {
215214
navigate(
216215
isNotificationAlert
217216
? getNotificationAlertsEditPath(fqn)
218-
: getObservabilityAlertsEditPath(fqn)
217+
: observabilityRouterClassBase.getObservabilityAlertsEditPath(fqn)
219218
);
220-
}, [history]);
219+
}, [navigate, fqn, isNotificationAlert]);
221220

222221
const handleAlertSync = useCallback(async () => {
223222
try {
@@ -309,11 +308,14 @@ function AlertDetailsPage({
309308
navigate(
310309
isNotificationAlert
311310
? getNotificationAlertDetailsPath(fqn, activeKey)
312-
: getObservabilityAlertDetailsPath(fqn, activeKey),
311+
: observabilityRouterClassBase.getObservabilityAlertDetailsPath(
312+
fqn,
313+
activeKey
314+
),
313315
{ replace: true }
314316
);
315317
},
316-
[history, fqn]
318+
[navigate, fqn, isNotificationAlert]
317319
);
318320

319321
const hideDeleteModal = useCallback(() => {

openmetadata-ui/src/main/resources/ui/src/pages/DataQuality/DataQualityPage.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ import { usePermissionProvider } from '../../context/PermissionProvider/Permissi
2626
import { TestCase } from '../../generated/tests/testCase';
2727
import { TestSuite } from '../../generated/tests/testSuite';
2828
import { withPageLayout } from '../../hoc/withPageLayout';
29+
import observabilityRouterClassBase from '../../utils/ObservabilityRouterClassBase';
2930
import {
30-
getDataQualityPagePath,
3131
getTestCaseDetailPagePath,
3232
getTestSuitePath,
3333
} from '../../utils/RouterUtils';
@@ -113,7 +113,11 @@ const DataQualityPage = () => {
113113

114114
const handleTabChange = (activeKey: string) => {
115115
if (activeKey !== activeTab) {
116-
navigate(getDataQualityPagePath(activeKey as DataQualityPageTabs));
116+
navigate(
117+
observabilityRouterClassBase.getDataQualityPagePath(
118+
activeKey as DataQualityPageTabs
119+
)
120+
);
117121
}
118122
};
119123

openmetadata-ui/src/main/resources/ui/src/pages/EntityImport/BulkEntityImportPage/BulkEntityImportPage.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ import {
5757
validateCsvString,
5858
} from '../../../utils/EntityImport/EntityImportUtils';
5959
import entityUtilClassBase from '../../../utils/EntityUtilClassBase';
60+
import observabilityRouterClassBase from '../../../utils/ObservabilityRouterClassBase';
6061
import {
61-
getDataQualityPagePath,
6262
getEntityDetailsPath,
6363
getTestSuitePath,
6464
} from '../../../utils/RouterUtils';
@@ -211,7 +211,9 @@ const BulkEntityImportPage = () => {
211211
return [
212212
{
213213
name: t('label.data-quality'),
214-
url: getDataQualityPagePath(DataQualityPageTabs.TEST_CASES),
214+
url: observabilityRouterClassBase.getDataQualityPagePath(
215+
DataQualityPageTabs.TEST_CASES
216+
),
215217
},
216218
];
217219
}
@@ -253,7 +255,9 @@ const BulkEntityImportPage = () => {
253255
return [
254256
{
255257
name: t('label.test-suite-plural'),
256-
url: getDataQualityPagePath(DataQualityPageTabs.TEST_SUITES),
258+
url: observabilityRouterClassBase.getDataQualityPagePath(
259+
DataQualityPageTabs.TEST_SUITES
260+
),
257261
},
258262
{
259263
name: entity.displayName ?? entity.name ?? '',

openmetadata-ui/src/main/resources/ui/src/pages/ObservabilityAlertsPage/ObservabilityAlertsPage.tsx

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import PageLayoutV1 from '../../components/PageLayoutV1/PageLayoutV1';
2727
import {
2828
DE_ACTIVE_COLOR,
2929
NO_DATA_PLACEHOLDER,
30-
ROUTES,
3130
} from '../../constants/constants';
3231
import { ALERTS_DOCS } from '../../constants/docs.constants';
3332
import { LEARNING_PAGE_IDS } from '../../constants/Learning.constants';
@@ -49,10 +48,7 @@ import LimitWrapper from '../../hoc/LimitWrapper';
4948
import { usePaging } from '../../hooks/paging/usePaging';
5049
import { getAllAlerts } from '../../rest/alertsAPI';
5150
import { getEntityName } from '../../utils/EntityUtils';
52-
import {
53-
getObservabilityAlertDetailsPath,
54-
getObservabilityAlertsEditPath,
55-
} from '../../utils/RouterUtils';
51+
import observabilityRouterClassBase from '../../utils/ObservabilityRouterClassBase';
5652
import { descriptionTableObject } from '../../utils/TableColumn.util';
5753
import { showErrorToast } from '../../utils/ToastUtils';
5854

@@ -207,7 +203,7 @@ const ObservabilityAlertsPage = () => {
207203
return (
208204
<Link
209205
data-testid="alert-name"
210-
to={getObservabilityAlertDetailsPath(
206+
to={observabilityRouterClassBase.getObservabilityAlertDetailsPath(
211207
record.fullyQualifiedName ?? ''
212208
)}>
213209
{getEntityName(record)}
@@ -224,7 +220,7 @@ const ObservabilityAlertsPage = () => {
224220
return resources?.join(', ') || '--';
225221
},
226222
},
227-
...descriptionTableObject(),
223+
...descriptionTableObject<EventSubscription>(),
228224
{
229225
title: t('label.action-plural'),
230226
dataIndex: 'fullyQualifiedName',
@@ -253,7 +249,10 @@ const ObservabilityAlertsPage = () => {
253249
<div className="d-flex items-center">
254250
{alertPermission.edit && (
255251
<Tooltip placement="bottom" title={t('label.edit')}>
256-
<Link to={getObservabilityAlertsEditPath(fqn)}>
252+
<Link
253+
to={observabilityRouterClassBase.getObservabilityAlertsEditPath(
254+
fqn
255+
)}>
257256
<Button
258257
className="flex flex-center"
259258
data-testid={`alert-edit-${record.name}`}
@@ -311,7 +310,11 @@ const ObservabilityAlertsPage = () => {
311310
<Button
312311
data-testid="create-observability"
313312
type="primary"
314-
onClick={() => navigate(ROUTES.ADD_OBSERVABILITY_ALERTS)}>
313+
onClick={() =>
314+
navigate(
315+
observabilityRouterClassBase.getAddObservabilityAlertsPath()
316+
)
317+
}>
315318
{t('label.add-entity', { entity: t('label.alert') })}
316319
</Button>
317320
</LimitWrapper>
@@ -345,7 +348,11 @@ const ObservabilityAlertsPage = () => {
345348
entity: t('label.alert'),
346349
})}
347350
type={ERROR_PLACEHOLDER_TYPE.CREATE}
348-
onClick={() => navigate(ROUTES.ADD_OBSERVABILITY_ALERTS)}
351+
onClick={() =>
352+
navigate(
353+
observabilityRouterClassBase.getAddObservabilityAlertsPath()
354+
)
355+
}
349356
/>
350357
),
351358
}}

0 commit comments

Comments
 (0)