Firebase-js-sdk: `transaction.get` does not match firestore-admin in @firebase/testing

Created on 14 Jan 2020  路  6Comments  路  Source: firebase/firebase-js-sdk


[REQUIRED] Describe your environment

  • Operating System version: Ubuntu 19.10
  • Browser version: N/A
  • Firebase SDK version: 7.6.2
  • Firebase Product: testing / firestore

[REQUIRED] Describe the problem

With an app running on cloud functions the firestore is accessed via firebase-admin initializeApp.
For testing purposes I import @firebase/testing and initializeAdminApp to create a firestore.

In production code the code below works, but in testing it throws an error:
> (node:23599) UnhandledPromiseRejectionWarning: FirebaseError: Function Transaction.get() requires its first argument to be a DocumentReference, but it was: a custom CollectionReference object

Relevant Code:

Here is a simple snippet of example;

if (process.env.NODE_ENV !== 'test') {
  admin = require('firebase-admin');

  admin.initializeApp();
} else {
  const firebase = require('@firebase/testing');

  admin = firebase.initializeAdminApp({
    projectId: 'sample_app'
  });
}

const firestore = admin.firestore();

const query = firestore.collection('foo');

const transaction = firestore.runTransaction(async transaction => {
  const col = await transaction.get(query);

  console.log(col.docs);
});

Now run this code with npx firebase emulators:start --only functions to see it working as expected.
Run again with NODE_ENV=test npx firebase emulators:start --only functions to see the error

Because @firebase/testing uses the firebase (client) package to emulate the admin SDK the Transaction methods are not the same as in the admin SDK. This makes writing my tests obsolete as I cannot replicate production process in my test env.

testing-sdk

Most helpful comment

@schmidt-sebastian is right about the situation with @firebase/testing.

However, for your case we recommend just using the Node.js Admin SDK with the FIRESTORE_EMULATOR_HOST environment variable set, which will instruct the SDK to connect to the host:port specified by the env var. As an added benefit, you can also simplify the initialization logic. Note that firebase emulators:exec automatically sets this env var for you.

All 6 comments

Looking at the error and reading the docs on transactions does expect the argument to be a Document.Reference, and I am passing a Collection Query;
https://firebase.google.com/docs/reference/node/firebase.firestore.Transaction.html#get

But the admin SDK does allow passing a collection reference like this.
For now I will refactor my code to not run transaction against the collection but it is something to point out that firebase testing is not the same as production libs.

I wish we were given the ability to stub them so it doesn't mess with the typescript typings when we use them on the same code

I'm having a similar issue but with the transaction.getAll() method, which isn't part of the client SDK but as mentioned by @ChromeQ, the client SDK seems to be used to initialize an admin app.

TypeError: t.getAll is not a function at _firebaseAdmin.default.firestore.runTransaction.t

Are there any updates from anybody working on this? Is it being looked into?

@ChromeQ / @Elyx0 / @zv3 I don't believe we have any short term plans to fix this issue. Unfortunately, this is an inherit issue in the way our APIs are designed and bundle in the testing SDK. That being said, I assigned this to @yuchenshi to see if he has more insight.

@schmidt-sebastian is right about the situation with @firebase/testing.

However, for your case we recommend just using the Node.js Admin SDK with the FIRESTORE_EMULATOR_HOST environment variable set, which will instruct the SDK to connect to the host:port specified by the env var. As an added benefit, you can also simplify the initialization logic. Note that firebase emulators:exec automatically sets this env var for you.

Was this page helpful?
0 / 5 - 0 ratings