Firebase-js-sdk: Unable to mock auth with @firebase/testing ('auth/invalid-api-key')

Created on 18 Apr 2020  路  6Comments  路  Source: firebase/firebase-js-sdk


[REQUIRED] Describe your environment

  • Operating System version: macOS 10.14.6
  • Browser version: N/A
  • Node.js version: v12.13.1
  • Firebase SDK version: [email protected], @firebase/[email protected]
  • Firebase Product: auth

[REQUIRED] Describe the problem

The firebase document claims that @firebase/testing supports mocking auth.

While many SDKs work with the emulators, only the @firebase/testing Node.js module supports mocking auth in Security Rules, making unit tests much easier.

However, when using @firebase/testing to mock auth, it throwes an error about Your API key is invalid.

Steps to reproduce:

Copy the javascript code blow into a file, and run the shell commands like this:

$ export DEBUG_TEST=
$ node --experimental-modules test.mjs 
using production firebase
user: null

$ export DEBUG_TEST=1
$ node --experimental-modules test.mjs 
using testing firebase

internal/modules/cjs/loader.js:1040
      internalBinding('errors').triggerUncaughtException(
                                ^
[u [Error]: Your API key is invalid, please check you have copied it correctly.] {
  code: 'auth/invalid-api-key',
  message: 'Your API key is invalid, please check you have copied it correctly.',
  a: null
}

Relevant Code:

import firebase from "firebase"
import firebaseTesting from "@firebase/testing"

const conf = {
    apiKey: "AIzaSyBNHCyZ-bpv-WA-HpXTmigJm2aq3z1kaH8",
    authDomain: "jscore-sandbox-141b5.firebaseapp.com",
    databaseURL: "https://jscore-sandbox-141b5.firebaseio.com",
    projectId: "jscore-sandbox-141b5",
    storageBucket: "jscore-sandbox-141b5.appspot.com",
    messagingSenderId: "280127633210"
  }

const getFirebaseApp = () => {
    if (process.env.DEBUG_TEST) {
        console.log('using testing firebase')
        if (firebaseTesting.apps().length) return firebaseTesting.apps()[0]
        else return firebaseTesting.initializeTestApp({
            auth: { uid: "alice", email: "[email protected]" },
            projectId: conf.projectId,
            databaseName: 'my-database'
        })
    } else {
        console.log('using production firebase')
        if (firebase.apps.length) return firebase.apps[0]
        else return firebase.initializeApp({ ...conf })
    }
}

const firebaseApp = getFirebaseApp()
const auth = firebaseApp.auth()
const user = auth.currentUser

console.log("user:", user)
internal-bug-filed testing-sdk

Most helpful comment

@cjpete We're working on an emulator for Firebase Auth as well, which will address your use case. We do not have timelines or anything else to share at this point.

All 6 comments

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

Thanks for filing the bug. As described in the doc, @firebase/testing only mocks out auth in security rules in Firestore, i.e. request.auth in firestore.rules. When you use getFirebaseApp().firestore to write to firestore, the security rules will behave as if you were logged in as the provided user. It however does not mock out the Firebase Auth JS SDK (i.e. firebase.auth(). The latter still reaches production.

I'll escalate this internally and we'll see how we can better clarify this in the docs.

I am experiencing this too. My particular user case is test a method which is calling admin.auth().getUser. I'd like to be able to provide a dummy user list / create a dummy user list in the same way that the test realtime database can be loaded with data.

@cjpete We're working on an emulator for Firebase Auth as well, which will address your use case. We do not have timelines or anything else to share at this point.

馃憤 - This is a common pattern for me:

const uid = this.firebaseApp.auth().currentUser?.uid;
const userRef = this.firebaseApp.database().ref('profiles')
userRef.child(uid).set(profileDataObject)

馃憤 - @cjpete here's my workaround in the test:

// @ts-ignore
firebaseApp.auth = () => {
    return { currentUser: { uid: "alice", email: "[email protected]" } };
}

Here's an even better way that Typescript does not barf on:

const auth = () => {
    return { currentUser: { uid: null } };
}
jest.spyOn(firebaseApp, 'auth').mockImplementation(auth);
Was this page helpful?
0 / 5 - 0 ratings