ken
ken

Reputation: 2672

Get Firebase Error: No Firebase App '[DEFAULT]' has been created when using React-hooks-testing-library with jest

I using Firebase auth in React, and I try to test it with react-hooks-testing-library. The code I write is working. But when I try to test with react-hooks-testing-library I get this error:

FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created , call Firebase App.initializeApp() (app/no-app).

Here is my actual code:

useAuth.tsx

const defaultValue = {
     .. some value here
}

const AuthContext = createContext(defaultValue)

const AuthContextProvider = (props) => {
    const auth = useFirebaseAuth()

    return (
        <AuthContext.Provider
            value={auth}
        >
            {props.children}
        </AuthContext.Provider>
    );
}

const useAuth = () => {
    return useContext(AuthContext)
}

// I will like to test the function and behaviour inside this hooks, useFirebaseAuth() here
export default function useFirebaseAuth() {

    const [user, setUser] = useState(null)

  
    const loginWithEmailPassword = (email: string, password: string) => {

        const auth = getAuth() // the error point to this line!!! 

        //this code I followed the Firebase docs    
        return signInWithEmailAndPassword(auth, email, password)
            .then(res => {

            }).catch(error => {

            })
    }

    const signUpWithEmailPassword = () => {

    }


    return {
        user,
        loginWithEmailPassword,
        signUpWithEmailPassword
    }

}

export { useAuth, AuthContextProvider }

Inside this hook will have 3 item, which user, loginWithEmailPassword, signUpWithEmailPassword

Here is my test

useAuth.test.tsx

import React from 'react'
import { renderHook, act } from '@testing-library/react-hooks/native'
import useFirebaseAuth from '../useAuth';

// Here I tried to mock the auth function of Firebase
jest.mock('firebase/app', () => {
    return {
        App: () => ({
            app: mockGetApp
        }),
        auth: () => ({
            signInWithEmailAndPassword: mockSignIn,
            createUserWithEmailAndPassword: mockSignUp
        })
    }
})

const mockInitializeFirebase = jest.fn()
const mockSignUp = jest.fn(() => Promise.resolve())
const mockSignIn = jest.fn(() => Promise.resolve())
const mockGetApp = jest.fn()

jest.mock('../../utils/initAuth', () => {
    return {
        app: mockInitializeFirebase
    }
})

describe('useAuth Hooks testing', () => {

    test('Login with Email and Password', () => {
        const { result } = renderHook(() => useFirebaseAuth())

        console.log(result)

        //arrange it, confirm the initial state 
        expect(result.current.user).toBe(null)
        expect(typeof result.current.loginWithEmailPassword).toBe('function')
        expect(typeof result.current.signUpWithEmailPassword).toBe('function')

        const email = '[email protected]'
        const password = '123456'
        // here act
        act(() => {
            // The problem come from this line
            result.current.loginWithEmailPassword(email, password)
        })
        // here assert 
        expect(mockSignIn).toBeCalledWith(email, password)

    })
})

So when I fired the loginWithEmailPassword(email,password) function, it keep showing No Firebase App error. But in my project I already have this file, which is initialize the Firebase app already.

./initFirebase.tsx, here already initialize the app, and called it in index.tsx

import { initializeApp, getApps, getApp } from "firebase/app";
import getEnvVars from '../environment'

const env = getEnvVars()

interface firebaseType {
    apiKey: string,
    authDomain: string,
    projectId: string,
    messagingSenderId: string
}

let firebaseConfig: firebaseType;

if (env !== null) {

    const { apiKey, authDomain, projectId, messagingSenderId } = env
    firebaseConfig = {
        apiKey: apiKey,
        authDomain: authDomain,
        projectId: projectId,
        messagingSenderId: messagingSenderId
    };
}

export const initFirebase = () => {
    if (getApps().length === 0) {
        initializeApp(firebaseConfig);
    } else {
        getApp()
    }
}

So the error is only happened in test, so I think I should mock the initializeApp function and call it somewhere in the test. But I dont know how to do that.

I just get started in testing field. Somebody that have experience please give some help.

Here is the question:

  1. What happened to my code and test that make the error occured?

  2. What should I do in order to solve this error?

Thank you in advance.

Upvotes: 1

Views: 842

Answers (1)

ken
ken

Reputation: 2672

Solved this by mock it like this:

const mockSignUp = jest.fn(() => {
    return Promise.resolve({
        user: {
            uid: "fakeuid",
        },
    });
})
const mockSignIn = jest.fn(() => Promise.resolve({
    user: {
        uid: "fakeUid"
    }
}))

const mockGetAuth = jest.fn()

jest.mock('firebase/auth', () => {
    return {
        getAuth: () => mockGetAuth,
        signInWithEmailAndPassword: () => mockSignIn,
        createUserWithEmailAndPassword: () => mockSignUp
    }
})

Noted by this:

getAuth: ()=> mockGetAuth the 3 function there, this will mock as getAuth() in firebase to the mockGetAuth function I defined.

Then in test I can called the mock function like this:

// here check the mock function 
mockSignIn(mockGetAuth, email, password)
expect(mockSignIn).toBeCalledWith(mockGetAuth, email, password)

Upvotes: 1

Related Questions