Jest-dom: Type definitions not properly loaded when importing from jest's setupTests

Created on 26 Jul 2018  ·  19Comments  ·  Source: testing-library/jest-dom

  • jest-dom version: 1.10.0
  • node version: 8.11.3
  • react-testing-library version: 4.1.4

Relevant code or config:

// package.json
  "jest": {
    "setupTestFrameworkScriptFile": "<rootDir>/src/setupTests.ts",
  },

// src/setupTests.ts
import 'jest-dom/extend-expect';

// src/components/SomeComponent/SomeComponent.test.ts
expect(element).toHaveTextContent('Hello World!');
// TypeScript error in the line above:
// Property 'toHaveTextContent' does not exist on type 'Matchers<void>'

Problem description:

When importing jest-dom/extend-expect, as instructed in the README, within jest's setupTestFrameworkScriptFile file, and using TypeScript at the same time, I get TypeScript errors in my test files saying that this library's custom matchers are not found:

Property 'toHaveTextContent' does not exist on type 'Matchers<void>'

However, when I import jest-dom/extend-expect from within the very text files that need those matchers it all works. Moreover, it even works if I import it in just one of those files, which suddenly removes the TS warning from a second test file, without having to import it again from that second test file.

Suggested solution:

This StackOverflow answer may be part of the solution, but I wanted to bring this up first to see if someone more knowledgeable with TypeScript can help. @jgoz maybe?

question

Most helpful comment

It would be helpful to see the tsconfig.json file too, but my guess would be that setupTests.ts is not being included as a source file in the TypeScript config when compiling the tests, which means TypeScript would never see the import statement and would therefore not augment the jest namespace. It would also explain why adding the import to a single test file fixes it (since the namespace only needs to be augmented once).

I can think of a couple possible solutions:

  1. Make sure setupTests.ts is in the files or include section of your tsconfig.json file
  2. Add a .d.ts file to your project (like jest-dom.d.ts), making sure it's included in the files or include section, that looks like the following:
```ts
import "jest-dom/extend-expect";
```
(This is what I do in my projects.)

You can try either one of the above - no need to do both.

All 19 comments

It would be helpful to see the tsconfig.json file too, but my guess would be that setupTests.ts is not being included as a source file in the TypeScript config when compiling the tests, which means TypeScript would never see the import statement and would therefore not augment the jest namespace. It would also explain why adding the import to a single test file fixes it (since the namespace only needs to be augmented once).

I can think of a couple possible solutions:

  1. Make sure setupTests.ts is in the files or include section of your tsconfig.json file
  2. Add a .d.ts file to your project (like jest-dom.d.ts), making sure it's included in the files or include section, that looks like the following:
```ts
import "jest-dom/extend-expect";
```
(This is what I do in my projects.)

You can try either one of the above - no need to do both.

Thanks! Your tips got me in the right direction. I did not even have to add the file to the includes, but rather remove it from the excludes. Turns out create-react-app-typescript's default configuration excludes it, as you can see here. I wonder why they do that? Should I file an issue with them?

Anyway, thanks again. I'm closing this.

Great!

It looks like excluding that file was deliberate: https://github.com/wmonk/create-react-app-typescript/commit/8e24948ce2a06148fd8e229c6b356a62d7ab83dc

It should probably be handled in the tsconfig.test.json file (which I assume is used for tests), but it would involve duplicating the exclude config from tsconfig.json due to the rules around extends and include, exclude:

tsconfig.test.json:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "commonjs"
  },
  "exclude": [
    "node_modules",
    "build",
    "scripts",
    "webpack"
  ]
}

Hmmm, but when I do that, vscode still flags me the error. And not just vscode, but CRA's npm run start as well:

Failed to compile.

/Users/ernesto/code/mck/org-admin/src/lib/api/__tests__/Query.tsx
(45,21): Property 'toHaveTextContent' does not exist on type 'Matchers<void>'.

BTW I nevertheless opened the ticket wmonk/create-react-app-typescript#371 though your response does clarify a bit about the why. I'll try your second method and see how it goes.

Maybe the tsconfig.test.json file is not actually being used when executing the tests. Does this use ts-jest?

Wouldn't know. I'm using create-react-app-typescript and this is my first TypeScript project ever. I'll continue digging and hopefully also someone in that ticket will respond.

For anyone else wondering here: We were having this problem mainly with VSCode. Project ran tests fine without warnings. Creating a src/@types/jest-dom.d.ts with:

import "jest-dom/extend-expect";

"fixed" it for us :)

I started with what @Darep did but it looks like there is no need for creating separate @types folder.
To make it work I added below into globals.d.ts and it seems to fix the problem.

