@pinelab/vendure-plugin-metrics
Version:
Vendure plugin measuring and visualizing e-commerce metrics
287 lines (286 loc) • 14.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const metric_request_entity_1 = require("../entities/metric-request.entity");
const metric_util_1 = require("./metric-util");
(0, vitest_1.describe)('getMonthName()', () => {
(0, vitest_1.it)('returns correct month names for valid indices', () => {
(0, vitest_1.expect)((0, metric_util_1.getMonthName)(0)).toBe('Jan');
(0, vitest_1.expect)((0, metric_util_1.getMonthName)(6)).toBe('Jul');
(0, vitest_1.expect)((0, metric_util_1.getMonthName)(11)).toBe('Dec');
});
(0, vitest_1.it)('returns undefined for invalid indices', () => {
(0, vitest_1.expect)((0, metric_util_1.getMonthName)(12)).toBeUndefined();
(0, vitest_1.expect)((0, metric_util_1.getMonthName)(-1)).toBeUndefined();
});
});
(0, vitest_1.describe)('splitEntitiesInMonths()', () => {
// Test entities with different date fields
const testEntities = [
{
id: 1,
createdAt: new Date('2023-01-15T00:00:00Z'),
updatedAt: new Date('2023-01-20T00:00:00Z'),
orderPlacedAt: new Date('2023-01-25T00:00:00Z'),
},
{
id: 2,
createdAt: new Date('2023-02-10T00:00:00Z'),
updatedAt: new Date('2023-02-15T00:00:00Z'),
orderPlacedAt: new Date('2023-02-20T00:00:00Z'),
},
{
id: 3,
createdAt: new Date('2023-02-25T00:00:00Z'),
updatedAt: new Date('2023-03-05T00:00:00Z'),
orderPlacedAt: new Date('2023-03-10T00:00:00Z'),
},
{
id: 4,
createdAt: new Date('2023-04-03T00:00:00Z'),
updatedAt: new Date('2023-04-02T00:00:00Z'),
orderPlacedAt: new Date('2023-04-03T00:00:00Z'),
},
];
(0, vitest_1.it)('splits entities by createdAt correctly', () => {
const from = new Date('2023-01-04T00:00:00Z');
const to = new Date('2023-03-04T00:00:00Z');
const result = (0, metric_util_1.groupEntitiesPerMonth)(testEntities, 'createdAt', from, to);
// Should have 3 months (Jan, Feb, Mar)
(0, vitest_1.expect)(result.length).toBe(3);
// January should have 1 entity
(0, vitest_1.expect)(result.find((m) => m.monthNr === 0)?.entities.length).toBe(1);
// February should have 2 entities
(0, vitest_1.expect)(result.find((m) => m.monthNr === 1)?.entities.length).toBe(2);
});
(0, vitest_1.it)('splits entities by orderPlacedAt correctly', () => {
const from = new Date('2023-01-02T00:00:00Z');
const to = new Date('2023-05-03T00:00:00Z');
const result = (0, metric_util_1.groupEntitiesPerMonth)(testEntities, 'orderPlacedAt', from, to);
// Should have 4 months (Jan, Feb, Mar, Apr, May)
(0, vitest_1.expect)(result.length).toBe(5);
// Check entity count per month
(0, vitest_1.expect)(result.find((m) => m.monthNr === 0 && m.year === 2023)?.entities.length).toBe(1);
(0, vitest_1.expect)(result.find((m) => m.monthNr === 1 && m.year === 2023)?.entities.length).toBe(1);
(0, vitest_1.expect)(result.find((m) => m.monthNr === 2 && m.year === 2023)?.entities.length).toBe(1);
(0, vitest_1.expect)(result.find((m) => m.monthNr === 3 && m.year === 2023)?.entities.length).toBe(1);
(0, vitest_1.expect)(result.find((m) => m.monthNr === 4 && m.year === 2023)?.entities.length).toBe(0);
});
(0, vitest_1.it)('includes empty months in the range', () => {
const from = new Date('2022-11-03T00:00:00Z');
const to = new Date('2023-02-03T00:00:00Z');
const result = (0, metric_util_1.groupEntitiesPerMonth)(testEntities, 'createdAt', from, to);
// Should have months (Nov, Dec, Jan, Feb)
(0, vitest_1.expect)(result.length).toBe(4);
// November and December should be empty
(0, vitest_1.expect)(result.find((m) => m.monthNr === 10 && m.year === 2022)?.entities.length).toBe(0);
(0, vitest_1.expect)(result.find((m) => m.monthNr === 11 && m.year === 2022)?.entities.length).toBe(0);
// January should have 1 entity
(0, vitest_1.expect)(result.find((m) => m.monthNr === 0 && m.year === 2023)?.entities.length).toBe(1);
// February should have 1 entity
(0, vitest_1.expect)(result.find((m) => m.monthNr === 1 && m.year === 2023)?.entities.length).toBe(2);
});
(0, vitest_1.it)('throws error for entities with invalid dates', () => {
const invalidEntities = [{ id: 1, createdAt: new Date('invalid date') }];
const from = new Date('2023-01-03T00:00:00Z');
const to = new Date('2023-02-03T00:00:00Z');
(0, vitest_1.expect)(() => {
(0, metric_util_1.groupEntitiesPerMonth)(invalidEntities, 'createdAt', from, to);
}).toThrow();
});
(0, vitest_1.it)('handles empty entity array', () => {
const from = new Date('2023-01-03T00:00:00Z');
const to = new Date('2023-03-03T00:00:00Z');
const result = (0, metric_util_1.groupEntitiesPerMonth)([], 'createdAt', from, to);
// Should still have 2 months, just with empty entity arrays
(0, vitest_1.expect)(result.length).toBe(3);
(0, vitest_1.expect)(result[0].entities.length).toBe(0);
(0, vitest_1.expect)(result[1].entities.length).toBe(0);
(0, vitest_1.expect)(result[2].entities.length).toBe(0);
});
});
(0, vitest_1.describe)('mapToSeries()', () => {
(0, vitest_1.it)('transforms empty map to empty array', () => {
const dataPointsMap = new Map();
const result = (0, metric_util_1.mapToSeries)(dataPointsMap);
(0, vitest_1.expect)(result).toEqual([]);
});
(0, vitest_1.it)('transforms single series correctly', () => {
const dataPointsMap = new Map();
dataPointsMap.set('Series A', [10, 20, 30]);
const result = (0, metric_util_1.mapToSeries)(dataPointsMap);
(0, vitest_1.expect)(result).toEqual([{ name: 'Series A', values: [10, 20, 30] }]);
});
(0, vitest_1.it)('transforms multiple series correctly', () => {
const dataPointsMap = new Map();
dataPointsMap.set('Series A', [10, 20, 30]);
dataPointsMap.set('Series B', [5, 15, 25]);
dataPointsMap.set('Series C', [1, 2, 3]);
const result = (0, metric_util_1.mapToSeries)(dataPointsMap);
// Check length
(0, vitest_1.expect)(result.length).toBe(3);
// Check contents (order might vary)
(0, vitest_1.expect)(result).toContainEqual({ name: 'Series A', values: [10, 20, 30] });
(0, vitest_1.expect)(result).toContainEqual({ name: 'Series B', values: [5, 15, 25] });
(0, vitest_1.expect)(result).toContainEqual({ name: 'Series C', values: [1, 2, 3] });
});
(0, vitest_1.it)('preserves empty values arrays', () => {
const dataPointsMap = new Map();
dataPointsMap.set('Empty Series', []);
const result = (0, metric_util_1.mapToSeries)(dataPointsMap);
(0, vitest_1.expect)(result).toEqual([{ name: 'Empty Series', values: [] }]);
});
});
(0, vitest_1.describe)('getSessions()', () => {
// Helper function to create a MetricRequest with the given properties
function createRequest(identifier, timestamp, deviceType = 'Desktop') {
const request = new metric_request_entity_1.MetricRequest();
request.identifier = identifier;
request.createdAt = timestamp;
request.deviceType = deviceType;
return request;
}
(0, vitest_1.it)('returns empty array for empty input', () => {
const sessions = (0, metric_util_1.getSessions)([], 30);
(0, vitest_1.expect)(sessions).toEqual([]);
});
(0, vitest_1.it)('creates a single session for a single request', () => {
const timestamp = new Date('2023-01-03T12:00:00Z');
const request = createRequest('user1', timestamp);
const sessions = (0, metric_util_1.getSessions)([request], 30);
(0, vitest_1.expect)(sessions).toHaveLength(1);
(0, vitest_1.expect)(sessions[0]).toEqual({
identifier: 'user1',
start: timestamp,
end: timestamp,
deviceType: 'Desktop',
});
});
(0, vitest_1.it)('combines requests within session window into one session', () => {
const startTime = new Date('2023-01-03T12:00:00Z');
const fiveMinLater = new Date(startTime.getTime() + 5 * 60 * 1000);
const tenMinLater = new Date(startTime.getTime() + 10 * 60 * 1000);
const requests = [
createRequest('user1', startTime),
createRequest('user1', fiveMinLater),
createRequest('user1', tenMinLater),
];
const sessions = (0, metric_util_1.getSessions)(requests, 30);
(0, vitest_1.expect)(sessions).toHaveLength(1);
(0, vitest_1.expect)(sessions[0]).toEqual({
identifier: 'user1',
start: startTime,
end: tenMinLater,
deviceType: 'Desktop',
});
});
(0, vitest_1.it)('creates separate sessions for requests outside session window', () => {
const startTime = new Date('2023-01-03T12:00:00Z');
const fiveMinLater = new Date(startTime.getTime() + 5 * 60 * 1000);
const tenMinLater = new Date(startTime.getTime() + 10 * 60 * 1000);
const requests = [
createRequest('user1', startTime),
createRequest('user1', fiveMinLater),
createRequest('user1', tenMinLater),
];
const sessions = (0, metric_util_1.getSessions)(requests, 6);
(0, vitest_1.expect)(sessions).toHaveLength(2);
(0, vitest_1.expect)(sessions[0]).toEqual({
identifier: 'user1',
start: startTime,
end: fiveMinLater,
deviceType: 'Desktop',
});
(0, vitest_1.expect)(sessions[1]).toEqual({
identifier: 'user1',
start: tenMinLater,
end: tenMinLater,
deviceType: 'Desktop',
});
});
(0, vitest_1.it)('handles requests from different identifiers as separate sessions', () => {
const baseTime = new Date('2023-01-03T12:00:00Z');
const requests = [
createRequest('user1', baseTime),
createRequest('user2', baseTime),
createRequest('user1', new Date(baseTime.getTime() + 5 * 60 * 1000)),
createRequest('user2', new Date(baseTime.getTime() + 5 * 60 * 1000)),
];
const sessions = (0, metric_util_1.getSessions)(requests, 30);
(0, vitest_1.expect)(sessions).toHaveLength(2);
const user1Session = sessions.find((s) => s.identifier === 'user1');
const user2Session = sessions.find((s) => s.identifier === 'user2');
(0, vitest_1.expect)(user1Session?.start).toEqual(baseTime);
(0, vitest_1.expect)(user1Session?.end).toEqual(new Date(baseTime.getTime() + 5 * 60 * 1000));
(0, vitest_1.expect)(user2Session?.start).toEqual(baseTime);
(0, vitest_1.expect)(user2Session?.end).toEqual(new Date(baseTime.getTime() + 5 * 60 * 1000));
});
(0, vitest_1.it)('counts each request as separate session if session length is 0', () => {
const now = new Date('2023-01-03T12:00:00Z');
const requests = [
createRequest('user1', now),
createRequest('user1', now),
createRequest('user1', now),
];
const sessions = (0, metric_util_1.getSessions)(requests, 0);
(0, vitest_1.expect)(sessions).toHaveLength(3);
(0, vitest_1.expect)(sessions[0]).toEqual({
identifier: 'user1',
start: now,
end: now,
deviceType: 'Desktop',
});
(0, vitest_1.expect)(sessions[1]).toEqual({
identifier: 'user1',
start: now,
end: now,
deviceType: 'Desktop',
});
});
(0, vitest_1.it)('preserves device type information', () => {
const baseTime = new Date('2023-01-03T12:00:00Z');
const requests = [
createRequest('user1', baseTime, 'Desktop'),
createRequest('user2', baseTime, 'Mobile'),
createRequest('user3', baseTime, 'Tablet'),
];
const sessions = (0, metric_util_1.getSessions)(requests, 30);
(0, vitest_1.expect)(sessions).toHaveLength(3);
(0, vitest_1.expect)(sessions.find((s) => s.identifier === 'user1')?.deviceType).toBe('Desktop');
(0, vitest_1.expect)(sessions.find((s) => s.identifier === 'user2')?.deviceType).toBe('Mobile');
(0, vitest_1.expect)(sessions.find((s) => s.identifier === 'user3')?.deviceType).toBe('Tablet');
});
});
(0, vitest_1.describe)('getEntitiesForMonth()', () => {
// Test entities with different date fields
const testEntities = [
{
id: 1,
createdAt: new Date('2023-01-15T00:00:00Z'),
},
{
id: 2,
createdAt: new Date('2023-02-10T00:00:00Z'),
},
{
id: 3,
createdAt: new Date('2024-01-25T00:00:00Z'), // Correct month, wrong year
},
];
(0, vitest_1.it)('returns entities for the specified month and year', () => {
const date = new Date('2023-01-15T00:00:00Z');
const result = (0, metric_util_1.getEntitiesForMonth)(testEntities, date, 'createdAt');
(0, vitest_1.expect)(result).toHaveLength(1);
(0, vitest_1.expect)(result[0].id).toBe(1);
});
(0, vitest_1.it)('returns empty array when no entities match the month and year', () => {
const date = new Date('2023-03-15T00:00:00Z');
const result = (0, metric_util_1.getEntitiesForMonth)(testEntities, date, 'createdAt');
(0, vitest_1.expect)(result).toHaveLength(0);
});
(0, vitest_1.it)('handles empty entity array', () => {
const date = new Date('2023-01-15T00:00:00Z');
const result = (0, metric_util_1.getEntitiesForMonth)([], date, 'createdAt');
(0, vitest_1.expect)(result).toHaveLength(0);
});
});