diff --git a/app/webpacker/js/services/localize_currency.js b/app/webpacker/js/services/localize_currency.js new file mode 100644 index 0000000000..c542d19592 --- /dev/null +++ b/app/webpacker/js/services/localize_currency.js @@ -0,0 +1,24 @@ +// Convert number to string currency using injected currency configuration. + +// Requires global variable from page: ofn_currency_config +export default function (amount) { + // Set country code (eg. "US"). + const currency_code = ofn_currency_config.display_currency + ? " " + ofn_currency_config.currency + : ""; + // Set decimal points, 2 or 0 if hide_cents. + const decimals = ofn_currency_config.hide_cents === "true" ? 0 : 2; + // Set format if the currency symbol should come after the number, otherwise (default) use the locale setting. + const format = ofn_currency_config.symbol_position === "after" ? "%n %u" : undefined; + // We need to use parseFloat as the amount should come in as a string. + amount = parseFloat(amount); + + // Build the final price string. + return ( + I18n.toCurrency(amount, { + precision: decimals, + unit: ofn_currency_config.symbol, + format: format, + }) + currency_code + ); +} diff --git a/spec/javascripts/services/localize_currency_test.js b/spec/javascripts/services/localize_currency_test.js new file mode 100644 index 0000000000..fd8a2da359 --- /dev/null +++ b/spec/javascripts/services/localize_currency_test.js @@ -0,0 +1,63 @@ +/** + * @jest-environment jsdom + */ + +import localizeCurrency from "js/services/localize_currency"; + +describe("convert number to localised currency", function () { + beforeAll(() => { + const mockedToCurrency = jest.fn(); + mockedToCurrency.mockImplementation((amount, options) => { + if (options.format == "%n %u") { + return `${amount.toFixed(options.precision)}${options.unit}`; + } else { + return `${options.unit}${amount.toFixed(options.precision)}`; + } + }); + + global.I18n = { toCurrency: mockedToCurrency }; + + // Requires global var from page + global.ofn_currency_config = { + symbol: "$", + symbol_position: "before", + currency: "D", + hide_cents: "false", + }; + }); + // (jest still doesn't have aroundEach https://github.com/jestjs/jest/issues/4543 ) + afterAll(() => { + delete global.I18n; + }); + + it("adds decimal fraction to an amount", function () { + expect(localizeCurrency(10)).toEqual("$10.00"); + }); + + it("handles an existing fraction", function () { + expect(localizeCurrency(9.9)).toEqual("$9.90"); + }); + + it("can use any currency symbol", function () { + global.ofn_currency_config.symbol = "£"; + expect(localizeCurrency(404.04)).toEqual("£404.04"); + }); + + it("can place symbols after the amount", function () { + global.ofn_currency_config.symbol = "$"; + global.ofn_currency_config.symbol_position = "after"; + expect(localizeCurrency(333.3)).toEqual("333.30$"); + }); + + it("can add a currency string", function () { + global.ofn_currency_config.display_currency = true; + global.ofn_currency_config.symbol_position = "before"; + expect(localizeCurrency(5)).toEqual("$5.00 D"); + }); + + it("can hide cents", function () { + global.ofn_currency_config.display_currency = false; + global.ofn_currency_config.hide_cents = "true"; + expect(localizeCurrency(5)).toEqual("$5"); + }); +});