Tom Andrews

Tom Andrews

Testing tokens

I’ve recently started working on a new project that makes heavy use of JWT. This has meant that I’ve been wrirting a decent number of tests to ensure that the token contains the correct contents and will expire at the correct time. A lot of the tests started looking like this.

const { iat: _iat, exp, ...contents } = jwt.decode(token)
expect(contents).toMatchObject(expectedContents)
expect(exp).toEqual(Math.floor(Date.now() / 1000) + 60 * 60)

As you can see this is very verbose and hides the intention of the test. It would be great if we could write a much cleaner test. Like this

expect(token).toBeTokenContaining(expectedContents)
expect(token).toBeTokenExpiringIn("1h")

As we using Jest there is a way of extending it to add our own matchers. So I created a new npm package that adds a couple of custom assertions for working with JWT. It is called jest-expect-jwt

This was an overall great experience in extending jest by following the docs. The only complexity came from the integration with typescript and ensuring that the types for the new assertions were detected. When using it in a test it would execute successfully but would show an error in vscode.

Property 'toBeTokenContaining' does not exist on type 'JestMatchersShape<Matchers<void, string>, Matchers<Promise<void>, string>>'.ts(2339)

I eventually found a solution by reading the docs for jest-extended and it should that you need to import the types into a global.d.ts.

But either way it will nice writing better tests. And you can too jest-expect-jwt