Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

firestore-jest-mock

Package Overview
Dependencies
Maintainers
2
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

firestore-jest-mock

Jest helper for mocking Google Cloud Firestore

  • 0.25.0
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
16K
decreased by-61.75%
Maintainers
2
Weekly downloads
 
Created
Source

Mock Firestore

Jest Mock for testing Google Cloud Firestore

A simple way to mock calls to Cloud Firestore, allowing you to assert that you are requesting data correctly.

This is not a pseudo-database -- it is only for testing you are interfacing with firebase/firestore the way you expect.

⚠️ WARNING ⚠️

This library is NOT feature complete with all available methods exposed by Firestore.

Small, easy to grok pull requests are welcome, but please note that there is no official roadmap for making this library fully featured.

Table of Contents

What's in the Box

This library provides an easy to use mocked version of firestore.

Installation

With npm:

npm install --save-dev firestore-jest-mock

With yarn:

yarn add --dev firestore-jest-mock

Usage

mockFirebase

The default method to use is mockFirebase, which returns a jest mock, overwriting firebase and firebase-admin. It accepts an object with two pieces:

  • database -- A mock of your collections
  • currentUser -- (optional) overwrites the currently logged in user

Example usage:

const { mockFirebase } = require('firestore-jest-mock');

// Create a fake Firestore with a `users` and `posts` collection
mockFirebase({
  database: {
    users: [
      { id: 'abc123', name: 'Homer Simpson' },
      { id: 'abc456', name: 'Lisa Simpson' },
    ],
    posts: [{ id: '123abc', title: 'Really cool title' }],
  },
});

If you are using TypeScript, you can import mockFirebase using ES module syntax:

import { mockFirebase } from 'firestore-jest-mock';

This will populate a fake database with a users and posts collection. This database is read-only by default, meaning that any Firestore write calls will not actually persist across invocations.

Now you can write queries or requests for data just as you would with Firestore:

const { mockCollection } = require('firestore-jest-mock/mocks/firestore');

test('testing stuff', () => {
  const firebase = require('firebase'); // or import firebase from 'firebase';
  const db = firebase.firestore();

  return db
    .collection('users')
    .get()
    .then(userDocs => {
      // Assert that a collection ID was referenced
      expect(mockCollection).toHaveBeenCalledWith('users');

      // Write other assertions here
    });
});

In TypeScript, you would import mockCollection using ES module syntax:

import { mockCollection } from 'firestore-jest-mock/mocks/firestore';

The other mock functions may be imported similarly.

@google-cloud/firestore compatibility

If you use @google-cloud/firestore, use mockGoogleCloudFirestore instead of mockFirebase in all the documentation.

const { mockGoogleCloudFirestore } = require('firestore-jest-mock');

mockGoogleCloudFirestore({
  database: {
    users: [
      { id: 'abc123', name: 'Homer Simpson' },
      { id: 'abc456', name: 'Lisa Simpson' },
    ],
    posts: [{ id: '123abc', title: 'Really cool title' }],
  },
});

const { mockCollection } = require('firestore-jest-mock/mocks/firestore');

test('testing stuff', () => {
  const { Firestore } = require('@google-cloud/firestore');
  const firestore = new Firestore();

  return firestore
    .collection('users')
    .get()
    .then(userDocs => {
      expect(mockCollection).toHaveBeenCalledWith('users');
      expect(userDocs.docs[0].data().name).toEqual('Homer Simpson');
    });
});

Note: Authentication with @google-cloud/firestore is not handled in the same way as with firebase. The Auth module is not available for @google-cloud/firestore compatibility.

@react-native-firebase/firestore compatibility

If you use @react-native-firebase/firestore, use mockReactNativeFirestore instead of mockFirebase in all the documentation.

const { mockReactNativeFirestore } = require('firestore-jest-mock');

mockReactNativeFirestore({
  database: {
    users: [
      { id: 'abc123', name: 'Homer Simpson' },
      { id: 'abc456', name: 'Lisa Simpson' },
    ],
    posts: [{ id: '123abc', title: 'Really cool title' }],
  },
});

const { mockCollection } = require('firestore-jest-mock/mocks/firestore');

test('testing stuff', () => {
  const { Firestore } = require('@react-native-firebase/firestore');
  const firestore = new Firestore();

  return firestore
    .collection('users')
    .get()
    .then(userDocs => {
      expect(mockCollection).toHaveBeenCalledWith('users');
      expect(userDocs.docs[0].data().name).toEqual('Homer Simpson');
    });
});

Note: Authentication with @react-native-firebase/firestore is not handled in the same way as with firebase. The Auth module is not available for @react-native-firebase/firestore compatibility.

Subcollections

A common Firestore use case is to store data in document subcollections. You can model these with firestore-jest-mock like so:

