Tuesday, August 21, 2018

More on tsconfig paths with Jest

In my last post I explain how you can manually update your jest configuration to reflect paths that you may have setup in tsconfig.json.

I found this utility called tsconfig-paths-jest, that will do that automatically for you. To use this, you will need to set up a jest.config.js file so that you can assign values dynamically at test runtime, and if you have jest configuration info in package.json you should remove that when you set up your jest.config.js file. Please see the tsconfig-paths-jest project for full instructions.

One other pointer there - be careful if like me you have copied the tsconfig.json file from somewhere on the internet. The utility uses JSON.parse, and the implementation is strict and doesn't like trailing commas at the end of arrays and objects.

So something like this:

"paths": {
"@assets/*": [ "src/assets/*" ],
"@source/*": [ "src/*" ],
}

Should be changed to:

"paths": {
"@assets/*": [ "src/assets/*" ],
"@source/*": [ "src/*" ]
}

Wednesday, August 1, 2018

Configuring unit testing path aliases with Jest, Typescript and React-native


Update: 21/8/2018: This post describes how to set up tsconfig.json paths manually for jest. In the next post I describe how to do that automatically.

I ran into some nasty problems recently (well the latest set of them anyway) trying to run tests with the Jest setup in a react-native project. A while ago I had seen a nice Typescript feature where you can set up an alias for a path in your source code (details of that in this post and others). Having been round the block a few times over the years with "../../../../" relative paths, these path aliases felt like something of a solution.

A while after that, I started setting up some Jest unit tests, and while some worked just fine, others would fail on imports. The reason is that Jest has no clue about these path aliases that Typescript is using (although there might be an argument that something like ts-jest should relay that information). I'm not a fan of having these nice features, and then finding that you need to set them up in more than one place, but the only way I have found to fix the issue so far is using the moduleNameMapper configuration for Jest.


As an example, let's say we have an assets directory path set up in tsconfig.json as per the following snippet:

"paths":  
{  
    "@assets/*": [ "src/assets/*" ],  
},  

And remembering that we need an extra package.json file in the assets directory with the following configuration:

{ "name": "@assets" }

Then we can tell Jest about that in the jest config in our main package.json (or in jest.config.js if you went that way):

"moduleNameMapper": 
{  
    "@assets/(.*)$": "<rootDir>/src/assets/$1"  
},  

Which essentially says "for anything that begins with @assets/ substitute with the root directory of the project then src/assets and then whatever comes after" so:

@assets/images/icons/icon1.png

becomes something like

/users/example/react-native-projects/my-app/src/assets/images/icons/icon1.png

This is documented on the ts-jest github docs. You will save a lot of time and potentially major frustration by carefully reading  the information there that pertains to your project before you start using ts-jest.