import { parseRubMoney, rubMoney } from './rub-money'; describe('RUB money', () => { it.each([ ['0', 0n], ['-100', -10000n], ['0.01', 1n], ['123.4', 12340n], ['90071992547409.93', 9007199254740993n], ['92233720368547758.07', 2n ** 63n - 1n], ['-92233720368547758.08', -(2n ** 63n)], ])('roundtrips %s exactly', (value, kopecks) => { expect(parseRubMoney({ currency: 'RUB', value })).toBe(kopecks); expect(rubMoney(kopecks)).toEqual({ currency: 'RUB', value }); }); it.each([ '92233720368547758.08', '-92233720368547758.09', '1.001', '1.000', 'NaN', 'Infinity', '1e2', '1,23', '', ' 1', '1\n', '01', ])('rejects invalid input %s without rounding', (value) => { expect(() => parseRubMoney({ currency: 'RUB', value })).toThrow(); }); it('rejects other currencies and non-string values', () => { expect(() => parseRubMoney({ currency: 'USD', value: '1' })).toThrow(); expect(() => parseRubMoney({ currency: 'RUB', value: 1 as unknown as string }), ).toThrow(); }); it('requires positive operation amounts, including at the maximum', () => { for (const value of ['0', '-0.00', '-0.01']) { expect(() => parseRubMoney({ currency: 'RUB', value }, true)).toThrow(); } expect(parseRubMoney({ currency: 'RUB', value: '0.01' }, true)).toBe(1n); expect( parseRubMoney({ currency: 'RUB', value: '92233720368547758.07' }, true), ).toBe(2n ** 63n - 1n); }); it('formats computed sums beyond the storage range without losing precision', () => { expect(rubMoney(2n * (2n ** 63n - 1n))).toEqual({ currency: 'RUB', value: '184467440737095516.14', }); expect(rubMoney(-1n)).toEqual({ currency: 'RUB', value: '-0.01' }); }); });