mirror of
				https://github.com/open-metadata/OpenMetadata.git
				synced 2025-10-31 10:39:30 +00:00 
			
		
		
		
	Minor: dynamic min/max bound in graph for test case details page (#16944)
* Minor: dynamic min/max bound in graph for test case details page * added dynamic graph * minor fix
This commit is contained in:
		
							parent
							
								
									d58cc28fba
								
							
						
					
					
						commit
						83968f529c
					
				| @ -133,7 +133,7 @@ export type TestCaseAction = { | |||||||
| 
 | 
 | ||||||
| export type TestCaseChartDataType = { | export type TestCaseChartDataType = { | ||||||
|   information: { label: string; color: string }[]; |   information: { label: string; color: string }[]; | ||||||
|   data: Record<string, string | number | undefined | Thread>[]; |   data: Record<string, string | number | undefined | Thread | number[]>[]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export interface LineChartRef { | export interface LineChartRef { | ||||||
|  | |||||||
| @ -12,14 +12,15 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| import { Typography } from 'antd'; | import { Typography } from 'antd'; | ||||||
| import { first, isEmpty, isUndefined, omitBy, round } from 'lodash'; | import { first, isEmpty, isUndefined } from 'lodash'; | ||||||
| import React, { ReactElement, useMemo, useRef, useState } from 'react'; | import React, { ReactElement, useMemo, useRef, useState } from 'react'; | ||||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||||
| import { | import { | ||||||
|  |   Area, | ||||||
|   CartesianGrid, |   CartesianGrid, | ||||||
|  |   ComposedChart, | ||||||
|   Legend, |   Legend, | ||||||
|   Line, |   Line, | ||||||
|   LineChart, |  | ||||||
|   LineProps, |   LineProps, | ||||||
|   ReferenceArea, |   ReferenceArea, | ||||||
|   ReferenceLine, |   ReferenceLine, | ||||||
| @ -39,7 +40,6 @@ import { | |||||||
|   YELLOW_2, |   YELLOW_2, | ||||||
| } from '../../../../constants/Color.constants'; | } from '../../../../constants/Color.constants'; | ||||||
| import { GRAPH_BACKGROUND_COLOR } from '../../../../constants/constants'; | import { GRAPH_BACKGROUND_COLOR } from '../../../../constants/constants'; | ||||||
| import { COLORS } from '../../../../constants/profiler.constant'; |  | ||||||
| import { ERROR_PLACEHOLDER_TYPE } from '../../../../enums/common.enum'; | import { ERROR_PLACEHOLDER_TYPE } from '../../../../enums/common.enum'; | ||||||
| import { | import { | ||||||
|   Thread, |   Thread, | ||||||
| @ -47,13 +47,11 @@ import { | |||||||
| } from '../../../../generated/entity/feed/thread'; | } from '../../../../generated/entity/feed/thread'; | ||||||
| import { TestCaseStatus } from '../../../../generated/tests/testCase'; | import { TestCaseStatus } from '../../../../generated/tests/testCase'; | ||||||
| import { axisTickFormatter } from '../../../../utils/ChartUtils'; | import { axisTickFormatter } from '../../../../utils/ChartUtils'; | ||||||
|  | import { prepareChartData } from '../../../../utils/DataQuality/TestSummaryGraphUtils'; | ||||||
| import { formatDateTime } from '../../../../utils/date-time/DateTimeUtils'; | import { formatDateTime } from '../../../../utils/date-time/DateTimeUtils'; | ||||||
| import { useActivityFeedProvider } from '../../../ActivityFeed/ActivityFeedProvider/ActivityFeedProvider'; | import { useActivityFeedProvider } from '../../../ActivityFeed/ActivityFeedProvider/ActivityFeedProvider'; | ||||||
| import ErrorPlaceHolder from '../../../common/ErrorWithPlaceholder/ErrorPlaceHolder'; | import ErrorPlaceHolder from '../../../common/ErrorWithPlaceholder/ErrorPlaceHolder'; | ||||||
| import { | import { LineChartRef } from '../ProfilerDashboard/profilerDashboard.interface'; | ||||||
|   LineChartRef, |  | ||||||
|   TestCaseChartDataType, |  | ||||||
| } from '../ProfilerDashboard/profilerDashboard.interface'; |  | ||||||
| import TestSummaryCustomTooltip from '../TestSummaryCustomTooltip/TestSummaryCustomTooltip.component'; | import TestSummaryCustomTooltip from '../TestSummaryCustomTooltip/TestSummaryCustomTooltip.component'; | ||||||
| import { TestSummaryGraphProps } from './TestSummaryGraph.interface'; | import { TestSummaryGraphProps } from './TestSummaryGraph.interface'; | ||||||
| 
 | 
 | ||||||
| @ -83,50 +81,12 @@ function TestSummaryGraph({ | |||||||
|   }, [chartRef, chartMouseEvent]); |   }, [chartRef, chartMouseEvent]); | ||||||
| 
 | 
 | ||||||
|   const chartData = useMemo(() => { |   const chartData = useMemo(() => { | ||||||
|     const chartData: TestCaseChartDataType['data'] = []; |     return prepareChartData({ | ||||||
| 
 |       testCaseParameterValue: testCaseParameterValue ?? [], | ||||||
|     testCaseResults.forEach((result) => { |       testCaseResults, | ||||||
|       const values = result.testResultValue?.reduce((acc, curr) => { |       entityThread, | ||||||
|         const value = round(parseFloat(curr.value ?? ''), 2) || 0; |  | ||||||
| 
 |  | ||||||
|         return { |  | ||||||
|           ...acc, |  | ||||||
|           [curr.name ?? 'value']: value, |  | ||||||
|         }; |  | ||||||
|       }, {}); |  | ||||||
|       const metric = { |  | ||||||
|         passedRows: result.passedRows, |  | ||||||
|         failedRows: result.failedRows, |  | ||||||
|         passedRowsPercentage: isUndefined(result.passedRowsPercentage) |  | ||||||
|           ? undefined |  | ||||||
|           : `${round(result.passedRowsPercentage, 2)}%`, |  | ||||||
|         failedRowsPercentage: isUndefined(result.failedRowsPercentage) |  | ||||||
|           ? undefined |  | ||||||
|           : `${round(result.failedRowsPercentage, 2)}%`, |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       chartData.push({ |  | ||||||
|         name: result.timestamp, |  | ||||||
|         status: result.testCaseStatus, |  | ||||||
|         ...values, |  | ||||||
|         ...omitBy(metric, isUndefined), |  | ||||||
|         incidentId: result.incidentId, |  | ||||||
|         task: entityThread.find( |  | ||||||
|           (task) => task.task?.testCaseResolutionStatusId === result.incidentId |  | ||||||
|         ), |  | ||||||
|     }); |     }); | ||||||
|     }); |   }, [testCaseResults, entityThread, testCaseParameterValue]); | ||||||
|     chartData.reverse(); |  | ||||||
| 
 |  | ||||||
|     return { |  | ||||||
|       information: |  | ||||||
|         testCaseResults[0]?.testResultValue?.map((info, i) => ({ |  | ||||||
|           label: info.name ?? '', |  | ||||||
|           color: COLORS[i], |  | ||||||
|         })) ?? [], |  | ||||||
|       data: chartData, |  | ||||||
|     }; |  | ||||||
|   }, [testCaseResults, entityThread]); |  | ||||||
| 
 | 
 | ||||||
|   const incidentData = useMemo(() => { |   const incidentData = useMemo(() => { | ||||||
|     const data = chartData.data ?? []; |     const data = chartData.data ?? []; | ||||||
| @ -191,10 +151,10 @@ function TestSummaryGraph({ | |||||||
|     ); |     ); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   const referenceArea = () => { |   const referenceArea = useMemo(() => { | ||||||
|     const params = testCaseParameterValue ?? []; |     const params = testCaseParameterValue ?? []; | ||||||
| 
 | 
 | ||||||
|     if (params.length && params.length < 2) { |     if (params.length === 1) { | ||||||
|       return ( |       return ( | ||||||
|         <ReferenceLine |         <ReferenceLine | ||||||
|           label={params[0].name} |           label={params[0].name} | ||||||
| @ -203,20 +163,9 @@ function TestSummaryGraph({ | |||||||
|         /> |         /> | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|     const yValues = params.reduce((acc, curr, i) => { |  | ||||||
|       return { ...acc, [`y${i + 1}`]: parseInt(curr.value ?? '') }; |  | ||||||
|     }, {}); |  | ||||||
| 
 | 
 | ||||||
|     return ( |     return <></>; | ||||||
|       <ReferenceArea |   }, [testCaseParameterValue]); | ||||||
|         fill={GREEN_3_OPACITY} |  | ||||||
|         ifOverflow="extendDomain" |  | ||||||
|         stroke={GREEN_3} |  | ||||||
|         strokeDasharray="4" |  | ||||||
|         {...yValues} |  | ||||||
|       /> |  | ||||||
|     ); |  | ||||||
|   }; |  | ||||||
| 
 | 
 | ||||||
|   if (isEmpty(testCaseResults)) { |   if (isEmpty(testCaseResults)) { | ||||||
|     return ( |     return ( | ||||||
| @ -246,7 +195,7 @@ function TestSummaryGraph({ | |||||||
|       className="bg-white" |       className="bg-white" | ||||||
|       id={`${testCaseName}_graph`} |       id={`${testCaseName}_graph`} | ||||||
|       minHeight={minHeight ?? 400}> |       minHeight={minHeight ?? 400}> | ||||||
|       <LineChart |       <ComposedChart | ||||||
|         data={chartData.data} |         data={chartData.data} | ||||||
|         margin={{ |         margin={{ | ||||||
|           top: 16, |           top: 16, | ||||||
| @ -278,8 +227,18 @@ function TestSummaryGraph({ | |||||||
|           position={{ y: 100 }} |           position={{ y: 100 }} | ||||||
|           wrapperStyle={{ pointerEvents: 'auto' }} |           wrapperStyle={{ pointerEvents: 'auto' }} | ||||||
|         /> |         /> | ||||||
|         {referenceArea()} |         {referenceArea} | ||||||
|         <Legend payload={customLegendPayLoad} /> |         <Legend payload={customLegendPayLoad} /> | ||||||
|  |         <Area | ||||||
|  |           connectNulls | ||||||
|  |           activeDot={false} | ||||||
|  |           dataKey="boundArea" | ||||||
|  |           dot={false} | ||||||
|  |           fill={GREEN_3_OPACITY} | ||||||
|  |           stroke={GREEN_3} | ||||||
|  |           strokeDasharray="4" | ||||||
|  |           type="monotone" | ||||||
|  |         /> | ||||||
|         {chartData?.information?.map((info) => ( |         {chartData?.information?.map((info) => ( | ||||||
|           <Line |           <Line | ||||||
|             dataKey={info.label} |             dataKey={info.label} | ||||||
| @ -300,7 +259,7 @@ function TestSummaryGraph({ | |||||||
|               x2={data.x2} |               x2={data.x2} | ||||||
|             /> |             /> | ||||||
|           ))} |           ))} | ||||||
|       </LineChart> |       </ComposedChart> | ||||||
|     </ResponsiveContainer> |     </ResponsiveContainer> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  | |||||||
| @ -27,7 +27,7 @@ const TestSummaryCustomTooltip = ( | |||||||
|   const { t } = useTranslation(); |   const { t } = useTranslation(); | ||||||
|   const { active, payload = [] } = props; |   const { active, payload = [] } = props; | ||||||
|   const data = payload.length |   const data = payload.length | ||||||
|     ? entries(omit(payload[0].payload, ['name', 'incidentId'])) |     ? entries(omit(payload[0].payload, ['name', 'incidentId', 'boundArea'])) | ||||||
|     : []; |     : []; | ||||||
| 
 | 
 | ||||||
|   if (!active || payload.length === 0) { |   if (!active || payload.length === 0) { | ||||||
|  | |||||||
| @ -39,7 +39,7 @@ import { | |||||||
|   PAGE_SIZE_MEDIUM, |   PAGE_SIZE_MEDIUM, | ||||||
| } from '../../constants/constants'; | } from '../../constants/constants'; | ||||||
| import { PAGE_HEADERS } from '../../constants/PageHeaders.constant'; | import { PAGE_HEADERS } from '../../constants/PageHeaders.constant'; | ||||||
| import { DEFAULT_SELECTED_RANGE } from '../../constants/profiler.constant'; | import { PROFILER_FILTER_RANGE } from '../../constants/profiler.constant'; | ||||||
| import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider'; | import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider'; | ||||||
| import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; | import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; | ||||||
| import { EntityTabs, EntityType, FqnPart } from '../../enums/entity.enum'; | import { EntityTabs, EntityType, FqnPart } from '../../enums/entity.enum'; | ||||||
| @ -84,13 +84,20 @@ import { Option } from '../TasksPage/TasksPage.interface'; | |||||||
| import { TestCaseIncidentStatusData } from './IncidentManager.interface'; | import { TestCaseIncidentStatusData } from './IncidentManager.interface'; | ||||||
| 
 | 
 | ||||||
| const IncidentManagerPage = () => { | const IncidentManagerPage = () => { | ||||||
|  |   const defaultRange = useMemo( | ||||||
|  |     () => ({ | ||||||
|  |       key: 'last30days', | ||||||
|  |       title: PROFILER_FILTER_RANGE.last30days.title, | ||||||
|  |     }), | ||||||
|  |     [] | ||||||
|  |   ); | ||||||
|   const [testCaseListData, setTestCaseListData] = |   const [testCaseListData, setTestCaseListData] = | ||||||
|     useState<TestCaseIncidentStatusData>({ |     useState<TestCaseIncidentStatusData>({ | ||||||
|       data: [], |       data: [], | ||||||
|       isLoading: true, |       isLoading: true, | ||||||
|     }); |     }); | ||||||
|   const [filters, setFilters] = useState<TestCaseIncidentStatusParams>({ |   const [filters, setFilters] = useState<TestCaseIncidentStatusParams>({ | ||||||
|     startTs: getEpochMillisForPastDays(DEFAULT_SELECTED_RANGE.days), |     startTs: getEpochMillisForPastDays(PROFILER_FILTER_RANGE.last30days.days), | ||||||
|     endTs: getCurrentMillis(), |     endTs: getCurrentMillis(), | ||||||
|   }); |   }); | ||||||
|   const [users, setUsers] = useState<{ |   const [users, setUsers] = useState<{ | ||||||
| @ -506,6 +513,7 @@ const IncidentManagerPage = () => { | |||||||
|           </Space> |           </Space> | ||||||
|           <DatePickerMenu |           <DatePickerMenu | ||||||
|             showSelectedCustomRange |             showSelectedCustomRange | ||||||
|  |             defaultDateRange={defaultRange} | ||||||
|             handleDateRangeChange={handleDateRangeChange} |             handleDateRangeChange={handleDateRangeChange} | ||||||
|           /> |           /> | ||||||
|         </Col> |         </Col> | ||||||
|  | |||||||
| @ -135,12 +135,16 @@ describe('Tests for CommonUtils', () => { | |||||||
|         { value: 1000, result: '1K' }, |         { value: 1000, result: '1K' }, | ||||||
|         { value: 10000, result: '10K' }, |         { value: 10000, result: '10K' }, | ||||||
|         { value: 10200, result: '10.2K' }, |         { value: 10200, result: '10.2K' }, | ||||||
|  |         { value: 10230, result: '10.23K' }, | ||||||
|         { value: 1000000, result: '1M' }, |         { value: 1000000, result: '1M' }, | ||||||
|  |         { value: 1230000, result: '1.23M' }, | ||||||
|         { value: 100000000, result: '100M' }, |         { value: 100000000, result: '100M' }, | ||||||
|         { value: 1000000000, result: '1B' }, |         { value: 1000000000, result: '1B' }, | ||||||
|         { value: 1500000000, result: '1.5B' }, |         { value: 1500000000, result: '1.5B' }, | ||||||
|  |         { value: 1550000000, result: '1.55B' }, | ||||||
|         { value: 1000000000000, result: '1T' }, |         { value: 1000000000000, result: '1T' }, | ||||||
|         { value: 1100000000000, result: '1.1T' }, |         { value: 1100000000000, result: '1.1T' }, | ||||||
|  |         { value: 1110000000000, result: '1.11T' }, | ||||||
|       ]; |       ]; | ||||||
| 
 | 
 | ||||||
|       values.map(({ value, result }) => { |       values.map(({ value, result }) => { | ||||||
|  | |||||||
| @ -594,7 +594,7 @@ export const digitFormatter = (value: number) => { | |||||||
|   // convert 1000 to 1k
 |   // convert 1000 to 1k
 | ||||||
|   return Intl.NumberFormat('en', { |   return Intl.NumberFormat('en', { | ||||||
|     notation: 'compact', |     notation: 'compact', | ||||||
|     maximumFractionDigits: 1, |     maximumFractionDigits: 2, | ||||||
|   }).format(value); |   }).format(value); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -0,0 +1,170 @@ | |||||||
|  | /* | ||||||
|  |  *  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 { | ||||||
|  |   prepareChartData, | ||||||
|  |   PrepareChartDataType, | ||||||
|  | } from './TestSummaryGraphUtils'; | ||||||
|  | 
 | ||||||
|  | jest.mock('../../constants/profiler.constant', () => { | ||||||
|  |   return { | ||||||
|  |     COLORS: ['#7147E8', '#B02AAC', '#B02AAC', '#1890FF', '#008376'], | ||||||
|  |   }; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | describe('prepareChartData', () => { | ||||||
|  |   it('should prepare chart data correctly', () => { | ||||||
|  |     const testObj = { | ||||||
|  |       testCaseParameterValue: [ | ||||||
|  |         { | ||||||
|  |           name: 'minValueForMaxInCol', | ||||||
|  |           value: '1720165283528', | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           name: 'maxValueForMaxInCol', | ||||||
|  |           value: '1720275283528', | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |       testCaseResults: [ | ||||||
|  |         { | ||||||
|  |           timestamp: 1720525804736, | ||||||
|  |           testCaseStatus: 'Failed', | ||||||
|  |           result: | ||||||
|  |             'Found max=1720520076998 vs.  the expected min=1720165283528.0, max=1720275283528.0.', | ||||||
|  |           testResultValue: [ | ||||||
|  |             { | ||||||
|  |               name: 'max', | ||||||
|  |               value: '1720520076998', | ||||||
|  |             }, | ||||||
|  |           ], | ||||||
|  |           incidentId: '3093dbee-196b-4284-9f97-7103063d0dd7', | ||||||
|  |           maxBound: 1720275283528, | ||||||
|  |           minBound: 1720165283528, | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           timestamp: 1720525503943, | ||||||
|  |           testCaseStatus: 'Failed', | ||||||
|  |           result: | ||||||
|  |             'Found max=1720520076998 vs.  the expected min=1720165283528.0, max=1720275283528.0.', | ||||||
|  |           testResultValue: [ | ||||||
|  |             { | ||||||
|  |               name: 'max', | ||||||
|  |               value: '1720520076998', | ||||||
|  |             }, | ||||||
|  |           ], | ||||||
|  |           incidentId: '3093dbee-196b-4284-9f97-7103063d0dd7', | ||||||
|  |           maxBound: 1720275283528, | ||||||
|  |           minBound: 1720165283528, | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |       entityThread: [], | ||||||
|  |     } as PrepareChartDataType; | ||||||
|  | 
 | ||||||
|  |     const result = prepareChartData(testObj); | ||||||
|  | 
 | ||||||
|  |     expect(result).toEqual({ | ||||||
|  |       data: [ | ||||||
|  |         { | ||||||
|  |           boundArea: [1720165283528, 1720275283528], | ||||||
|  |           incidentId: '3093dbee-196b-4284-9f97-7103063d0dd7', | ||||||
|  |           max: 1720520076998, | ||||||
|  |           name: 1720525503943, | ||||||
|  |           status: 'Failed', | ||||||
|  |           task: undefined, | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           boundArea: [1720165283528, 1720275283528], | ||||||
|  |           incidentId: '3093dbee-196b-4284-9f97-7103063d0dd7', | ||||||
|  |           max: 1720520076998, | ||||||
|  |           name: 1720525804736, | ||||||
|  |           status: 'Failed', | ||||||
|  |           task: undefined, | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |       information: [ | ||||||
|  |         { | ||||||
|  |           color: '#7147E8', | ||||||
|  |           label: 'max', | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should handle empty testCaseParameterValue correctly', () => { | ||||||
|  |     const testObj = { | ||||||
|  |       testCaseParameterValue: [], | ||||||
|  |       testCaseResults: [ | ||||||
|  |         { | ||||||
|  |           timestamp: 1720525804736, | ||||||
|  |           testCaseStatus: 'Failed', | ||||||
|  |           result: | ||||||
|  |             'Found max=1720520076998 vs.  the expected min=1720165283528.0, max=1720275283528.0.', | ||||||
|  |           testResultValue: [ | ||||||
|  |             { | ||||||
|  |               name: 'max', | ||||||
|  |               value: '1720520076998', | ||||||
|  |             }, | ||||||
|  |           ], | ||||||
|  |           incidentId: '3093dbee-196b-4284-9f97-7103063d0dd7', | ||||||
|  |           maxBound: 1720275283528, | ||||||
|  |           minBound: 1720165283528, | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |       entityThread: [], | ||||||
|  |     } as PrepareChartDataType; | ||||||
|  | 
 | ||||||
|  |     const result = prepareChartData(testObj); | ||||||
|  | 
 | ||||||
|  |     expect(result).toEqual({ | ||||||
|  |       data: [ | ||||||
|  |         { | ||||||
|  |           boundArea: [1720165283528, 1720275283528], | ||||||
|  |           incidentId: '3093dbee-196b-4284-9f97-7103063d0dd7', | ||||||
|  |           max: 1720520076998, | ||||||
|  |           name: 1720525804736, | ||||||
|  |           status: 'Failed', | ||||||
|  |           task: undefined, | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |       information: [ | ||||||
|  |         { | ||||||
|  |           color: '#7147E8', | ||||||
|  |           label: 'max', | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   it('should handle empty testCaseResults correctly', () => { | ||||||
|  |     const testObj = { | ||||||
|  |       testCaseParameterValue: [ | ||||||
|  |         { | ||||||
|  |           name: 'minValueForMaxInCol', | ||||||
|  |           value: '1720165283528', | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           name: 'maxValueForMaxInCol', | ||||||
|  |           value: '1720275283528', | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |       testCaseResults: [], | ||||||
|  |       entityThread: [], | ||||||
|  |     } as PrepareChartDataType; | ||||||
|  | 
 | ||||||
|  |     const result = prepareChartData(testObj); | ||||||
|  | 
 | ||||||
|  |     expect(result).toEqual({ | ||||||
|  |       data: [], | ||||||
|  |       information: [], | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @ -0,0 +1,85 @@ | |||||||
|  | /* | ||||||
|  |  *  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 { isUndefined, omitBy, round } from 'lodash'; | ||||||
|  | import { TestCaseChartDataType } from '../../components/Database/Profiler/ProfilerDashboard/profilerDashboard.interface'; | ||||||
|  | import { COLORS } from '../../constants/profiler.constant'; | ||||||
|  | import { Thread } from '../../generated/entity/feed/thread'; | ||||||
|  | import { | ||||||
|  |   TestCaseParameterValue, | ||||||
|  |   TestCaseResult, | ||||||
|  | } from '../../generated/tests/testCase'; | ||||||
|  | 
 | ||||||
|  | export type PrepareChartDataType = { | ||||||
|  |   testCaseParameterValue: TestCaseParameterValue[]; | ||||||
|  |   testCaseResults: TestCaseResult[]; | ||||||
|  |   entityThread: Thread[]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export const prepareChartData = ({ | ||||||
|  |   testCaseParameterValue, | ||||||
|  |   testCaseResults, | ||||||
|  |   entityThread, | ||||||
|  | }: PrepareChartDataType) => { | ||||||
|  |   const params = | ||||||
|  |     testCaseParameterValue.length === 2 ? testCaseParameterValue : []; | ||||||
|  |   const dataPoints: TestCaseChartDataType['data'] = []; | ||||||
|  |   const yValues = params.reduce((acc, curr, i) => { | ||||||
|  |     return { ...acc, [`y${i + 1}`]: parseInt(curr.value ?? '') }; | ||||||
|  |   }, {}); | ||||||
|  |   testCaseResults.forEach((result) => { | ||||||
|  |     const values = result.testResultValue?.reduce((acc, curr) => { | ||||||
|  |       const value = round(parseFloat(curr.value ?? ''), 2) || 0; | ||||||
|  | 
 | ||||||
|  |       return { | ||||||
|  |         ...acc, | ||||||
|  |         [curr.name ?? 'value']: value, | ||||||
|  |       }; | ||||||
|  |     }, {}); | ||||||
|  |     const metric = { | ||||||
|  |       passedRows: result.passedRows, | ||||||
|  |       failedRows: result.failedRows, | ||||||
|  |       passedRowsPercentage: isUndefined(result.passedRowsPercentage) | ||||||
|  |         ? undefined | ||||||
|  |         : `${round(result.passedRowsPercentage, 2)}%`, | ||||||
|  |       failedRowsPercentage: isUndefined(result.failedRowsPercentage) | ||||||
|  |         ? undefined | ||||||
|  |         : `${round(result.failedRowsPercentage, 2)}%`, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     dataPoints.push({ | ||||||
|  |       name: result.timestamp, | ||||||
|  |       status: result.testCaseStatus, | ||||||
|  |       ...values, | ||||||
|  |       ...omitBy(metric, isUndefined), | ||||||
|  |       boundArea: [ | ||||||
|  |         result?.minBound ?? yValues.y1, | ||||||
|  |         result?.maxBound ?? yValues.y2, | ||||||
|  |       ], | ||||||
|  |       incidentId: result.incidentId, | ||||||
|  |       task: entityThread.find( | ||||||
|  |         (task) => task.task?.testCaseResolutionStatusId === result.incidentId | ||||||
|  |       ), | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   dataPoints.reverse(); | ||||||
|  | 
 | ||||||
|  |   return { | ||||||
|  |     information: | ||||||
|  |       testCaseResults[0]?.testResultValue?.map((info, i) => ({ | ||||||
|  |         label: info.name ?? '', | ||||||
|  |         color: COLORS[i], | ||||||
|  |       })) ?? [], | ||||||
|  |     data: dataPoints, | ||||||
|  |   }; | ||||||
|  | }; | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Shailesh Parmar
						Shailesh Parmar