Skip to content

Commit

Permalink
chore: use modular firebase api functions
Browse files Browse the repository at this point in the history
  • Loading branch information
thdk committed Oct 5, 2021
1 parent f8b98e4 commit 30d58eb
Show file tree
Hide file tree
Showing 19 changed files with 744 additions and 498 deletions.
668 changes: 445 additions & 223 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,20 @@
"homepage": "https://github.com/thdk/firestorable#readme",
"peerDependencies": {
"mobx": ">= 6",
"firebase": ">= 8",
"firebase": ">= 9",
"@firebase/rules-unit-testing": "^2",
"firebase-admin": "^9"
},
"dependencies": {},
"devDependencies": {
"@firebase/rules-unit-testing": "^2.0.0",
"@firebase/rules-unit-testing": "^2.0.1",
"@rollup/plugin-commonjs": "^16.0.0",
"@rollup/plugin-node-resolve": "^10.0.0",
"@rollup/plugin-typescript": "^6.1.0",
"@testing-library/dom": "^7.28.1",
"@types/jest": "^24.0.23",
"coveralls": "^3.1.0",
"firebase": "^9.0.2",
"firebase": "^9.1.1",
"firebase-admin": "^9.11.1",
"jest": "^26.6.3",
"mobx": "^6.3.3",
Expand Down
46 changes: 26 additions & 20 deletions src/__test-utils__/firestore.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,38 @@
import type firebase from "firebase/compat";
import {
addDoc,
doc,
PartialWithFieldValue,
setDoc,
WithFieldValue,
SetOptions,
getDoc,
CollectionReference,
WriteBatch,
} from "firebase/firestore";

export const addAsync = <T>(
collectionRef: firebase.firestore.CollectionReference,
data: Partial<T>,
export function addAsync<T>(
collectionRef: CollectionReference<T>,
data: WithFieldValue<T> | PartialWithFieldValue<T>,
id?: string,
setOptions?: firebase.firestore.SetOptions,
) => {
setOptions?: SetOptions,
) {
if (id || setOptions) {
const docRef = id ? collectionRef.doc(id) : collectionRef.doc();
return docRef
.set(data, { ...setOptions })
const docRef = id ? doc(collectionRef, id) : doc(collectionRef);
return setDoc(docRef, data, { ...setOptions })
.then(() => docRef.id);
}

return collectionRef
.add(data)
.then(docRef => docRef.id);
return addDoc(collectionRef, data as WithFieldValue<T>).then((ref) => ref.id);
};

/**
* Returns a promise that resolves with T if document with id exists
* or rejects if document with id does not exist.
*/
export function getAsync<T>(collectionRef: firebase.firestore.CollectionReference, id: string) {
return collectionRef.doc(id)
.get()
export function getAsync<T>(collectionRef: CollectionReference<T>, id: string) {
return getDoc(doc(collectionRef, id))
.then(d => {
if (!d.exists) {
if (!d.exists()) {
throw new Error(`Collection '${collectionRef.id}' contains no document with id '${id}'`);
}

Expand All @@ -35,11 +41,11 @@ export function getAsync<T>(collectionRef: firebase.firestore.CollectionReferenc
};

export const addItemInBatch = (
batch: firebase.firestore.WriteBatch,
batch: WriteBatch,
data: any,
collectionRef: firebase.firestore.CollectionReference,
collectionRef: CollectionReference,
id?: string,
) => {
const doc = id === undefined ? collectionRef.doc() : collectionRef.doc(id);
batch.set(doc, data);
const docRef = id === undefined ? doc(collectionRef) : doc(collectionRef, id);
batch.set(docRef, data);
};
38 changes: 19 additions & 19 deletions src/collection/__tests__/add-document.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules
import { ICollectionOptions, Collection } from "../..";
import { logger } from "../../__test-utils__";

import firebase from "firebase/compat";

import { FirebaseFirestore } from "@firebase/firestore-types";
import { collection, CollectionReference, deleteField, doc, getDoc } from "firebase/firestore";
interface IBook {
name: string;
total: number;
Expand All @@ -13,9 +13,9 @@ interface IBook {

describe("Collection.addAsync", () => {
let testEnv: RulesTestEnvironment;
let collection: Collection<IBook>;
let collectionRef: firebase.firestore.CollectionReference;
let firestore: firebase.firestore.Firestore;
let bookCollection: Collection<IBook>;
let collectionRef: CollectionReference<any>;
let firestore: FirebaseFirestore;

function createCollection<T, K = T>(options?: ICollectionOptions<T, K>) {
return new Collection<T, K>(
Expand All @@ -41,17 +41,17 @@ describe("Collection.addAsync", () => {
});

firestore = testEnv.unauthenticatedContext().firestore();
collectionRef = firestore.collection("books");
collectionRef = collection(firestore, "books");
});

beforeEach(() => {
collection = createCollection<IBook>({
bookCollection = createCollection<IBook>({
serialize: data => {
if (!data) {
throw new Error("Deleting not supported");
}
const firestoreData: any = {
award: firebase.firestore.FieldValue.delete(),
award: deleteField(),
...data
};
return firestoreData;
Expand All @@ -67,14 +67,14 @@ describe("Collection.addAsync", () => {
describe("when no forced id is provided", () => {
test("it should add the document with a generated id", () => {

return collection.addAsync({
return bookCollection.addAsync({
total: 11,
name: "Book"
})
.then(id => {
return collectionRef.doc(id).get()
return getDoc(doc(collectionRef, id))
.then(snapshot => {
expect(snapshot.exists).toBe(true);
expect(snapshot.exists()).toBe(true);
});
});
});
Expand All @@ -83,17 +83,17 @@ describe("Collection.addAsync", () => {
describe("when a forced id is provided", () => {
test("it should add the document with the given id", () => {

return collection.addAsync(
return bookCollection.addAsync(
{
name: "Book",
total: 11,
},
"given-id"
)
.then(() => {
return collectionRef.doc("given-id").get()
return getDoc(doc(collectionRef, "given-id"))
.then(snapshot => {
expect(snapshot.exists).toBe(true);
expect(snapshot.exists()).toBe(true);
});
});
});
Expand All @@ -102,19 +102,19 @@ describe("Collection.addAsync", () => {

describe("Adding multiple documents", () => {
test("it should add the documents with generated ids", () => {
return collection.addAsync([
return bookCollection.addAsync([
{ total: 11, name: "Book" },
{ total: 22, name: "Book 2" }
])
.then(ids => {
return Promise.all(
[
collectionRef.doc(ids[0]).get(),
collectionRef.doc(ids[1]).get(),
getDoc(doc(collectionRef, ids[0])),
getDoc(doc(collectionRef, ids[1]))
]
).then(([snapshot1, snapshot2]) => {
expect(snapshot1.exists).toBe(true);
expect(snapshot2.exists).toBe(true);
expect(snapshot1.exists()).toBe(true);
expect(snapshot2.exists()).toBe(true);
});
});
});
Expand Down
14 changes: 7 additions & 7 deletions src/collection/__tests__/constructor.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules-unit-testing";
import { Collection } from "../..";

import type firebase from "firebase/compat";

import { FirebaseFirestore } from "@firebase/firestore-types";
import { collection } from "firebase/firestore";

const projectId = "test-constructor-collection";
describe("Collection.constructor", () => {
let firestore: firebase.firestore.Firestore;
let firestore: FirebaseFirestore;
let testEnv: RulesTestEnvironment;

beforeAll(async () => {
Expand All @@ -28,14 +28,14 @@ describe("Collection.constructor", () => {
});

test("it should create a Collection instance with a function as collectionRef", () => {
const collection = new Collection(firestore, () => firestore.collection("books"));
const booksCollection = new Collection(firestore, () => collection(firestore, "books"));

expect(collection).toBeInstanceOf(Collection);
expect(booksCollection).toBeInstanceOf(Collection);
});

test("it should create a Collection instance with a CollectionReference as collectionRef", () => {
const collection = new Collection(firestore, firestore.collection("books"));
const booksCollection = new Collection(firestore, collection(firestore, "books"));

expect(collection).toBeInstanceOf(Collection);
expect(booksCollection).toBeInstanceOf(Collection);
});
});
29 changes: 15 additions & 14 deletions src/collection/__tests__/delete-documents.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { initializeTestEnvironment, RulesTestEnvironment } from "@firebase/rules
import { Collection, ICollectionOptions, RealtimeMode } from "../..";
import { logger } from "../../__test-utils__";

import type firebase from "firebase/compat";
import { FirebaseFirestore } from "@firebase/firestore-types";
import { collection, CollectionReference, doc, getDoc, setDoc } from "firebase/firestore";

const projectId = "test-delete-documents";
describe("Collection.deleteAsync", () => {
let collectionRef: firebase.firestore.CollectionReference;
let firestore: firebase.firestore.Firestore;
let collectionRef: CollectionReference<any>;
let firestore: FirebaseFirestore;
let testEnv: RulesTestEnvironment;

beforeAll(async () => {
Expand All @@ -20,7 +21,7 @@ describe("Collection.deleteAsync", () => {
});

firestore = testEnv.unauthenticatedContext().firestore();
collectionRef = firestore.collection("books");
collectionRef = collection(firestore, "books");
});


Expand All @@ -41,10 +42,10 @@ describe("Collection.deleteAsync", () => {
await testEnv.clearFirestore()
// Add initial data
return Promise.all([
collectionRef.doc("id1").set({ total: 1, name: "A" }),
collectionRef.doc("id2").set({ total: 2, name: "B" }),
collectionRef.doc("id3").set({ total: 3, name: "C" }),
collectionRef.doc("id4").set({ total: 2, name: "C" }),
setDoc(doc(collectionRef, "id1"), { total: 1, name: "A" }),
setDoc(doc(collectionRef, "id2"), { total: 1, name: "B" }),
setDoc(doc(collectionRef, "id3"), { total: 1, name: "C" }),
setDoc(doc(collectionRef, "id4"), { total: 1, name: "C" }),
]);
});

Expand All @@ -54,9 +55,9 @@ describe("Collection.deleteAsync", () => {

return collection.deleteAsync("id2")
.then(() => {
return collectionRef.doc("id2").get()
return getDoc(doc(collectionRef, "id2"))
.then(doc => {
expect(doc.exists).toBe(false);
expect(doc.exists()).toBe(false);
});
});
});
Expand All @@ -67,12 +68,12 @@ describe("Collection.deleteAsync", () => {
return collection.deleteAsync("id2", "id3")
.then(() => {
return Promise.all([
collectionRef.doc("id2").get(),
collectionRef.doc("id3").get(),
getDoc(doc(collectionRef, "id2")),
getDoc(doc(collectionRef, "id3")),
])
.then(([snapshot1, snapshot2]) => {
expect(snapshot1.exists).toBe(false);
expect(snapshot2.exists).toBe(false);
expect(snapshot1.exists()).toBe(false);
expect(snapshot2.exists()).toBe(false);
});
});
});
Expand Down
Loading

0 comments on commit 30d58eb

Please sign in to comment.