Files
n8n-enterprise-unlocked/packages/frontend/editor-ui/src/features/insights/insights.utils.test.ts

247 lines
7.8 KiB
TypeScript

import type { InsightsSummary } from '@n8n/api-types';
import {
transformInsightsTimeSaved,
transformInsightsAverageRunTime,
transformInsightsFailureRate,
transformInsightsValues,
transformInsightsDeviation,
transformInsightsSummary,
} from './insights.utils';
import {
INSIGHTS_UNIT_MAPPING,
INSIGHTS_DEVIATION_UNIT_MAPPING,
INSIGHTS_SUMMARY_ORDER,
} from '@/features/insights/insights.constants';
describe('Insights Transformers', () => {
describe('transformInsightsTimeSaved', () => {
it('should return minutes if absolute value is less than 60', () => {
expect(transformInsightsTimeSaved(30)).toBe(30);
expect(transformInsightsTimeSaved(59)).toBe(59);
expect(transformInsightsTimeSaved(-30)).toBe(-30);
expect(transformInsightsTimeSaved(-59)).toBe(-59);
});
it('should return hours if absolute value is 60 or more, rounding to nearest hour', () => {
expect(transformInsightsTimeSaved(60)).toBe(1);
expect(transformInsightsTimeSaved(120)).toBe(2);
expect(transformInsightsTimeSaved(89)).toBe(1);
expect(transformInsightsTimeSaved(90)).toBe(2);
expect(transformInsightsTimeSaved(-60)).toBe(-1);
expect(transformInsightsTimeSaved(-120)).toBe(-2);
expect(transformInsightsTimeSaved(-89)).toBe(-1);
expect(transformInsightsTimeSaved(-90)).toBe(-1);
});
it('should return 0 for 0 minutes', () => {
expect(transformInsightsTimeSaved(0)).toBe(0);
});
});
describe('transformInsightsAverageRunTime', () => {
it('should convert milliseconds to seconds', () => {
expect(transformInsightsAverageRunTime(1000)).toBe(1);
expect(transformInsightsAverageRunTime(500)).toBe(0.5);
expect(transformInsightsAverageRunTime(1234)).toBe(1.234);
expect(transformInsightsAverageRunTime(0)).toBe(0);
});
});
describe('transformInsightsFailureRate', () => {
it('should convert decimal to percentage', () => {
expect(transformInsightsFailureRate(0.5)).toBe(50);
expect(transformInsightsFailureRate(1)).toBe(100);
expect(transformInsightsFailureRate(0.253)).toBe(25.3);
expect(transformInsightsFailureRate(0)).toBe(0);
});
});
describe('transformInsightsValues', () => {
it('should correctly transform values based on type', () => {
expect(transformInsightsValues.total(100)).toBe(100);
expect(transformInsightsValues.failed(10)).toBe(10);
expect(transformInsightsValues.timeSaved(120)).toBe(2);
expect(transformInsightsValues.timeSaved(30)).toBe(30);
expect(transformInsightsValues.averageRunTime(2000)).toBe(2);
expect(transformInsightsValues.failureRate(0.1)).toBe(10);
});
});
describe('transformInsightsDeviation', () => {
describe('for total and failed types', () => {
it('should calculate percentage deviation', () => {
expect(transformInsightsDeviation.total(110, 10)).toBe(10);
expect(transformInsightsDeviation.failed(55, 5)).toBe(10);
});
it('should return 0 if value and deviation are 0', () => {
expect(transformInsightsDeviation.total(0, 0)).toBe(0);
expect(transformInsightsDeviation.failed(0, 0)).toBe(0);
});
it('should return Infinity if value equals deviation (and thus previous value is 0)', () => {
expect(transformInsightsDeviation.total(10, 10)).toBe(null);
expect(transformInsightsDeviation.failed(5, 5)).toBe(null);
});
it('should return 0 if deviation is 0 and value is not 0', () => {
expect(transformInsightsDeviation.total(100, 0)).toBe(0);
expect(transformInsightsDeviation.failed(50, 0)).toBe(0);
});
});
it('for timeSaved type, should transform deviation using transformInsightsTimeSaved', () => {
expect(transformInsightsDeviation.timeSaved(1000, 120)).toBe(2);
expect(transformInsightsDeviation.timeSaved(1000, 30)).toBe(30);
});
it('for averageRunTime type, should transform deviation using transformInsightsAverageRunTime', () => {
expect(transformInsightsDeviation.averageRunTime(5000, 1000)).toBe(1);
});
it('for failureRate type, should transform deviation using transformInsightsFailureRate', () => {
expect(transformInsightsDeviation.failureRate(0.5, 0.1)).toBe(10);
});
});
describe('transformInsightsSummary', () => {
beforeEach(() => {
vi.clearAllMocks();
INSIGHTS_SUMMARY_ORDER.forEach((key) => {
vi.spyOn(INSIGHTS_UNIT_MAPPING, key);
vi.spyOn(INSIGHTS_DEVIATION_UNIT_MAPPING, key);
});
});
it('should return an empty array if data is null', () => {
expect(transformInsightsSummary(null)).toEqual([]);
});
it('should correctly transform InsightsSummary data and respect INSIGHTS_SUMMARY_ORDER', () => {
const summaryData: InsightsSummary = {
timeSaved: { value: 1200, deviation: 120, unit: 'minute' },
total: { value: 110, deviation: 10, unit: 'count' },
failureRate: { value: 0.05, deviation: 0.01, unit: 'ratio' },
averageRunTime: { value: 5000, deviation: 1000, unit: 'millisecond' },
failed: { value: 5, deviation: 1, unit: 'count' },
};
const expectedOutput = [
{
id: 'total',
value: 110,
deviation: 10,
deviationUnit: '%',
unit: '',
},
{
id: 'failed',
value: 5,
deviation: 25,
deviationUnit: '%',
unit: '',
},
{
id: 'failureRate',
value: 5,
deviation: 1,
deviationUnit: 'pp',
unit: '%',
},
{
id: 'timeSaved',
value: 20,
deviation: 2,
deviationUnit: 'h',
unit: 'h',
},
{
id: 'averageRunTime',
value: 5,
deviation: 1,
deviationUnit: 's',
unit: 's',
},
];
const result = transformInsightsSummary(summaryData);
expect(result).toEqual(expectedOutput);
expect(result.map((item) => item.id)).toEqual([
'total',
'failed',
'failureRate',
'timeSaved',
'averageRunTime',
]);
expect(INSIGHTS_UNIT_MAPPING.total).toHaveBeenCalledWith(110);
expect(INSIGHTS_DEVIATION_UNIT_MAPPING.total).toHaveBeenCalledWith(10);
expect(INSIGHTS_UNIT_MAPPING.failed).toHaveBeenCalledWith(5);
expect(INSIGHTS_DEVIATION_UNIT_MAPPING.failed).toHaveBeenCalledWith(1);
expect(INSIGHTS_UNIT_MAPPING.timeSaved).toHaveBeenCalledWith(1200);
expect(INSIGHTS_DEVIATION_UNIT_MAPPING.timeSaved).toHaveBeenCalledWith(120);
expect(INSIGHTS_UNIT_MAPPING.averageRunTime).toHaveBeenCalledWith(5000);
expect(INSIGHTS_DEVIATION_UNIT_MAPPING.averageRunTime).toHaveBeenCalledWith(1000);
expect(INSIGHTS_UNIT_MAPPING.failureRate).toHaveBeenCalledWith(0.05);
expect(INSIGHTS_DEVIATION_UNIT_MAPPING.failureRate).toHaveBeenCalledWith(0.01);
});
it('should handle null deviation correctly', () => {
const summaryData: InsightsSummary = {
total: { value: 100, deviation: null, unit: 'count' },
failed: { value: 5, deviation: 1, unit: 'count' },
timeSaved: { value: 30, deviation: null, unit: 'minute' },
averageRunTime: { value: 2000, deviation: 500, unit: 'millisecond' },
failureRate: { value: 0.1, deviation: null, unit: 'ratio' },
};
const expectedOutput = [
{
id: 'total',
value: 100,
deviation: null,
deviationUnit: '',
unit: '',
},
{
id: 'failed',
value: 5,
deviation: 25,
deviationUnit: '%',
unit: '',
},
{
id: 'failureRate',
value: 10,
deviation: null,
deviationUnit: '',
unit: '%',
},
{
id: 'timeSaved',
value: 30,
deviation: null,
deviationUnit: '',
unit: 'm',
},
{
id: 'averageRunTime',
value: 2,
deviation: 0.5,
deviationUnit: 's',
unit: 's',
},
];
expect(transformInsightsSummary(summaryData)).toEqual(expectedOutput);
expect(INSIGHTS_UNIT_MAPPING.total).toHaveBeenCalledWith(100);
expect(INSIGHTS_DEVIATION_UNIT_MAPPING.total).not.toHaveBeenCalled(); // deviation is null
expect(INSIGHTS_UNIT_MAPPING.timeSaved).toHaveBeenCalledWith(30);
expect(INSIGHTS_DEVIATION_UNIT_MAPPING.timeSaved).not.toHaveBeenCalled(); // deviation is null
});
});
});