jmargolisvt
jmargolisvt

Reputation: 6088

Intl.NumberFormat space character does not match

I'm running into an issue where Intl.NumberFormat is formatting the space character in some way that is different from what Jest is expecting. Tests against the same function with values that do not yield spaces as separators pass fine. Jest is considering the space between the 4 and the 5 characters to be different. I am using the intl polyfill for fr_CA both in my app and in my test.

Here is my function, but the only really relevant part is the Intl.NumberFormat output. How can I reconcile the formatting for the space character so that my test passes?

  export function formatCurrency( num, locale = 'en_US', showFractionDigits = false) {
    const options = {
        style: locale === 'fr_CA' ? 'decimal' : 'currency',
        currency: locale.length && locale.indexOf('CA') > -1 ? 'CAD' : 'USD'
    };

    const final = new Intl.NumberFormat(locale.replace('_', '-'), options).format(num);

    if (locale === 'fr_CA') {
        return `${final} $`;
    } else {
        return final;
    }
  }

My assertion:

expect(formatCurrency(24555.55, 'fr_CA', true)).toBe('24 555,55 $');

Result:

Expected value to be:
  "24 555,55 $"
Received:
  "24 555,55 $"

Upvotes: 45

Views: 13094

Answers (4)

Matt
Matt

Reputation: 344

If you need the character for the thousand separator that Intl.NumberFormat uses (for example in case you using locale: 'fr_US') this is what you are looking for:

\u202f

Example:

    const numberToFormat = '1000000.012345678912345678';
    const expectedFR = '1\u202f000\u202f000,012345678912345678';
    expect(Intl.NumberFormat('fr-US').format(numberToFormat).toBe(expectedFR);

Upvotes: 0

Dan Monego
Dan Monego

Reputation: 10087

Because every jest-fails-on-whitespace question points here, I feel it's necessary to say many cases might be served by checking for whitespace rather than specific characters. Using .toMatch() with a regex containing the \W character will match either space or non-breaking space:

expect(formatCurrency(24555.55, 'fr_CA', true)).toMatch(/24\W555,55\W$/);

It also matches a small non-breaking space:

expect(new Intl.NumberFormat("fr-FR", {
  style: "currency",
  currency: "EUR",
}).format(126126)).toMatch(/126\W126,00\W€/)

Upvotes: 2

Guillaume Vincent
Guillaume Vincent

Reputation: 14791

NumberFormat use small non-breaking space (\u202f) for thousand separator and normal non-breaking space beforece currency (\xa0)

  expect(new Intl.NumberFormat("fr-FR", {
    style: "currency",
    currency: "EUR",
  }).format(126126)).toBe("126\u202f126,00\xa0€")

Upvotes: 29

jmargolisvt
jmargolisvt

Reputation: 6088

'11 111.11'.split('').map(x => console.log((x.charCodeAt(0))))

Yields "32" for the space character which is a normal space.

new Intl.NumberFormat('fr-CA').format(11111.11).split('').map(x => console.log((x.charCodeAt(0))))

Yields "160" for the space character, which is a non-breaking space.

To make these tests pass, you need to add the non-breaking space UTF-16 (\xa0) character code into the assertion.

expect(formatCurrency(24555.55, 'fr_CA', true)).toBe('24\xa0555,55 $');

Upvotes: 64

Related Questions