Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

strategy:
matrix:
node-version: [12.x, 14.x, 16.x, 18.x]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for removing the old versions here? Looks like the pipeline is still looking for them to have passed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readded them for the pipeline to pass, I'm not sure when to change that. 🤔 I removed initially because we are not using those versions anywhere anymore.

node-version: [18.x, 20.x, 22.x, 24.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

steps:
Expand Down
16 changes: 15 additions & 1 deletion src/driver/Firestore/InProcessFirestore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,21 @@ export class InProcessFirestoreQuery implements IFirestoreQuery {
}

offset(offset: number): IFirestoreQuery {
throw new Error("InProcessFirestoreQuery.offset not implemented")
const newQuery: IQueryBuilder = _.cloneDeep<IQueryBuilder>(this.query)

newQuery.transforms.push((collection) => {
if (_.isObject(collection)) {
collection = Object.keys(collection)
.slice(offset)
.reduce((obj: { [key: string]: any }, key: string) => {
obj[key] = collection[key]
return obj
}, {})
}
return collection
})

return new InProcessFirestoreQuery(this.firestore, this.path, newQuery)
}

limit(limit: number): IFirestoreQuery {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { InProcessFirestore } from "../../../src/driver/Firestore/InProcessFirestore"

describe("In-process Firestore offset queries on a collectionGroup", () => {
const db = new InProcessFirestore()

beforeEach(() => {
db.resetStorage()
})

test("offset less than total size", async () => {
// Given some data in a collectionGroup;
await db.collection("zooA/animals").add({ name: "cat" })
await db.collection("zooA/animals").add({ name: "ant" })
await db.collection("zooB/animals").add({ name: "bee" })

// When we offset by one item with deterministic ordering;
const result = await db
.collectionGroup("animals")
.orderBy("name")
.offset(1)
.get()

// Then we should get the remaining items.
expect(result.size).toBe(2)
expect(result.empty).toBeFalsy()
expect(result.docs).toHaveLength(2)
expect(result.docs.map((doc) => doc.data())).toEqual([
{ name: "bee" },
{ name: "cat" },
])
})

test("offset equal to total size", async () => {
// Given some data in a collectionGroup;
await db.collection("zooA/animals").add({ name: "cat" })
await db.collection("zooA/animals").add({ name: "ant" })
await db.collection("zooB/animals").add({ name: "bee" })

// When we offset by the total number of rows;
const result = await db
.collectionGroup("animals")
.orderBy("name")
.offset(3)
.get()

// Then the result should be empty.
expect(result.size).toBe(0)
expect(result.empty).toBeTruthy()
expect(result.docs).toHaveLength(0)
})

test("offset composes with limit for pagination", async () => {
// Given some data in a collectionGroup;
await db.collection("zooA/animals").add({ name: "dog" })
await db.collection("zooA/animals").add({ name: "cat" })
await db.collection("zooB/animals").add({ name: "ant" })
await db.collection("zooB/animals").add({ name: "bee" })

// When we request a page using offset + limit;
const result = await db
.collectionGroup("animals")
.orderBy("name")
.offset(1)
.limit(2)
.get()

// Then we should get the expected page.
expect(result.size).toBe(2)
expect(result.empty).toBeFalsy()
expect(result.docs).toHaveLength(2)
expect(result.docs.map((doc) => doc.data())).toEqual([
{ name: "bee" },
{ name: "cat" },
])
})
})
76 changes: 76 additions & 0 deletions tests/driver/Firestore/InProcessFirestore.offset.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { InProcessFirestore } from "../../../src/driver/Firestore/InProcessFirestore"

describe("In-process Firestore offset queries", () => {
const db = new InProcessFirestore()

beforeEach(() => {
db.resetStorage()
})

test("offset less than total size", async () => {
// Given some data in a collection;
await db.collection("animals").add({ name: "cat" })
await db.collection("animals").add({ name: "ant" })
await db.collection("animals").add({ name: "bee" })

// When we offset by one item with deterministic ordering;
const result = await db
.collection("animals")
.orderBy("name")
.offset(1)
.get()

// Then we should get the remaining items.
expect(result.size).toBe(2)
expect(result.empty).toBeFalsy()
expect(result.docs).toHaveLength(2)
expect(result.docs.map((doc) => doc.data())).toEqual([
{ name: "bee" },
{ name: "cat" },
])
})

test("offset equal to total size", async () => {
// Given some data in a collection;
await db.collection("animals").add({ name: "cat" })
await db.collection("animals").add({ name: "ant" })
await db.collection("animals").add({ name: "bee" })

// When we offset by the total number of rows;
const result = await db
.collection("animals")
.orderBy("name")
.offset(3)
.get()

// Then the result should be empty.
expect(result.size).toBe(0)
expect(result.empty).toBeTruthy()
expect(result.docs).toHaveLength(0)
})

test("offset composes with limit for pagination", async () => {
// Given some data in a collection;
await db.collection("animals").add({ name: "dog" })
await db.collection("animals").add({ name: "cat" })
await db.collection("animals").add({ name: "ant" })
await db.collection("animals").add({ name: "bee" })

// When we request a page using offset + limit;
const result = await db
.collection("animals")
.orderBy("name")
.offset(1)
.limit(2)
.get()

// Then we should get the expected page.
expect(result.size).toBe(2)
expect(result.empty).toBeFalsy()
expect(result.docs).toHaveLength(2)
expect(result.docs.map((doc) => doc.data())).toEqual([
{ name: "bee" },
{ name: "cat" },
])
})
})
Loading