Using the NestJS CLI GraphQL Plugin for E2E Testing

Jay McDoniel - Sep 9 '20 - - Dev Community

Jay is a member of the NestJS core team, primarily helping out the community on Discord and Github and contributing to various parts of the framework.

If you've been using NestJS for GraphQL, you probably know about the sweet @nestjs/cli plugin to auto-annotate all of your DTOs with GraphQL metadata, meaning you can cut down on code and make your development cycle faster (and let's be honest, who doesn't want that?). So you've written your code, using that awesome plugin, your unit tests are passing, you fire up your e2e tests and everything fails. GraphQL errors left and right about missing metadata, jest complaining about failures, and everything right in the world is now all so very wrong. Why did this happen, and how can we fix it?

Why did this happen?

To understand the why of this, we need to figure out what all Nest's build command does and how it works from a very high level. Below is a short list of what the build command is responsible for

  • compile code from ts to js
  • map paths properly for us (if using path aliases)
  • annotate DTOs with swagger decorators (if applied)
  • annotates DTOs with GraphQL decorators (if applied)
  • set up an automatic watcher to recompile on change (if using start --watch)

Now all of this looks really sweet compared to the standard Typescript compiler. In fact, Nest uses the Typescript compiler under the hood by default (though this can be swapped out for Webpack if you choose to do so). What's important to note here though, is that this is more than what tsc does by default. And because of all this, when we try to run our e2e tests through ts-jest, the default tsc compiler just isn't enough.

Okay, so how do I fix it?

The way I see it, there's two main options:

1) Create a ts-jest compiler plugin that can be swapped out with typescript
2) Create a process for building your test files specifically for e2e testing

While the first option sounds great, there's a couple of problems with it. It's specific to ts-jest so if anyone wanted to use something like mocha a whole new plugin would need to be written, and it's difficult to write, because Nest's build command is a wrap around of tsc, not an entirely new compiler in the first place.

So we go with option two and write a build process for e2e tests.

The Build Process

The first thing that we will need now is a new tsconfig, so that we can get the build to include both our source code and our test code. So, taking the standard setup from a nest new project, we can make a tsconfig.test.json that looks like this

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "dist-test"
  },
  "include": ["src", "test"]
}
Enter fullscreen mode Exit fullscreen mode

This will test nest build to include both the src directory and the test dir, and use a different output directory than our normal build process.

hint: you should probably add the dist-test dir to your .gitignore so it isn't checked into version control

Now we need to update our jest-e2e.json that Nest provides for us. We need to remove the transform property, and change the regex used for finding the tests. The new jest-e2e.json should look something like this:

{
  "moduleFileExtensions": ["js", "json", "ts"],
  "rootDir": ".",
  "testEnvironment": "node",
  "testRegex": ".e2e-spec.js$"
}
Enter fullscreen mode Exit fullscreen mode

Now the last thing to do is to create a build script and a test script to build the entire source code with tests and move them all to a single directory for tests. We can make use of pre scripts here and make two new scripts in the package.json that look like this

"pretest:e2e": "nest build -p tsconfig.test.json && cp ./test/jest-e2e.json ./dist-test/test/",
"test:e2e": "jest --config ./dist-test/test/jest-e2e.json"
Enter fullscreen mode Exit fullscreen mode

With these commands, when we run npm run test:e2e or yarn test:e2e, we are telling nest to build the project using the new tsconfig.test.json we created, move the jest-e2e.json to the ./dist-test/test/ directory, to act similarly to where it already lives in the ./test/ dir (Typescript won't move non ts files by default), and then for jest (not ts-jest) to run the tests based on the config file.

To see a running version of this you can view my sample repository here.

If you have questions or comments let me know. And if you want to discuss more about NestJS in general feel free to check out our Discord.

. . . . . . . . . . . . . . . . .