From a6824db622e2c5456ec0a2ed4e254116c69ac03b Mon Sep 17 00:00:00 2001 From: Amlan Kumar Nandy <45410599+amlannandy@users.noreply.github.com> Date: Wed, 23 Apr 2025 17:42:09 +0700 Subject: [PATCH] fix: metric details something went wrong message (#7686) --- .../api/metricsExplorer/getMetricDetails.ts | 2 +- .../MetricDetails/MetricDetails.tsx | 10 +- .../__tests__/MetricDetails.test.tsx | 175 ++++++++++++++++++ 3 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 frontend/src/container/MetricsExplorer/MetricDetails/__tests__/MetricDetails.test.tsx diff --git a/frontend/src/api/metricsExplorer/getMetricDetails.ts b/frontend/src/api/metricsExplorer/getMetricDetails.ts index 06ab7e62bb..74bde3e671 100644 --- a/frontend/src/api/metricsExplorer/getMetricDetails.ts +++ b/frontend/src/api/metricsExplorer/getMetricDetails.ts @@ -15,7 +15,7 @@ export interface MetricDetails { timeSeriesTotal: number; timeSeriesActive: number; lastReceived: string; - attributes: MetricDetailsAttribute[]; + attributes: MetricDetailsAttribute[] | null; metadata?: { metric_type: MetricType; description: string; diff --git a/frontend/src/container/MetricsExplorer/MetricDetails/MetricDetails.tsx b/frontend/src/container/MetricsExplorer/MetricDetails/MetricDetails.tsx index 0d0a640b20..2781ce5870 100644 --- a/frontend/src/container/MetricsExplorer/MetricDetails/MetricDetails.tsx +++ b/frontend/src/container/MetricsExplorer/MetricDetails/MetricDetails.tsx @@ -130,7 +130,11 @@ function MetricDetails({ destroyOnClose closeIcon={} > - {isMetricDetailsLoading && } + {isMetricDetailsLoading && ( +
+ +
+ )} {isMetricDetailsError && !isMetricDetailsLoading && ( )} @@ -171,7 +175,9 @@ function MetricDetails({ metadata={metric.metadata} refetchMetricDetails={refetchMetricDetails} /> - + {metric.attributes && ( + + )} )} diff --git a/frontend/src/container/MetricsExplorer/MetricDetails/__tests__/MetricDetails.test.tsx b/frontend/src/container/MetricsExplorer/MetricDetails/__tests__/MetricDetails.test.tsx new file mode 100644 index 0000000000..5eb7e867ea --- /dev/null +++ b/frontend/src/container/MetricsExplorer/MetricDetails/__tests__/MetricDetails.test.tsx @@ -0,0 +1,175 @@ +import { render, screen } from '@testing-library/react'; +import { MetricDetails } from 'api/metricsExplorer/getMetricDetails'; +import { MetricType } from 'api/metricsExplorer/getMetricsList'; +import ROUTES from 'constants/routes'; +import * as useGetMetricDetails from 'hooks/metricsExplorer/useGetMetricDetails'; +import * as useUpdateMetricMetadata from 'hooks/metricsExplorer/useUpdateMetricMetadata'; + +import MetricDetailsView from '../MetricDetails'; + +const mockMetricName = 'test-metric'; +const mockMetricDescription = 'description for a test metric'; +const mockMetricData: MetricDetails = { + name: mockMetricName, + description: mockMetricDescription, + unit: 'count', + attributes: [ + { + key: 'test-attribute', + value: ['test-value'], + valueCount: 1, + }, + ], + alerts: [], + dashboards: [], + metadata: { + metric_type: MetricType.SUM, + description: mockMetricDescription, + unit: 'count', + }, + type: '', + timeseries: 0, + samples: 0, + timeSeriesTotal: 0, + timeSeriesActive: 0, + lastReceived: '', +}; +const mockOpenInspectModal = jest.fn(); +const mockOnClose = jest.fn(); + +const mockUseGetMetricDetailsData = { + data: { + payload: { + data: mockMetricData, + }, + }, + isLoading: false, + isFetching: false, + isError: false, + error: null, + refetch: jest.fn(), +}; + +jest + .spyOn(useGetMetricDetails, 'useGetMetricDetails') + .mockReturnValue(mockUseGetMetricDetailsData as any); + +jest.spyOn(useUpdateMetricMetadata, 'useUpdateMetricMetadata').mockReturnValue({ + mutate: jest.fn(), + isLoading: false, + isError: false, + error: null, +} as any); + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useLocation: (): { pathname: string } => ({ + pathname: `${ROUTES.METRICS_EXPLORER}`, + }), +})); +jest.mock('hooks/useSafeNavigate', () => ({ + useSafeNavigate: (): any => ({ + safeNavigate: jest.fn(), + }), +})); + +describe('MetricDetails', () => { + it('renders metric details correctly', () => { + render( + , + ); + + expect(screen.getByText(mockMetricName)).toBeInTheDocument(); + expect(screen.getByText(mockMetricDescription)).toBeInTheDocument(); + expect(screen.getByText(`${mockMetricData.unit}`)).toBeInTheDocument(); + }); + + it('should render error state when metric details are not found', () => { + jest.spyOn(useGetMetricDetails, 'useGetMetricDetails').mockReturnValue({ + ...mockUseGetMetricDetailsData, + isError: true, + error: { + message: 'Error fetching metric details', + }, + } as any); + + render( + , + ); + + expect(screen.getByText('Error fetching metric details')).toBeInTheDocument(); + }); + + it('should render loading state when metric details are loading', () => { + jest.spyOn(useGetMetricDetails, 'useGetMetricDetails').mockReturnValue({ + ...mockUseGetMetricDetailsData, + isLoading: true, + } as any); + + render( + , + ); + + expect(screen.getByTestId('metric-details-skeleton')).toBeInTheDocument(); + }); + + it('should render all attributes section', () => { + jest + .spyOn(useGetMetricDetails, 'useGetMetricDetails') + .mockReturnValue(mockUseGetMetricDetailsData as any); + render( + , + ); + + expect(screen.getByText('All Attributes')).toBeInTheDocument(); + }); + + it('should not render all attributes section when relevant data is not present', () => { + jest.spyOn(useGetMetricDetails, 'useGetMetricDetails').mockReturnValue({ + ...mockUseGetMetricDetailsData, + data: { + payload: { + data: { + ...mockMetricData, + attributes: null, + }, + }, + }, + } as any); + render( + , + ); + + expect(screen.queryByText('All Attributes')).not.toBeInTheDocument(); + }); +});