Property 'toBeOnTheScreen' does not exist on type 'JestMatchers<ReactTestInstance>' (TS project)
-
react-nativeorexpo: RN -
@testing-library/react-nativeversion: ^11.4.0 -
jest-preset: "react-native" -
react-nativeversion: 0.70.6 -
nodeversion: 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
@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.
@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.
Hey, you have forgot to install testing-library/jest-native
Install it and then check it will work.
Thanks,
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();
});
@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.
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,
})
@Aure77 @frankcalise @emflomed17 Does the issue affect only toBeOnTheScreen matcher or other marchers as well?
@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 yourjest-setup.js(make sure it'ssetupFilesAfterEnv) 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)
@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"]
},
"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)
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)
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
}
}
}
Recommended Workarounds 🚑
After some investigation I've found that the TS types (tsc --noEmit or intellisense in VSCode) work correctly in three alternative cases:
- You have a top-level
declarations.d.tsfile 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 ----
- You use
import '@testing-library/jest-native/extend-expect';in yourjest-setup.tsfile (note: it has to be.ts), which is added tosetupFilesAfterEnvJest config.
Not sure why this works, but it works fine with allowJs: false TypeScript compiler option.
---- OR ----
-
tsconfig.jsonincludesallowJs: trueas compiler option and you havejest-setup.jsfile 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.
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.
I've added the documentation for official TS workarounds: https://github.com/testing-library/jest-native#typescript-support
@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:
- testing/library jest-dom: https://github.com/testing-library/jest-dom#usage
Talking about VS Code intellisense, I've tried every workaround and only following solutions worked
- adding following to
tsconfig.json
"compilerOptions": {
"types": ["@testing-library/jest-native", "jest"]
},
- adding
import '@testing-library/jest-native/extend-expect';to every.testfile
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"
@CptFabulouso could you check if using TS 'jest-setup.ts' + 'include' option in 'tsconfig.json' as describe here solves the issue for you?
@mdjastrzebski Yes, that change in tsconfig.json was the missing part, thank you. So to summarise I have:
-
jest-setup.tsfile with:
import '@testing-library/jest-native/extend-expect';
- and in
tsconfig.json
"include": [
...
"./jest-setup.ts"
],
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__"]