React Native Jest Test TypeError: _reactNative.Linking.addEventListener is not a function - reactjs

As the title states I'm getting a weird error with the default jest test that is included in a React Native fresh install. The actual test:
import 'react-native';
import React from 'react';
import App from '../src/App';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('renders correctly', () => {
renderer.create(<App />);
});
My jest.setup.js:
// as supplied by the react navigation testing docs
import 'react-native-gesture-handler/jestSetup';
// Mock Ionicons pack
jest.mock('react-native-vector-icons/Ionicons', () => 'Icon');
// Silence the warning: Animated: `useNativeDriver` is not supported because the native animated module is missing
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');
My babel.config.js:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
};
Then I just try to run npm test (i.e. jest), and I get the following errors:
npm test
> optionscreener#0.0.1 test
> jest
ReferenceError: You are trying to `import` a file after the Jest environment has been torn down.
at Object.prefixes [as Linking] (node_modules/react-native/index.js:320:12)
at subscribe (node_modules/#react-navigation/native/src/useLinking.native.tsx:104:36)
at node_modules/#react-navigation/native/lib/commonjs/useLinking.native.js:183:12
at commitHookEffectListMount (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12932:26)
at commitPassiveMountOnFiber (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14346:11)
at commitPassiveMountEffects_complete (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14306:9)
at commitPassiveMountEffects_begin (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14293:7)
at commitPassiveMountEffects (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14281:3)
at flushPassiveEffectsImpl (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16233:3)
at flushPassiveEffects (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16182:14)
at node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16002:9
at workLoop (node_modules/scheduler/cjs/scheduler.development.js:266:34)
at flushWork (node_modules/scheduler/cjs/scheduler.development.js:239:14)
at Immediate.performWorkUntilDeadline [as _onImmediate] (node_modules/scheduler/cjs/scheduler.development.js:533:21)
RUNS __tests__/App-test.tsx
/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2608
throw error;
^
TypeError: _reactNative.Linking.addEventListener is not a function
at subscribe (/Users/chris/enterprise/OptionScreener/node_modules/#react-navigation/native/src/useLinking.native.tsx:104:45)
at /Users/chris/enterprise/OptionScreener/node_modules/#react-navigation/native/lib/commonjs/useLinking.native.js:183:12
at commitHookEffectListMount (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12932:26)
at commitPassiveMountOnFiber (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14346:11)
at commitPassiveMountEffects_complete (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14306:9)
at commitPassiveMountEffects_begin (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14293:7)
at commitPassiveMountEffects (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14281:3)
at flushPassiveEffectsImpl (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16233:3)
at flushPassiveEffects (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16182:14)
at /Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16002:9
Node.js v18.12.1
Just once I wish Jest and React Native would play nicely. But, once again, not today. Does anyone have any ideas as to what could be going wrong?

Can you try using jest.useFakeTimers in your jest.setup.js
It’s just a guess but can you give it a try?
If this doesn‘t work can you change the implementation of AppState from:
componentDidMount() {
AppState.addEventListener(
'change',
this._handleAppStateChange
);
}
componentWillUnmount() {
AppState.removeEventListener(
'change',
this._handleAppStateChange
);
}
To the new version:
useEffect(() => {
const subscription = AppState.addEventListener("change", nextAppState => {});
return () => {
subscription.remove();
};
}, []);

Related

Supabase to React data fetch error - supabaseUrl is required

I'm trying to set up my React app with Supabase for fetching data but everytime getting the error Uncaught Error: supabaseUrl is required.
Error Image
I've checked all the previous answers but still getting the error:
My .env.local file:
REACT_APP_SUPABASE_URL=https://eyd.....
REACT_APP_SUPABASE_ANON_KEY=eyJIUzI1Ni.....
My supabase.js file:
import { createClient } from "#supabase/supabase-js";
const supabaseUrl = process.env.REACT_APP_SUPABASE_URL;
const supabaseAnonKey = process.env.REACT_APP_SUPABASE_ANON_KEY;
export default createClient(supabaseUrl, supabaseAnonKey);
The file where I'm trying to fetch my data:
import React from "react";
import { useEffect } from "react";
import supabase from "../supabase";
export default function BlogPosts() {
async function fetchData() {
let { data: bposts, error } = await supabase.from("bposts").select("*");
console.log(bposts);
}
useEffect(() => {
fetchData();
}, []);
return <pre>{JSON.stringify(bposts, null, 2)}</pre>;
}
The error I'm getting:
SupabaseClient.ts:87
Uncaught Error: supabaseUrl is required.
at new SupabaseClient (SupabaseClient.ts:87:1)
at createClient (index.ts:38:1)
at ./src/supabase.js (supabase.js:6:1)
at options.factory (react refresh:6:1)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
at ./src/components/Blog/BlogCard.js (Blog.js:28:1)
at options.factory (react refresh:6:1)
at __webpack_require__ (bootstrap:24:1)
at fn (hot module replacement:62:1)
I've tried:
✅ restarted my dev instance
✅ rechecked the api values for REACT_APP_SUPABASE_URL and REACT_APP_SUPABASE_ANON_KEY
✅ checked if the REACT_APP_SUPABASE_URL is the same at the .env file
But nothing helped. Looking for a solution, would appreciate the help :)
If code is not able to access the env variable then try require("dotenv").config();
npm install dotenv

import 'useAuthenticator' from aws-amplify outputs "TypeError: window.URL.createObjectURL is not a function" when jest testing

I would like to know how to mock this kind of dependency's error. If I omit this import and comment out related source code, the test process is going to be fine. Already have got through Mock Function Jest, but no idea what I should do.
*This project was created by CRA with template typescript.
App component.
import { useAuthenticator } from '#aws-amplify/ui-react';
const App = () => {
const { user } = useAuthenticator((context) => [context.user]);
return (
<div>{user?.username}</div>
);
};
export default App;
Test code here.
import App from 'src/App';
import { render, screen } from '#testing-library/react';
describe('First group',()=>{
test('rendering App component',()=>{
// App includes 'import { useAuthenticator } from '#aws-amplify/ui-react';'
render(<App/>)
screen.debug()
})
})
Error outputs here.
● Test suite failed to run
TypeError: window.URL.createObjectURL is not a function
> 1 | import { useAuthenticator } from '#aws-amplify/ui-react';
| ^
2 |
3 | const App = () => {
4 | const { user } = useAuthenticator((context) => [context.user]);
at define (node_modules/maplibre-gl/dist/maplibre-gl.js:25:43)
at node_modules/maplibre-gl/dist/maplibre-gl.js:35:1
at node_modules/maplibre-gl/dist/maplibre-gl.js:3:81
at Object.<anonymous> (node_modules/maplibre-gl/dist/maplibre-gl.js:6:2)
at Object.<anonymous> (node_modules/#aws-amplify/ui-react/dist/index.js:1:484)
at Object.<anonymous> (src/App.tsx:1:1)
Based on slideshowp2's answer, added setup and config file. But still hits the error. Both are located rootDir.
jest.setup.js
if (typeof window.URL.createObjectURL === 'undefined') {
window.URL.createObjectURL = jest.fn();
}
jest.config.js
module.exports = {
setupFilesAfterEnv: ['./jest.setup.js'],
};
UPDATE
This PJ was created by CRA so it required to follow their rule. I finally resolved this by slideshowp2's answer and the correct location to put the pollyfilling code.
src/setupTests.ts
if (typeof window.URL.createObjectURL === 'undefined') {
window.URL.createObjectURL = jest.fn();
}
See troubleshooting#jest
As of v2.15.0 of #aws-amplify/ui-react which included the release of Geo components, users of the Jest testing framework may run into the following error when attempting to run tests:
window.URL.createObjectURL is not a function
Please follow the steps below to resolve this issue.
Navigate to or create a Jest setup file for your project.
Add the following code to polyfill the unrecognized function in your Jest setup file:
jest.setup.js:
if (typeof window.URL.createObjectURL === 'undefined') {
window.URL.createObjectURL = jest.fn();
}
jest.config.js:
module.exports = {
//...
setupFilesAfterEnv: ['./jest.setup.js'],
//...
}
This is a known problem when using the jsdom library (a dependency of Jest) with a package that uses an unrecognized function. See this issue.

Why is jest test not recognizing react native components?

I have a react native app that I am trying to run tests on, I have set up a basic greeting component as shown below called Greetings.js:
import React from 'react';
import {View, Text} from 'react-native';
const Greetings = ({hello}) => {
return (
<View>
<Text>{hello}</Text>
</View>
);
};
export default Greetings;
This is the test I am running called Greetings.test.js:
import React from 'react';
import {render, screen} from '#testing-library/react-native';
import Greetings from './Greetings';
describe('Greetings component', () => {
it('renders hello world as a test', () => {
render(<Greetings hello="Hello World!" />);
const helloWorldElement = screen.getByText('Hello World!');
expect(helloWorldElement).toBeInTheDocument();
});
});
For some reason it doesnt recognise the react native components, this is the error when running the test:
FAIL app/__tests__/components/Account/Greetings.test.js
● Console
console.error
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You li
forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `Greetings`.
at Greetings (C:\Users\meeve\OneDrive\Desktop\Cozify\smartliving-app\app\__tests__\components\Account\Greetings.js:4:21)
5 | return (
6 | <View>
> 7 | <Text>{hello}</Text>
| ^
8 | </View>
9 | );
10 | };
at printWarning (node_modules/react/cjs/react.development.js:220:30)
at error (node_modules/react/cjs/react.development.js:196:5)
at Object.createElementWithValidation [as createElement] (node_modules/react/cjs/react.development.js:2215:7)
at Greetings (app/__tests__/components/Account/Greetings.js:7:7)
at renderWithHooks (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6016:18)
at mountIndeterminateComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8744:13)
at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9966:16)
at performUnitOfWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13800:12)
It shows the same error for the View Component.
Should it not automatically recognize these components after initial setup?
I have installed the following:
yarn add install -dev react-test-renderer#17.0.1 #testing-library/react-native #testing-library/jest-native
The current Jest configuration in the package.json file:
"jest": {
"preset": "react-native",
"coverageThreshold": {
"app/**/selectors.{js,ts,tsx}": {
"_comment": "Let's strive to increase coverage, instead of lowering it!",
"lines": 57
}
},
"coverageDirectory": ".coverage/",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"native"
],
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js|jsx)$",
"testPathIgnorePatterns": [
"\\.snap$",
"<rootDir>/node_modules/"
],
"cacheDirectory": ".jest/cache",
"setupFiles": [
"./jest.setup.js"
]
}
Seems nothing wrong with the component rendering but the test.
You can use getByText query which can be obtained from render.
Please refer to React Native Testing Library for more information.
import React from 'react';
import {render} from '#testing-library/react-native';
import Greetings from './Greetings';
describe('Greetings component', () => {
it('renders hello world as a test', () => {
const {getByText} = render(<Greetings hello="Hello World!" />);
expect(getByText('Hello World!')).toBeDefined();
});
});
The application was set up a while back and it seems they had mocked out the react-native imports in the jest.setup.js file so that was causing the issue

