Five quick jest and typescript tips

Published on September 06, 2020

Tagged: #typescript #frontend-development #nodejs

Follow me on twitter for more posts like this

I’ve been working with jest every day for the past month or so. I had to learn a few tricks as I went. I was mocking, using async, upgrading versions and working in vscode. Here are five things I learned.

Creating typed jest mocks

Jest has a decent mocking system but the creation and typing can be made a bit easier by using a helper library. I have used jest-create-mock-instance for the past couple of months and it works really well.

# You should install the library in your project
yarn add -D jest-create-mocked-instance

Then in your test where you need to mock a dependency you just need to

import createMockInstance from 'jest-create-mock-instance'

let mockedDependency: MyDependencyClass

mockedDependency = createMockInstance(MyDependencyClass)

let classUnderTest: MyClassToTest

classUnderTest = new MyClassToTest(mockedDependency)

Typing a typescript array for jest test-each cases

I wanted to create a truth table in another file to pass into jest’s test.each() helper.

The typing for this method is an array of sub arrays with the specific parameters defined. The way to define this in TS is

export const getTruthTable = (): Array<
    [
        MyEnumType1,
        MyEnumType2,
        string,
        boolean
    ]
> => {
    return [
        [
            MyEnumType1.YES,
            MyEnumType2.PRIMARY,
            "string test value1",
            false,
        ],
        [
            MyEnumType1.NO,
            MyEnumType2.SECONDARY,
            "string test value2",
            true,
        ],

        // and then use this in jest with

 test.each(getTruthTable())(
        "is applicable as expected",
        (
            val1: MyEnumType1,
            val1: MyEnumType2,
            val1: string,
            expected: boolean
        ) => {
          // test the case here
          expect(result).toEqual(expected)
        }

jest catch rejection

Jest has some specific methods for helping to test promises and async code

You can mock them using these helpers

jest
  .spyOn(myJestMock, 'myAsyncMethodIWantToResolveWithValue')
  .mockResolvedValue(new ThingToResolveWith())
jest
  .spyOn(myJestMock, 'myAsyncMethodIWantToReject')
  .mockRejectedValue(new ErrorToRejectWith())

You can expect a specific resolution or rejection using

await expect(result).resolves.toEqual(expectedResponse)
await expect(result).rejects.toThrowError(MyCustomError)

Upgrading to the latest ts-jest preset

If you had this setup in your jest.config.js file

    transform: {
        "^.+\\.(t|j)sx?$": "ts-jest",
    }

You can just change it to this now (unless you had a custom setup where you have typescript files that you don’t want ts-jest to inspect).

    preset: "ts-jest",

The preset is awesome and will find all your ts and tsx files.

Adding a snippet

To bring all this together in vscode I like to add a jest test snippet to avoid typing some of the boilerplate each time.

You can easily add snippets to your project by placing a file with the extension .code-snippets in your .vscode folder. The .vscode folder is in the root of your project. You can just add it if it’s not already there.

The snippet syntax is json. It’s a bit annoying to setup because each line is a string. You can use the following tool to convert code into a snippet for visual studio code: https://snippet-generator.app/.

There is also a plugin for managing snippets in vscode called Easy Snippet. This is available in the extension marketplace here: https://marketplace.visualstudio.com/items?itemName=inu1255.easy-snippet.

The prefix parameter is the name you would type in vscode and then hit tab to print the snippet to your file. Usually the first couple of letters are enough. ne..<TAB> then enter the name of the class under test.

    "Simple Test": {
        "scope": "typescript",
        "prefix": "newtest",
        "body": [
            "import createMockInstance from \"jest-create-mock-instance\";",
            "",
            "describe(\"$1\", () => {",
            "    let classUnderTest: $1;",
            "",
            "    let myMockedDep: jest.Mocked<MockClass>;",
            "",
            "    beforeEach(() => {",
            "        jest.resetAllMocks();",
            "",
            "        myMockedDep = createMockInstance(MyDependency)",
            "        classUnderTest = new $1(myMockedDep);",
            "    });",
            "",
            "    test.each([",
            "        [\"true\", true],",
            "        [\"false\", false],",
            "    ])(\"is an expected response\", (input: string, expected: boolean) => {",
            "        const result = classUnderTest.methodToTest(input);",
            "        expect(result).toEqual(expected);",
            "    });",
            "});"
        ],
        "description": "A simple test template for starting a unit test"
Darragh ORiordan

Hi! I'm Darragh ORiordan.

I live and work in Sydney, Australia building supporting happy teams that create high quality software for the web.

I also make tools for busy developers! Do you have a new M1 Mac to setup? Have you ever spent a week getting your dev environment just right?

My DevShell tooling will save you 30+ hours configuring your dev environment with all the best modern tools. Get it here

https://darraghoriordan.gumroad.com/l/devshell


Read more articles like this one...

List of article summaries

#typescript

How to write an ESLint plugin in TypeScript

I use NestJS at my day job. It’s a complicated framework sometimes and there are lots of things that devs “just have to remember” or there will be bugs in your application that you won’t see until runtime.

I wanted to remove this cognitive load from NestJS engineers so that they can focus on valuable work instead. I wrote an ESLint plugin to alert developers directly in their IDE or editor when these common issues exist - (Available on NPM) https://www.npmjs.com/package/@darraghor/eslint-plugin-nestjs-typed

Here is what I learned about writing ESLint plugins in typescript for typescript while building the plugin.

#typescript

Create an only ever true boolean type in typescript

Integrating with an API where a boolean can only be undefined or true I needed to type it. It’s easy enough but I just wanted to jot it down in case any one else needs this in the future.

#typescript

How to change the type of output for a property filter in typescript

If you have an iterable filter on a property in typescript you might have a slightly different model coming out of the filter based on the filter condition.

By setting the types correctly you can potentially save having to add manual typing hints in whatever follows the filter.

It’s easier to show this with code so see below!

Thanks to one of my colleagues for suggesting this one in a code review.

#typescript

Copying missing files during a typescript build on deploy

If you build your nodeJS project using typescript, it’s important to know that the typescript compiler tsc will only include files that are .js or .ts.

If you have an issue where you deploy or build a typescript project and you get a file not found issue or similar, it’s probably because you missed that typescript does not process these kinds of files for you.

If you need to include files like XML (.xml) or images in your typescript project build output, you will have to copy them manually before or after the build process.

This is one way to copy assets in a typescript build.