Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to make this extend-expect work in Typescript? #36

Closed
tsiq-swyx opened this issue Apr 2, 2018 · 18 comments
Closed

How to make this extend-expect work in Typescript? #36

tsiq-swyx opened this issue Apr 2, 2018 · 18 comments
Labels
TypeScript Related to TypeScript. Note: only certain maintainers handle TypeScript labeled issues.

Comments

@tsiq-swyx
Copy link
Contributor

extend-expect throws a couple more things onto extend and of course typescript doesnt like that. Is there a way to also expand the types or otherwise modify index.d.ts to accommodate for the changed type signature of expect?

for google purposes this is the error i get:

[ts] Property 'toHaveTextContent' does not exist on type 'Matchers<void>'.
any
@kentcdodds
Copy link
Member

No idea. Perhaps there are clues in jest-extended?

@kentcdodds kentcdodds added the TypeScript Related to TypeScript. Note: only certain maintainers handle TypeScript labeled issues. label Apr 2, 2018
@tsiq-swyx
Copy link
Contributor Author

i just scanned through their code, they dont even have types -at all- so they're actually worse off than react-testing-library 😂

@tsiq-swyx
Copy link
Contributor Author

tsiq-swyx commented Apr 2, 2018

ok so i worked out how to use them, we might want to 1) document this 2) put this into the index.d.ts.

// standard stuff from the example
import * as React from 'react';
import {render, Simulate, wait} from 'react-testing-library'

// extends
import 'react-testing-library/extend-expect';
interface ExtendedMatchers extends jest.Matchers<void> {
  toHaveTextContent: (htmlElement: string) => object;
  toBeInTheDOM: () => void;
}

//usage example
test('displays greeting when clicking Load Greeting', async () => {
  const { getByLabelText, getByText, getByTestId, container } = render(
    <Tooltip label="hello world">Child</Tooltip>
  );
  (getByLabelText('name') as HTMLInputElement).value = 'Mary';
  (expect(getByTestId('greeting-text')) as ExtendedMatchers).toHaveTextContent(
    'Hello Mary'
  );
})

@tsiq-swyx
Copy link
Contributor Author

let me know how you want this to proceed kent. i can take care of this entirely in userland, but you could help a very little bit by including this in the index.d.ts

@kentcdodds
Copy link
Member

Seems fine to me. I don't maintain the typings myself, but if you want to help take over maintaining the typings that'd be super.

@tsiq-swyx
Copy link
Contributor Author

I would be happy to do that. I just realized though that any types that this lib ships with would bind it to a particular testing frame work, eg jest. so this is probably actually best solved in userland. I will just submit a minor documentation PR for a typescript section.

tsiq-swyx added a commit to tsiq-swyx/react-testing-library that referenced this issue Apr 2, 2018
@kentcdodds
Copy link
Member

Actually, this file is specific to Jest so if there's a way to only apply these types if this file is utilized then that'd be fine.

kentcdodds pushed a commit that referenced this issue Apr 2, 2018
@antsmartian
Copy link
Collaborator

antsmartian commented Apr 3, 2018

@tsiq-swyx Thanks for the fix. @kentcdodds Somehow, I'm not getting the notifications on this project, even though I'm watching it ;) Checking manually now :)

@antsmartian
Copy link
Collaborator

Closing this w.r.t 3a5eab8

@michalstocki
Copy link

Just passing by looking for solution for a similar issue. I've found out a solution. You can probably fix the issue by putting the following code in the typings of react-testing-library:

declare namespace jest {
  interface Matchers<R> {
    toHaveTextContent: (htmlElement: string) => object;
    toBeInTheDOM: () => void;
  }

  interface Expect {
    toHaveTextContent: (htmlElement: string) => object;
    toBeInTheDOM: () => void;
  }
}

It uses Declaration Merging.

@michalstocki
Copy link

Ok I realized that it seems that the issue is already fixed here: testing-library/jest-dom#11

@simonhaenisch
Copy link

I just ran into the same issue and found a nice solution, similar to what @michalstocki was suggesting, but wanted to clarify it more. If you create a file called jest.d.ts, its namespace declaration will be merged with the one provided by Jest itself. For example, for a custom matcher

expect('string').toEndWith('ing');

you would extend the namespace

// custom jest.d.ts somewhere in the source

declare namespace jest {
  interface Matchers<R> {
    toEndWith(value: string): CustomMatcherResult;
  }
}

and implement

expect.extend({
  toEndWith: (actualString: string, expectedEnding: string) => ({
    message: `expected that ${actualString} ends with ${expectedEnding}`,
    pass: actualString.endsWith(expectedEnding),
  }),
});

Thought I'd leave this here because this is the first search result that came up for me 🤓

@erichulburd
Copy link

@simonhaenisch thanks. Since jest is not an imported module, in jest.d.ts, I also had to declare this as a global, so:

declare global {
    namespace jest {
      interface Matchers<R> {
        toEndWith(value: string): CustomMatcherResult;
      }
  }
}

@SeanRoberts
Copy link

If anyone else ends up here after running through the stuff from TestingJavascript.com and getting an error about react-testing-library's matchers not existing on type 'Assertion', the issue is actually due to a conflict between Jest and Cypress, and has nothing to do with react-testing-library. The easiest fix I found was just adding the cypress folder to the excludes in my tsconfig.json in the root of my project:

{
  ...lots of config,
  "exclude": [
    "node_modules",
    "webpack",
    "jest",
    "cypress",
  ]
}

Hopefully this helps someone!

@thomasfl
Copy link

thomasfl commented Feb 5, 2019

I couldn't make any of the solutions above to work, so I went for a quick and dirty solution:.

const myExpect: any = Object.assign(expect);

myExpect.extend({
...

@yl92
Copy link

yl92 commented Feb 27, 2019

I couldn't make any of the solutions above to work, so I went for a quick and dirty solution:.

const myExpect: any = Object.assign(expect);

myExpect.extend({
...

In that case, one other way is to simply change the extension to .js if type checking is not that crucial in that test :)

@thewoolleyman
Copy link

None of the above options seemed to work for me (I'm using WebStorm 2019.2 and jest-dom 4.1.0).

I had to put the following in my test file.

I could NOT put these imports in a separate setupTests.ts or *.d.ts, that didn't work

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

Then I stopped getting warnings like "Error:(27, 16) TS2339: Property 'toBeVisible' does not exist on type 'Matchers'."

@kentcdodds
Copy link
Member

Related: testing-library/jest-dom#123

@testing-library testing-library locked as off-topic and limited conversation to collaborators Sep 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
TypeScript Related to TypeScript. Note: only certain maintainers handle TypeScript labeled issues.
Projects
None yet
Development

No branches or pull requests

10 participants