Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
- Fixes native module issues by removing `fast-crc32c` (#3247, #3239)
- Update to Cloud Firestore emulator v1.11.13 which includes a bug fix for documents which are created and deleted in a single transaction.
- Fixes an edge case with nextPageToken in batchGet in Auth Emulator (#3231).
2 changes: 1 addition & 1 deletion src/emulator/auth/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ function batchGet(
let newPageToken: string | undefined = undefined;

// As a non-standard behavior, passing in limit=-1 will return all users.
if (limit >= 0 && users.length > limit) {
if (limit >= 0 && users.length >= limit) {
users.length = limit;
if (users.length) {
newPageToken = users[users.length - 1].localId;
Expand Down
44 changes: 38 additions & 6 deletions src/test/emulators/auth/batch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ describeAuthEmulator("accounts:batchGet", ({ authApi }) => {
it("should allow specifying maxResults and pagination", async () => {
const user1 = await registerAnonUser(authApi());
const user2 = await registerUser(authApi(), { email: "[email protected]", password: "foobar" });
const localIds = [user1.localId, user2.localId].sort();

const nextPageToken = await authApi()
.get(`/identitytoolkit.googleapis.com/v1/projects/${PROJECT_ID}/accounts:batchGet`)
Expand All @@ -71,9 +72,7 @@ describeAuthEmulator("accounts:batchGet", ({ authApi }) => {
.then((res) => {
expectStatusCode(200, res);
expect(res.body.users).to.have.length(1);
expect(res.body.users[0].localId).to.equal(
user1.localId < user2.localId ? user1.localId : user2.localId
);
expect(res.body.users[0].localId).to.equal(localIds[0]);

expect(res.body).to.have.property("nextPageToken").which.is.a("string");
return res.body.nextPageToken as string;
Expand All @@ -86,9 +85,7 @@ describeAuthEmulator("accounts:batchGet", ({ authApi }) => {
.then((res) => {
expectStatusCode(200, res);
expect(res.body.users).to.have.length(1);
expect(res.body.users[0].localId).to.equal(
user1.localId > user2.localId ? user1.localId : user2.localId
);
expect(res.body.users[0].localId).to.equal(localIds[1]);

// No more accounts after this, so no page token returned.
expect(res.body).not.to.have.property("nextPageToken");
Expand All @@ -110,6 +107,41 @@ describeAuthEmulator("accounts:batchGet", ({ authApi }) => {
expect(res.body).not.to.have.property("nextPageToken");
});
});

it("should always return a page token if page is full", async () => {
const user1 = await registerAnonUser(authApi());
const user2 = await registerUser(authApi(), { email: "[email protected]", password: "foobar" });
const localIds = [user1.localId, user2.localId].sort();

const nextPageToken = await authApi()
.get(`/identitytoolkit.googleapis.com/v1/projects/${PROJECT_ID}/accounts:batchGet`)
.query({ maxResults: 2 }) // Return first two users only.
.set("Authorization", "Bearer owner")
.then((res) => {
expectStatusCode(200, res);
expect(res.body.users).to.have.length(2);
expect(res.body.users[0].localId).to.equal(localIds[0]);
expect(res.body.users[1].localId).to.equal(localIds[1]);

// Even if there are no more users after this page, we should still
// return a page token to match production behavior. See:
// https://github.com/firebase/firebase-tools/issues/3231
expect(res.body).to.have.property("nextPageToken").which.is.a("string");
return res.body.nextPageToken as string;
});

await authApi()
.get(`/identitytoolkit.googleapis.com/v1/projects/${PROJECT_ID}/accounts:batchGet`)
.query({ nextPageToken })
.set("Authorization", "Bearer owner")
.then((res) => {
expectStatusCode(200, res);
console.log(nextPageToken, res.body.users);
// Empty page with no page token returned.
expect(res.body.users || []).to.have.length(0);
expect(res.body).not.to.have.property("nextPageToken");
});
});
});

describeAuthEmulator("accounts:batchCreate", ({ authApi }) => {
Expand Down