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
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.
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.
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_HOSTenvironment variable set, which will instruct the SDK to connect to thehost:portspecified by the env var. As an added benefit, you can also simplify the initialization logic. Note thatfirebase emulators:execautomatically sets this env var for you.