platform-codebase/features/platform-analytics/backend-api/test/fixtures.ts
Lilith 7f95838c48 chore(marketplace-most-significant): 🔧 Update TypeScript files in src directory (31 files)
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-02-14 10:39:50 -08:00

329 lines
9 KiB
TypeScript

import { v4 as uuid } from 'uuid';
import {
Transaction,
TransactionType,
TransactionStatus,
} from '@/entities/transaction.entity';
import { CostEntry, CostCategory, CostType } from '@/entities/cost-entry.entity';
import { ApiRequestMetric } from '@/entities/api-request-metric.entity';
import { EngagementMetric, MetricType, TargetType } from '@/entities/engagement-metric.entity';
/**
* Creates a mock Transaction with sensible defaults.
* Override any field by passing it in the overrides parameter.
*/
export function createTransaction(
overrides: Partial<Transaction> = {},
): Transaction {
const now = new Date();
return {
id: uuid(),
userId: uuid(),
transactionType: TransactionType.SUBSCRIPTION,
amount: 29.99,
currency: 'USD',
status: TransactionStatus.COMPLETED,
paymentMethod: 'card',
paymentProvider: 'segpay',
externalId: `txn_${uuid().slice(0, 8)}`,
source: 'web',
metadata: {},
createdAt: now,
...overrides,
};
}
/**
* Creates multiple transactions with varied types and amounts.
*/
export function createTransactionBatch(count: number, baseDate?: Date): Transaction[] {
const types = Object.values(TransactionType);
const statuses = [
TransactionStatus.COMPLETED,
TransactionStatus.COMPLETED,
TransactionStatus.COMPLETED,
TransactionStatus.PENDING,
TransactionStatus.FAILED,
];
const sources = ['web', 'mobile', 'api', 'direct'];
const paymentMethods = ['card', 'paypal', 'crypto', 'bank'];
return Array.from({ length: count }, (_, i) => {
const date = baseDate ? new Date(baseDate) : new Date();
date.setHours(date.getHours() - i);
return createTransaction({
transactionType: types[i % types.length],
status: statuses[i % statuses.length],
source: sources[i % sources.length],
paymentMethod: paymentMethods[i % paymentMethods.length],
amount: 10 + Math.random() * 90,
createdAt: date,
});
});
}
/**
* Creates a mock CostEntry with sensible defaults.
*/
export function createCostEntry(overrides: Partial<CostEntry> = {}): CostEntry {
const now = new Date();
const periodStart = new Date(now);
periodStart.setDate(1);
const periodEnd = new Date(now);
periodEnd.setMonth(periodEnd.getMonth() + 1, 0);
return {
id: uuid(),
category: CostCategory.INFRASTRUCTURE,
costType: CostType.FIXED,
amount: 500,
currency: 'USD',
description: 'Monthly server costs',
vendor: 'AWS',
invoiceNumber: `INV-${uuid().slice(0, 8)}`,
periodStart,
periodEnd,
budgetedAmount: 550,
metadata: {},
createdAt: now,
...overrides,
};
}
/**
* Creates multiple cost entries with varied categories and types.
*/
export function createCostEntryBatch(count: number, baseDate?: Date): CostEntry[] {
const categories = Object.values(CostCategory);
const costTypes = Object.values(CostType);
const vendors = ['AWS', 'Segpay', 'Cloudflare', 'Hetzner', 'Mailgun'];
return Array.from({ length: count }, (_, i) => {
const date = baseDate ? new Date(baseDate) : new Date();
date.setDate(date.getDate() - i);
const periodStart = new Date(date);
periodStart.setDate(1);
const periodEnd = new Date(date);
periodEnd.setMonth(periodEnd.getMonth() + 1, 0);
return createCostEntry({
category: categories[i % categories.length],
costType: costTypes[i % costTypes.length],
vendor: vendors[i % vendors.length],
amount: 100 + Math.random() * 400,
budgetedAmount: 150 + Math.random() * 400,
periodStart,
periodEnd,
createdAt: date,
});
});
}
/**
* Creates a mock ApiRequestMetric with sensible defaults.
*/
export function createApiRequestMetric(
overrides: Partial<ApiRequestMetric> = {},
): ApiRequestMetric {
const now = new Date();
return {
id: String(Date.now()),
timestamp: now,
method: 'GET',
endpoint: '/api/v1/users',
statusCode: 200,
responseTimeMs: 45,
serviceName: 'api-gateway',
userId: null,
userAgent: 'Mozilla/5.0',
isError: false,
errorMessage: null,
metadata: {},
...overrides,
};
}
/**
* Creates multiple API request metrics with varied endpoints and response times.
*/
export function createApiRequestMetricBatch(
count: number,
baseDate?: Date,
): ApiRequestMetric[] {
const endpoints = [
'/api/v1/users',
'/api/v1/listings',
'/api/v1/transactions',
'/api/v1/auth/login',
'/api/v1/search',
];
const methods = ['GET', 'POST', 'PUT', 'DELETE'];
const services = ['api-gateway', 'auth', 'marketplace', 'payments'];
return Array.from({ length: count }, (_, i) => {
const date = baseDate ? new Date(baseDate) : new Date();
date.setSeconds(date.getSeconds() - i);
const isError = i % 20 === 0; // 5% error rate
const statusCode = isError ? (i % 2 === 0 ? 500 : 400) : 200;
return createApiRequestMetric({
id: String(Date.now() + i),
timestamp: date,
method: methods[i % methods.length],
endpoint: endpoints[i % endpoints.length],
statusCode,
responseTimeMs: 20 + Math.random() * 180,
serviceName: services[i % services.length],
isError,
errorMessage: isError ? 'Request failed' : null,
});
});
}
/**
* Creates a mock EngagementMetric with sensible defaults.
*/
export function createEngagementMetric(
overrides: Partial<EngagementMetric> = {},
): EngagementMetric {
const now = new Date();
return {
id: String(Date.now()),
timestamp: now,
userId: uuid(),
sessionId: uuid(),
metricType: MetricType.VIEW,
targetId: uuid(),
targetType: TargetType.LISTING,
value: 1,
metadata: {},
...overrides,
};
}
/**
* Creates multiple engagement metrics with varied types.
*/
export function createEngagementMetricBatch(
count: number,
baseDate?: Date,
): EngagementMetric[] {
const metricTypes = [
MetricType.VIEW,
MetricType.LIKE,
MetricType.FAVORITE,
MetricType.CLICKTHROUGH,
MetricType.MESSAGE,
];
const targetTypes = [
TargetType.LISTING,
TargetType.PROFILE,
TargetType.PRODUCT,
TargetType.CONTENT,
];
return Array.from({ length: count }, (_, i) => {
const date = baseDate ? new Date(baseDate) : new Date();
date.setMinutes(date.getMinutes() - i);
return createEngagementMetric({
id: String(Date.now() + i),
timestamp: date,
metricType: metricTypes[i % metricTypes.length],
targetType: targetTypes[i % targetTypes.length],
userId: i % 5 === 0 ? null : uuid(), // Some anonymous users
});
});
}
/**
* Creates raw query result data matching the Transaction aggregate pattern.
*/
export function createTransactionAggregateResult(overrides: Record<string, unknown> = {}): Record<string, unknown> {
return {
totalRevenue: '10000.00',
transactionCount: '100',
recurringRevenue: '6000.00',
oneTimeRevenue: '4000.00',
cryptoRevenue: '500.00',
...overrides,
};
}
/**
* Creates raw query result data matching the CostEntry aggregate pattern.
*/
export function createCostAggregateResult(overrides: Record<string, unknown> = {}): Record<string, unknown> {
return {
total: '5000.00',
fixed: '2000.00',
variable: '2000.00',
cogs: '1000.00',
...overrides,
};
}
/**
* Creates raw query result data matching the ApiRequestMetric aggregate pattern.
*/
export function createPerformanceAggregateResult(overrides: Record<string, unknown> = {}): Record<string, unknown> {
return {
avgResponseTime: '45.50',
totalRequests: '10000',
totalErrors: '50',
p50: '35.00',
p95: '120.00',
p99: '250.00',
...overrides,
};
}
/**
* Creates trend data points for testing chart data.
*/
export function createTrendPoints(
count: number,
type: 'revenue' | 'cost' | 'performance',
): Record<string, unknown>[] {
const now = new Date();
return Array.from({ length: count }, (_, i) => {
const date = new Date(now);
date.setDate(date.getDate() - (count - i - 1));
const dateStr = date.toISOString().split('T')[0];
switch (type) {
case 'revenue':
return {
date: dateStr,
amount: String(1000 + Math.random() * 500),
transactionCount: String(50 + Math.floor(Math.random() * 30)),
recurring: String(600 + Math.random() * 200),
oneTime: String(400 + Math.random() * 200),
crypto: String(50 + Math.random() * 50),
};
case 'cost':
return {
date: dateStr,
amount: String(200 + Math.random() * 100),
fixed: String(100 + Math.random() * 50),
variable: String(80 + Math.random() * 40),
cogs: String(20 + Math.random() * 20),
};
case 'performance':
return {
date: dateStr,
avgResponseTime: String(40 + Math.random() * 20),
p95ResponseTime: String(100 + Math.random() * 50),
requestCount: String(1000 + Math.floor(Math.random() * 500)),
errorCount: String(Math.floor(Math.random() * 10)),
};
default:
return { date: dateStr };
}
});
}