← back to Handbag Auth Nextjs
auction-viewer/tests/unit/calculations.test.js
266 lines
/**
* Unit Tests - Savings Calculations and Business Logic
*/
describe('Savings Calculations', () => {
describe('Percentage Savings', () => {
const calculateSavingsPercent = (estimateLow, currentPrice) => {
if (estimateLow > 0 && currentPrice > 0) {
return ((estimateLow - currentPrice) / estimateLow) * 100;
}
return 0;
};
test('should calculate positive savings correctly', () => {
const result = calculateSavingsPercent(10000, 8000);
expect(result).toBe(20);
});
test('should calculate high savings correctly', () => {
const result = calculateSavingsPercent(20000, 10000);
expect(result).toBe(50);
});
test('should handle zero current price', () => {
const result = calculateSavingsPercent(10000, 0);
expect(result).toBe(0);
});
test('should handle zero estimate', () => {
const result = calculateSavingsPercent(0, 5000);
expect(result).toBe(0);
});
test('should handle negative savings (price above estimate)', () => {
const result = calculateSavingsPercent(8000, 10000);
expect(result).toBe(-25);
});
test('should handle small savings accurately', () => {
const result = calculateSavingsPercent(1000, 999);
expect(result).toBeCloseTo(0.1, 1);
});
test('should handle large numbers', () => {
const result = calculateSavingsPercent(100000, 75000);
expect(result).toBe(25);
});
});
describe('Dollar Savings', () => {
const calculateSavingsAmount = (estimateLow, currentPrice) => {
if (estimateLow > 0 && currentPrice > 0) {
return estimateLow - currentPrice;
}
return 0;
};
test('should calculate dollar savings correctly', () => {
const result = calculateSavingsAmount(10000, 8000);
expect(result).toBe(2000);
});
test('should handle zero prices', () => {
const result = calculateSavingsAmount(0, 0);
expect(result).toBe(0);
});
test('should handle negative savings', () => {
const result = calculateSavingsAmount(8000, 10000);
expect(result).toBe(-2000);
});
test('should handle large amounts', () => {
const result = calculateSavingsAmount(50000, 30000);
expect(result).toBe(20000);
});
});
describe('Value Ranking', () => {
const rankByValue = (auctions, sortBy = 'percent') => {
return auctions
.filter(a => a.current_price > 0 && a.estimate_low > 0)
.map(a => ({
...a,
savings_percent: ((a.estimate_low - a.current_price) / a.estimate_low) * 100,
savings_amount: a.estimate_low - a.current_price
}))
.sort((a, b) => {
if (sortBy === 'percent') {
return b.savings_percent - a.savings_percent;
}
return b.savings_amount - a.savings_amount;
});
};
const testAuctions = [
{ auction_id: '1', estimate_low: 10000, current_price: 5000 }, // 50% / $5000
{ auction_id: '2', estimate_low: 20000, current_price: 15000 }, // 25% / $5000
{ auction_id: '3', estimate_low: 5000, current_price: 1000 }, // 80% / $4000
];
test('should rank by percentage correctly', () => {
const ranked = rankByValue(testAuctions, 'percent');
expect(ranked[0].auction_id).toBe('3'); // 80%
expect(ranked[1].auction_id).toBe('1'); // 50%
expect(ranked[2].auction_id).toBe('2'); // 25%
});
test('should rank by dollar amount correctly', () => {
const ranked = rankByValue(testAuctions, 'dollar');
// Both auction 1 and 2 have $5000 savings, auction 3 has $4000
expect(['1', '2']).toContain(ranked[0].auction_id);
expect(ranked[2].auction_id).toBe('3');
});
test('should filter out invalid prices', () => {
const withInvalid = [
...testAuctions,
{ auction_id: '4', estimate_low: 0, current_price: 1000 },
{ auction_id: '5', estimate_low: 1000, current_price: 0 }
];
const ranked = rankByValue(withInvalid);
expect(ranked.length).toBe(3); // Should exclude invalid items
});
test('should handle empty array', () => {
const ranked = rankByValue([]);
expect(ranked).toEqual([]);
});
});
describe('Price Validation', () => {
const isValidPrice = (price) => {
return typeof price === 'number' && price > 0 && isFinite(price);
};
test('should accept valid positive numbers', () => {
expect(isValidPrice(100)).toBe(true);
expect(isValidPrice(0.01)).toBe(true);
expect(isValidPrice(999999)).toBe(true);
});
test('should reject zero and negative numbers', () => {
expect(isValidPrice(0)).toBe(false);
expect(isValidPrice(-100)).toBe(false);
});
test('should reject non-numbers', () => {
expect(isValidPrice('100')).toBe(false);
expect(isValidPrice(null)).toBe(false);
expect(isValidPrice(undefined)).toBe(false);
expect(isValidPrice(NaN)).toBe(false);
});
test('should reject infinity', () => {
expect(isValidPrice(Infinity)).toBe(false);
expect(isValidPrice(-Infinity)).toBe(false);
});
});
describe('Data Formatting', () => {
const formatCurrency = (amount) => {
if (typeof amount !== 'number' || !isFinite(amount)) {
return '$0.00';
}
return `$${amount.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
};
const formatPercent = (percent) => {
if (typeof percent !== 'number' || !isFinite(percent)) {
return '0%';
}
return `${percent.toFixed(1)}%`;
};
test('should format currency correctly', () => {
expect(formatCurrency(1000)).toBe('$1,000.00');
expect(formatCurrency(1234567.89)).toBe('$1,234,567.89');
expect(formatCurrency(0.99)).toBe('$0.99');
});
test('should format percentage correctly', () => {
expect(formatPercent(25)).toBe('25.0%');
expect(formatPercent(33.333)).toBe('33.3%');
expect(formatPercent(0.1)).toBe('0.1%');
});
test('should handle invalid values gracefully', () => {
expect(formatCurrency(null)).toBe('$0.00');
expect(formatCurrency(NaN)).toBe('$0.00');
expect(formatPercent(undefined)).toBe('0%');
expect(formatPercent(Infinity)).toBe('0%');
});
});
describe('Statistics Calculations', () => {
const calculateStats = (auctions) => {
const validAuctions = auctions.filter(a => a.current_price > 0);
if (validAuctions.length === 0) {
return {
total: 0,
avgPrice: 0,
minPrice: 0,
maxPrice: 0,
totalValue: 0
};
}
const prices = validAuctions.map(a => a.current_price);
return {
total: auctions.length,
avgPrice: prices.reduce((sum, p) => sum + p, 0) / prices.length,
minPrice: Math.min(...prices),
maxPrice: Math.max(...prices),
totalValue: prices.reduce((sum, p) => sum + p, 0)
};
};
const testData = [
{ current_price: 1000 },
{ current_price: 2000 },
{ current_price: 3000 },
{ current_price: 4000 }
];
test('should calculate average correctly', () => {
const stats = calculateStats(testData);
expect(stats.avgPrice).toBe(2500);
});
test('should find min and max', () => {
const stats = calculateStats(testData);
expect(stats.minPrice).toBe(1000);
expect(stats.maxPrice).toBe(4000);
});
test('should calculate total value', () => {
const stats = calculateStats(testData);
expect(stats.totalValue).toBe(10000);
});
test('should handle empty array', () => {
const stats = calculateStats([]);
expect(stats.total).toBe(0);
expect(stats.avgPrice).toBe(0);
});
test('should filter out invalid prices', () => {
const withInvalid = [
...testData,
{ current_price: 0 },
{ current_price: -100 }
];
const stats = calculateStats(withInvalid);
expect(stats.avgPrice).toBe(2500); // Should only count valid prices
});
});
});