import "jest-dom/extend-expect";

@Darep What's your reasoning behind @types folder?

The issue for us turned out to be that the setup file was still a .js instead of .ts! 😅

I still have problems, even though my setupTests file is .ts. I still ge errors liket:

error TS2304: Cannot find name 'afterAll'.
error TS2339: Property 'toBeInTheDocument' does not exist on type 'Assertion'.
https://travis-ci.org/MoeSauber/change/builds/570179189#L363-L397

Failing PR: https://github.com/MoeSauber/change/pull/50

error TS2304: Cannot find name 'afterAll'.

afterAll is not provided by jest-dom but by jest itself. So it looks like you've got deeper issues with TS+jest and not just with jest-dom.

It would be helpful to see the tsconfig.json file too, but my guess would be that setupTests.ts is not being included as a source file in the TypeScript config when compiling the tests, which means TypeScript would never see the import statement and would therefore not augment the jest namespace. It would also explain why adding the import to a single test file fixes it (since the namespace only needs to be augmented once).

I can think of a couple possible solutions:

  1. Make sure setupTests.ts is in the files or include section of your tsconfig.json file
  2. Add a .d.ts file to your project (like jest-dom.d.ts), making sure it's included in the files or include section, that looks like the following:

    import "jest-dom/extend-expect";
    

    (This is what I do in my projects.)

You can try either one of the above - no need to do both.

My solve is to define a file called "scripts/setupEnv.d.ts", and include it in tsconfig.json file, it seems it can pass the test case, however the api of @testing-library/jest-dom/extend-expect is still in red.

image

Maybe this would help:

import '@testing-library/jest-dom/extend-expect';

Also add @types/testing-library__jest-dom to dependencies of your project.

add a file named 'jest-dom-d.ts' in src/@types include
import '@testing-library/jest-dom/extend-expect';

Maybe this would help:

import '@testing-library/jest-dom/extend-expect';

Also add @types/testing-library__jest-dom to dependencies of your project.

@kirill-konshin THANK YOU! I added this at the top of my test file, and it fixed the issue.

I have a setupTests.ts configured with jest.config setupFilesAfterEnv with import '@testing-library/jest-dom/extend-expect'.

My test compiles & passes, but VSCode still complains that Property 'toBeInTheDocument' does not exist on type 'Matchers<HTMLElement> unless I add "testing-library__jest-dom" to my tsconfig.json "types" option.

But this is not a proper fix as the method toBeInTheDocument is of type any, and when trying to navigate to definition it says "No definition found for ...".

Any ideas? Why doesn't this just work out-of-the-box like other "npm @types" packages? What am I missing?

Why doesn't this just work out-of-the-box like other "npm @types" packages

There are differences with regular packages. For starters a regular package you'll most likely import explicitly what you need from it in the modules you are using it. Custom jest matches OTOH are not imported in the modules you use it, but in a central location, and they also are not used explicitly from the dependency, but they are injected instead into the custom matchers namespace provided by whatever expect(...) returns.

That being said, importing jest-dom from the file configured in jest's setupFilesAfterEnv should work out of the box. I can't say why it isn't working in your case without having a reproducible example. Can you reproduce this in a minimal repo? (ideally not created with CRA because it is mostly certain that it'll work in CRA out-of-the-box, but that also is an example of how it works, in case you want to compare your setup with a newly created CRA app).

@gnapse ah ok. Thanks for the response & info. In the end my problem was I had a mismatched version of "@types/jest" (24.x vs latest of everything else) that was causing a conflict with the Matcher interface 🤦‍♂️ (it was not explicitly complaining about that though, so it was hard to find). Also my project is a components library so a little different project configs than CRA.

Through this problem I also learnt more about the tsconfig "types" option, originally I had "types": ["node", "react", "jest"], remove all of them I learnt then loads everything in "rootDirs" i.e default @types. This plus fixing my versions meant everything was fine... Until I came across compile issues with styled-components v5 @types weird react-native dependency. So my final tsconfig is

"types": [
      "node",
      "react",
      "jest",
      "jest-styled-components",
      "@types/testing-library__jest-dom"
    ],

with jest config (I removed the setupTests.ts file in favour of just doing it like this):

setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect', 'jest-styled-components'],

Noting that jest-styled-components does a similar thing you mentioned regarding the injected custom matchers.

Just for anyone else maybe working with these packages. Cheers

thank you @xaun. adding "@types/testing-library__jest-dom" to types in tsconfig.json fixed the issue for me

"types": [
      "node",
      "jest",
      "@types/testing-library__jest-dom"
    ],
Was this page helpful?
0 / 5 - 0 ratings