mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-10 02:19:00 +08:00
chore: add unit tests
This commit is contained in:
parent
1bf8e6bef6
commit
f0c627eebe
75
frontend/src/components/Graph/__tests__/xAxisConfig.test.ts
Normal file
75
frontend/src/components/Graph/__tests__/xAxisConfig.test.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { expect } from '@jest/globals';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
import { convertTimeRange, TIME_UNITS } from '../xAxisConfig';
|
||||||
|
|
||||||
|
describe('xAxisConfig for Chart', () => {
|
||||||
|
describe('convertTimeRange', () => {
|
||||||
|
it('should return relevant time units for given range', () => {
|
||||||
|
{
|
||||||
|
const start = dayjs();
|
||||||
|
const end = start.add(10, 'millisecond');
|
||||||
|
|
||||||
|
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||||
|
TIME_UNITS.millisecond,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const start = dayjs();
|
||||||
|
const end = start.add(10, 'second');
|
||||||
|
|
||||||
|
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||||
|
TIME_UNITS.second,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const start = dayjs();
|
||||||
|
const end = start.add(10, 'minute');
|
||||||
|
|
||||||
|
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||||
|
TIME_UNITS.minute,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const start = dayjs();
|
||||||
|
const end = start.add(10, 'hour');
|
||||||
|
|
||||||
|
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||||
|
TIME_UNITS.hour,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const start = dayjs();
|
||||||
|
const end = start.add(10, 'day');
|
||||||
|
|
||||||
|
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||||
|
TIME_UNITS.day,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const start = dayjs();
|
||||||
|
const end = start.add(10, 'week');
|
||||||
|
|
||||||
|
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||||
|
TIME_UNITS.week,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const start = dayjs();
|
||||||
|
const end = start.add(10, 'month');
|
||||||
|
|
||||||
|
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||||
|
TIME_UNITS.month,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const start = dayjs();
|
||||||
|
const end = start.add(10, 'year');
|
||||||
|
|
||||||
|
expect(convertTimeRange(start.valueOf(), end.valueOf()).unitName).toEqual(
|
||||||
|
TIME_UNITS.year,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -27,7 +27,7 @@ import { useSelector } from 'react-redux';
|
|||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import AppReducer from 'types/reducer/app';
|
import AppReducer from 'types/reducer/app';
|
||||||
|
|
||||||
import { ITimeRange, useXAxisTimeUnit } from './xAxisConfig';
|
import { useXAxisTimeUnit } from './xAxisConfig';
|
||||||
Chart.register(
|
Chart.register(
|
||||||
LineElement,
|
LineElement,
|
||||||
PointElement,
|
PointElement,
|
||||||
@ -60,10 +60,7 @@ const Graph = ({
|
|||||||
const chartRef = useRef<HTMLCanvasElement>(null);
|
const chartRef = useRef<HTMLCanvasElement>(null);
|
||||||
const currentTheme = isDarkMode ? 'dark' : 'light';
|
const currentTheme = isDarkMode ? 'dark' : 'light';
|
||||||
|
|
||||||
/**
|
const xAxisTimeUnit = useXAxisTimeUnit(data); // Computes the relevant time unit for x axis by analyzing the time stamp data
|
||||||
* Computes the relevant time unit for x axis by analyzing the time stamp data
|
|
||||||
*/
|
|
||||||
const xAxisTimeUnit = useXAxisTimeUnit(data);
|
|
||||||
|
|
||||||
const lineChartRef = useRef<Chart>();
|
const lineChartRef = useRef<Chart>();
|
||||||
|
|
||||||
|
@ -4,7 +4,10 @@ import { useSelector } from 'react-redux';
|
|||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
interface IAxisTimeUint {
|
interface ITimeUnit {
|
||||||
|
[key: string]: TimeUnit;
|
||||||
|
}
|
||||||
|
interface IAxisTimeUintConfig {
|
||||||
unitName: TimeUnit;
|
unitName: TimeUnit;
|
||||||
multiplier: number;
|
multiplier: number;
|
||||||
}
|
}
|
||||||
@ -19,44 +22,59 @@ export interface ITimeRange {
|
|||||||
maxTime: number | null;
|
maxTime: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TIME_UNITS: IAxisTimeUint[] = [
|
export const TIME_UNITS: ITimeUnit = {
|
||||||
|
millisecond: 'millisecond',
|
||||||
|
second: 'second',
|
||||||
|
minute: 'minute',
|
||||||
|
hour: 'hour',
|
||||||
|
day: 'day',
|
||||||
|
week: 'week',
|
||||||
|
month: 'month',
|
||||||
|
year: 'year',
|
||||||
|
};
|
||||||
|
|
||||||
|
const TIME_UNITS_CONFIG: IAxisTimeUintConfig[] = [
|
||||||
{
|
{
|
||||||
unitName: 'millisecond',
|
unitName: TIME_UNITS.millisecond,
|
||||||
multiplier: 1,
|
multiplier: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
unitName: 'second',
|
unitName: TIME_UNITS.second,
|
||||||
multiplier: 1 / 1e3,
|
multiplier: 1 / 1e3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
unitName: 'minute',
|
unitName: TIME_UNITS.minute,
|
||||||
multiplier: 1 / (1e3 * 60),
|
multiplier: 1 / (1e3 * 60),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
unitName: 'hour',
|
unitName: TIME_UNITS.hour,
|
||||||
multiplier: 1 / (1e3 * 60 * 60),
|
multiplier: 1 / (1e3 * 60 * 60),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
unitName: 'day',
|
unitName: TIME_UNITS.day,
|
||||||
multiplier: 1 / (1e3 * 60 * 60 * 24),
|
multiplier: 1 / (1e3 * 60 * 60 * 24),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
unitName: 'week',
|
unitName: TIME_UNITS.week,
|
||||||
multiplier: 1 / (1e3 * 60 * 60 * 24 * 7),
|
multiplier: 1 / (1e3 * 60 * 60 * 24 * 7),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
unitName: 'month',
|
unitName: TIME_UNITS.month,
|
||||||
multiplier: 1 / (1e3 * 60 * 60 * 24 * 30),
|
multiplier: 1 / (1e3 * 60 * 60 * 24 * 30),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
unitName: 'year',
|
unitName: TIME_UNITS.year,
|
||||||
multiplier: 1 / (1e3 * 60 * 60 * 24 * 365),
|
multiplier: 1 / (1e3 * 60 * 60 * 24 * 365),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts Chart.js data's data-structure and returns the relevant time unit for the axis based on the range of the data.
|
||||||
|
*/
|
||||||
export const useXAxisTimeUnit = (data: Chart['data']): IAxisTimeConfig => {
|
export const useXAxisTimeUnit = (data: Chart['data']): IAxisTimeConfig => {
|
||||||
let localTime: ITimeRange;
|
// Local time is the time range inferred from the input chart data.
|
||||||
{
|
let localTime: ITimeRange | null;
|
||||||
|
try {
|
||||||
let minTime = Number.POSITIVE_INFINITY;
|
let minTime = Number.POSITIVE_INFINITY;
|
||||||
let maxTime = Number.NEGATIVE_INFINITY;
|
let maxTime = Number.NEGATIVE_INFINITY;
|
||||||
data?.labels?.forEach((timeStamp: any) => {
|
data?.labels?.forEach((timeStamp: any) => {
|
||||||
@ -69,11 +87,17 @@ export const useXAxisTimeUnit = (data: Chart['data']): IAxisTimeConfig => {
|
|||||||
minTime: minTime === Number.POSITIVE_INFINITY ? null : minTime,
|
minTime: minTime === Number.POSITIVE_INFINITY ? null : minTime,
|
||||||
maxTime: maxTime === Number.NEGATIVE_INFINITY ? null : maxTime,
|
maxTime: maxTime === Number.NEGATIVE_INFINITY ? null : maxTime,
|
||||||
};
|
};
|
||||||
|
} catch (error) {
|
||||||
|
localTime = null;
|
||||||
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Global time is the time selected from the global time selector menu.
|
||||||
const globalTime = useSelector<AppState, GlobalReducer>(
|
const globalTime = useSelector<AppState, GlobalReducer>(
|
||||||
(state) => state.globalTime,
|
(state) => state.globalTime,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Use local time if valid else use the global time range
|
||||||
const { maxTime, minTime } = useMemo(() => {
|
const { maxTime, minTime } = useMemo(() => {
|
||||||
if (localTime && localTime.maxTime && localTime.minTime) {
|
if (localTime && localTime.maxTime && localTime.minTime) {
|
||||||
return {
|
return {
|
||||||
@ -87,24 +111,34 @@ export const useXAxisTimeUnit = (data: Chart['data']): IAxisTimeConfig => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}, [globalTime, localTime]);
|
}, [globalTime, localTime]);
|
||||||
// debugger;
|
|
||||||
return convertTimeRange(minTime, maxTime);
|
return convertTimeRange(minTime, maxTime);
|
||||||
};
|
};
|
||||||
|
|
||||||
const convertTimeRange = (start: number, end: number): IAxisTimeConfig => {
|
/**
|
||||||
|
* Finds the relevant time unit based on the input time stamps (in ms)
|
||||||
|
*/
|
||||||
|
export const convertTimeRange = (
|
||||||
|
start: number,
|
||||||
|
end: number,
|
||||||
|
): IAxisTimeConfig => {
|
||||||
const MIN_INTERVALS = 6;
|
const MIN_INTERVALS = 6;
|
||||||
const range = end - start;
|
const range = end - start;
|
||||||
let relevantTimeUnit = TIME_UNITS[1];
|
let relevantTimeUnit = TIME_UNITS_CONFIG[1];
|
||||||
let stepSize = 1;
|
let stepSize = 1;
|
||||||
for (let idx = TIME_UNITS.length - 1; idx >= 0; idx--) {
|
try {
|
||||||
const timeUnit = TIME_UNITS[idx];
|
for (let idx = TIME_UNITS_CONFIG.length - 1; idx >= 0; idx--) {
|
||||||
const units = range * timeUnit.multiplier;
|
const timeUnit = TIME_UNITS_CONFIG[idx];
|
||||||
const steps = units / MIN_INTERVALS;
|
const units = range * timeUnit.multiplier;
|
||||||
if (steps >= 1) {
|
const steps = units / MIN_INTERVALS;
|
||||||
relevantTimeUnit = timeUnit;
|
if (steps >= 1) {
|
||||||
stepSize = steps;
|
relevantTimeUnit = timeUnit;
|
||||||
break;
|
stepSize = steps;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
unitName: relevantTimeUnit.unitName,
|
unitName: relevantTimeUnit.unitName,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user