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

Property 'toBeOnTheScreen' does not exist on type 'JestMatchers<ReactTestInstance>' (TS project) #146

Open
Aure77 opened this issue Jan 20, 2023 · 20 comments

Comments

@Aure77
Copy link

Aure77 commented Jan 20, 2023

  • react-native or expo: RN
  • @testing-library/react-native version: ^11.4.0
  • jest-preset: "react-native"
  • react-native version: 0.70.6
  • node version: 16

Relevant code or config:

const menuTitle = screen.getByText("My wonderful title");
expect(menuTitle).toBeOnTheScreen(); // tsc error

What you did:

Try to use custom matcher in a TS project that check types with tsc.

What happened:

Typescript check error.

Reproduction:

const menuTitle = screen.getByText("My wonderful title");
expect(menuTitle).toBeOnTheScreen(); // tsc error

Problem description:

Custom matcher of jest-native are not exposed as TS types. So a TS project have issue when build with TS compiler (tsc):
Ex:
Property 'toBeOnTheScreen' does not exist on type 'JestMatchers<ReactTestInstance>' (TS project)

Suggested solution:

expose types in package.json

@mdjastrzebski
Copy link
Collaborator

mdjastrzebski commented Jan 26, 2023

@Aure77 we have an basic example app in RNTL repo that showcases correct config for RNTL + JestNative + TS. Pls compare your config with that.

Matchers should be properly exposed for TS. Make sure that you are using the latest version of Jest Native (5.4.1) because of #138.

@jonathanj
Copy link

@Aure77 I had the same problem, in my setup I had .jest/setup.ts which meant that the include option in tsconfig.json wasn't including this file (since it was src/**/*). Maybe you have a similar issue.

@komalharmale
Copy link

Hey, you have forgot to install testing-library/jest-native
Install it and then check it will work.

Thanks,

@emflomed17
Copy link

I had same issue. All my config files were ok.

I fixed it importing: import '@testing-library/jest-native/'; on every test.

Example:

import React from 'react';
import { render, screen } from '@testing-library/react-native';
import '@testing-library/jest-native/'; // HERE!!
import MyComponent from '../MyComponent';


it('should render with the correct props', () => {
  const onPress = jest.fn();

  render(
    <TestWrapper>
      <MyComponent text="Click Here" variant="filled" onPress={onPress} />
    </TestWrapper>
  );

  const btnText = screen.getByText('Click Here');
  
  expect(btnText).toBeOnTheScreen();

});

@mdjastrzebski
Copy link
Collaborator

@emflomed17 did you follow the installation instructions at https://github.com/testing-library/jest-native#usage ?

In correct setting adding import '@testing-library/jest-native/extend-expect'; to your jest-setup.js (make sure it's setupFilesAfterEnv ) file should be enough to make matchers work correctly.

@frankcalise
Copy link

I experience the same. It only goes away if like @emflomed17 mentions, you import it on the test or extend expect inline in the test file.

The only other thing to mention is I'm in a yarn workspace within a monorepo? Not sure that matters though. The error clearly goes away when you bring in the import line to the test file specifically. The tests all pass whether or not TS has an error about the matcher

package.json config

  "jest": {
    "preset": "@testing-library/react-native",
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "jsx",
      "json"
    ],
    "setupFilesAfterEnv": [
      "./jest-setup.js"
    ],
    "setupFiles": [
      "../../node_modules/react-native-gesture-handler/jestSetup.js"
    ],
    "transformIgnorePatterns": [
      "../../node_modules/(?!(jest-)?@?react-native|@react-native-community|@react-navigation)"
    ],
    "collectCoverage": true,
    "coverageThreshold": {
      "global": {
        "branches": 7,
        "functions": 15,
        "lines": 20,
        "statements": 20
      }
    }
  }

jest-setup.js config

import { configure } from '@testing-library/react-native'

// Import Jest Native matchers
import '@testing-library/jest-native/extend-expect'

// Silence the warning: Animated: `useNativeDriver` is not supported because the native animated module is missing
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper')

// Mock Async storage
import mockAsyncStorage from '@react-native-async-storage/async-storage/jest/async-storage-mock'
jest.mock('@react-native-async-storage/async-storage', () => mockAsyncStorage)

// Mock Safe Area insets
jest.mock('react-native-safe-area-context', () => {
  const inset = { top: 0, right: 0, bottom: 0, left: 0 }
  return {
    ...jest.requireActual('react-native-safe-area-context'),
    SafeAreaProvider: jest.fn(({ children }) => children),
    SafeAreaConsumer: jest.fn(({ children }) => children(inset)),
    useSafeAreaInsets: jest.fn(() => inset),
    useSafeAreaFrame: jest.fn(() => ({ x: 0, y: 0, width: 390, height: 844 })),
  }
})

// Mock Reanimated
jest.mock('react-native-reanimated', () => {
  const Reanimated = require('react-native-reanimated/mock')

  // The mock for `call` immediately calls the callback which is incorrect
  // So we override it with a no-op
  Reanimated.default.call = () => {}

  return Reanimated
})

// Enable excluding hidden elements from the queries by default
configure({
  defaultIncludeHiddenElements: false,
})