const { mockFirebase } = require('firestore-jest-mock');
// Using our fake Firestore from above:
mockFirebase({
  database: {
    users: [
      {
        id: 'abc123',
        name: 'Homer Simpson',
      },
      {
        id: 'abc456',
        name: 'Lisa Simpson',
        _collections: {
          notes: [
            {
              id: 'note123',
              text: 'This is a document in a subcollection!',
            },
          ],
        },
      },
    ],
    posts: [{ id: '123abc', title: 'Really cool title' }],
  },
});

Similar to how the id key defines a document object to firestore-jest-mock, the _collections key defines a subcollection. You model each subcollection structure in the same way that database is modeled above: an object keyed by collection IDs and populated with document arrays.

This lets you model and validate more complex document access:

const { mockCollection, mockDoc } = require('firestore-jest-mock/mocks/firestore');

test('testing stuff', () => {
  const firebase = require('firebase');
  const db = firebase.firestore();

  return db
    .collection('users')
    .doc('abc456')
    .collection('notes')
    .get()
    .then(noteDocs => {
      // Assert that a collection or document ID was referenced
      expect(mockCollection).toHaveBeenNthCalledWith(1, 'users');
      expect(mockDoc).toHaveBeenCalledWith('abc456');
      expect(mockCollection).toHaveBeenNthCalledWith(2, 'notes');

      // Write other assertions here
    });
});

What would you want to test?

The job of the this library is not to test Firestore, but to allow you to test your code without hitting Firebase servers or booting a local emulator. Since this package simulates most of the Firestore interface in plain JavaScript, unit tests can be quick and easy both to write and to execute.

Take this example:

function maybeGetUsersInState(state) {
  const query = firestore.collection('users');

  if (state) {
    query = query.where('state', '==', state);
  }

  return query.get();
}

We have a conditional query here. If you pass state to this function, we will query against it; otherwise, we just get all of the users. So, you may want to write a test that ensures you are querying correctly:

const { mockFirebase } = require('firestore-jest-mock');

// Import the mock versions of the functions you expect to be called
const { mockCollection, mockWhere } = require('firestore-jest-mock/mocks/firestore');
describe('we can query', () => {
  mockFirebase({
    database: {
      users: [
        {
          id: 'abc123',
          name: 'Homer Simpson',
          state: 'connecticut',
        },
        {
          id: 'abc456',
          name: 'Lisa Simpson',
          state: 'alabama',
        },
      ],
    },
  });

  test('query with state', async () => {
    await maybeGetUsersInState('alabama');

    // Assert that we call the correct Firestore methods
    expect(mockCollection).toHaveBeenCalledWith('users');
    expect(mockWhere).toHaveBeenCalledWith('state', '==', 'alabama');
  });

  test('no state', async () => {
    await maybeGetUsersInState();

    // Assert that we call the correct Firestore methods
    expect(mockCollection).toHaveBeenCalledWith('users');
    expect(mockWhere).not.toHaveBeenCalled();
  });
});

In this test, we don't necessarily care what gets returned from Firestore (it's not our job to test Firestore), but instead we try to assert that we built our query correctly.

If I pass a state to this function, does it properly query the users collection?

That's what we want to answer.

Don't forget to reset your mocks

In jest, mocks will not reset between test instances unless you specify them to. This can be an issue if you have two tests that make an asseration against something like mockCollection. If you call it in one test and assert that it was called in another test, you may get a false positive.

Luckily, jest offers a few methods to reset or clear your mocks.

  • clearAllMocks() clears all the calls for all of your mocks. It's good to run this in a beforeEach to reset between each test
jest.clearAllMocks();
mockCollection.mockClear();
I wrote a where clause, but all the records were returned!

The where clause in the mocked Firestore will not actually filter the data at all. We are not recreating Firestore in this mock, just exposing an API that allows us to write assertions. It is also not the job of the developer (you) to test that Firestore filtered the data appropriately. Your application doesn't double-check Firestore's response -- it trusts that it's always correct!

Additional options

The default state of this mock is meant for basic testing that should cover most everyone. However, you can pass an options object to the mock to overwrite some default behavior.

const options = {
  includeIdsInData: true,
  mutable: true,
  simulateQueryFilters: true,
};

mockFirebase(database, options);
includeIdsInData

By default, id's are not returned with the document's data. Although you can declare an id when setting up your fake database, it will not be returned with data() as that is not the default behavior of firebase. However, a common practice for firestore users is to manually write an id property to their documents, allowing them to query collectionGroup by id.

mutable

Warning: Thar be dragons

By default, the mock database you set up is immutable. This means it doesn't update, even when you call things like set or add, as the result isn't typically important for your tests. If you need your tests to update the mock database, you can set mutable to true when calling mockFirebase. Calling .set() on a document or collection would update the mock database you created. This can make your tests less predictable, as they may need to be run in the same order.

Use with caution.

Note: not all APIs that update the database are supported yet. PRs welcome!

