diff --git a/__tests__/Str-test.js b/__tests__/Str-test.js index fc2d290b..af7dab5a 100644 --- a/__tests__/Str-test.js +++ b/__tests__/Str-test.js @@ -96,6 +96,38 @@ describe('Str.sanitizeURL', () => { }); }); +describe('Str.fromCurrencyToNumber', () => { + it('Handles negative amounts with minus sign', () => { + expect(Str.fromCurrencyToNumber('-$5.23')).toBe(-523); + expect(Str.fromCurrencyToNumber('$-5.23')).toBe(-523); + }); + + it('Handles negative amounts with ()', () => { + expect(Str.fromCurrencyToNumber('($5.23)')).toBe(-523); + }); + + it('Handles fractional cents when allowed', () => { + expect(Str.fromCurrencyToNumber('$5.223', true)).toBe(522.3); + }); + + it('Handles amounts without leading zeros', () => { + expect(Str.fromCurrencyToNumber('$.23')).toBe(23); + }); + + it('Handles amounts without cents', () => { + expect(Str.fromCurrencyToNumber('$5')).toBe(500); + }); + + it('Handles currency symbols with a period', () => { + expect(Str.fromCurrencyToNumber('Bs.S2.48')).toBe(248); + expect(Str.fromCurrencyToNumber('Bs.S-2.48')).toBe(-248); + expect(Str.fromCurrencyToNumber('-Bs.S2.48')).toBe(-248); + expect(Str.fromCurrencyToNumber('(Bs.S2.48)')).toBe(-248); + expect(Str.fromCurrencyToNumber('Bs.S.48')).toBe(48); + expect(Str.fromCurrencyToNumber('Bs.S2')).toBe(200); + }); +}); + describe('Str.isValidEmail', () => { it('Correctly detects a valid email', () => { expect(Str.isValidEmail('abc@gmail.com')).toBeTruthy(); diff --git a/lib/str.js b/lib/str.js index ad48560e..2adb4c7b 100644 --- a/lib/str.js +++ b/lib/str.js @@ -24,19 +24,25 @@ const Str = { }, /** - * Converts a USD string into th number of cents it represents. + * Converts a currency string into the number of cents it represents. * - * @param {String} amountStr A string representing a USD value. - * @param {Boolean} allowFraction Flag indicating if fractions of cents should be - * allowed in the output. + * @param {String} amountStr String representing a currency symbol and value, like $4.02 or Bs.S97.9 + * @param {Boolean} allowFraction Flag indicating if fractions of cents should be allowed in the output. * * @return {Number} The cent value of the @p amountStr. */ - fromUSDToNumber(amountStr, allowFraction) { - let amount = String(amountStr).replace(/[^\d.\-()]+/g, ''); - if (amount.match(/\(.*\)/)) { - const modifiedAmount = amount.replace(/[()]/g, ''); - amount = `-${modifiedAmount}`; + fromCurrencyToNumber(amountStr, allowFraction) { + // eslint-disable-next-line no-param-reassign + amountStr = String(amountStr); + + // Ideally, we would pass the currency symbol directly here the same string + // could be interpreted differently based on currency symbol but for now + // we match the amount from the end of the string. + let amount = amountStr.match(/(-?(?:\.\d+|\d+\.?\d*))\)?$/)[1]; + + // We want to support both -$5.00 and $-5.00, so we check if the string starts with - + if (amountStr.match(/\(.*\)/) || amountStr[0] === '-') { + amount = `-${amount}`; } amount = Number(amount) * 100; @@ -50,6 +56,19 @@ const Str = { return allowFraction ? amount : Math.round(amount); }, + /** + * Wrapper around fromCurrencyToNumber + * + * @deprecated + * @param {String} amountStr String representing a currency symbol and value, like $4.02 or Bs.S97.9 + * @param {Boolean} allowFraction Flag indicating if fractions of cents should be allowed in the output. + * + * @return {Number} The cent value of the @p amountStr. + */ + fromUSDToNumber(...args) { + return Str.fromCurrencyToNumber(...args); + }, + /** * Truncates the middle section of a string based on the max allowed length * @param {string} fullStr