Skip to content

Commit 9b3a2ab

Browse files
authored
fix(auth): Fixing flaky deleteUsers() integration tests (#917)
1 parent b93a3c3 commit 9b3a2ab

File tree

2 files changed

+31
-13
lines changed

2 files changed

+31
-13
lines changed

src/index.d.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,8 @@ declare namespace admin.auth {
590590
export import UpdatePhoneMultiFactorInfoRequest = _auth.admin.auth.UpdatePhoneMultiFactorInfoRequest;
591591
export import MultiFactorCreateSettings = _auth.admin.auth.MultiFactorCreateSettings;
592592
export import MultiFactorUpdateSettings = _auth.admin.auth.MultiFactorUpdateSettings;
593+
export import DeleteUsersResult = _auth.admin.auth.DeleteUsersResult;
594+
export import GetUsersResult = _auth.admin.auth.GetUsersResult;
593595
}
594596

595597
declare namespace admin.credential {
@@ -882,7 +884,7 @@ declare namespace admin.remoteConfig {
882884

883885
/**
884886
* Interface representing a Remote Config parameter.
885-
* At minimum, a `defaultValue` or a `conditionalValues` entry must be present for the
887+
* At minimum, a `defaultValue` or a `conditionalValues` entry must be present for the
886888
* parameter to have any effect.
887889
*/
888890
interface RemoteConfigParameter {
@@ -894,7 +896,7 @@ declare namespace admin.remoteConfig {
894896

895897
/**
896898
* A `(condition name, value)` map. The condition name of the highest priority
897-
* (the one listed first in the Remote Config template's conditions list) determines the value of
899+
* (the one listed first in the Remote Config template's conditions list) determines the value of
898900
* this parameter.
899901
*/
900902
conditionalValues?: { [key: string]: RemoteConfigParameterValue };
@@ -977,7 +979,7 @@ declare namespace admin.remoteConfig {
977979

978980
/**
979981
* Type representing a Remote Config parameter value.
980-
* A `RemoteConfigParameterValue` could be either an `ExplicitParameterValue` or
982+
* A `RemoteConfigParameterValue` could be either an `ExplicitParameterValue` or
981983
* an `InAppDefaultValue`.
982984
*/
983985
type RemoteConfigParameterValue = ExplicitParameterValue | InAppDefaultValue;
@@ -1012,11 +1014,11 @@ declare namespace admin.remoteConfig {
10121014
*
10131015
* @param template The Remote Config template to be published.
10141016
* @param options Optional options object when publishing a Remote Config template:
1015-
* - {boolean} `force` Setting this to `true` forces the Remote Config template to
1016-
* be updated and circumvent the ETag. This approach is not recommended
1017-
* because it risks causing the loss of updates to your Remote Config
1017+
* - {boolean} `force` Setting this to `true` forces the Remote Config template to
1018+
* be updated and circumvent the ETag. This approach is not recommended
1019+
* because it risks causing the loss of updates to your Remote Config
10181020
* template if multiple clients are updating the Remote Config template.
1019-
* See {@link https://firebase.google.com/docs/remote-config/use-config-rest#etag_usage_and_forced_updates
1021+
* See {@link https://firebase.google.com/docs/remote-config/use-config-rest#etag_usage_and_forced_updates
10201022
* ETag usage and forced updates}.
10211023
*
10221024
* @return A Promise that fulfills with the published `RemoteConfigTemplate`.

test/integration/auth.spec.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ describe('admin.auth', () => {
257257
// left over from a prior run).
258258
const uidsToDelete = usersToCreate.map((user) => user.uid);
259259
uidsToDelete.push(importUser1.uid);
260-
await admin.auth().deleteUsers(uidsToDelete);
260+
await deleteUsersWithDelay(uidsToDelete);
261261

262262
// Create/import users required by these tests
263263
await Promise.all(usersToCreate.map((user) => admin.auth().createUser(user)));
@@ -267,7 +267,7 @@ describe('admin.auth', () => {
267267
after(async () => {
268268
const uidsToDelete = usersToCreate.map((user) => user.uid);
269269
uidsToDelete.push(importUser1.uid);
270-
await admin.auth().deleteUsers(uidsToDelete);
270+
await deleteUsersWithDelay(uidsToDelete);
271271
});
272272

273273
it('returns users by various identifier types in a single call', async () => {
@@ -1461,7 +1461,7 @@ describe('admin.auth', () => {
14611461
const uid3 = await admin.auth().createUser({}).then((ur) => ur.uid);
14621462
const ids = [{uid: uid1}, {uid: uid2}, {uid: uid3}];
14631463

1464-
return admin.auth().deleteUsers([uid1, uid2, uid3])
1464+
return deleteUsersWithDelay([uid1, uid2, uid3])
14651465
.then((deleteUsersResult) => {
14661466
expect(deleteUsersResult.successCount).to.equal(3);
14671467
expect(deleteUsersResult.failureCount).to.equal(0);
@@ -1480,7 +1480,7 @@ describe('admin.auth', () => {
14801480
const uid2 = 'uid-that-doesnt-exist';
14811481
const ids = [{uid: uid1}, {uid: uid2}];
14821482

1483-
return admin.auth().deleteUsers([uid1, uid2])
1483+
return deleteUsersWithDelay([uid1, uid2])
14841484
.then((deleteUsersResult) => {
14851485
expect(deleteUsersResult.successCount).to.equal(2);
14861486
expect(deleteUsersResult.failureCount).to.equal(0);
@@ -1497,13 +1497,13 @@ describe('admin.auth', () => {
14971497
it('is idempotent', async () => {
14981498
const uid = await admin.auth().createUser({}).then((ur) => ur.uid);
14991499

1500-
return admin.auth().deleteUsers([uid])
1500+
return deleteUsersWithDelay([uid])
15011501
.then((deleteUsersResult) => {
15021502
expect(deleteUsersResult.successCount).to.equal(1);
15031503
expect(deleteUsersResult.failureCount).to.equal(0);
15041504
})
15051505
// Delete the user again, ensuring that everything still counts as a success.
1506-
.then(() => admin.auth().deleteUsers([uid]))
1506+
.then(() => deleteUsersWithDelay([uid]))
15071507
.then((deleteUsersResult) => {
15081508
expect(deleteUsersResult.successCount).to.equal(1);
15091509
expect(deleteUsersResult.failureCount).to.equal(0);
@@ -2083,6 +2083,22 @@ function safeDelete(uid: string): Promise<void> {
20832083
return deletePromise;
20842084
}
20852085

2086+
/**
2087+
* Deletes the specified list of users by calling the `deleteUsers()` API. This
2088+
* API is rate limited at 1 QPS, and therefore this helper function staggers
2089+
* subsequent invocations by adding 1 second delay to each call.
2090+
*
2091+
* @param {string[]} uids The list of user identifiers to delete.
2092+
* @return {Promise} A promise that resolves when delete operation resolves.
2093+
*/
2094+
function deleteUsersWithDelay(uids: string[]): Promise<admin.auth.DeleteUsersResult> {
2095+
return new Promise((resolve) => {
2096+
setTimeout(resolve, 1000);
2097+
}).then(() => {
2098+
return admin.auth().deleteUsers(uids);
2099+
});
2100+
}
2101+
20862102
/**
20872103
* Asserts actual object is equal to expected object while ignoring key order.
20882104
* This is useful since to.deep.equal fails when order differs.

0 commit comments

Comments
 (0)