Storybook: ReferenceError: jest is not defined

I have around 8-9 unit tests build on Jest-enzyme and running on storybook.
All of these tests runs and pass successfully using jest cli but when using storybook it throws error.
jest is not defined
ReferenceError: jest is not defined
at Module.<anonymous> (http://localhost:9010/main.b25dbb30a24ed968ce5a.bundle.js:596:1)
at Module../src/components/__tests__/inspectionType.stories.js (http://localhost:9010/main.b25dbb30a24ed968ce5a.bundle.js:620:30)
at __webpack_require__ (http://localhost:9010/runtime~main.b25dbb30a24ed968ce5a.bundle.js:785:30)
at fn (http://localhost:9010/runtime~main.b25dbb30a24ed968ce5a.bundle.js:151:20)
at webpackContext (http://localhost:9010/main.b25dbb30a24ed968ce5a.bundle.js:444:9)
at http://localhost:9010/main.b25dbb30a24ed968ce5a.bundle.js:31:34
at Array.forEach (<anonymous>)
at loadStories (http://localhost:9010/main.b25dbb30a24ed968ce5a.bundle.js:31:14)
at http://localhost:9010/vendors~main.b25dbb30a24ed968ce5a.bundle.js:5951:24
at render (http://localhost:9010/vendors~main.b25dbb30a24ed968ce5a.bundle.js:3965:13)
Now when I go to the story inspectionType.stories.js The code is -
import React, { useState as useStateMock } from "react";
import expect from "expect";
import { mount } from "enzyme";
// import jest from "jest";
import { storiesOf, describe, it, specs } from "../../../.storybook/facade";
import Root from "../../root";
import InspectionType from "../instant-inspection/inspectionType";
import consumerSchema from "./mock-consumer-schema.json";
import "../instant-inspection/index.scss";
const getElement = () => {
return (
<Root>
<InspectionType />
</Root>
);
};
jest.mock("react", () => ({ //The part throwing error//
...jest.requireActual("react"),
useState: jest.fn(),
}));
storiesOf("Inspection Type Page", module).add("Inspection Type component", () => {
specs(() =>
describe("Inspection page", () => {
localStorage.setItem("consumerSchemaSelected", JSON.stringify(consumerSchema));
const setState = jest.fn();
useStateMock.mockImplementation((init) => [init, setState]);
it("should render a primary button to open a sample report", () => {
const wrapper = mount(getElement());
expect(
wrapper
.find(".primary")
.at(0)
.text()
).toEqual(" VIEW SAMPLE REPORT");
});
it("should render a button with text buy now", () => {
const wrapper = mount(getElement());
expect(
wrapper
.find(".primary")
.at(1)
.text()
).toEqual("Buy Now");
});
it("Should simulate a state change on buy now button", () => {
const wrapper = mount(getElement());
wrapper
.find(".primary")
.at(1)
.props()
.onClick();
expect(setState).toHaveBeenCalledWith(true);
});
})
);
return getElement();
});
If I try to to import jest which is right now commented storybook doesn't build and throws the error -
ERROR in ./node_modules/jest-worker/build/workers/NodeThreadsWorker.js
Module not found: Error: Can't resolve 'worker_threads' in 'C:\Users\ATIN\Desktop\client master\client-2.0\react-ui\node_modules\jest-worker\build\workers'
# ./node_modules/jest-worker/build/workers/NodeThreadsWorker.js 29:15-40
# ./node_modules/jest-worker/build/WorkerPool.js
# ./node_modules/jest-worker/build/index.js
# ./node_modules/#jest/core/node_modules/jest-haste-map/build/index.js
# ./node_modules/#jest/core/node_modules/jest-runtime/build/index.js
# ./node_modules/#jest/core/node_modules/jest-jasmine2/build/index.js
# ./node_modules/#jest/core/node_modules/jest-config/build/normalize.js
# ./node_modules/#jest/core/node_modules/jest-config/build/index.js
# ./node_modules/#jest/core/build/SearchSource.js
# ./node_modules/#jest/core/build/jest.js
# ./node_modules/jest/build/jest.js
# ./src/components/__tests__/inspectionType.stories.js
# ./src/components sync \.stories\.js$
# ./.storybook/config.js
# multi ./node_modules/#storybook/core/dist/server/common/polyfills.js ./node_modules/#storybook/core/dist/server/preview/globals.js ./.storybook/config.js ./node_modules/webpack-hot-middleware/client.js?reload=true&quiet=true
Been trying to figure out how to solve the error but I am stuck.
EDIT: I resolved the error Jest is not defined by importing import "jest-enzyme"; but now I get expect is not defined. Even though I have imported expect.
Try doing what Joe Lloyd recommended which is adding the #storybook/addon-jest to your config file and that should do it.
# config.js
import { withTests } from '#storybook/addon-jest';
...
addDecorator(withTests({ results, filesExt: '\\.(test|story).tsx?$' }));
For those stating that jest shouldn't be used and not to mix it with the stories, in some cases it is needed, for instance:
<Parent>
<Child/> <--- consumes useSomeRandomHook()
</Parent>
In this case you need a way to mock the values returned by useSomeRandomHook if you want to avoid prop drilling.

React Native Expo - Jest - React Native Firebase - Invariant Violation: Native module cannot be null

I try to run tests with jest but it breaks with an error:
Invariant Violation: Native module cannot be null.
at invariant (node_modules/invariant/invariant.js:40:15)
at RNFBNativeEventEmitter.NativeEventEmitter (node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter.js:36:7)
at new RNFBNativeEventEmitter (node_modules/#react-native-firebase/app/lib/internal/RNFBNativeEventEmitter.js:24:5)
at Object.<anonymous> (node_modules/#react-native-firebase/app/lib/internal/RNFBNativeEventEmitter.js:48:16)
at Object.<anonymous> (node_modules/#react-native-firebase/app/lib/internal/registry/nativeModule.js:21:1)
I use latest versions for RN, Expo, Typescript and others.
My jest config is:
"jest": {
"preset": "jest-expo",
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native|react-native|react-clone-referenced-element|#react-native-community|expo(nent)?|#expo(nent)?/.*|react-navigation|#react-navigation/.*|#unimodules/.*|sentry-expo|native-base|#ui-kitten|#react-native-firebase/auth|#react-native-firebase/app)"
]
},
If I remove #react-native-firebase from transformIgnorePatterns then test fails with error:
import { isAndroid, isBoolean } from '#react-native-firebase/app/lib/common';
^^^^^^
SyntaxError: Cannot use import statement outside a module
1 | import * as React from 'react';
> 2 | import auth, { FirebaseAuthTypes } from '#react-native-firebase/auth';
Try to mock #react-native-firebase/your/needed/module
For example:
jest.mock('#react-native-firebase/app/lib/common', () => ({
isAndroid: jest.fn(() => true),
isBoolean: jest.fn(() => false),
}));

Resources