1

I am writing a test which tests a firebase trigger. The problem, however, is that I cannot make it work. I want to use the local firestore emulator and Jest in order to simulate a change in the firestore and see if the trigger does what it needs to do.

I require the cloud function in my test and I initialize my app

Setup.js:

const firebase = require('@firebase/testing');
const PROJECT_ID = 'project';

let admin;
let db;

const setupAdmin = async () => {
    admin = firebase.initializeAdminApp({
        projectId: PROJECT_ID
    });
    db = admin.firestore();
};

const getAdmin = () => {
    return admin;
};

const getDb = () => {
    return db;
};

module.exports.setupAdmin = setupAdmin;
module.exports.getAdmin = getAdmin;
module.exports.getDb = getDb;

Test.js

describe('Billing', () => {
    let dbRef;
    beforeAll(async () => {
        const {db, admin} = require('../../../functions/helpers/setup');
        dbRef = db;
    });

    afterAll(async () => {
        await Promise.all(firebase.apps().map(app => app.delete()));
        console.log(`View rule coverage information at ${COVERAGE_URL}\n`);
    });

    it('test', async () => {
        const mockData = {
            'Users/user1': {
                uid: 'user1'
            },
            ['Users/user1/Taxes/' + new Date().getFullYear().toString()]: {
                totalExpenseEuro: 0
            }
        };
        for (const key in mockData) {
            const ref = dbRef.doc(key);
            await ref.set(mockData[key]);
        }

        // Create mockup data
        await dbRef.collection('Users').doc('user1').collection('Expenses').doc('expense1').set({
            amountEuroInclVAT: 100
        });

        // Make snapshot for state of database beforehand
        const beforeSnap = test.firestore.makeDocumentSnapshot({amountEuroInclVAT: 0}, 'Users/user1/Expenses/expense1');
        // Make snapshot for state of database after the change
        const afterSnap = test.firestore.makeDocumentSnapshot(
            {amountEuroInclVAT: 100},
            'Users/user1/Expenses/expense1'
        );
        const change = test.makeChange(beforeSnap, afterSnap);

        // Call wrapped function with the Change object
        const wrapped = test.wrap(calculateTaxesOnExpenseUpdate);
        wrapped(change, {
            params: {
                uid: 'test1'
            }
        });
    });
});

Now the main problem comes when I try to access this db object in my trigger

const calculateTaxesOnExpenseUpdate = functions.firestore
    .document('Users/{uid}/Expenses/{expenseId}')
    .onWrite(async (change, context) => {
        const {getDb} = require('../helpers/setup'); // This setup is the same as above
        let db = getDb();
        ...

For some reason when I perform an action like (await db.collection('Users').get()).get('totalExpenseEuro'), Jest stops executing my code. When I set a debugger right after that line, it never gets printed. That piece of code crashes, and I have no idea why. I think the DB instance if not properly configured in my cloud trigger function.

Question: What is a good way of sharing the DB instance (admin.firestore()) between the test and the cloud trigger functions?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Robbe Claessens
  • 79
  • 1
  • 1
  • 6
  • Without any stack trace, it's very hard to identify where is the error. For this reason, I have found this very good tutorial [here](https://dev.to/ssagga/firebase-trigger-functions-testing-with-jest-and-emulators-5dc2) and this other similar case [here](https://stackoverflow.com/questions/52043886/how-do-you-mock-firebase-firestore-methods-using-jest), where it's about using Jest for tests with Firestore and Cloud Functions. Could you please check the differences and verify if you can debug as indicated on these links? – gso_gabriel Aug 06 '20 at 13:21

0 Answers0