Skip to content

Commit

Permalink
fix(auth): Fixing flaky deleteUsers() integration tests (#917)
Browse files Browse the repository at this point in the history
  • Loading branch information
hiranya911 committed Jun 24, 2020
1 parent b93a3c3 commit 9b3a2ab
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 13 deletions.
16 changes: 9 additions & 7 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,8 @@ declare namespace admin.auth {
export import UpdatePhoneMultiFactorInfoRequest = _auth.admin.auth.UpdatePhoneMultiFactorInfoRequest;
export import MultiFactorCreateSettings = _auth.admin.auth.MultiFactorCreateSettings;
export import MultiFactorUpdateSettings = _auth.admin.auth.MultiFactorUpdateSettings;
export import DeleteUsersResult = _auth.admin.auth.DeleteUsersResult;
export import GetUsersResult = _auth.admin.auth.GetUsersResult;
}

declare namespace admin.credential {
Expand Down Expand Up @@ -882,7 +884,7 @@ declare namespace admin.remoteConfig {

/**
* Interface representing a Remote Config parameter.
* At minimum, a `defaultValue` or a `conditionalValues` entry must be present for the
* At minimum, a `defaultValue` or a `conditionalValues` entry must be present for the
* parameter to have any effect.
*/
interface RemoteConfigParameter {
Expand All @@ -894,7 +896,7 @@ declare namespace admin.remoteConfig {

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

/**
* Type representing a Remote Config parameter value.
* A `RemoteConfigParameterValue` could be either an `ExplicitParameterValue` or
* A `RemoteConfigParameterValue` could be either an `ExplicitParameterValue` or
* an `InAppDefaultValue`.
*/
type RemoteConfigParameterValue = ExplicitParameterValue | InAppDefaultValue;
Expand Down Expand Up @@ -1012,11 +1014,11 @@ declare namespace admin.remoteConfig {
*
* @param template The Remote Config template to be published.
* @param options Optional options object when publishing a Remote Config template:
* - {boolean} `force` Setting this to `true` forces the Remote Config template to
* be updated and circumvent the ETag. This approach is not recommended
* because it risks causing the loss of updates to your Remote Config
* - {boolean} `force` Setting this to `true` forces the Remote Config template to
* be updated and circumvent the ETag. This approach is not recommended
* because it risks causing the loss of updates to your Remote Config
* template if multiple clients are updating the Remote Config template.
* See {@link https://firebase.google.com/docs/remote-config/use-config-rest#etag_usage_and_forced_updates
* See {@link https://firebase.google.com/docs/remote-config/use-config-rest#etag_usage_and_forced_updates
* ETag usage and forced updates}.
*
* @return A Promise that fulfills with the published `RemoteConfigTemplate`.
Expand Down
28 changes: 22 additions & 6 deletions test/integration/auth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ describe('admin.auth', () => {
// left over from a prior run).
const uidsToDelete = usersToCreate.map((user) => user.uid);
uidsToDelete.push(importUser1.uid);
await admin.auth().deleteUsers(uidsToDelete);
await deleteUsersWithDelay(uidsToDelete);

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

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

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

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

return admin.auth().deleteUsers([uid])
return deleteUsersWithDelay([uid])
.then((deleteUsersResult) => {
expect(deleteUsersResult.successCount).to.equal(1);
expect(deleteUsersResult.failureCount).to.equal(0);
})
// Delete the user again, ensuring that everything still counts as a success.
.then(() => admin.auth().deleteUsers([uid]))
.then(() => deleteUsersWithDelay([uid]))
.then((deleteUsersResult) => {
expect(deleteUsersResult.successCount).to.equal(1);
expect(deleteUsersResult.failureCount).to.equal(0);
Expand Down Expand Up @@ -2083,6 +2083,22 @@ function safeDelete(uid: string): Promise<void> {
return deletePromise;
}

/**
* Deletes the specified list of users by calling the `deleteUsers()` API. This
* API is rate limited at 1 QPS, and therefore this helper function staggers
* subsequent invocations by adding 1 second delay to each call.
*
* @param {string[]} uids The list of user identifiers to delete.
* @return {Promise} A promise that resolves when delete operation resolves.
*/
function deleteUsersWithDelay(uids: string[]): Promise<admin.auth.DeleteUsersResult> {
return new Promise((resolve) => {
setTimeout(resolve, 1000);
}).then(() => {
return admin.auth().deleteUsers(uids);
});
}

/**
* Asserts actual object is equal to expected object while ignoring key order.
* This is useful since to.deep.equal fails when order differs.
Expand Down

0 comments on commit 9b3a2ab

Please sign in to comment.