@mdjastrzebski
Copy link
Collaborator

mdjastrzebski commented Mar 7, 2023

@Aure77 @frankcalise @emflomed17 Does the issue affect only toBeOnTheScreen matcher or other marchers as well?

@Aure77
Copy link
Author

Aure77 commented Mar 7, 2023

@emflomed17 did you follow the installation instructions at https://github.com/testing-library/jest-native#usage ?

In correct setting adding import '@testing-library/jest-native/extend-expect'; to your jest-setup.js (make sure it's setupFilesAfterEnv ) file should be enough to make matchers work correctly.

setupFilesAfterEnv doesn't impact TS typing on jest files (may only be used at runtime by jest runner)

@frankcalise
Copy link

@mdjastrzebski

If affects all matchers extended by jest-native, none of them show up in the intellisense / are underlined taht the property doesn't exist. Same for toBeEnabled, toBeDisabled etc.

Although, this seemed to help in my tsconfig.json

  "compilerOptions": {
    "types": ["@testing-library/jest-native", "jest"]
  },

@Aure77
Copy link
Author

Aure77 commented Mar 7, 2023

"types": ["@testing-library/jest-native", "jest"]

With this workaround, you need to add all your types manually (including @types/node, @types/react-native & all your custom types from dependencies...). I prefer import "@testing-library/jest-native" in each test file instead (more explicit but boring)

@callumskeet-bom
Copy link

I used a triple slash directive to get the correct types added:

/// <reference types="@testing-library/jest-native/extend-expect" />

This was in a .d.ts file that the ts compiler had visibility of (e.g. src/types/jest.d.ts)

@callumskeet-bom
Copy link

I was having issues getting types for this and reanimated's jest extensions. My updated file now looks like this:

import { JestNativeMatchers } from '@testing-library/jest-native/extend-expect'

declare global {
  namespace jest {
    interface Matchers<R> extends JestNativeMatchers<R> {
      // declaring this here as the library has the wrong typedef
      toHaveAnimatedStyle(
        style: Record<string, unknown>[] | Record<string, unknown>,
        options?: { exact?: boolean },
      ): R
    }
  }
}

@mdjastrzebski
Copy link
Collaborator

mdjastrzebski commented May 8, 2023

Recommended Workarounds 🚑

After some investigation I've found that the TS types (tsc --noEmit or intellisense in VSCode) work correctly in three alternative cases:

  1. You have a top-level declarations.d.ts file in your project and it contains:
/// <reference types="@testing-library/jest-native" />

This works because it causes typescript to globally import Jest type extension.

---- OR ----

  1. You use import '@testing-library/jest-native/extend-expect'; in your jest-setup.ts file (note: it has to be .ts), which is added to setupFilesAfterEnv Jest config.

Not sure why this works, but it works fine with allowJs: false TypeScript compiler option.

---- OR ----

  1. tsconfig.json includes allowJs: true as compiler option and you have jest-setup.js file which contains:
import '@testing-library/jest-native/extend-expect'; 

This basically disables type-checking on expect(...).toXxx matches, but the VS Code intellisense still works correctly.

@mdjastrzebski
Copy link
Collaborator

TBH I have no idea for "automatic" resolution, that would propagate Jest type extension just by including @testing-library/jest-native/extend-expect" in the setupFilesAfterEnv`.

Perhaps you folks will have any idea: @callumskeet-bom, @Aure77 , @frankcalise how to do such thing.

@mdjastrzebski
Copy link
Collaborator

I've added the documentation for official TS workarounds: https://github.com/testing-library/jest-native#typescript-support

@frankcalise
Copy link

@mdjastrzebski thanks for the documentation.

As far as the "automatic" resolution, I have to dive deeper into it. However, I know jest-dom adds custom matchers and the setup is documented as so:

@CptFabulouso
Copy link

Talking about VS Code intellisense, I've tried every workaround and only following solutions worked

  • adding following totsconfig.json
"compilerOptions": {
    "types": ["@testing-library/jest-native", "jest"]
  },
  • adding import '@testing-library/jest-native/extend-expect'; to every .test file

not sure why the declarations.d.ts solution is not working - is there anything additional I have to do? If I declare some random module there and try to import it, then the VS Code intellisense finds that module, so the file is loaded properly.

Using latest "@testing-library/jest-native": "^5.4.2", with "typescript": "^5.0.4"

@mdjastrzebski
Copy link
Collaborator

@CptFabulouso could you check if using TS 'jest-setup.ts' + 'include' option in 'tsconfig.json' as describe here solves the issue for you?

@CptFabulouso
Copy link

@mdjastrzebski Yes, that change in tsconfig.json was the missing part, thank you. So to summarise I have:

  • jest-setup.ts file with:
import '@testing-library/jest-native/extend-expect';
  • and in tsconfig.json
 "include": [
    ...
    "./jest-setup.ts"
  ],

@moriwang
Copy link

I had the same issue. The error was the exclude option in tsconfig.json, which included the folder containing the test files. TypeScript will not attempt to type-check or compile them.

"exclude": ["src/__tests__"]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants