ES6 ships a namespace to handle internationalization, it covers cases like:
For instance, if we want to format a currency using es-ES culture (Spain), we can easily create a formatted output by coding something like:
const value = 200;
const formattedValue = new Intl.NumberFormat("es-ES", {
style: "currency",
currency: "EUR"
}).format(value);
console.log(formattedValue);
This code should output a string like:
200,00 €
Ok cool, but if I write a Jest test to check this piece of code, it will fail; instead of generating the following output: 200,00 € it will generate €200.00 :-(, what's happening here?
Let's write the following function:
export const formatCurrency = value =>
new Intl.NumberFormat("es-ES", {
style: "currency",
currency: "EUR"
}).format(value);
Let's add a test to check if it's working properly
import { formatCurrency } from "./sample-formatter";
it("Display a number in es-ES currency format", () => {
// Arrange
const value = 200;
// Act
const formattedText = formatCurrency(value);
// Assert
expect(formattedText).toEqual("200,00 €");
});
What result do we get? Agggh! Test failing...
It seems that the test execution is not taking into account the Intl es-ES configuration!
Jest tests don't run on top of the browser; they run under Node.js, which doesn't ship the full internationalization support by default. You can find more info about this issue in this link.
How can we fix that?
If you are in a hurry, here you have a quick solution:
npm install full-icu --save-dev
npm install cross-env --save-dev
If you are on a custom solution
./package.json
- "test": "jest --verbose",
+ "test": "cross-env NODE_ICU_DATA=node_modules/full-icu jest --verbose",
If you are on a create-react-app based project
./package.json
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
- "test": "react-scripts test",
+ "test": "cross-env NODE_ICU_DATA=node_modules/full-icu react-scripts test",
"eject": "react-scripts eject"
},
And you're good to go! Execute npm test and check that the test is passing now. You can find the full implementation in this repo .
If you want to learn more about how this works (plus bonus point: how to set this up for VS Code debugging), keep on reading :).
Node.js doesn't ship by default a full ICU installation (International Components for Unicode). The reason behind this is that most Node.js users will make use of only a small portion of ICU functionality. Only a subset of the full ICU data set is provided by Node.js by default.
What options do we have available?
Then... the solution seems to be easy: just install it locally and Bob's your uncle? Well, it's not that straightforward. You need to set up some plumbing before running your Jest tests to ensure Node.js is using full-icu
Let's start by installing full-icu in our project:
npm install full-icu --save-dev
When we install this package we get an interesting message:
Node will use this ICU datafile if the environment variable NODE_ICU_DATA is set to “node_modules/full-icu”
So, we need to set up the environment variable right before running our test battery.
If we want to set up these variables in a consistent way (so it works on Windows and Linux platforms), we need to make use of the cross-env library. Let's install it:
npm install cross-env --save-dev
We need to set up an environment variable in our test command that will indicate Node.js the path to the full-icu implementation.
Let's update our package.json test command and include the environment variable before running the Jest test battery.
./package.json
- "test": "jest --verbose",
+ "test": "cross-env NODE_ICU_DATA=node_modules/full-icu jest --verbose",
If you start the test command you can check that the test is passing:
npm test
That was great, but I use Visual Studio Code to debug my jest tests... how can I set this up for VS Code? You can just add the following environment config entry in the launch.json file:
./.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Jest single run all tests",
+ "env": { "NODE_ICU_DATA": "node_modules/full-icu" },
"program": "${workspaceRoot}/node_modules/jest/bin/jest.js",
"args": ["--verbose", "-i", "--no-cache"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}
If you need more info about how to debug jest unit tests using Visual Studio Code, check this article.
To make this work on a project created by using create-react-app you have to follow almost the same steps; the only step that is slightly different is tweaking the test command on your package.json file.
Let's start by installing full-icu in our project:
npm install full-icu --save-dev
So, we need to set up the environment variable right before running our test battery.
If we want to set up these variables in a consistent way (so it works on Windows and Linux platforms), we need to make use of the cross-env library. Let's install it:
npm install cross-env --save-dev
Now we need to set up an environment variable in our test command that will instruct Node.js the path to the full-icu implementation.
Let's update our package.json test command and include the environment variable before running the Jest test battery.
./package.json
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
- "test": "react-scripts test",
+ "test": "cross-env NODE_ICU_DATA=node_modules/full-icu react-scripts test",
"eject": "react-scripts eject"
},
If you want to learn more about ES6 Intl you can check MDN official documentation.
For Node.js and Intl support you can check Node.js official documentation node.js intl
We have published both custom and create-react-app examples of this post in this Github repo.
Jest is great, but you have to bear in mind that it doesn't run the tests on the browser. This may lead to different behaviour patterns in certain scenarios, differences which could become critical not only for Jest based testing, but also for server side rendering based projects.
Fortunately there are workarounds available to overcome these limitations.
We are a team of JavaScript experts. If you need coaching or consultancy services, don't hesitate to contact us.
C/ Pintor Martínez Cubells 5 Málaga (Spain)
info@lemoncode.net
+34 693 84 24 54
Copyright 2018 Basefactor. All Rights Reserved.