Search code examples
typescriptgoogle-cloud-firestoremockingreact-testing-libraryts-jest

How to mock Firestore v9 getDocs() with Jest


We recently upgraded our webapp from Firebase v8 to v9, and got all kind of problems from the new syntax. I am still quite new to Jest and Firebase/Firestore, so not everything is crystal clear to me yet ...

I am trying to mock getDocs from firebase/firestore because I get this error message:

      TypeError: Cannot read properties of undefined (reading 'docs')
          at /.../src/.../operations.ts:123:45
          at processTicksAndRejections (node:internal/process/task_queues:34:5)
          at Object.<anonymous> (/.../src/.../index.test.ts:1234:6)

The error happens when testing gets into the following code:

const firestoreInstance = getFirestore(firebaseApp)
...
      const dataList = query(
        getDataCollection(),
        where('id', 'in', idList)
      )
      const dataDict: { [key: string]: {id: string, name: string} } = {}
      ;(await getDocs(dataList)).docs.forEach(
        (dataItem) => {
          const data = dataItem.data()
          dataDict[data['id']].name = data.name
        }
      )

Where getDataCollection is someting like:

export const getDataCollection = (): CollectionReference  =>
  collection(
    firestoreInstance,
    `path-to-collection`
  )

Because getDocs is not mocked. If I mock getDocs like this:

    ;(getDocs as any).mockImplementation(() => Promise.resolve({
      docs: {
        data: () => ({
          name: 'name-for-this-data-item',
        }),
      },
    }))

I get the following error in the Jest output for this test:

TypeError: _firestore.getDocs.mockImplementation is not a function

Mocking Firebase v9 seems to be hard from all the unanswered questions I have seen on the internet and I did not find any direct answer to my problem.

Any idea about what I am doing wrong? And any pointer to how to solve my problem?


Solution

  • As often, I hesitate to ask questions here, and when I do, I often end up finding an answer myself soon after ...

    So to put it simply: no need to mock getDocs!

    Instead, the mock for the collection get function had to be modified from:

       ;(getDataCollection as any).mockImplementation(() => ({
          docs: {
            data: () => ({
              name: 'name-for-this-data-item',
            }),
          },
        }))
    

    To:

        ;(getDataCollection as any).mockImplementation(() => ({
          query: {
            docs:[{
              data: () => ({
                id: 'id-for-this-data-item',
                name: 'name-for-this-data-item',
              }),
            }],
          },
        }))
      })
    

    To add a level for the query function.

    I also added an id field in the data to correct a second UNRELATED error in my algorithm.

    I hope that helps other Jest/Firebase/Firestore newbies like me.