UNPKG

firestore-vitest-mock

Version:
403 lines (337 loc) 12.2 kB
import { beforeEach, describe, expect, vi, test, afterEach } from "vitest"; describe.each([ { library: "@google-cloud/firestore", mockFunction: "mockGoogleCloudFirestore", }, { library: "@react-native-firebase/firestore", mockFunction: "mockReactNativeFirestore", }, ])("mocking $library with %mockFunction", async ({ library, mockFunction }) => { const FirestoreMock = await import(".."); const flushPromises = async (): Promise<void> => { await new Promise(setImmediate); }; const { Timestamp } = await import("../mocks/timestamp"); const { mockGet, mockSelect, mockAdd, mockSet, mockUpdate, mockWhere, mockCollectionGroup, mockBatch, mockBatchCommit, mockBatchDelete, mockBatchUpdate, mockBatchSet, mockSettings, mockOnSnapShot, mockListCollections, mockTimestampNow, CollectionReference, } = await import("../mocks/firestore"); describe("we can start a firestore application", () => { FirestoreMock[mockFunction]({ database: { users: [ { id: "abc123", first: "Bob", last: "builder", born: 1998 }, { id: "123abc", first: "Blues", last: "builder", born: 1996, _collections: { cities: [ { id: "LA", name: "Los Angeles", state: "CA", country: "USA", visited: true, }, ], }, }, ], cities: [ { id: "LA", name: "Los Angeles", state: "CA", country: "USA" }, { id: "DC", name: "Disctric of Columbia", state: "DC", country: "USA", }, ], }, }); let Firestore; beforeEach(async () => { const package = await import(library); Firestore = package.Firestore; }); afterEach(() => mockTimestampNow.mockClear()); test("We can start an application", async () => { const firestore = new Firestore(); firestore.settings({ ignoreUndefinedProperties: true }); expect(mockSettings).toHaveBeenCalledWith({ ignoreUndefinedProperties: true, }); }); describe("Examples from documentation", () => { test("add a user", () => { const firestore = new Firestore(); return firestore .collection("users") .add({ first: "Ada", last: "Lovelace", born: 1815, }) .then(function (docRef) { expect(mockAdd).toHaveBeenCalled(); expect(docRef).toHaveProperty("id"); }); }); test("get all users", () => { const firestore = new Firestore(); return firestore .collection("users") .get() .then((querySnapshot) => { expect(querySnapshot.forEach).toBeTruthy(); expect(querySnapshot.docs.length).toBe(2); expect(querySnapshot.size).toBe(querySnapshot.docs.length); querySnapshot.forEach((doc) => { expect(doc.exists).toBe(true); expect(doc.data()).toBeTruthy(); }); }); }); test("select specific fields only", () => { const firestore = new Firestore(); return firestore .collection("users") .select("first", "last") .get() .then((querySnapshot) => { expect(mockSelect).toHaveBeenCalledWith("first", "last"); const data = querySnapshot.docs[0].data(); expect(Object.keys(data).length).toBe(2); expect(data.first).toBe("Bob"); expect(data.last).toBe("builder"); }); }); test("select refs only", () => { const firestore = new Firestore(); return firestore .collection("users") .select() .get() .then((querySnapshot) => { expect(mockSelect).toHaveBeenCalledWith(); const data = querySnapshot.docs[0].data(); expect(Object.keys(data).length).toBe(0); }); }); test("collectionGroup at root", () => { const firestore = new Firestore(); return firestore .collectionGroup("users") .where("last", "==", "builder") .get() .then((querySnapshot) => { expect(mockCollectionGroup).toHaveBeenCalledWith("users"); expect(mockGet).toHaveBeenCalled(); expect(mockWhere).toHaveBeenCalledWith("last", "==", "builder"); expect(querySnapshot.forEach).toBeTruthy(); expect(querySnapshot.docs.length).toBe(2); expect(querySnapshot.size).toBe(querySnapshot.docs.length); querySnapshot.forEach((doc) => { expect(doc.exists).toBe(true); expect(doc.data()).toBeTruthy(); }); }); }); test("collectionGroup with subcollections", () => { vi.clearAllMocks(); const firestore = new Firestore(); return firestore .collectionGroup("cities") .where("country", "==", "USA") .get() .then((querySnapshot) => { expect(mockCollectionGroup).toHaveBeenCalledWith("cities"); expect(mockGet).toHaveBeenCalledTimes(1); expect(mockWhere).toHaveBeenCalledWith("country", "==", "USA"); expect(querySnapshot.forEach).toBeTruthy(); expect(querySnapshot.docs.length).toBe(3); expect(querySnapshot.size).toBe(querySnapshot.docs.length); querySnapshot.forEach((doc) => { expect(doc.exists).toBe(true); expect(doc.data()).toBeTruthy(); }); }); }); test("set a city", () => { const firestore = new Firestore(); return firestore .collection("cities") .doc("LA") .set({ name: "Los Angeles", state: "CA", country: "USA", }) .then(function () { expect(mockSet).toHaveBeenCalledWith({ name: "Los Angeles", state: "CA", country: "USA", }); }); }); test("updating a city", () => { const firestore = new Firestore(); const now = Timestamp._fromMillis(new Date().getTime()); const washingtonRef = firestore.collection("cities").doc("DC"); mockTimestampNow.mockReturnValue(now); return washingtonRef .update({ capital: true, }) .then(function (value) { expect(value.updateTime).toStrictEqual(now); expect(mockUpdate).toHaveBeenCalledWith({ capital: true }); }); }); test("batch writes", () => { const firestore = new Firestore(); // Get a new write batch const batch = firestore.batch(); // Set the value of 'NYC' const nycRef = firestore.collection("cities").doc("NYC"); batch.set(nycRef, { name: "New York City" }); // Update the population of 'SF' const sfRef = firestore.collection("cities").doc("SF"); batch.update(sfRef, { population: 1000000 }); // Delete the city 'LA' const laRef = firestore.collection("cities").doc("LA"); batch.delete(laRef); // Commit the batch return batch.commit().then(function () { expect(mockBatch).toHaveBeenCalled(); expect(mockBatchDelete).toHaveBeenCalledWith(laRef); expect(mockBatchUpdate).toHaveBeenCalledWith(sfRef, { population: 1000000, }); expect(mockBatchSet).toHaveBeenCalledWith(nycRef, { name: "New York City", }); expect(mockBatchCommit).toHaveBeenCalled(); }); }); test("listCollections returns a promise", async () => { const firestore = new Firestore(); const listCollectionsPromise = firestore .collection("cities") .doc("LA") .listCollections(); expect(listCollectionsPromise).toEqual(expect.any(Promise)); }); test("listCollections resolves with child collections", async () => { const firestore = new Firestore(); const result = await firestore .collection("users") .doc("123abc") .listCollections(); expect(result).toEqual(expect.any(Array)); expect(result).toHaveLength(1); expect(result[0]).toEqual(expect.any(CollectionReference)); expect(result[0].id).toBe("cities"); }); test("listCollections resolves with empty array if there are no collections in document", async () => { const firestore = new Firestore(); const result = await firestore .collection("users") .doc("abc123") .listCollections(); expect(result).toEqual(expect.any(Array)); expect(result).toHaveLength(0); }); test("listCollections calls mockListCollections", async () => { const firestore = new Firestore(); await firestore.collection("users").doc("abc123").listCollections(); expect(mockListCollections).toHaveBeenCalled(); }); test("onSnapshot single doc", async () => { const firestore = new Firestore(); const now = Timestamp._fromMillis(new Date().getTime()); mockTimestampNow.mockReturnValue(now); firestore .collection("cities") .doc("LA") .onSnapshot((doc) => { expect(doc).toHaveProperty("createTime"); expect(doc).toHaveProperty("data"); expect(doc.data).toBeInstanceOf(Function); expect(doc).toHaveProperty("metadata"); expect(doc).toHaveProperty("readTime"); expect(doc).toHaveProperty("updateTime"); expect(doc.readTime).toStrictEqual(now); }); await flushPromises(); expect(mockOnSnapShot).toHaveBeenCalled(); }); test("onSnapshot can work with options", async () => { const firestore = new Firestore(); const now = Timestamp._fromMillis(new Date().getTime()); mockTimestampNow.mockReturnValue(now); firestore .collection("cities") .doc("LA") .onSnapshot( { // Listen for document metadata changes includeMetadataChanges: true, }, (doc) => { expect(doc).toHaveProperty("createTime"); expect(doc).toHaveProperty("data"); expect(doc.data).toBeInstanceOf(Function); expect(doc).toHaveProperty("metadata"); expect(doc).toHaveProperty("readTime"); expect(doc).toHaveProperty("updateTime"); expect(doc.readTime).toStrictEqual(now); } ); await flushPromises(); expect(mockOnSnapShot).toHaveBeenCalled(); }); test("onSnapshot with query", async () => { const firestore = new Firestore(); const unsubscribe = firestore .collection("cities") .where("state", "==", "CA") .onSnapshot((querySnapshot) => { expect(querySnapshot).toHaveProperty( "forEach", expect.any(Function) ); expect(querySnapshot).toHaveProperty("docChanges"); expect(querySnapshot).toHaveProperty("docs", expect.any(Array)); expect(querySnapshot.forEach).toBeInstanceOf(Function); expect(querySnapshot.docChanges).toBeInstanceOf(Function); expect(querySnapshot.docs).toBeInstanceOf(Array); expect(querySnapshot.docChanges()).toBeInstanceOf(Array); }); await flushPromises(); expect(unsubscribe).toBeInstanceOf(Function); expect(mockWhere).toHaveBeenCalled(); expect(mockOnSnapShot).toHaveBeenCalled(); }); }); }); });