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"]
}
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$"
}
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"
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.
Top comments (5)
Great article.
Question: when I try to run my tests, it fails with:
SyntaxError:.../models/activity.entity.ts: Support for the experimental syntax 'decorators-legacy' isn't currently enabled (13:1):
Any ideas?
Thanks!
Joel Stevick
It most likely happens because of your
TypeORM
configuration points to typescript entities in theentities
configurationThanks for sharing, it's a great workaround.
However, when writing E2E tests in the current setup, the development process becomes slow because the project needs to be fully rebuilt each time a test is run. This rebuild process hinders the ability to use watch capabilities, which could otherwise speed up the testing and development cycle.
The current solution of compiling all TS files and running them as JS files in Jest works but is cumbersome and not ideal for a streamlined development workflow.
I think it would be great with a way to have the nest cli work natively with jest.
Hey @jmcdo29 - perhaps you should update this article with an update that this is no longer required, instead we can use: docs.nestjs.com/graphql/cli-plugin...
Outstanding article! Thanks for sharing it with the community!