1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-10-13 11:17:26 +02:00
unleash.unleash/frontend/src/utils/traffic-calculations.test.ts
Gastón Fournier abe160eb7d
feat: Unleash v7 ESM migration (#9877)
We're migrating to ESM, which will allow us to import the latest
versions of our dependencies.

Co-Authored-By: Christopher Kolstad <chriswk@getunleash.io>
2025-05-14 09:47:12 +02:00

333 lines
11 KiB
TypeScript

import { format, getDaysInMonth } from 'date-fns';
import {
calculateEstimatedMonthlyCost,
calculateOverageCost,
calculateProjectedUsage,
calculateTotalUsage,
cleanTrafficData,
} from './traffic-calculations.js';
import { toSelectablePeriod } from '../component/admin/network/NetworkTrafficUsage/selectable-periods.js';
import type {
TrafficUsageDataSegmentedCombinedSchema,
TrafficUsageDataSegmentedCombinedSchemaApiDataItem,
} from 'openapi';
const testData4Days = [
{
label: 'Frontend',
data: [23_000_000, 22_000_000, 24_000_000, 21_000_000],
backgroundColor: 'red',
hoverBackgroundColor: 'red',
},
{
label: 'Admin',
data: [23_000_000, 22_000_000, 24_000_000, 21_000_000],
backgroundColor: 'red',
hoverBackgroundColor: 'red',
},
{
label: 'SDK',
data: [23_000_000, 22_000_000, 24_000_000, 21_000_000],
backgroundColor: 'red',
hoverBackgroundColor: 'red',
},
];
const dataPoint = (month: Date) => (day: number, count: number) => {
const monthPrefix = format(month, 'yyyy-MM');
return {
period: `${monthPrefix}-${day.toString().padStart(2, '0')}`,
trafficTypes: [{ count, group: 'successful-requests' }],
};
};
const trafficData4Days = (
month: Date,
): TrafficUsageDataSegmentedCombinedSchemaApiDataItem[] => {
const point = dataPoint(month);
const dataPoints = [
point(1, 23_000_000),
point(2, 22_000_000),
point(3, 24_000_000),
point(4, 21_000_000),
];
return [
{ apiPath: '/api/frontend', dataPoints },
{ apiPath: '/api/admin', dataPoints },
{ apiPath: '/api/client', dataPoints },
];
};
describe('traffic overage calculation', () => {
it('should return 0 if there is no overage this month', () => {
const dataUsage = 52_900_000;
const includedTraffic = 53_000_000;
const result = calculateOverageCost(dataUsage, includedTraffic);
expect(result).toBe(0);
});
it('should return 0 if overage this month is atleast 1 request above included', () => {
const dataUsage = 53_000_001;
const includedTraffic = 53_000_000;
const result = calculateOverageCost(dataUsage, includedTraffic);
expect(result).toBe(0);
});
it('should return 5 if overage this month is atleast 1M request above included', () => {
const dataUsage = 54_000_000;
const includedTraffic = 53_000_000;
const result = calculateOverageCost(dataUsage, includedTraffic);
expect(result).toBe(5);
});
it('should return 10 if overage this month is > 2M request above included', () => {
const dataUsage = 55_100_000;
const includedTraffic = 53_000_000;
const result = calculateOverageCost(dataUsage, includedTraffic);
expect(result).toBe(10);
});
it('doesnt estimate when having less than 5 days worth of data', () => {
const now = new Date();
const period = toSelectablePeriod(now);
const testNow = new Date(now.getFullYear(), now.getMonth(), 4);
const includedTraffic = 53_000_000;
const rawData = trafficData4Days(now);
const result = calculateEstimatedMonthlyCost(
rawData,
includedTraffic,
testNow,
);
expect(result).toBe(0);
});
it('needs 5 days or more to estimate for the month', () => {
const testData = testData4Days;
testData[0].data.push(23_000_000);
testData[1].data.push(23_000_000);
testData[2].data.push(23_000_000);
const now = new Date();
const testNow = new Date(now.getFullYear(), now.getMonth(), 5);
const includedTraffic = 53_000_000;
const rawData = trafficData4Days(now);
rawData[0].dataPoints.push(dataPoint(now)(5, 23_000_000));
rawData[1].dataPoints.push(dataPoint(now)(5, 23_000_000));
rawData[2].dataPoints.push(dataPoint(now)(5, 23_000_000));
const result = calculateEstimatedMonthlyCost(
rawData,
includedTraffic,
testNow,
);
expect(result).toBeGreaterThan(1430);
});
it('estimates projected data usage', () => {
const testData = testData4Days;
testData[0].data.push(22_500_000);
testData[1].data.push(22_500_000);
testData[2].data.push(22_500_000);
// Testing April 5th of 2024 (30 days)
const now = new Date(2024, 3, 5);
const period = toSelectablePeriod(now);
const rawData = trafficData4Days(now);
rawData[0].dataPoints.push(dataPoint(now)(5, 22_500_000));
rawData[1].dataPoints.push(dataPoint(now)(5, 22_500_000));
rawData[2].dataPoints.push(dataPoint(now)(5, 22_500_000));
const result = calculateProjectedUsage({
dayOfMonth: now.getDate(),
daysInMonth: period.dayCount,
trafficData: rawData,
});
// 22_500_000 * 3 * 30 = 2_025_000_000
expect(result).toBe(2_025_000_000);
});
it('supports custom price and unit size', () => {
const dataUsage = 54_000_000;
const includedTraffic = 53_000_000;
const result = calculateOverageCost(
dataUsage,
includedTraffic,
10,
500_000,
);
expect(result).toBe(20);
});
it('estimates based on custom price and unit size', () => {
const testData = testData4Days;
testData[0].data.push(22_500_000);
testData[1].data.push(22_500_000);
testData[2].data.push(22_500_000);
const now = new Date();
const period = toSelectablePeriod(now);
const testNow = new Date(now.getFullYear(), now.getMonth(), 5);
const includedTraffic = 53_000_000;
const trafficUnitSize = 500_000;
const trafficUnitCost = 10;
const rawData = trafficData4Days(now);
rawData[0].dataPoints.push(dataPoint(now)(5, 22_500_000));
rawData[1].dataPoints.push(dataPoint(now)(5, 22_500_000));
rawData[2].dataPoints.push(dataPoint(now)(5, 22_500_000));
const result = calculateEstimatedMonthlyCost(
rawData,
includedTraffic,
testNow,
trafficUnitCost,
trafficUnitSize,
);
const totalExpectedUsage = 22_500_000 * 3 * getDaysInMonth(now);
const overage = totalExpectedUsage - includedTraffic;
const overageUnits = Math.floor(overage / trafficUnitSize);
const total = overageUnits * trafficUnitCost;
expect(result).toBe(total);
});
});
describe('filtering out unwanted data', () => {
it('removes the /edge endpoint data', () => {
const input: TrafficUsageDataSegmentedCombinedSchema = {
grouping: 'daily',
dateRange: { from: '2025-02-01', to: '2025-02-28' },
apiData: [
{ apiPath: '/api/client', dataPoints: [] },
{ apiPath: '/edge', dataPoints: [] },
{ apiPath: '/api/admin', dataPoints: [] },
{ apiPath: '/api/frontend', dataPoints: [] },
],
};
const expected = {
grouping: 'daily',
dateRange: { from: '2025-02-01', to: '2025-02-28' },
apiData: [
{ apiPath: '/api/client', dataPoints: [] },
{ apiPath: '/api/admin', dataPoints: [] },
{ apiPath: '/api/frontend', dataPoints: [] },
],
};
expect(cleanTrafficData(input)).toStrictEqual(expected);
});
it('removes any data from before the traffic measuring was put in place', () => {
const input: TrafficUsageDataSegmentedCombinedSchema = {
grouping: 'monthly',
dateRange: {
from: '2024-02-01',
to: '2025-06-31',
},
apiData: [
{
apiPath: '/api/client',
dataPoints: [
{ period: '2024-06', trafficTypes: [] },
{ period: '2024-05', trafficTypes: [] },
{ period: '2024-04', trafficTypes: [] },
{ period: '2024-03', trafficTypes: [] },
{ period: '2024-02', trafficTypes: [] },
],
},
],
};
const expected = {
grouping: 'monthly',
dateRange: {
from: '2024-02-01',
to: '2025-06-31',
},
apiData: [
{
apiPath: '/api/client',
dataPoints: [
{ period: '2024-06', trafficTypes: [] },
{ period: '2024-05', trafficTypes: [] },
],
},
],
};
expect(cleanTrafficData(input)).toStrictEqual(expected);
});
});
describe('calculateTotalUsage', () => {
const dataPoint = (period: string, count: number) => ({
period,
trafficTypes: [{ count, group: 'successful-requests' }],
});
it('calculates total from daily data', () => {
const input: TrafficUsageDataSegmentedCombinedSchema = {
grouping: 'daily',
dateRange: { from: '2025-02-01', to: '2025-02-28' },
apiData: [
{
apiPath: '/api/client',
dataPoints: [
dataPoint('2024-02-01', 1),
dataPoint('2024-02-15', 2),
dataPoint('2024-02-07', 3),
],
},
{
apiPath: '/api/admin',
dataPoints: [
dataPoint('2024-02-01', 4),
dataPoint('2024-02-15', 5),
dataPoint('2024-02-07', 6),
],
},
{
apiPath: '/api/frontend',
dataPoints: [
dataPoint('2024-02-01', 7),
dataPoint('2024-02-15', 8),
dataPoint('2024-02-07', 9),
],
},
],
};
expect(calculateTotalUsage(input)).toBe(45);
});
it('calculates total for the most recent month in monthly data', () => {
const input: TrafficUsageDataSegmentedCombinedSchema = {
grouping: 'monthly',
dateRange: { from: '2024-10-01', to: '2025-01-31' },
apiData: [
{
apiPath: '/api/client',
dataPoints: [
dataPoint('2025-01', 1),
dataPoint('2024-12', 2),
dataPoint('2024-10', 3),
],
},
{
apiPath: '/api/admin',
dataPoints: [
dataPoint('2025-01', 4),
dataPoint('2024-11', 5),
dataPoint('2024-10', 6),
],
},
{
apiPath: '/api/frontend',
dataPoints: [
dataPoint('2024-11', 7),
dataPoint('2024-12', 8),
dataPoint('2024-10', 9),
],
},
],
};
expect(calculateTotalUsage(input)).toBe(5);
});
});