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

[Question] How i can test my functions with jest? #3035

Closed
approached opened this issue Dec 23, 2019 · 32 comments
Closed

[Question] How i can test my functions with jest? #3035

approached opened this issue Dec 23, 2019 · 32 comments
Labels
Type: Question Type: Stale Issue has become stale - automatically added by Stale bot Type: Testing Issues or PRs relating to testing (the library or user code testing) Version: >= 6

Comments

@approached
Copy link

Hi@all,

How i can test my functions with jest? I become follow error:

 FAIL  src/data/auth/__test__/register.test.js
  ● Test suite failed to run

    /Users/approach/workspace/TakeActive/node_modules/@react-native-firebase/analytics/lib/index.js:18
    import {
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

    > 1 | import analytics from "@react-native-firebase/analytics";
        | ^

My jest.config.js

module.exports = {
  roots: ['src'],
};

Has anybody a idea? In the documentation i don't found help.


Think react-native-firebase is great? Please consider supporting all of the project maintainers and contributors by donating via our Open Collective where all contributors can submit expenses. [Learn More]

@tattivitorino
Copy link

I am having a similar problem with imports.

`
import { getFirebaseRoot } from './internal/registry/namespace';

SyntaxError: Cannot use import statement outside a module

> 1 | import firebase from '@react-native-firebase/app';
    | ^
  2 | import '@react-native-firebase/firestore';
  3 | import '@react-native-firebase/crashlytics';`

@mikehardy
Copy link
Collaborator

Add it to transformIgnorePattern perhaps - I'm still on v5 but I imagine I'll have to add it as an extra entry in the 'or' part of the pattern match like this

(base) mike@kunashir:~/work/Kullki/ksocialscore/packages/public-app (onboarding) % more jest.config.js 
module.exports = {
  rootDir: './dist/tests/rnapp/js',
  roots: ['<rootDir>'],
  // transform: {
  //   '^.+\\.tsx?$': 'ts-jest',
  // },
  transformIgnorePatterns: [
    'node_modules/(?!@react-native-community/google-signin|react-native|reactxp-webview|react-pose-core|animated-pose|@react-native-community/async-storage|@invertase/react-native-apple-authentication)',
  ],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  preset: 'react-native',
  testEnvironment: 'jsdom',
  collectCoverage: true,
  setupFilesAfterEnv: [
    './__mocks__/mockFirebase.js',
    './__mocks__/mockReactNative.js',
    './__mocks__/mockAsyncStorage.js',
  ],
};
// module.exports = {
//  testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
// };

@tattivitorino
Copy link

tattivitorino commented Jan 6, 2020

@mikehardy I have a transformIgnorePattern setup like below in the package.json and I'm on v6

{
  "scripts": {
    "postinstall": "jetify",
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "web": "expo start --web",
    "start": "react-native start",
    "test": "jest"
  },
  "dependencies": {
    "@react-native-community/async-storage": "^1.7.1",
    "@react-native-firebase/app": "^6.2.0",
    "@react-native-firebase/auth": "^6.2.0",
    "@react-native-firebase/crashlytics": "^6.2.0",
    "@react-native-firebase/firestore": "^6.2.0",
    "expo": "~36.0.0",
    "expo-asset": "^8.0.0",
    "expo-font": "^8.0.0",
    "expo-linear-gradient": "^8.0.0",
    "expo-location": "^8.0.0",
    "expo-permissions": "^8.0.0",
    "formik": "^2.0.8",
    "geofirestore": "^3.3.1",
    "geolib": "^3.2.0",
    "haversine": "^1.1.1",
    "js-sha256": "^0.9.0",
    "lodash": "^4.17.15",
    "moment": "^2.24.0",
    "moment-duration-format": "^2.3.2",
    "native-base": "^2.13.8",
    "react": "~16.9.0",
    "react-dom": "~16.9.0",
    "react-native": "~0.61.4",
    "react-native-base64": "^0.0.2",
    "react-native-dotenv": "^0.2.0",
    "react-native-elements": "^1.2.7",
    "react-native-gesture-handler": "~1.5.0",
    "react-native-keyboard-aware-scroll-view": "^0.9.1",
    "react-native-maps": "^0.26.1",
    "react-native-maps-animated-polyline": "^1.0.6",
    "react-native-maps-super-cluster": "^1.6.0",
    "react-native-reanimated": "~1.4.0",
    "react-native-safe-area-context": "0.6.0",
    "react-native-safe-area-view": "^1.0.0",
    "react-native-scalable-image": "^1.0.0",
    "react-native-screens": "~2.0.0-alpha.12",
    "react-native-splash-screen": "^3.2.0",
    "react-native-svg": "^9.13.6",
    "react-native-unimodules": "~0.7.0",
    "react-native-web": "~0.11.7",
    "react-navigation": "^4.0.10",
    "react-navigation-drawer": "^2.2.2",
    "react-navigation-header-buttons": "^3.0.4",
    "react-navigation-stack": "^1.9.4",
    "react-navigation-tabs": "^2.5.6",
    "react-redux": "^7.1.1",
    "redux": "^4.0.4",
    "redux-thunk": "^2.3.0",
    "reselect": "^4.0.0",
    "throttle-debounce": "^2.1.0"
  },
  "devDependencies": {
    "@babel/core": "~7.6.0",
    "babel-jest": "~24.9.0",
    "jest": "~24.9.0",
    "jest-expo": "^36.0.0",
    "jetifier": "~1.6.4",
    "metro-react-native-babel-preset": "~0.56.0",
    "react-native-svg-transformer": "^0.14.3",
    "react-test-renderer": "~16.9.0",
    "redux-devtools-extension": "^2.13.8"
  },
  "jest": {
    "projects": [
      {
        "preset": "jest-expo/ios"
      },
      {
        "preset": "jest-expo/android"
      }
    ],
    "transformIgnorePatterns": [
      "node_modules/(?!(jest-)?react-native|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|@react-native-firebase/app)"
    ]
  },
  "private": true
}

@mikehardy
Copy link
Collaborator

why just @react-native-firebase/app? Try all @react-native-firebase maybe

@tattivitorino
Copy link

@mikehardy I tried @react-native-firebase and @react-native-firebase/.* and still having the same error! :( I must say I am new to Jest testing so I'm quite lost in the middle of so many configs.

and thanks a lot for taking the time to try and help

@Shaquu
Copy link

Shaquu commented Jan 12, 2020

Well I have the same problem. Do anyone have a solution?

@stale
Copy link

stale bot commented Feb 10, 2020

Hello 👋, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community's attention?

This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.

@stale stale bot added the Type: Stale Issue has become stale - automatically added by Stale bot label Feb 10, 2020
@midal
Copy link

midal commented Feb 14, 2020

I still have the same problem. Any updates? Please don't close this

@stale stale bot removed the Type: Stale Issue has become stale - automatically added by Stale bot label Feb 14, 2020
@anfriis
Copy link

anfriis commented Feb 27, 2020

I also have this problem, and couldn't solve it with the suggested transformIgnorePattern's...

@anfriis
Copy link

anfriis commented Feb 27, 2020

I added my transformIgnorePattern to my jest.config.js instead which was overriding the setting in package.json.
Now I get this issue instead:

 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)

Looking around similar issues it seems like it can be mocked - just gotta figure out how.

@anfriis
Copy link

anfriis commented Feb 28, 2020

I'm also on v6 and Crashlytics were causing the issue in my case but managed to solve it.
To solve the before mentioned Invariant Violation issue, I added a crashlytics.js file in this folder structure: <rootDir>/jest/mocks/firebase/crashlytics.js:

export default () => ({
    log: message => {},
    recordError: err => {},
})

And added the following to my jest.config.js:

moduleNameMapper: {
    '@react-native-firebase/crashlytics': '<rootDir>/jest/mocks/firebase/crashlytics.js',
}

I actually didn't need the transformIgnorePattern in the jest.config.js to make it work.
@mikehardy @approached

@LorandP
Copy link

LorandP commented Mar 25, 2020

This worked for me.
You can try to use jest.mock() right above the first import in your test file like this:

jest.mock('../location_of_your_module', () => {
    return () => ({
      function_that_you_want_to_mock: jest.fn(),
      ....
     });
});

@stale
Copy link

stale bot commented Apr 23, 2020

Hello 👋, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community's attention?

This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.

@stale stale bot added the Type: Stale Issue has become stale - automatically added by Stale bot label Apr 23, 2020
@januarioprime
Copy link

Facing the same problem with v6 even though I've tried the suggested workarounds. Any thoughts ?

@stale stale bot removed the Type: Stale Issue has become stale - automatically added by Stale bot label May 5, 2020
@PierreCapo
Copy link

@januarioprime to fix the problem:

Create a __mocks__ folder at the root of your project, and add the mocked modules you are using there. For instance:

// __mocks__/@react-native-firebase/app.js

export default () => ({
  currentUser: { idToken: 'mocked-id-token' },
});
// __mocks__/@react-native-firebase/auth.js

export default () => ({
  signInWithEmailAndPassword: jest.fn(),
  createUserWithEmailAndPassword: jest.fn(),
  signOut: jest.fn(),
  sendPasswordResetEmail: jest.fn(),
});

For me it has solved the problem.

@Salakar
Copy link
Member

Salakar commented May 15, 2020

Hey all,

We use jest testing now on this mono-repo; our config file can be seen here: https://github.com/invertase/react-native-firebase/blob/master/jest.config.js

To get JS imports working correctly; the transform ignore pattern @mikehardy mentioned above is probably the way to go.

In terms of mocking you could do this via a jest setup file;

module.exports = {
  // ...
  setupFiles: ['./jest.setup.ts'],
  // ...
};

For our current testing cases this is what we've done in our jest.setup.ts file: https://github.com/invertase/react-native-firebase/blob/master/jest.setup.ts - this doesn't cover all native modules - you'll need to add additional ones that you're using.

Hopefully this helps.

@ccanalesb
Copy link

Well @mikehardy told me that i cannot laught, so i show my problem here.

Im still facing the issue
Have in my package.json

    "@react-native-firebase/app": "^6.7.1",
    "@react-native-firebase/crashlytics": "^6.7.1",
    "@react-native-firebase/database": "^6.7.1",
    "@react-native-firebase/messaging": "^6.7.1",

in my setup-jest.js

jest.mock('@react-native-firebase/app');

jest.mock('react-native-notifications');

jest.mock('@react-native-firebase/database');

jest.mock('@react-native-firebase/crashlytics', () => () => ({
  recordError: jest.fn(),
  logEvent: jest.fn(),
  setUserProperties: jest.fn(),
  setUserId: jest.fn(),
  setCurrentScreen: jest.fn(),
}));


jest.mock('@react-native-firebase/messaging', () => () => ({
  hasPermission: jest.fn(() => Promise.resolve(true)),
  subscribeToTopic: jest.fn(),
  unsubscribeFromTopic: jest.fn(),
  requestPermission: jest.fn(() => Promise.resolve(true)),
  getToken: jest.fn(() => Promise.resolve('myMockToken')),
  onTokenRefresh: jest.fn((callback) => callback(Promise.resolve('Example'))),
}));

But im still getting

  ● Test suite failed to run

    Invariant Violation: Native module cannot be null.

      at invariant (node_modules/invariant/invariant.js:40:15)
      at RNFBNativeEventEmitter.invariant (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)

Idk what more mock

@mikehardy
Copy link
Collaborator

I dunno, laughing while helping is a great combo. May be something missing still @Salakar how would you stub out the native emitter stuff? Why is that even being called in a jest environment (are there events to emit?)

@ccanalesb
Copy link

ccanalesb commented May 15, 2020

My friend @JulioOrellana find the solution to my problem

It was necesary create a mock file for every lib used

 __mocks__/@react-native-firebase/app.js         
 __mocks__/@react-native-firebase/crashlytics.js 
 __mocks__/@react-native-firebase/database.js    
 __mocks__/@react-native-firebase/messaging.js 
 __mocks__/react-native-notifications.js 

And in each of those file make the correct export
Idk if was a misconfiguration before, but mock in setup-test.js will not work for me

@Salakar
Copy link
Member

Salakar commented May 18, 2020

I linked above what you need to mock for Native modules e.g. the event emitter; https://github.com/invertase/react-native-firebase/blob/master/jest.setup.ts

If you mock the underlying react native native modules rather than the RNFB packages themselves you'll have a much better/accurate mock - or at least in our testing for RNFB itself that was the best way.

@alexwasner
Copy link

I also did the __mocks__/@react-native-firebase/... but for some of my tests, I had to create instances of the functions for the toHaveBeenCalled to be correct.

const hasPermission = jest.fn(() => Promise.resolve(true));
const requestPermission = jest.fn(() => Promise.resolve(true));
const subscribeToTopic = jest.fn();
const unsubscribeFromTopic = jest.fn();
const getToken = jest.fn(() => Promise.resolve('myMockToken'));

export default jest.fn(() => ({
  hasPermission,
  subscribeToTopic,
  unsubscribeFromTopic,
  requestPermission,
  getToken,
}));

for the test

    const result = await hasPermission();
    expect(messaging).toHaveBeenCalledTimes(1);
    expect(messaging().hasPermission).toHaveBeenCalledTimes(1);
    return expect(result).toEqual(true);

@russellwheatley russellwheatley added Type: Question Type: Testing Issues or PRs relating to testing (the library or user code testing) Version: >= 6 labels May 21, 2020
@stale
Copy link

stale bot commented Jun 20, 2020

Hello 👋, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community's attention?

This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.

@stale stale bot added the Type: Stale Issue has become stale - automatically added by Stale bot label Jun 20, 2020
@stale
Copy link

stale bot commented Jul 5, 2020

Closing this issue after a prolonged period of inactivity. If this is still present in the latest release, please feel free to create a new issue with up-to-date information.

@stale stale bot closed this as completed Jul 5, 2020
@garry-bit
Copy link

I am running into the same issue and have been following mikehardy's lead and still get this error:

image

my mock file looks like this:
image

and my package.json entry looks like this:
image

@mikehardy any ideas how to proceed?

Garry

@mikehardy
Copy link
Collaborator

You'll need to mock out RNFBEventEmitter from app as well

@hrdyjan1
Copy link

hrdyjan1 commented Oct 8, 2021

The solution, that works for me:

  1. create a file named jest/mocks/@react-native-firebase/crashlytics.js
export default () => ({
  log: jest.fn(),
  recordError: jest.fn(),
});
  1. create a file named jest/jestSetupFile.js
import mockFirebaseCrashlytics from './mocks/@react-native-firebase/crashlytics';

jest.mock('@react-native-firebase/crashlytics', () => mockFirebaseCrashlytics);
  1. in package.json add
 "jest": {
    "setupFiles": ["./jest/jestSetupFile.js"]
  },

@mikehardy
Copy link
Collaborator

@hrdyjan1 If you want to do a PR to our main jest setup file here

RNFBCrashlyticsModule: {},

Then you could just reference it, and everyone would benefit (including yourself as whatever future modules you wanted to mock would also work...)

@MAIDUONGTHAO2010
Copy link

MAIDUONGTHAO2010 commented Oct 17, 2021

I have some warning,when i run npm run test with jest and logger firebase-function.How can i remove this warning.Please help me
image

@levino
Copy link

levino commented Nov 22, 2021

The suggested workarounds disable any possibility to actually test the code. What is the purpose of jest tests, if I cannot run them against an emulator? Instead of these mocks, I think one should write the code so that @react-native-firebase packages are only imported / loaded when building for mobile and use firebase in the jest tests. To this end one will have to work with dependency injection.

@mikehardy
Copy link
Collaborator

even the emulator is a network round trip, it's external to your code and running an actual function on the other side, just not costing you a function execution in the cloud. I believe that's the definition of an integration test.

For jest testing react-native-firebase code against functions you do want to mock out the function itself and assert the function was called with expected arguments, and that your code then handled expected return values correctly.

To test the actual function code is another thing - that's the firebase node sdk and is a completely different thing, in my project I have that in another package in my monorepo, next to the react-native app but separate except for some shared model typings

@eFosk
Copy link

eFosk commented May 31, 2022

My friend @JulioOrellana find the solution to my problem

It was necesary create a mock file for every lib used

 __mocks__/@react-native-firebase/app.js         
 __mocks__/@react-native-firebase/crashlytics.js 
 __mocks__/@react-native-firebase/database.js    
 __mocks__/@react-native-firebase/messaging.js 
 __mocks__/react-native-notifications.js 

And in each of those file make the correct export Idk if was a misconfiguration before, but mock in setup-test.js will not work for me

What if a want to mock Firebase/storage? what is the export in this case

@anisurrahman072
Copy link

great

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Question Type: Stale Issue has become stale - automatically added by Stale bot Type: Testing Issues or PRs relating to testing (the library or user code testing) Version: >= 6
Projects
None yet
Development

No branches or pull requests