Closed
Description
[REQUIRED] Environment info
firebase-tools: 9.2.2
Platform: Windows
[REQUIRED] Test case
Trying to test an HTTP onRequest function that writes to the emulated Firestore.
[REQUIRED] Steps to reproduce
index.ts
import * as functions from 'firebase-functions';
export const testFirestoreWrite = functions.https.onRequest(
async (request, response) => {
await (await import('./testWrite')).testWrite(request, response);
},
);
testWrite.ts
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();
export async function testWrite(
request: functions.https.Request,
response: functions.Response<unknown>,
) {
const body = request.body;
const { collection, docId, doc } = body;
console.log({ collection, docId, doc });
try {
await admin.firestore().collection(collection).doc(docId).create(doc);
} catch (e) {
console.error(e);
}
response.send(body);
}
functions.spec.js
const { expect } = require('chai');
const test = require('firebase-functions-test')({
projectId: process.env.GCLOUD_PROJECT,
});
const admin = require('firebase-admin');
const myFunctions = require('../lib/index');
describe('Unit tests', () => {
after(() => {
test.cleanup();
});
it('tests a firestore write', async () => {
const req = {
body: {
collection: 'test-collection',
docId: 'abc1234',
doc: { name: 'Mark Goho' },
},
};
const sendPromise = new Promise(resolve => {
const res = {
send: text => { resolve(text); },
};
myFunctions.testFirestoreWrite(req, res);
});
const body = await sendPromise;
expect(body).to.eq(req.body);
});
});
[REQUIRED] Expected behavior
Currently this test passes because the assertion evaluates to true, but I'd also expect the firestore write to succeed as well.
[REQUIRED] Actual behavior
- I've started the emulator with
cross-env GCLOUD_PROJECT=fakeproject firebase emulators:start --project=fakeproject --only=firestore,functions,auth
- Functions directory is being watched with
tsc watch
- Tests are running with
mocha functions.spec.js --exit
This is the error output (from the try/catch block above):
Error: 400 undefined: Getting metadata from plugin failed with error: invalid_grant
at Object.callErrorFromStatus (C:\Users\Mark\Documents\IdeaCrew\active-branch-tracker\functions\node_modules\@grpc\grpc-js\build\src\call.js:31:26)
at Object.onReceiveStatus (C:\Users\Mark\Documents\IdeaCrew\active-branch-tracker\functions\node_modules\@grpc\grpc-js\build\src\client.js:176:52)
at Object.onReceiveStatus (C:\Users\Mark\Documents\IdeaCrew\active-branch-tracker\functions\node_modules\@grpc\grpc-js\build\src\client-interceptors.js:334:141)
at Object.onReceiveStatus (C:\Users\Mark\Documents\IdeaCrew\active-branch-tracker\functions\node_modules\@grpc\grpc-js\build\src\client-interceptors.js:297:181)
at C:\Users\Mark\Documents\IdeaCrew\active-branch-tracker\functions\node_modules\@grpc\grpc-js\build\src\call-stream.js:130:78
at processTicksAndRejections (internal/process/task_queues.js:79:11)
Caused by: Error
at WriteBatch.commit (C:\Users\Mark\Documents\IdeaCrew\active-branch-tracker\functions\node_modules\@google-cloud\firestore\build\src\write-batch.js:426:23)
at DocumentReference.create (C:\Users\Mark\Documents\IdeaCrew\active-branch-tracker\functions\node_modules\@google-cloud\firestore\build\src\reference.js:285:14)
at Object.testWrite (C:\Users\Mark\Documents\IdeaCrew\active-branch-tracker\functions\lib\testWrite.js:11:67)
at C:\Users\Mark\Documents\IdeaCrew\active-branch-tracker\functions\lib\index.js:28:72 {
code: '400',
details: 'Getting metadata from plugin failed with error: invalid_grant',
metadata: Metadata { internalRepr: Map {}, options: {} },
note: 'Exception occurred in retry method that was not classified as transient'
}
Side Note
This would be a great quickstart testing example to include in https://github.com/firebase/quickstart-testing
UPDATE:
When running firebase emulators:exec 'npm run test'
I am not getting these errors. I can't discern what the difference is when running emulators using this command vs. firebase emulators:start