Skip to content

Testing async firebase functions.https.onRequest does not await #606

Closed
@ChromeQ

Description

@ChromeQ

[REQUIRED] Describe your environment

  • Operating System version: Ubuntu 19.10
  • Browser version: node v8.16.0
  • Jest version: 24.9.0
  • Firebase version: 7.6.1
  • Firebase-Functions version: 3.3.0

[REQUIRED] Describe the problem

Steps to reproduce:

Write an async functions.https.onRequest cloud function
Import the function into a test file
Call the function with await

Relevant Code:

// 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions