Write an async functions.https.onRequest cloud function
Import the function into a test file
Call the function with await
// funcs.js
import * as functions from 'firebase-functions';
import * as firebase from '@firebase/testing';
const admin = firebase.initializeAdminApp({ projectId: 'foo' });
const firestore = admin.firestore();
export const direct = async (req, res) => {
console.log('inside direct, before await');
await new Promise(resolve => {
setTimeout(() => {
resolve();
}, 3000);
});
console.log('inside direct, after await');
return res.status(200).send('ok');
};
export const request = functions.https.onRequest(async (req, res) => {
console.log('inside request, before await');
await new Promise(resolve => {
setTimeout(() => {
resolve();
}, 3000);
});
console.log('inside request, after await');
return res.status(200).send('ok');
});
// funcs.test.js
import * as funcs from '../funcs';
describe('simple async functions test', () => {
it('calling directly', async () => {
const req = {};
const res = {};
res.status = jest.fn().mockReturnValue(res);
res.send = jest.fn().mockReturnValue(res);
await funcs.direct(req, res);
expect(res.status).toHaveBeenCalledWith(200);
expect(res.send).toHaveBeenCalledWith('ok');
});
it('calling from https.onRequest', async () => {
const req = {};
const res = {};
res.status = jest.fn().mockReturnValue(res);
res.send = jest.fn().mockReturnValue(res);
await funcs.request(req, res);
expect(res.status).toHaveBeenCalledWith(200);
expect(res.send).toHaveBeenCalledWith('ok');
});
});
The first test passes as expected. The 2nd one does not.
I am using jest but should replicate with other test runners
This is a simplified version of my code, my function needs to await some upstream data which is what the setTimeout is faking.
The workaround I have at the moment is to create the function and reference it in the onRequest
I've found that the function is wrapped here:
https://github.com/firebase/firebase-functions/blob/master/src/providers/https.ts#L63
The issue is that this function wrapper is not an async/await.
I have fixed this locally by simply putting await on L63 and async on the wrapping function.
I am not sure if this would affect or impact anything else and I'd rather have you guys look into itas there may be a good reason this is not async/awaited
Are there any updates from anybody working on this? Is it being looked into?
I stumbled across this very same issue, and the fix is rather straightforward. The wrapper just needs to return the result of the wrapped function. Specifically on this line https://github.com/firebase/firebase-functions/blob/3491a6d4e57432b5747acddd47e1a6a1109f2b20/src/providers/https.ts#L63.
As a workaround while the patch is accepted, you can do the following before importing your function
const functions = require('firebase-functions');
functions.https.onRequest = (handler) => handler;
Disclaimer: haven't checked whether that affects types.
It's been released in v3.6.0. Thanks for the contribution @sk- !
Most helpful comment
It's been released in v3.6.0. Thanks for the contribution @sk- !