mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-30 18:17:53 +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