I've defined a function toCurrency
to convert string or number to locale strings:
function toCurrency(
value: string | number,
locale: string = "pt-BR",
currency: string = "BRL",
options?: Intl.NumberFormatOptions
) {
return Number(value).toLocaleString(locale, {
maximumFractionDigits: 2,
style: "currency",
currency: currency,
...options,
});
}
and a test to validate it:
describe("toCurrency", () => {
test("toCurrency defined", async () => {
expect(toCurrency).toBeDefined();
});
test("toCurrency", () => {
const result = toCurrency(1, "pt-BR", "BRL");
expect(result).toEqual("R$ 1,00");
});
test("toCurrency USD", () => {
const result = toCurrency(1, "en-US", "USD");
expect(result).toEqual("$1.00");
});
});
But the tests fails only for pt-BR:
The Node.js version you're running may have a different version of the CLDR data than your test expects, and so you get a different result for toLocaleString
.
Alternately, if you haven't written your test specifically against CLDR data, your test expects e.g. a normal 0x20 space between R$
and the number, while chances are the character as formatted is actually e.g. a non-breaking space (\xA0
):
> function toCurrency(
... value,
... locale = "pt-BR",
... currency = "BRL"
... ) {
... return Number(value).toLocaleString(locale, {
... maximumFractionDigits: 2,
... style: "currency",
... currency,
... });
... }
> toCurrency(1)
'R$ 1,00'
> [...toCurrency(1)].map(c => c.codePointAt(0))
[
82, 36, 160, 49,
44, 48, 48
]
Note how the third codepoint is 160 – that's 0xA0.