simulateQueryFilters

By default, query filters (read: where clauses) pass through all mock Firestore data without applying the requested filters.

If you need your tests to perform where queries on mock database data, you can set simulateQueryFilters to true when calling mockFirebase.

Functions you can test

Firestore
MethodUseMethod in Firestore
mockCollectionAssert the correct collection is being queriedcollection
mockCollectionGroupAssert the correct collectionGroup is being queriedcollectionGroup
mockDocAssert the correct record is being fetched by id. Tells the mock you are fetching a single recorddoc
mockBatchAssert batch was calledbatch
mockBatchDeleteAssert correct refs are passedbatch delete
mockBatchCommitAssert commit is called. Returns a promisebatch commit
mockGetAllAssert correct refs are passed. Returns a promise resolving to array of docs.getAll
mockUpdateAssert correct params are passed to update. Returns a promiseupdate
mockAddAssert correct params are passed to add. Returns a promise resolving to the doc with new idadd
mockSetAssert correct params are passed to set. Returns a promiseset
mockDeleteAssert delete is called on ref. Returns a promisedelete
mockUseEmulatorAssert correct host and port are passeduseEmulator
Firestore.Query
MethodUseMethod in Firestore
mockGetAssert get is called. Returns a promise resolving either to a single doc or querySnapshotget
mockWhereAssert the correct query is written. Tells the mock you are fetching multiple recordswhere
mockLimitAssert limit is set properlylimit
mockOrderByAssert correct field is passed to orderByorderBy
mockOffsetAssert offset is set properlyoffset
mockStartAfterAssert startAfter is calledstartAfter
mockStartAtAssert startAt is calledstartAt
mockWithConverterAssert withConverter is calledwithConverter
Firestore.FieldValue
MethodUseMethod in Firestore
mockArrayRemoveFieldValueAssert the correct elements are removed from an arrayarrayRemove
mockArrayUnionFieldValueAssert the correct elements are added to an arrayarrayUnion
mockDeleteFieldValueAssert the correct fields are removed from a documentdelete
mockIncrementFieldValueAssert a number field is incremented by the correct amountincrement
mockServerTimestampFieldValueAssert a server Firebase.Timestamp value will be storedserverTimestamp
Firestore.Timestamp
MethodUseMethod in Firestore
mockTimestampToDateAssert the call and mock the result, or use the default implementationtoDate
mockTimestampToMillisAssert the call and mock the result, or use the default implementationtoMillis
mockTimestampFromDateAssert the call and mock the result, or use the default implementationfromDate
mockTimestampFromMillisAssert the call and mock the result, or use the default implementationfromMillis
mockTimestampNowAssert the call and mock the result, or use the default implementationnow
Firestore.Transaction
MethodUseMethod in Firestore
mockGetTransactionAssert transaction.get is called with correct params. Returns a promiseget
mockGetAllTransactionAssert transaction.getAll is called with correct params. Returns a promiseget
mockSetTransactionAssert transaction.set is called with correct params. Returns the transaction objectset
mockUpdateTransactionAssert transaction.update is called with correct params. Returns the transaction objectupdate
mockDeleteTransactionAssert transaction.delete is called with correct params. Returns the transaction objectdelete
Auth
MethodUseMethod in Firebase
mockCreateUserWithEmailAndPasswordAssert correct email and password are passed. Returns a promisecreateUserWithEmailAndPassword
mockGetUserAssert correct user IDs are passed. Returns a promisegetUser
mockDeleteUserAssert correct ID is passed to delete method. Returns a promisedeleteUser
mockSendVerificationEmailAssert request for verification email was sent. Lives on the currentUsersendVerificationEmail
mockCreateCustomTokenAssert correct user ID and claims are passed. Returns a promisecreateCustomToken
mockSetCustomUserClaimsAssert correct user ID and claims are set.setCustomUserClaims
mockSignInWithEmailAndPasswordAssert correct email and password were passed. Returns a promisesignInWithEmailAndPassword
mockSendPasswordResetEmailAssert correct email was passed.sendPasswordResetEmail
mockVerifyIdTokenAssert correct token is passed. Returns a promiseverifyIdToken
mockUseEmulatorAssert correct emulator url is passeduseEmulator
mockSignOutAssert sign out is called. Returns a promisesignOut

Contributing

We welcome all contributions to our projects! Filing bugs, feature requests, code changes, docs changes, or anything else you'd like to contribute are all more than welcome! More information about contributing can be found in the contributing guidelines.

To get set up, simply clone this repository and npm install!

Use npm run build to compile JavaScript from the TypeScript source. For backward compatibility, built files are put into the root of the working directory.

Code of Conduct

We strive to provide a welcoming, inclusive environment for all users. To hold ourselves accountable to that mission, we have a strictly-enforced code of conduct.

Keywords

FAQs

Package last updated on 12 Apr 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc