I'm trying to write tests for my react native firebase/firestore methods, which are written with jest and typescript. I'm getting different kinds of errors with different approaches, which have led me to follow a ts-jest guide to set up with react native, which led me through an error saying I couldn't use imports (fixed by adding the relevant node_modules to transformIgnorePatterns in jest.config.js), and now I have the error "Invariant Violation: Native module cannot be null".
I also tried setting automock:true
in jest.config.js, but this gave me 'Cannot read TypeError: Cannot read property 'OS' of undefined', where undefined is Platform inside @react-native-firebase/app. Does this mean I cannot test these functions on a normal windows machine, and instead need to be running the tests in some ios emulator? I've just migrated from MongoDB+my own server code to using firebase directly from react native in the hopes of avoiding a separate backend for just transporting data from the DB.
In some solutions, I've seen people mocking the functions in /firestore, but I want to actually store data on the emulator running on my machine to actually see if these functions are working. Does anyone have a solution to this? There has to be a lot of people who have had the same issue, but I can't find any solutions for it, so any help would be greatly appreciated.
Here are my current relevant files, tell me if you need more:
package.json:
{"name": "somename","version": "0.0.1","private": true,"scripts": {"android": "react-native run-android","ios": "react-native run-ios","start": "react-native start","emulators:start:firestore": "firebase emulators:start --only firestore","test": "jest", },"dependencies": { //Lots of other stuff here, but this is the important one"@react-native-firebase/firestore": "^7.2.2" },"devDependencies": {"@babel/core": "^7.10.5","@babel/plugin-transform-runtime": "^7.10.5","@babel/runtime": "^7.10.5","@firebase/testing": "^0.20.7","@react-native-community/eslint-config": "^0.0.5","@types/jest": "^26.0.4","@types/react-native": "^0.60.25","@typescript-eslint/eslint-plugin": "^2.12.0","@typescript-eslint/parser": "^2.12.0","babel-jest": "^26.1.0","eslint": "^6.5.1","jest": "^26.1.0","metro-react-native-babel-preset": "^0.56.0","react-test-renderer": "16.9.0","ts-jest": "^26.1.3","typescript": "^3.7.3" }}
jest.config.js (notice my transformIgnorePattern to ensure the firebase node_modules are compiled correctly):
const { defaults: tsjPreset } = require('ts-jest/presets');module.exports = { ...tsjPreset, preset: 'react-native', transform: { ...tsjPreset.transform,'\\.js$': './node_modules/react-native/jest/preprocessor.js', }, transformIgnorePatterns: ["node_modules/?!(@react-native-firebase/firestore|@firebase/testing|@react-native-firebase/app)"], globals: {'ts-jest': { babelConfig: true, } }, cacheDirectory: '.jest/cache',};
babel.config.js:
module.exports = { presets: ['module:metro-react-native-babel-preset'],};
My testfile:
import * as Members from '../../DBCommunications/MemberService';import firebase, {assertSucceeds} from '@firebase/testing';const memberId = '123';const memberName = 'Test';const memberImage = 'image.png';beforeAll(() => { firebase.initializeTestApp({projectId: 'testid', auth: {uid: 'tester', email: 'test@test.com'}})});afterAll(async () => { await Promise.all(firebase.apps().map((app: any) => app.delete())); await firebase.clearFirestoreData({projectId: 'testid'});});describe('Member Service', () => { it('Can create a member', async () => { const member = await Members.createMember(memberId, memberName, memberImage); expect(member).toBe(true); expect(true).toBeTruthy(); });});
Members.createMember (important bits):
import firestore, {FirebaseFirestoreTypes} from '@react-native-firebase/firestore'import {Member} from "../Interfaces/Member";export const createMember = async (id: string, name: string, image: string): Promise<boolean> => { return new Promise<boolean>((resolve, reject) => { const member: Member = { id: id, name: name, image: image }; firestore().collection(membersCollectionName).add(member) .then(() => resolve(true)) .catch(() => reject('Could not create member')); })};