Skip to content

Commit

Permalink
Merge pull request #105 from HassanBahati/add-useGetCountFromServerQu…
Browse files Browse the repository at this point in the history
…ery-hook
  • Loading branch information
Ehesp authored Sep 30, 2024
2 parents 64346b7 + 90795ac commit 84d67f4
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
> [!IMPORTANT]
> This project is not currently being maintained. If you are interested in maintaining, please reach out on [Discord](https://invertase.link/discord) to a member of the team.
> This project is currently undergoing a overhaul, to support TanStack v5 - this includes a package restructuring, and enables support for other web frameworks!
<h1 align="center">React Query Firebase</h1>
<p align="center">
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/firestore/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
// useWriteBatchCommitMutation (WriteBatch)
export { useDocumentQuery } from "./useDocumentQuery";
export { useCollectionQuery } from "./useCollectionQuery";
// useGetCountFromServerQuery
export { useGetCountFromServerQuery } from "./useGetCountFromServerQuery";
// useGetAggregateFromServerQuery
// useNamedQuery
124 changes: 124 additions & 0 deletions packages/react/src/firestore/useGetCountFromServerQuery.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import React, { type ReactNode } from "react";
import { describe, expect, test, beforeEach } from "vitest";
import { useGetCountFromServerQuery } from "./useGetCountFromServerQuery";
import { renderHook, waitFor } from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { collection, addDoc, query, where } from "firebase/firestore";
import {
expectFirestoreError,
firestore,
wipeFirestore,
} from "~/testing-utils";

const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});

const wrapper = ({ children }: { children: ReactNode }) => (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
);

describe("useGetCountFromServerQuery", () => {
beforeEach(async () => await wipeFirestore());

test("returns correct count for empty collection", async () => {
const collectionRef = collection(firestore, "tests");

const { result } = renderHook(
() =>
useGetCountFromServerQuery(collectionRef, {
queryKey: ["count", "empty"],
}),
{ wrapper }
);

await waitFor(() => expect(result.current.isSuccess).toBe(true));

Check failure on line 39 in packages/react/src/firestore/useGetCountFromServerQuery.test.tsx

View workflow job for this annotation

GitHub Actions / test

packages/react/src/firestore/useGetCountFromServerQuery.test.tsx > useGetCountFromServerQuery > returns correct count for empty collection

AssertionError: expected false to be true // Object.is equality Ignored nodes: comments, script, style <html> <head /> <body> <p class="firebase-emulator-warning" style="position: fixed; width: 100%; background-color: #ffffff; border: 0.1em solid #000000; color: #b50000; bottom: 0px; left: 0px; margin: 0px; z-index: 10000; text-align: center;" > Running in emulator mode. Do not use with production credentials. </p> <div /> </body> </html> - Expected + Received - true + false ❯ packages/react/src/firestore/useGetCountFromServerQuery.test.tsx:39:58 ❯ runWithExpensiveErrorDiagnosticsDisabled node_modules/.pnpm/@testing-library[email protected]/node_modules/@testing-library/dom/dist/config.js:47:12 ❯ checkCallback node_modules/.pnpm/@testing-library[email protected]/node_modules/@testing-library/dom/dist/wait-for.js:124:77 ❯ Timeout.checkRealTimersCallback node_modules/.pnpm/@testing-library[email protected]/node_modules/@testing-library/dom/dist/wait-for.js:118:16

expect(result.current.data?.data().count).toBe(0);
});

test("returns correct count for non-empty collection", async () => {
const collectionRef = collection(firestore, "tests");

await addDoc(collectionRef, { foo: "bar1" });
await addDoc(collectionRef, { foo: "bar2" });
await addDoc(collectionRef, { foo: "bar3" });

const { result } = renderHook(
() =>
useGetCountFromServerQuery(collectionRef, {
queryKey: ["count", "non-empty"],
}),
{ wrapper }
);

await waitFor(() => expect(result.current.isSuccess).toBe(true));

expect(result.current.data?.data().count).toBe(3);

Check failure on line 61 in packages/react/src/firestore/useGetCountFromServerQuery.test.tsx

View workflow job for this annotation

GitHub Actions / test

packages/react/src/firestore/useGetCountFromServerQuery.test.tsx > useGetCountFromServerQuery > returns correct count for non-empty collection

AssertionError: expected +0 to be 3 // Object.is equality - Expected + Received - 3 + 0 ❯ packages/react/src/firestore/useGetCountFromServerQuery.test.tsx:61:47
});

test("handles complex queries", async () => {
const collectionRef = collection(firestore, "tests");

await addDoc(collectionRef, { category: "A", value: 1 });
await addDoc(collectionRef, { category: "B", value: 2 });
await addDoc(collectionRef, { category: "A", value: 3 });
await addDoc(collectionRef, { category: "C", value: 4 });

const complexQuery = query(collectionRef, where("category", "==", "A"));

const { result } = renderHook(
() =>
useGetCountFromServerQuery(complexQuery, {
queryKey: ["count", "complex"],
}),
{ wrapper }
);

await waitFor(() => expect(result.current.isSuccess).toBe(true));
expect(result.current.data?.data().count).toBe(2);
});

test("handles restricted collections appropriately", async () => {
const collectionRef = collection(firestore, "restrictedCollection");

const { result } = renderHook(
() =>
useGetCountFromServerQuery(collectionRef, {
queryKey: ["count", "restricted"],
}),
{ wrapper }
);

await waitFor(() => expect(result.current.isError).toBe(true));

expectFirestoreError(result.current.error, "permission-denied");
});

test("returns pending state initially", async () => {
const collectionRef = collection(firestore, "tests");

await addDoc(collectionRef, { foo: "bar" });

const { result } = renderHook(
() =>
useGetCountFromServerQuery(collectionRef, {
queryKey: ["count", "pending"],
}),
{ wrapper }
);

// Initially isPending should be true
expect(result.current.isPending).toBe(true);

await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
});

expect(result.current.data?.data().count).toBe(1);
});
});
41 changes: 41 additions & 0 deletions packages/react/src/firestore/useGetCountFromServerQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useQuery, type UseQueryOptions } from "@tanstack/react-query";
import {
type AggregateField,
type AggregateQuerySnapshot,
getCountFromServer,
type FirestoreError,
type Query,
type DocumentData,
} from "firebase/firestore";

type FirestoreUseQueryOptions<TData = unknown, TError = Error> = Omit<
UseQueryOptions<TData, TError>,
"queryFn"
>;

export function useGetCountFromServerQuery<
AppModelType = DocumentData,
DbModelType extends DocumentData = DocumentData
>(
query: Query<AppModelType, DbModelType>,
options: FirestoreUseQueryOptions<
AggregateQuerySnapshot<
{ count: AggregateField<number> },
AppModelType,
DbModelType
>,
FirestoreError
>
) {
return useQuery<
AggregateQuerySnapshot<
{ count: AggregateField<number> },
AppModelType,
DbModelType
>,
FirestoreError
>({
...options,
queryFn: () => getCountFromServer(query),
});
}

0 comments on commit 84d67f4

Please sign in to comment.