v0.0.01b
This commit is contained in:
109
src/lib/format.test.ts
Normal file
109
src/lib/format.test.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import {
|
||||
DURATION_OPTIONS,
|
||||
calculatePricing,
|
||||
durationByDays,
|
||||
pluralize,
|
||||
round2,
|
||||
sumAddonPrices,
|
||||
devicesLabel,
|
||||
formatMoney,
|
||||
} from './format';
|
||||
import type { AddonData, PricingPlans } from '../types';
|
||||
|
||||
const pricing: PricingPlans = {
|
||||
device_price: 100,
|
||||
addons: [
|
||||
{ id: 'a', name: 'A', price: 50, free_threshold: 0 },
|
||||
{ id: 'b', name: 'B', price: 30, free_threshold: 0 },
|
||||
],
|
||||
};
|
||||
|
||||
describe('round2', () => {
|
||||
it('rounds to two decimals', () => {
|
||||
expect(round2(1.005)).toBe(1.01);
|
||||
expect(round2(2.345)).toBe(2.35);
|
||||
expect(round2(10)).toBe(10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sumAddonPrices', () => {
|
||||
const addons: AddonData[] = pricing.addons;
|
||||
it('sums selected addon prices', () => {
|
||||
expect(sumAddonPrices(addons, ['a', 'b'])).toBe(80);
|
||||
expect(sumAddonPrices(addons, ['a'])).toBe(50);
|
||||
expect(sumAddonPrices(addons, ['unknown'])).toBe(0);
|
||||
expect(sumAddonPrices(addons, [])).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('calculatePricing', () => {
|
||||
it('computes linear device cost + addons + duration total', () => {
|
||||
const r = calculatePricing({
|
||||
pricing,
|
||||
devices: 6,
|
||||
addonIds: ['a'],
|
||||
duration: DURATION_OPTIONS[1]!, // 90 days
|
||||
});
|
||||
// monthly = 6*100 + 50 = 650
|
||||
// total = 650 * 90 / 30 = 1950
|
||||
expect(r.deviceCost).toBe(600);
|
||||
expect(r.addonCost).toBe(50);
|
||||
expect(r.monthly).toBe(650);
|
||||
expect(r.periodTotal).toBe(1950);
|
||||
});
|
||||
|
||||
it('handles 1 month / 30 days', () => {
|
||||
const r = calculatePricing({
|
||||
pricing,
|
||||
devices: 3,
|
||||
addonIds: [],
|
||||
duration: DURATION_OPTIONS[0]!,
|
||||
});
|
||||
expect(r.monthly).toBe(300);
|
||||
expect(r.periodTotal).toBe(300);
|
||||
});
|
||||
|
||||
it('12 months / 365 days yields near 12x', () => {
|
||||
const r = calculatePricing({
|
||||
pricing,
|
||||
devices: 1,
|
||||
addonIds: [],
|
||||
duration: DURATION_OPTIONS[3]!,
|
||||
});
|
||||
// monthly=100, total = 100 * 365/30 = 1216.67
|
||||
expect(r.periodTotal).toBeCloseTo(1216.67, 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('durationByDays', () => {
|
||||
it('finds duration by days', () => {
|
||||
expect(durationByDays(30).months).toBe(1);
|
||||
expect(durationByDays(90).months).toBe(3);
|
||||
expect(durationByDays(180).months).toBe(6);
|
||||
expect(durationByDays(365).months).toBe(12);
|
||||
});
|
||||
it('falls back to first option for unknown days', () => {
|
||||
expect(durationByDays(7).months).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('pluralize / devicesLabel', () => {
|
||||
it('picks correct form', () => {
|
||||
expect(pluralize(1, 'устройство', 'устройства', 'устройств')).toBe('устройство');
|
||||
expect(pluralize(2, 'устройство', 'устройства', 'устройств')).toBe('устройства');
|
||||
expect(pluralize(5, 'устройство', 'устройства', 'устройств')).toBe('устройств');
|
||||
expect(pluralize(11, 'устройство', 'устройства', 'устройств')).toBe('устройств');
|
||||
});
|
||||
it('devicesLabel combines number and noun', () => {
|
||||
expect(devicesLabel(3)).toBe('3 устройства');
|
||||
expect(devicesLabel(6)).toBe('6 устройств');
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatMoney', () => {
|
||||
it('formats rubles', () => {
|
||||
expect(formatMoney(100)).toMatch(/100/);
|
||||
expect(formatMoney(1950)).toMatch(/1\s950/);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user