chore: add unit tests

This commit is contained in:
Pranshu Chittora 2022-03-11 13:39:04 +05:30
parent 1bf8e6bef6
commit f0c627eebe
No known key found for this signature in database
GPG Key ID: 3A9E57A016CC0626
3 changed files with 134 additions and 28 deletions

View 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,
);
}
});
});
});

View File

@ -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>();

View File

@ -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,