Skip to content

Testing onWrite cloud function does not correctly return ref.parent #84

Open
@ospfranco

Description

@ospfranco

Version info

firebase-functions-test: 0.2.3

firebase-functions: 3.12.0

firebase-admin: 9.4.1

Test case

Assume the following firebase function that triggers on a sub-field change:

functions.database.ref(`/users/{uid}/${fieldname}`).onWrite((change, context) => {
    const uid = context.params.uid
    const value = change.after.val()

    if (!change.before.exists() && !value) {
      return null
    }

    return change.after.ref.parent?.once('value').then(snapshot => {
      const user = snapshot.val()
      const email = user?.providerData?.email

      if (typeof email !== 'string') {
        return null
      }

      return createOrUpdateContact(uid, user)
    })
  })

Now to write a unit test for such function:

it('correctly updates flag at mailer', async (done) => {
    const userId = chance.guid();
    const userEmail = chance.email()
    const userAfter = {
      uid: userId,
      subscription: true,
      providerData: {
        email: userEmail
      }
    };

    const beforeSnap = functionsMock.database.makeDataSnapshot(
      {
        uid: userId,
        subscription: false,
        providerData: {
          email: userEmail
        }
      },
      `/users/${userId}`
    );

    const afterSnap = functionsMock.database.makeDataSnapshot(
      true,
      `/users/${userId}/subscription`
    );

    const wrapped = functionsMock.wrap(update_subscription_flag);

    const change = functionsMock.makeChange(beforeSnap, afterSnap);

    const res = await wrapped(change, {
      params: {
        uid: userId
      }
    });

    expect(res).toBeTruthy()

    expect(createOrUpdateContact).toHaveBeenCalledWith(userId, userAfter)


    done()
  })

Steps to reproduce

So, the exact problem occurs on this line:

return change.after.ref.parent?.once('value').then(snapshot => {

Even though change.after does correctly reference only the field that changed, when trying to get it's parent null is returned instead of the value in the beforeSnap

Expected behavior

The correct parent ref is detected or at least there is a way to set it so the real firebase behavior can be replicated

Actual behavior

The ref's parent is set to null, which diverges from real firebase behavior

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions