UNPKG

tanisa

Version:

An utility to convert Malagasy 🇲🇬 numbers, including decimals, into their word representations.

202 lines (184 loc) • 7.09 kB
import { describe, it, expect, beforeEach } from 'vitest' import { Tanisa, MalagasyNumerals } from '../src' import { TanisaOptions } from '../src/interface' describe('MalagasyNumberToWords', () => { let converter: Tanisa beforeEach(() => { converter = new Tanisa() }) const testCases: [number | string, string][] = [ [0, 'aotra'], [1, 'iray'], [5, 'dimy'], [9, 'sivy'], // // Tens [10, 'folo'], [11, 'iraika amby folo'], [15, 'dimy amby folo'], [20, 'roapolo'], [21, 'iraika amby roapolo'], [35, 'dimy amby telopolo'], [99, 'sivy amby sivifolo'], // // Hundreds [100, 'zato'], [101, 'iraika amby zato'], [110, 'folo amby zato'], [111, 'iraika amby folo amby zato'], [121, 'iraika amby roapolo amby zato'], [200, 'roanjato'], [201, 'iraika amby roanjato'], [210, 'folo sy roanjato'], [225, 'dimy amby roapolo sy roanjato'], [600, 'eninjato'], [999, 'sivy amby sivifolo sy sivinjato'], // // Thousands [1000, 'arivo'], [1001, 'iray sy arivo'], [1010, 'folo sy arivo'], [1011, 'iraika amby folo sy arivo'], [1378, 'valo amby fitopolo sy telonjato sy arivo'], [2000, 'roa arivo'], [2023, 'telo amby roapolo sy roa arivo'], // Ten Thousands (Alina) [10000, 'iray alina'], [15000, 'dimy arivo sy iray alina'], [20000, 'roa alina'], [98_765, 'dimy amby enimpolo sy fitonjato sy valo arivo sy sivy alina'], // Hundred Thousands (Hetsy) [100000, 'iray hetsy'], [ 123456, 'enina amby dimampolo sy efajato sy telo arivo sy roa alina sy iray hetsy', ], [500000, 'dimy hetsy'], [ 654321, 'iraika amby roapolo sy telonjato sy efatra arivo sy dimy alina sy enina hetsy', ], // Millions (Tapitrisa) [1000000, 'iray tapitrisa'], [1000001, 'iray sy iray tapitrisa'], [2500000, 'dimy hetsy sy roa tapitrisa'], [ 9876543, 'telo amby efapolo sy dimanjato sy enina arivo sy fito alina sy valo hetsy sy sivy tapitrisa', ], // Larger Units [10000000, 'iray safatsiroa'], [100000000, 'iray tsitamboisa'], [1000000000, 'iray lavitrisa'], [ 12345678901, 'iraika amby sivinjato sy valo arivo sy fito alina sy enina hetsy sy dimy tapitrisa sy efatra safatsiroa sy telo tsitamboisa sy roa lavitrisa sy iray alinkisa', ], [1_100_000_000_000, 'iray tsipesimpesina sy iray tsitokotsiforohana'], // Decimals [0.5, 'aotra faingo dimy'], [0.1, 'aotra faingo iray'], ['2.00100', 'roa faingo aotra aotra zato'], [ 1378.23, 'valo amby fitopolo sy telonjato sy arivo faingo telo amby roapolo', ], [100.01, 'zato faingo aotra iray'], [0.005, 'aotra faingo aotra aotra dimy'], ] it.each(testCases)('should convert %s to "%s"', (input, expected) => { expect(converter.toWords(input)).toBe(expected) }) describe('Error Handling', () => { it('should throw TypeError for invalid input', () => { expect(() => converter.toWords('not a number')).toThrow(TypeError) expect(() => converter.toWords('123.abc')).toThrow(TypeError) expect(() => converter.toWords(NaN)).toThrow(TypeError) }) it('should throw RangeError for negative numbers', () => { expect(() => converter.toWords(-1)).toThrow(RangeError) expect(() => converter.toWords(-100.5)).toThrow(RangeError) expect(() => converter.toWords('-0')).not.toThrow(RangeError) expect(converter.toWords('-0')).toBe('aotra') }) it('should throw RangeError for numbers exceeding the limit', () => { const limit = MalagasyNumerals.MAX_SUPPORTED_INTEGER const largeNumber = BigInt(limit) + BigInt(1) expect(() => converter.toWords(limit)).toThrow(RangeError) expect(() => converter.toWords(largeNumber.toString())).toThrow( RangeError ) }) it('should handle string input correctly', () => { expect(converter.toWords('123')).toBe('telo amby roapolo amby zato') expect(converter.toWords('1000.5')).toBe('arivo faingo dimy') }) it('should handle number input with maximum safe integer', () => { const safeInt = Number.MAX_SAFE_INTEGER // 9_007_199_254_740_991 expect(() => converter.toWords(safeInt)).not.toThrow() }) }) describe('ignoreDecimal option', () => { it('should ignore decimal part when ignoreDecimal is true', () => { const options: TanisaOptions = { ignoreDecimal: true } expect(converter.toWords(123.456, options)).toBe( 'telo amby roapolo amby zato' ) expect(converter.toWords(0.99, options)).toBe('aotra') expect(converter.toWords(1000.001, options)).toBe('arivo') }) it('should NOT ignore decimal part when ignoreDecimal is false or absent', () => { expect(converter.toWords(10.5, { ignoreDecimal: false })).toBe( 'folo faingo dimy' ) expect(converter.toWords(10.5)).toBe('folo faingo dimy') }) }) describe('decimalPlaces option', () => { it('should ignore decimal part when decimalPlaces is 0', () => { const options: TanisaOptions = { decimalPlaces: 0 } expect(converter.toWords(123.456, options)).toBe( 'telo amby roapolo amby zato' ) expect(converter.toWords(0.99, options)).toBe('aotra') }) it('should truncate decimal part to specified places', () => { expect(converter.toWords(1.2345, { decimalPlaces: 1 })).toBe( 'iray faingo roa' ) expect(converter.toWords(1.2345, { decimalPlaces: 2 })).toBe( 'iray faingo telo amby roapolo' ) expect(converter.toWords(1.2345, { decimalPlaces: 3 })).toBe( 'iray faingo efatra amby telopolo sy roanjato' ) }) it('should handle leading zeros correctly with truncation', () => { expect(converter.toWords(10.056, { decimalPlaces: 1 })).toBe('folo') expect(converter.toWords(10.056, { decimalPlaces: 2 })).toBe( 'folo faingo aotra dimy' ) expect(converter.toWords(10.056, { decimalPlaces: 3 })).toBe( 'folo faingo aotra enina amby dimampolo' ) expect(converter.toWords(10.009, { decimalPlaces: 2 })).toBe('folo') expect(converter.toWords(10.009, { decimalPlaces: 3 })).toBe( 'folo faingo aotra aotra sivy' ) }) it('should convert all decimals if decimalPlaces is equal to or greater than actual places', () => { expect(converter.toWords(5.67, { decimalPlaces: 2 })).toBe( 'dimy faingo fito amby enimpolo' ) expect(converter.toWords(5.67, { decimalPlaces: 3 })).toBe( 'dimy faingo fito amby enimpolo' ) expect(converter.toWords(5.67, { decimalPlaces: 10 })).toBe( 'dimy faingo fito amby enimpolo' ) }) }) describe('decimalPlaces and ignoreDecimal options', () => { it('should ignore decimal part if both params is set', () => { const options: TanisaOptions = { decimalPlaces: 2, ignoreDecimal: true } expect(converter.toWords(3.134343, options)).toBe('telo') }) }) })