import { describe, it, expect } from 'vitest'; import { formatPrice, formatVND, formatPricePerM2, parseVND, } from '../currency'; // --------------------------------------------------------------------------- // formatPrice — compact notation without currency suffix // --------------------------------------------------------------------------- describe('formatPrice', () => { it('formats billions as "X ty"', () => { expect(formatPrice(1_000_000_000)).toBe('1 t\u1ef7'); expect(formatPrice(1_500_000_000)).toBe('1.5 t\u1ef7'); expect(formatPrice(3_500_000_000)).toBe('3.5 t\u1ef7'); expect(formatPrice(10_000_000_000)).toBe('10 t\u1ef7'); }); it('formats millions as "X trieu"', () => { expect(formatPrice(1_000_000)).toBe('1 tri\u1ec7u'); expect(formatPrice(1_500_000)).toBe('1.5 tri\u1ec7u'); expect(formatPrice(150_000_000)).toBe('150 tri\u1ec7u'); expect(formatPrice(800_000_000)).toBe('800 tri\u1ec7u'); expect(formatPrice(999_000_000)).toBe('999 tri\u1ec7u'); }); it('formats values below 1 million with locale separator', () => { expect(formatPrice(500_000)).toMatch(/500/); expect(formatPrice(1_000)).toMatch(/1/); expect(formatPrice(0)).toBe('0'); }); it('accepts string inputs', () => { expect(formatPrice('3500000000')).toBe('3.5 t\u1ef7'); expect(formatPrice('150000000')).toBe('150 tri\u1ec7u'); }); it('handles edge cases gracefully', () => { expect(formatPrice(-1)).toBe('0'); expect(formatPrice(NaN)).toBe('0'); expect(formatPrice(Infinity)).toBe('0'); expect(formatPrice('')).toBe('0'); }); it('strips trailing .0', () => { expect(formatPrice(2_000_000_000)).toBe('2 t\u1ef7'); expect(formatPrice(5_000_000)).toBe('5 tri\u1ec7u'); }); }); // --------------------------------------------------------------------------- // formatVND — with currency suffix "d" // --------------------------------------------------------------------------- describe('formatVND', () => { it('returns "Mien phi" for zero', () => { expect(formatVND(0)).toBe('Mi\u1ec5n ph\u00ed'); }); it('formats billions with suffix', () => { expect(formatVND(1_500_000_000)).toBe('1.5 t\u1ef7 \u0111'); }); it('formats millions with suffix', () => { expect(formatVND(5_000_000)).toBe('5 tri\u1ec7u \u0111'); expect(formatVND(4_990_000)).toBe('5 tri\u1ec7u \u0111'); }); it('formats values below 1 million with suffix', () => { expect(formatVND(500_000)).toMatch(/\u0111$/); }); it('accepts string input', () => { expect(formatVND('1500000000')).toBe('1.5 t\u1ef7 \u0111'); }); }); // --------------------------------------------------------------------------- // formatPricePerM2 — price per square metre // --------------------------------------------------------------------------- describe('formatPricePerM2', () => { it('formats millions as "X tr/m\u00b2"', () => { expect(formatPricePerM2(50_500_000)).toBe('50.5 tr/m\u00b2'); expect(formatPricePerM2(1_000_000)).toBe('1 tr/m\u00b2'); }); it('formats billions as "X ty/m\u00b2"', () => { expect(formatPricePerM2(1_500_000_000)).toBe('1.5 t\u1ef7/m\u00b2'); }); it('formats values below 1 million with "/m\u00b2" suffix', () => { expect(formatPricePerM2(500_000)).toMatch(/m\u00b2$/); }); it('accepts string input', () => { expect(formatPricePerM2('50500000')).toBe('50.5 tr/m\u00b2'); }); it('handles edge cases', () => { expect(formatPricePerM2(0)).toBe('0 \u0111/m\u00b2'); expect(formatPricePerM2(-1)).toBe('0 \u0111/m\u00b2'); }); }); // --------------------------------------------------------------------------- // parseVND — reverse parse // --------------------------------------------------------------------------- describe('parseVND', () => { it('parses formatted number back', () => { expect(parseVND('500.000')).toBe(500000); }); it('returns null for empty / non-numeric input', () => { expect(parseVND('')).toBeNull(); expect(parseVND('abc')).toBeNull(); }); it('strips non-digit characters', () => { expect(parseVND('1.500.000 \u0111')).toBe(1500000); }); });