voluptasmollitia
Version:
Monorepo for the Firebase JavaScript SDK
1,521 lines (1,428 loc) • 530 kB
JavaScript
/**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Tests for authuser.js
*/
goog.provide('fireauth.AuthUserTest');
goog.require('fireauth.ActionCodeSettings');
goog.require('fireauth.Auth');
goog.require('fireauth.AuthCredential');
goog.require('fireauth.AuthError');
goog.require('fireauth.AuthErrorWithCredential');
goog.require('fireauth.AuthEvent');
goog.require('fireauth.AuthEventManager');
goog.require('fireauth.AuthUser');
goog.require('fireauth.AuthUserInfo');
goog.require('fireauth.EmailAuthProvider');
goog.require('fireauth.GoogleAuthProvider');
goog.require('fireauth.MultiFactorAssertion');
goog.require('fireauth.MultiFactorInfo');
goog.require('fireauth.MultiFactorSession');
goog.require('fireauth.MultiFactorUser');
goog.require('fireauth.OAuthSignInHandler');
goog.require('fireauth.PhoneAuthCredential');
goog.require('fireauth.PhoneAuthProvider');
goog.require('fireauth.ProactiveRefresh');
goog.require('fireauth.RpcHandler');
goog.require('fireauth.SAMLAuthProvider');
goog.require('fireauth.StsTokenManager');
goog.require('fireauth.TokenRefreshTime');
goog.require('fireauth.UserEventType');
goog.require('fireauth.UserMetadata');
goog.require('fireauth.authenum.Error');
goog.require('fireauth.common.testHelper');
goog.require('fireauth.constants');
goog.require('fireauth.deprecation');
goog.require('fireauth.idp');
goog.require('fireauth.iframeclient.IfcHandler');
goog.require('fireauth.object');
goog.require('fireauth.storage.PendingRedirectManager');
goog.require('fireauth.storage.RedirectUserManager');
goog.require('fireauth.util');
goog.require('goog.Promise');
goog.require('goog.Uri');
goog.require('goog.events');
goog.require('goog.events.EventTarget');
goog.require('goog.object');
goog.require('goog.testing.AsyncTestCase');
goog.require('goog.testing.MockClock');
goog.require('goog.testing.MockControl');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.recordFunction');
goog.setTestOnly('fireauth.AuthUserTest');
var config = {
apiKey: 'apiKey1'
};
var user = null;
var accountInfo = null;
var accountInfoWithPhone = null;
var providerData1 = null;
var providerData2 = null;
var providerDataPhone = null;
var config1 = null;
var config2 = null;
var rpcHandler = null;
var token = null;
var tokenResponse = null;
var accountInfo2 = null;
var getAccountInfoResponse = null;
var getAccountInfoResponseProviderData1 = null;
var getAccountInfoResponseProviderData2 = null;
// A sample JWT, along with its decoded contents.
var idTokenGmail = {
data: {
iss: 'https://securetoken.google.com/projectId',
auth_time: 1522715325,
sub: '679',
aud: 'projectId',
iat: 1522776807,
provider_id: 'gmail.com',
email: 'test123456@gmail.com',
federated_id: 'https://www.google.com/accounts/123456789',
firebase: {
identities: {
email: [
'test123456@gmail.com'
]
},
sign_in_provider: 'password'
}
}
};
var idTokenSaml = {
data: {
iss: 'https://securetoken.google.com/projectId',
sub: '679',
aud: 'projectId',
federated_id: 'https://www.example.com/saml/1234567890',
provider_id: 'saml.provider',
email: 'test123456@gmail.com'
}
};
var idTokenCustomClaims = {
data: {
iss: 'https://securetoken.google.com/projectId',
name: 'John Doe',
admin: true,
aud: 'projectId',
auth_time: 1522715325,
sub: 'nep2uwNCK4PqjvoKjb0InVJHlGi1',
iat: 1522776807,
email: "testuser@gmail.com",
email_verified: true,
firebase: {
identities: {
email: [
'testuser@gmail.com'
]
},
sign_in_provider: 'password'
}
}
};
var expectedTokenResponseWithIdPData;
var expectedAdditionalUserInfo;
var expectedGoogleCredential;
var expectedReauthenticateTokenResponse;
var now = Date.now();
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
var stubs = new goog.testing.PropertyReplacer();
var ignoreArgument;
var mockControl;
var app;
var auth;
var getAccountInfoResponseGoogleProviderData;
var getAccountInfoResponsePhoneAuthProviderData;
var expectedPhoneNumber;
var appVerifier;
var expectedRecaptchaToken;
var actionCodeSettings = {
'url': 'https://www.example.com/?state=abc',
'iOS': {
'bundleId': 'com.example.ios'
},
'android': {
'packageName': 'com.example.android',
'installApp': true,
'minimumVersion': '12'
},
'handleCodeInApp': true,
'dynamicLinkDomain': 'example.page.link'
};
var lastLoginAt = '1506050282000';
var createdAt = '1506044998000';
var lastLoginAt2 = '1506053999000';
var createdAt2 = '1505980145000';
var expectedSamlTokenResponseWithIdPData;
var expectedSamlAdditionalUserInfo;
var jwt;
var newJwt;
var userReloadedEventHandler;
var multiFactor;
var mfaInfo;
var multiFactorErrorServerResponse;
var multiFactorTokenResponse;
var multiFactorGetAccountInfoResponse;
var nonMultiFactorTokenResponse;
function setUp() {
// Disable Auth event manager by default unless needed for a specific test.
fireauth.AuthEventManager.ENABLED = false;
config1 = {
apiKey: 'apiKey1',
appName: 'appId1'
};
config2 = {
apiKey: 'apiKey2',
appName: 'appId2'
};
idTokenGmail.data.exp = now / 1000 + 3600;
idTokenGmail.jwt =
fireauth.common.testHelper.createMockJwt(idTokenGmail.data);
idTokenSaml.data.exp = now / 1000 + 3600;
idTokenSaml.jwt = fireauth.common.testHelper.createMockJwt(idTokenSaml.data);
idTokenCustomClaims.data.exp = now / 1000 + 3600;
idTokenCustomClaims.jwt =
fireauth.common.testHelper.createMockJwt(idTokenCustomClaims.data);
// Assume origin is a valid one.
stubs.replace(
fireauth.RpcHandler.prototype,
'getAuthorizedDomains',
function() {
var uri = goog.Uri.parse(fireauth.util.getCurrentUrl());
var domain = uri.getDomain();
return goog.Promise.resolve([domain]);
});
// Simulate tab can run in background.
stubs.replace(
fireauth.util,
'runsInBackground',
function() {
return true;
});
// In case the tests are run from an iframe.
stubs.replace(
fireauth.util,
'isIframe',
function() {
return false;
});
stubs.replace(
Date,
'now',
function() {
return now;
});
multiFactor = {
'enrolledFactors': [
{
'uid': 'ENROLLMENT_UID1',
'displayName': 'Work phone number',
'enrollmentTime': new Date(now).toUTCString(),
'factorId': fireauth.constants.SecondFactorType.PHONE,
'phoneNumber': '+16505551234'
},
{
'uid': 'ENROLLMENT_UID2',
'displayName': null,
'enrollmentTime': new Date(now).toUTCString(),
'factorId': fireauth.constants.SecondFactorType.PHONE,
'phoneNumber': '+16505556789'
}
]
};
mfaInfo = [
{
'mfaEnrollmentId': 'ENROLLMENT_UID1',
'displayName': 'Work phone number',
'enrolledAt': new Date(now).toISOString(),
'phoneInfo': '+16505551234'
},
{
'mfaEnrollmentId': 'ENROLLMENT_UID2',
'enrolledAt': new Date(now).toISOString(),
'phoneInfo': '+16505556789'
}
];
accountInfo = {
'uid': 'defaultUserId',
'email': 'user@default.com',
'displayName': 'defaultDisplayName',
'photoURL': 'https://www.default.com/default/default.png',
'emailVerified': true,
'lastLoginAt': lastLoginAt,
'createdAt': createdAt
};
accountInfoWithPhone = {
'uid': 'defaultUserId',
'email': 'user@default.com',
'displayName': 'defaultDisplayName',
'photoURL': 'https://www.default.com/default/default.png',
'emailVerified': true,
'phoneNumber': '+16505550101',
'lastLoginAt': lastLoginAt,
'createdAt': createdAt
};
accountInfoWithEnrolledFactors = {
'uid': 'defaultUserId',
'email': 'user@default.com',
'displayName': 'defaultDisplayName',
'photoURL': 'https://www.default.com/default/default.png',
'emailVerified': true,
'lastLoginAt': lastLoginAt,
'createdAt': createdAt,
'multiFactor': multiFactor
};
accountInfo2 = {
'uid': '14584746072031976743',
'email': 'uid123@fake.com',
'displayName': 'John Doe',
// common_typos_disable.
'photoURL': 'http://abs.twimg.com/sticky/default_profile_images/defaul' +
't_profile_3_normal.png',
'emailVerified': true,
'lastLoginAt': lastLoginAt2,
'createdAt': createdAt2
};
providerData1 = new fireauth.AuthUserInfo(
'providerUserId1',
'providerId1',
'user1@example.com',
'user1',
'https://www.example.com/user1/photo.png');
providerData2 = new fireauth.AuthUserInfo(
'providerUserId2',
'providerId2',
'user2@example.com',
'user2',
'https://www.example.com/user2/photo.png');
providerDataPhone = new fireauth.AuthUserInfo(
'+16505550101', 'phone', undefined, undefined, undefined, '+16505550101');
rpcHandler = new fireauth.RpcHandler('apiKey1');
token = new fireauth.StsTokenManager(rpcHandler);
token.setRefreshToken('refreshToken');
jwt = fireauth.common.testHelper.createMockJwt(
{'group': '1'}, now + 3600 * 1000);
newJwt = fireauth.common.testHelper.createMockJwt(
{'group': '2'}, now + 3600 * 1000);
token.setAccessToken(jwt);
tokenResponse = {
'idToken': jwt,
'refreshToken': 'refreshToken',
'expiresIn': '4800'
};
// accountInfo in the format of a getAccountInfo response.
getAccountInfoResponse = {
'users': [{
'localId': 'defaultUserId',
'email': 'user@default.com',
'emailVerified': true,
'phoneNumber': '+16505550101',
'displayName': 'defaultDisplayName',
'providerUserInfo': [],
'photoUrl': 'https://www.default.com/default/default.png',
'passwordUpdatedAt': 0.0,
'disabled': false,
'lastLoginAt': lastLoginAt,
'createdAt': createdAt
}]
};
// providerData1 and providerData2 in the format of a getAccountInfo response.
getAccountInfoResponseProviderData1 = {
'providerId': 'providerId1',
'displayName': 'user1',
'email': 'user1@example.com',
'photoUrl': 'https://www.example.com/user1/photo.png',
'rawId': 'providerUserId1'
};
getAccountInfoResponseProviderData2 = {
'providerId': 'providerId2',
'displayName': 'user2',
'email': 'user2@example.com',
'photoUrl': 'https://www.example.com/user2/photo.png',
'rawId': 'providerUserId2'
};
getAccountInfoResponseGoogleProviderData = {
'providerId': 'google.com',
'displayName': 'My Google Name',
'email': 'me@gmail.com',
'photoUrl': 'https://www.google.com/me.png',
'rawId': 'myGoogleId'
};
getAccountInfoResponsePhoneAuthProviderData = {
'providerId': 'phone',
'rawId': '+16505550101',
'phoneNumber': '+16505550101'
};
expectedTokenResponseWithIdPData = {
'idToken': newJwt,
'refreshToken': 'newRefreshToken',
// Credential returned.
'providerId': 'google.com',
'oauthAccessToken': 'googleAccessToken',
'oauthIdToken': 'googleIdToken',
'oauthExpireIn': 3600,
// Additional user info data.
'rawUserInfo': '{"kind":"plus#person","displayName":"John Doe","na' +
'me":{"givenName":"John","familyName":"Doe"}}'
};
expectedReauthenticateTokenResponse = {
'idToken': idTokenGmail.jwt,
'refreshToken': 'myRefreshToken',
// Credential returned.
'providerId': 'google.com',
'oauthAccessToken': 'googleAccessToken',
'oauthIdToken': 'googleIdToken',
'oauthExpireIn': 3600,
// Additional user info data.
'rawUserInfo': '{"kind":"plus#person","displayName":"John Doe","na' +
'me":{"givenName":"John","familyName":"Doe"}}'
};
expectedAdditionalUserInfo = {
'profile': {
'kind': 'plus#person',
'displayName': 'John Doe',
'name': {
'givenName': 'John',
'familyName': 'Doe'
}
},
'providerId': 'google.com',
'isNewUser': false
};
expectedGoogleCredential = fireauth.GoogleAuthProvider.credential(
'googleIdToken', 'googleAccessToken');
expectedSamlTokenResponseWithIdPData = {
'idToken': newJwt,
'refreshToken': 'newRefreshToken',
'providerId': 'saml.provider',
// Additional user info data.
'rawUserInfo': '{"kind":"plus#person","displayName":"John Doe","na' +
'me":{"givenName":"John","familyName":"Doe"}}'
};
expectedSamlAdditionalUserInfo = {
'profile': {
'kind': 'plus#person',
'displayName': 'John Doe',
'name': {
'givenName': 'John',
'familyName': 'Doe'
}
},
'providerId': 'saml.provider',
'isNewUser': false
};
expectedPhoneNumber = '+16505550101';
expectedRecaptchaToken = 'RECAPTCHA_TOKEN';
appVerifier = {
'type': 'recaptcha',
'verify': function() {
return goog.Promise.resolve(expectedRecaptchaToken);
}
};
ignoreArgument = goog.testing.mockmatchers.ignoreArgument;
mockControl = new goog.testing.MockControl();
mockControl.$resetAll();
nonMultiFactorTokenResponse = {
'idToken': fireauth.common.testHelper.createMockJwt({
'sub': 'defaultUserId',
'firebase': {
'sign_in_provider': 'password'
}
}),
'refreshToken': 'SINGLE_FACTOR_REFRESH_TOKEN'
};
multiFactorTokenResponse = {
'idToken': fireauth.common.testHelper.createMockJwt({
'sub': 'defaultUserId',
'firebase': {
'sign_in_provider': 'password',
'sign_in_second_factor': 'phone'
}
}),
'refreshToken': 'MULTI_FACTOR_REFRESH_TOKEN'
};
multiFactorErrorServerResponse = {
'mfaInfo': [
{
'mfaEnrollmentId': 'ENROLLMENT_UID1',
'enrolledAt': new Date(now).toISOString(),
'phoneInfo': '+*******1234'
},
{
'mfaEnrollmentId': 'ENROLLMENT_UID2',
'displayName': 'Spouse phone number',
'enrolledAt': new Date(now).toISOString(),
'phoneInfo': '+*******6789'
}
],
'mfaPendingCredential': 'PENDING_CREDENTIAL',
// Credential returned.
'providerId': 'google.com',
'oauthAccessToken': 'googleAccessToken',
'oauthIdToken': 'googleIdToken',
'oauthExpireIn': 3600,
// Additional user info data.
'rawUserInfo': '{"kind":"plus#person","displayName":"John Doe",' +
'"name":{"givenName":"John","familyName":"Doe"}}'
};
multiFactorGetAccountInfoResponse = {
'users': [{
'localId': 'defaultUserId',
'email': 'user@default.com',
'emailVerified': true,
'displayName': 'defaultDisplayName',
'providerUserInfo': [],
'photoUrl': 'https://www.default.com/default/default.png',
'passwordUpdatedAt': 0.0,
'disabled': false,
'lastLoginAt': '1506050282000',
'createdAt': '1506050282000',
'mfaInfo': [
{
'mfaEnrollmentId': 'ENROLLMENT_UID1',
'enrolledAt': new Date(now).toISOString(),
'phoneInfo': '+16505551234'
},
{
'mfaEnrollmentId': 'ENROLLMENT_UID2',
'displayName': 'Spouse phone number',
'enrolledAt': new Date(now).toISOString(),
'phoneInfo': '+16505556789'
}
]
}]
};
}
function tearDown() {
for (var i = 0; i < firebase.apps.length; i++) {
asyncTestCase.waitForSignals(1);
firebase.apps[i].delete().then(function() {
asyncTestCase.signal();
});
}
if (auth) {
auth.delete();
}
// Reset already initialized Auth event managers.
fireauth.AuthEventManager.manager_ = {};
user = null;
accountInfo = null;
accountInfoWithPhone = null;
accountInfoWithEnrolledFactors = null;
accountInfo2 = null;
getAccountInfoResponse = null;
getAccountInfoResponseProviderData1 = null;
getAccountInfoResponseProviderData2 = null;
providerData1 = null;
providerData2 = null;
providerDataPhone = null;
rpcHandler = null;
token = null;
tokenResponse = null;
config1 = null;
config2 = null;
multiFactor = null;
mfaInfo = null;
multiFactorErrorServerResponse = null;
multiFactorTokenResponse = null;
multiFactorGetAccountInfoResponse = null;
nonMultiFactorTokenResponse = null;
window.localStorage.clear();
window.sessionStorage.clear();
stubs.reset();
try {
mockControl.$verifyAll();
} finally {
mockControl.$tearDown();
}
}
/** @return {!goog.events.EventTarget} The event dispatcher test object. */
function createEventDispatcher() {
return new goog.events.EventTarget();
}
/**
* Asserts that token events do not trigger.
* @param {!fireauth.AuthUser} user
*/
function assertNoTokenEvents(user) {
goog.events.listen(
user, fireauth.UserEventType.TOKEN_CHANGED, function(event) {
fail('Token change should not trigger due to token being unchanged!');
});
}
/**
* Asserts that user invalidated events do not trigger.
* @param {!fireauth.AuthUser} user
*/
function assertNoUserInvalidatedEvents(user) {
goog.events.listen(
user, fireauth.UserEventType.USER_INVALIDATED, function(event) {
fail('User invalidate event should not trigger!');
});
}
/**
* Asserts that state events do not trigger.
* @param {!fireauth.AuthUser} user
*/
function assertNoStateEvents(user) {
user.addStateChangeListener(function(userTemp) {
fail('State change listener should not trigger!');
});
}
/**
* Asserts that delete events do not trigger.
* @param {!fireauth.AuthUser} user
*/
function assertNoDeleteEvents(user) {
goog.events.listen(
user, fireauth.UserEventType.USER_DELETED, function(event) {
fail('User deleted listener should not trigger!');
});
}
/**
* Asserts that a method should fail when user is destroyed and no listeners
* are triggered.
* @param {string} methodName The name of the method of AuthUser that should
* fail if the user is destroyed.
* @param {!Array} parameters The arguments to pass to the method.
*/
function assertFailsWhenUserIsDestroyed(methodName, parameters) {
asyncTestCase.waitForSignals(1);
user = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
assertNoStateEvents(user);
assertNoTokenEvents(user);
assertNoDeleteEvents(user);
assertNoUserInvalidatedEvents(user);
user.destroy();
user[methodName].apply(user, parameters).then(fail, function(error) {
fireauth.common.testHelper.assertErrorEquals(
new fireauth.AuthError(fireauth.authenum.Error.MODULE_DESTROYED),
error);
asyncTestCase.signal(1);
});
}
function testProviderData() {
assertEquals('providerUserId1', providerData1['uid']);
assertEquals('providerId1', providerData1['providerId']);
assertEquals('user1@example.com', providerData1['email']);
assertEquals('user1', providerData1['displayName']);
assertEquals(
'https://www.example.com/user1/photo.png', providerData1['photoURL']);
}
function testUser() {
accountInfo['email'] = null;
providerData1 = new fireauth.AuthUserInfo(
'providerUserId1',
'providerId1',
'user1@example.com',
null,
'https://www.example.com/user1/photo.png');
user = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
user.addProviderData(providerData1);
user.addProviderData(providerData2);
assertObjectEquals(
new fireauth.UserMetadata(createdAt, lastLoginAt), user.metadata);
assertEquals(jwt, user.lastAccessToken_);
assertEquals('defaultUserId', user['uid']);
assertEquals('defaultDisplayName', user['displayName']);
assertNull(user['email']);
assertEquals('https://www.default.com/default/default.png', user['photoURL']);
assertEquals('firebase', user['providerId']);
assertEquals(false, user['isAnonymous']);
assertNull(user['tenantId']);
assertArrayEquals(['providerId1', 'providerId2'], user.getProviderIds());
assertObjectEquals(
{
'uid': 'providerUserId1',
'displayName': null,
'photoURL': 'https://www.example.com/user1/photo.png',
'email': 'user1@example.com',
'providerId': 'providerId1',
'phoneNumber': null
},
user['providerData'][0]);
assertObjectEquals(
{
'uid': 'providerUserId2',
'displayName': 'user2',
'photoURL': 'https://www.example.com/user2/photo.png',
'email': 'user2@example.com',
'providerId': 'providerId2',
'phoneNumber': null
},
user['providerData'][1]);
// Test popup event ID setters and getters.
assertNull(user.getPopupEventId());
user.setPopupEventId('1234');
assertEquals('1234', user.getPopupEventId());
user.setPopupEventId('5678');
assertEquals('5678', user.getPopupEventId());
// Test redirect event ID setters and getters.
assertNull(user.getRedirectEventId());
user.setRedirectEventId('1234');
assertEquals('1234', user.getRedirectEventId());
user.setRedirectEventId('5678');
assertEquals('5678', user.getRedirectEventId());
// Test ApiKey getter.
assertEquals('apiKey1', user.getApiKey());
}
/**
* Asserts that a user initiated with an emulator config will propagate
* the config to the RPC handler.
*/
function tesUser_initWithEmulator() {
// Listen to emulator config calls on RpcHandler.
stubs.replace(
fireauth.RpcHandler.prototype,
'updateEmulatorConfig',
goog.testing.recordFunction());
// Initialize a user.
user = new fireauth.AuthUser(
{
appName: config1.appName,
apiKey: config1.apiKey,
emulatorConfig: {
url: 'http://emulator.test.domain:1234'
}
}
);
// Should notify the RPC handler.
assertEquals(
1, fireauth.RpcHandler.prototype.updateEmulatorConfig.getCallCount());
assertObjectEquals(
{
url: 'http://emulator.test.domain:1234',
},
fireauth.RpcHandler.prototype.updateEmulatorConfig.getLastCall()
.getArgument(0)
);
}
function testUser_multiFactor() {
user = new fireauth.AuthUser(
config1, tokenResponse, accountInfoWithEnrolledFactors);
user.addProviderData(providerData1);
user.addProviderData(providerData2);
assertTrue(user.multiFactor instanceof fireauth.MultiFactorUser);
assertObjectEquals(
new fireauth.MultiFactorUser(user, accountInfoWithEnrolledFactors),
user.multiFactor);
}
function testUser_copyUser() {
config1['authDomain'] = 'subdomain.firebaseapp.com';
config2['authDomain'] = 'subdomain.firebaseapp.com';
asyncTestCase.waitForSignals(1);
// Sets the tenant ID on user to be copied.
accountInfo['tenantId'] = 'TENANT_ID';
user = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
user.addProviderData(providerData1);
user.addProviderData(providerData2);
stubs.replace(
fireauth.RpcHandler.prototype,
'getAccountInfoByIdToken',
goog.testing.recordFunction(function(idToken) {
// Mocks that tenant ID is returned in getAccountInfo response.
getAccountInfoResponse['users'][0]['tenantId'] = 'TENANT_ID';
return goog.Promise.resolve(getAccountInfoResponse);
}));
var expectedEventId = '1234';
stubs.replace(
fireauth.util,
'generateEventId',
function() {
// An event ID should be generated.
return expectedEventId;
});
storageManager = new fireauth.storage.RedirectUserManager(
fireauth.util.createStorageKey(config2['apiKey'], config2['appName']));
var frameworks = ['firebaseui', 'angularfire'];
fireauth.AuthEventManager.ENABLED = true;
var oAuthSignInHandlerInstance =
mockControl.createStrictMock(fireauth.OAuthSignInHandler);
mockControl.createConstructorMock(fireauth, 'OAuthSignInHandler');
var instantiateOAuthSignInHandler = mockControl.createMethodMock(
fireauth.AuthEventManager, 'instantiateOAuthSignInHandler');
instantiateOAuthSignInHandler(
ignoreArgument, ignoreArgument, ignoreArgument, ignoreArgument,
ignoreArgument, ignoreArgument).$returns(oAuthSignInHandlerInstance);
oAuthSignInHandlerInstance.shouldBeInitializedEarly().$returns(false);
oAuthSignInHandlerInstance.hasVolatileStorage().$returns(false);
oAuthSignInHandlerInstance.processRedirect(
ignoreArgument,
ignoreArgument,
ignoreArgument,
ignoreArgument).$does(function(
actualMode,
actualProvider,
actualEventId) {
assertEquals(
fireauth.AuthEvent.Type.LINK_VIA_REDIRECT, actualMode);
assertEquals(expectedProvider, actualProvider);
assertEquals(expectedEventId, actualEventId);
return goog.Promise.resolve();
});
oAuthSignInHandlerInstance.unloadsOnRedirect().$returns(false);
mockControl.$replayAll();
var copiedUser = fireauth.AuthUser.copyUser(
user, config2, storageManager, frameworks);
// Verifies that user is not reloaded on copying.
assertEquals(
0, fireauth.RpcHandler.prototype.getAccountInfoByIdToken.getCallCount());
fireauth.common.testHelper.assertUserEqualsInWithDiffApikey(
user, copiedUser, config1['apiKey'], config2['apiKey']);
assertFalse(copiedUser['isAnonymous']);
assertEquals('TENANT_ID', copiedUser['tenantId']);
// Confirm frameworks set on created user.
assertArrayEquals(frameworks, copiedUser.getFramework());
var expectedProvider = new fireauth.GoogleAuthProvider();
expectedProvider.addScope('scope1');
expectedProvider.addScope('scope2');
copiedUser.enablePopupRedirect();
copiedUser.linkWithRedirect(expectedProvider).then(function() {
assertEquals(1,
fireauth.RpcHandler.prototype.getAccountInfoByIdToken.getCallCount());
// Redirect event ID should be saved.
assertEquals(expectedEventId, copiedUser.getRedirectEventId());
// Redirect user should be saved in storage with correct redirect event ID.
storageManager.getRedirectUser().then(function(user) {
assertEquals(expectedEventId, user.getRedirectEventId());
assertObjectEquals(copiedUser.toPlainObject(), user.toPlainObject());
asyncTestCase.signal();
});
});
}
function testUser_copyUser_defaultConfig() {
user = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
user.addProviderData(providerData1);
user.addProviderData(providerData2);
var copiedUser = fireauth.AuthUser.copyUser(user);
assertObjectEquals(copiedUser.toPlainObject(), user.toPlainObject());
assertNull(user.getPopupEventId());
assertNull(user.getRedirectEventId());
}
function testUser_copyUser_expiredToken() {
// Mock the expired token.
tokenResponse['idToken'] =
fireauth.common.testHelper.createMockJwt(null, now - 5);
stubs.replace(
fireauth.RpcHandler.prototype,
'requestStsToken',
function(data) {
// Copying user should not trigger token refresh even if the token
// expires.
fail('The token should not be refreshed!');
});
user = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
var copiedUser = fireauth.AuthUser.copyUser(user);
assertObjectEquals(copiedUser.toPlainObject(), user.toPlainObject());
}
function testUser_copyUser_multiFactor() {
user1 = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
user2 = new fireauth.AuthUser(
config1, tokenResponse, accountInfoWithEnrolledFactors);
user3 = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
var multiFactorUser1 = user1.multiFactor;
user1.copy(user2);
// Same reference should be kept.
assertEquals(user1.multiFactor, multiFactorUser1);
assertObjectEquals(
new fireauth.MultiFactorUser(user2, accountInfoWithEnrolledFactors)
.toPlainObject(),
user1.multiFactor.toPlainObject());
// user1.multiFactor user reference should keep pointing to user1.
assertEquals(user1, user1.multiFactor.getUser());
user1.copy(user3);
// Same reference should be kept.
assertEquals(user1.multiFactor, multiFactorUser1);
assertObjectEquals(
new fireauth.MultiFactorUser(user3, accountInfo).toPlainObject(),
user1.multiFactor.toPlainObject());
assertEquals(0, user1.multiFactor.enrolledFactors.length);
// user1.multiFactor user reference should keep pointing to user1.
assertEquals(user1, user1.multiFactor.getUser());
}
function testUser_rpcHandlerEndpoints() {
// Confirm expected endpoint config passed to underlying RPC handler.
var endpoint = fireauth.constants.Endpoint.STAGING;
var endpointConfig = {
'firebaseEndpoint': endpoint.firebaseAuthEndpoint,
'secureTokenEndpoint': endpoint.secureTokenEndpoint,
'identityPlatformEndpoint': endpoint.identityPlatformEndpoint
};
stubs.replace(
fireauth.constants,
'getEndpointConfig',
function(opt_id) {
return endpointConfig;
});
var rpcHandler = mockControl.createStrictMock(fireauth.RpcHandler);
var rpcHandlerConstructor = mockControl.createConstructorMock(
fireauth, 'RpcHandler');
rpcHandlerConstructor(config1['apiKey'], endpointConfig, ignoreArgument)
.$returns(rpcHandler);
rpcHandler.updateTenantId(null);
mockControl.$replayAll();
user = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
}
function testUser_rpcHandlerEndpoints_tenantId() {
// Confirm expected endpoint config passed to underlying RPC handler.
var endpoint = fireauth.constants.Endpoint.STAGING;
var endpointConfig = {
'firebaseEndpoint': endpoint.firebaseAuthEndpoint,
'secureTokenEndpoint': endpoint.secureTokenEndpoint
};
stubs.replace(
fireauth.constants,
'getEndpointConfig',
function(opt_id) {
return endpointConfig;
});
var rpcHandler = mockControl.createStrictMock(fireauth.RpcHandler);
var rpcHandlerConstructor = mockControl.createConstructorMock(
fireauth, 'RpcHandler');
rpcHandlerConstructor(config1['apiKey'], endpointConfig, ignoreArgument)
.$returns(rpcHandler);
// Tenant ID of RPC handler should be updated.
rpcHandler.updateTenantId('TENANT_ID');
mockControl.$replayAll();
// Sets the tenant ID on user.
accountInfo['tenantId'] = 'TENANT_ID';
user = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
assertEquals('TENANT_ID', user['tenantId']);
}
function testUser_stateChangeListeners() {
// Test user state change listeners: adding, removing and their execution.
asyncTestCase.waitForSignals(3);
var listener1 = goog.testing.recordFunction(function(userTemp) {
assertEquals(user, userTemp);
// Whether it resolves or rejects, it shouldn't affect the outcome.
return goog.Promise.resolve();
});
var listener2 = goog.testing.recordFunction(function(userTemp) {
assertEquals(user, userTemp);
// Whether it resolves or rejects, it shouldn't affect the outcome.
return goog.Promise.reject();
});
// Listener that does not return a promise.
var listener3 = goog.testing.recordFunction();
user = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
// Add all listeners.
user.addStateChangeListener(listener1);
user.addStateChangeListener(listener2);
user.addStateChangeListener(listener3);
// Notify listeners.
user.notifyStateChangeListeners_().then(function(userTemp) {
assertEquals(user, userTemp);
// All should run.
assertEquals(1, listener1.getCallCount());
assertEquals(1, listener2.getCallCount());
assertEquals(1, listener3.getCallCount());
// Remove second and third listener.
user.removeStateChangeListener(listener2);
user.removeStateChangeListener(listener3);
asyncTestCase.signal();
// Notify listeners.
user.notifyStateChangeListeners_().then(function(userTemp) {
assertEquals(user, userTemp);
// Only first listener should run.
assertEquals(2, listener1.getCallCount());
assertEquals(1, listener2.getCallCount());
assertEquals(1, listener3.getCallCount());
// Remove remaining listener.
user.removeStateChangeListener(listener1);
asyncTestCase.signal();
// Notify listeners.
user.notifyStateChangeListeners_().then(function(userTemp) {
assertEquals(user, userTemp);
// No listener should run.
assertEquals(2, listener1.getCallCount());
assertEquals(1, listener2.getCallCount());
assertEquals(1, listener3.getCallCount());
asyncTestCase.signal();
});
});
});
}
function testGetRpcHandler() {
user1 = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
user2 = new fireauth.AuthUser(config2, tokenResponse, accountInfo);
assertTrue(user1.getRpcHandler() instanceof fireauth.RpcHandler);
assertTrue(user2.getRpcHandler() instanceof fireauth.RpcHandler);
assertEquals(config1['apiKey'], user1.getRpcHandler().getApiKey());
assertEquals(config2['apiKey'], user2.getRpcHandler().getApiKey());
}
function testAddProviderData_sameProviderId() {
var providerData1 = new fireauth.AuthUserInfo(
'providerUserId1',
'theProviderId',
'user1@example.com',
null,
'https://www.example.com/user1/photo.png');
var providerData2 = new fireauth.AuthUserInfo(
'providerUserId2',
'theProviderId',
'user2@example.com',
null,
'https://www.example.com/user2/photo.png');
user = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
user.addProviderData(providerData1);
user.addProviderData(providerData2);
assertArrayEquals(['theProviderId'], user.getProviderIds());
assertArrayEquals([{
'uid': 'providerUserId2',
'displayName': null,
'photoURL': 'https://www.example.com/user2/photo.png',
'email': 'user2@example.com',
'providerId': 'theProviderId',
'phoneNumber': null
}], user['providerData']);
}
function testUser_removeProviderData() {
user = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
user.addProviderData(providerData1);
user.addProviderData(providerData2);
assertArrayEquals(['providerId1', 'providerId2'], user.getProviderIds());
user.removeProviderData('providerId1');
assertArrayEquals(['providerId2'], user.getProviderIds());
}
function testUser_setUserAccountInfoFromToken_success() {
var response = {
'users': [{
'localId': '14584746072031976743',
'email': 'uid123@fake.com',
'emailVerified': true,
'displayName': 'John Doe',
'providerUserInfo': [
{
'email': 'user@gmail.com',
'providerId': 'google.com',
'displayName': 'John G. Doe',
'photoUrl': 'https://lh5.googleusercontent.com/123456789/photo.jpg',
'federatedId': 'https://accounts.google.com/123456789',
'rawId': '123456789'
},
{
'providerId': 'twitter.com',
'displayName': 'John Gammell Doe',
'photoUrl': 'http://abs.twimg.com/sticky/default_profile_images/' +
'default_profile_3_normal.png',
'federatedId': 'http://twitter.com/987654321',
'rawId': '987654321'
}
],
'photoUrl': 'http://abs.twimg.com/sticky/default_profile_images/' +
'default_profile_3_normal.png',
'passwordUpdatedAt': 0.0,
'disabled': false
}]
};
var expectedUser = new fireauth.AuthUser(config1, tokenResponse, {
'uid': '14584746072031976743',
'email': 'uid123@fake.com',
'displayName': 'John Doe',
'photoURL': 'http://abs.twimg.com/sticky/default_profile_images/defaul' +
't_profile_3_normal.png',
'emailVerified': true
});
expectedUser.addProviderData(new fireauth.AuthUserInfo(
'123456789',
'google.com',
'user@gmail.com',
'John G. Doe',
'https://lh5.googleusercontent.com/123456789/photo.jpg'));
expectedUser.addProviderData(new fireauth.AuthUserInfo(
'987654321',
'twitter.com',
null,
'John Gammell Doe',
'http://abs.twimg.com/sticky/default_profile_images/default_profile_' +
'3_normal.png'));
stubs.replace(
fireauth.RpcHandler.prototype,
'getAccountInfoByIdToken',
function(data) {
return new goog.Promise(function(resolve, reject) {
assertEquals(jwt, data);
resolve(response);
});
});
asyncTestCase.waitForSignals(1);
// Initialize user with no account info or provider data.
user = new fireauth.AuthUser(config1, tokenResponse);
// Record event triggers on USER_RELOADED.
var userReloadedEventHandler = goog.testing.recordFunction();
goog.events.listen(
user, fireauth.UserEventType.USER_RELOADED, userReloadedEventHandler);
var stateChangedCounter = 0;
user.addStateChangeListener(function(user) {
stateChangedCounter++;
return goog.Promise.resolve();
});
assertNoTokenEvents(user);
assertNoUserInvalidatedEvents(user);
assertEquals(0, userReloadedEventHandler.getCallCount());
user.reload().then(function() {
assertEquals(1, stateChangedCounter);
fireauth.common.testHelper.assertUserEquals(expectedUser, user);
// Confirm event triggered on reload with the expected properties.
assertEquals(1, userReloadedEventHandler.getCallCount());
var event = userReloadedEventHandler.getLastCall().getArgument(0);
assertObjectEquals(response.users[0], event.userServerResponse);
asyncTestCase.signal();
});
}
function testSetUserAccountInfoFromToken_success_emailAndPassword() {
var response = {
'users': [{
'localId': '14584746072031976743',
'email': 'uid123@fake.com',
'emailVerified': true,
'displayName': 'John Doe',
'passwordHash': 'PASSWORD_HASH',
'providerUserInfo': [],
'photoUrl': 'http://abs.twimg.com/sticky/default_profile_images/' +
'default_profile_3_normal.png',
'passwordUpdatedAt': 0.0,
'disabled': false
}]
};
var expectedUser = new fireauth.AuthUser(config1, tokenResponse, {
'uid': '14584746072031976743',
'email': 'uid123@fake.com',
'displayName': 'John Doe',
'photoURL': 'http://abs.twimg.com/sticky/default_profile_images/defaul' +
't_profile_3_normal.png',
'emailVerified': true
});
stubs.replace(
fireauth.RpcHandler.prototype,
'getAccountInfoByIdToken',
function(data) {
return new goog.Promise(function(resolve, reject) {
assertEquals(jwt, data);
resolve(response);
});
});
user = new fireauth.AuthUser(config1, tokenResponse);
// Record event triggers on USER_RELOADED.
var userReloadedEventHandler = goog.testing.recordFunction();
goog.events.listen(
user, fireauth.UserEventType.USER_RELOADED, userReloadedEventHandler);
asyncTestCase.waitForSignals(1);
assertEquals(0, userReloadedEventHandler.getCallCount());
user.reload().then(function() {
fireauth.common.testHelper.assertUserEquals(expectedUser, user);
// Confirm event triggered on reload with the expected properties.
assertEquals(1, userReloadedEventHandler.getCallCount());
var event = userReloadedEventHandler.getLastCall().getArgument(0);
assertObjectEquals(response.users[0], event.userServerResponse);
asyncTestCase.signal();
});
}
function testSetUserAccountInfoFromToken_success_emailNoPassword() {
var response = {
'users': [{
'localId': '14584746072031976743',
'email': 'uid123@fake.com',
'emailVerified': true,
'displayName': 'John Doe',
'providerUserInfo': [],
'photoUrl': 'http://abs.twimg.com/sticky/default_profile_images/defaul' +
't_profile_3_normal.png',
'passwordUpdatedAt': 0.0,
'disabled': false
}]
};
var expectedUser = new fireauth.AuthUser(config1, tokenResponse, {
'uid': '14584746072031976743',
'email': 'uid123@fake.com',
'displayName': 'John Doe',
'photoURL': 'http://abs.twimg.com/sticky/default_profile_images/defaul' +
't_profile_3_normal.png',
'emailVerified': true,
'isAnonymous': false
});
stubs.replace(
fireauth.RpcHandler.prototype,
'getAccountInfoByIdToken',
function(data) {
return new goog.Promise(function(resolve, reject) {
assertEquals(jwt, data);
resolve(response);
});
});
user = new fireauth.AuthUser(config1, tokenResponse);
asyncTestCase.waitForSignals(1);
user.reload().then(function() {
assertObjectEquals(expectedUser.toPlainObject(), user.toPlainObject());
asyncTestCase.signal();
});
}
function testSetUserAccountInfoFromToken_success_passwordNoEmail() {
var response = {
'users': [{
'localId': '14584746072031976743',
'email': '',
'displayName': 'John Doe',
'passwordHash': 'PASSWORD_HASH',
'providerUserInfo': [],
'photoUrl': 'http://abs.twimg.com/sticky/default_profile_images/defaul' +
't_profile_3_normal.png',
'passwordUpdatedAt': 0.0,
'disabled': false
}]
};
var expectedUser = new fireauth.AuthUser(config1, tokenResponse, {
'uid': '14584746072031976743',
'email': '',
'displayName': 'John Doe',
'photoURL': 'http://abs.twimg.com/sticky/default_profile_images/defaul' +
't_profile_3_normal.png',
'isAnonymous': false
});
stubs.replace(
fireauth.RpcHandler.prototype,
'getAccountInfoByIdToken',
function(data) {
return new goog.Promise(function(resolve, reject) {
assertEquals(jwt, data);
resolve(response);
});
});
user = new fireauth.AuthUser(config1, tokenResponse);
asyncTestCase.waitForSignals(1);
user.reload().then(function() {
fireauth.common.testHelper.assertUserEquals(expectedUser, user);
asyncTestCase.signal();
});
}
function testUser_setUserAccountInfoFromToken_multiFactor_success() {
var response = {
'users': [{
'localId': '14584746072031976743',
'email': 'uid123@fake.com',
'emailVerified': true,
'displayName': 'John Doe',
'providerUserInfo': [
{
'email': 'user@gmail.com',
'providerId': 'google.com',
'displayName': 'John G. Doe',
'photoUrl': 'https://lh5.googleusercontent.com/123456789/photo.jpg',
'federatedId': 'https://accounts.google.com/123456789',
'rawId': '123456789'
},
{
'providerId': 'twitter.com',
'displayName': 'John Gammell Doe',
'photoUrl': 'http://abs.twimg.com/sticky/default_profile_images/' +
'default_profile_3_normal.png',
'federatedId': 'http://twitter.com/987654321',
'rawId': '987654321'
}
],
'photoUrl': 'http://abs.twimg.com/sticky/default_profile_images/' +
'default_profile_3_normal.png',
'passwordUpdatedAt': 0.0,
'disabled': false,
'mfaInfo': mfaInfo
}]
};
var expectedUser = new fireauth.AuthUser(config1, tokenResponse, {
'uid': '14584746072031976743',
'email': 'uid123@fake.com',
'displayName': 'John Doe',
'photoURL': 'http://abs.twimg.com/sticky/default_profile_images/defaul' +
't_profile_3_normal.png',
'emailVerified': true,
'multiFactor': multiFactor
});
expectedUser.addProviderData(new fireauth.AuthUserInfo(
'123456789',
'google.com',
'user@gmail.com',
'John G. Doe',
'https://lh5.googleusercontent.com/123456789/photo.jpg'));
expectedUser.addProviderData(new fireauth.AuthUserInfo(
'987654321',
'twitter.com',
null,
'John Gammell Doe',
'http://abs.twimg.com/sticky/default_profile_images/default_profile_' +
'3_normal.png'));
stubs.replace(
fireauth.RpcHandler.prototype,
'getAccountInfoByIdToken',
function(data) {
return new goog.Promise(function(resolve, reject) {
assertEquals(jwt, data);
resolve(response);
});
});
asyncTestCase.waitForSignals(1);
// Initialize user with no account info or provider data.
user = new fireauth.AuthUser(config1, tokenResponse);
var multiFactorUser = user.multiFactor;
assertEquals(0, user.multiFactor.enrolledFactors.length);
// Record event triggers on USER_RELOADED.
var userReloadedEventHandler = goog.testing.recordFunction();
goog.events.listen(
user, fireauth.UserEventType.USER_RELOADED, userReloadedEventHandler);
var stateChangedCounter = 0;
user.addStateChangeListener(function(user) {
stateChangedCounter++;
return goog.Promise.resolve();
});
assertNoTokenEvents(user);
assertNoUserInvalidatedEvents(user);
assertEquals(0, userReloadedEventHandler.getCallCount());
user.reload().then(function() {
assertEquals(1, stateChangedCounter);
fireauth.common.testHelper.assertUserEquals(expectedUser, user);
// Confirm event triggered on reload with the expected properties.
assertEquals(1, userReloadedEventHandler.getCallCount());
var event = userReloadedEventHandler.getLastCall().getArgument(0);
assertObjectEquals(response.users[0], event.userServerResponse);
// Confirm enrolled factors updated.
assertEquals(mfaInfo.length, user.multiFactor.enrolledFactors.length);
assertObjectEquals(
fireauth.MultiFactorInfo.fromServerResponse(mfaInfo[0]),
user.multiFactor.enrolledFactors[0]);
assertObjectEquals(
fireauth.MultiFactorInfo.fromServerResponse(mfaInfo[1]),
user.multiFactor.enrolledFactors[1]);
// Multifactor reference should not be updated.
assertEquals(multiFactorUser, user.multiFactor);
asyncTestCase.signal();
});
}
function testSetUserAccountInfoFromToken_success_tenantId() {
var response = {
'users': [{
'localId': '14584746072031976743',
'email': 'uid123@fake.com',
'emailVerified': true,
'displayName': 'John Doe',
'passwordHash': 'PASSWORD_HASH',
'providerUserInfo': [],
'photoUrl': 'http://abs.twimg.com/sticky/default_profile_images/' +
'default_profile_3_normal.png',
'passwordUpdatedAt': 0.0,
'disabled': false,
'tenantId': 'TENANT_ID'
}]
};
var updateTenantId = mockControl.createMethodMock(
fireauth.RpcHandler.prototype, 'updateTenantId');
// Tenant ID of RPC handler should be initialized to null.
updateTenantId(null).$once();
// Tenant ID of RPC handler should be updated by setAccountInfo.
updateTenantId('TENANT_ID').$once();
stubs.replace(
fireauth.RpcHandler.prototype,
'getAccountInfoByIdToken',
function(data) {
assertEquals(jwt, data);
return goog.Promise.resolve(response);
});
mockControl.$replayAll();
user = new fireauth.AuthUser(config1, tokenResponse);
asyncTestCase.waitForSignals(1);
user.reload().then(function() {
assertEquals('TENANT_ID', user['tenantId']);
asyncTestCase.signal();
});
}
function testUser_setUserAccountInfoFromToken_error() {
var error = {
'error': fireauth.authenum.Error.INTERNAL_ERROR
};
stubs.replace(
fireauth.RpcHandler.prototype,
'getAccountInfoByIdToken',
function(data) {
return goog.Promise.reject(error);
});
asyncTestCase.waitForSignals(1);
user = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
user.reload().thenCatch(function(e) {
// User data unchanged.
for (var key in accountInfo) {
// Metadata is structured differently in user compared to accountInfo.
if (key == 'lastLoginAt') {
assertEquals(
fireauth.util.utcTimestampToDateString(accountInfo[key]),
user['metadata']['lastSignInTime']);
} else if (key == 'createdAt') {
assertEquals(
fireauth.util.utcTimestampToDateString(accountInfo[key]),
user['metadata']['creationTime']);
} else {
assertEquals(accountInfo[key], user[key]);
}
}
assertObjectEquals(error, e);
asyncTestCase.signal();
});
}
function testUser_setUserAccountInfoFromToken_invalidResponse() {
// Test with invalid server response.
stubs.replace(
fireauth.RpcHandler.prototype,
'getAccountInfoByIdToken',
function(data) {
// Resolve getAccountInfo with invalid server response.
return goog.Promise.resolve({});
});
asyncTestCase.waitForSignals(1);
user = new fireauth.AuthUser(config1, tokenResponse, accountInfo);
user.reload().thenCatch(function(error) {
var expected = new fireauth.AuthError(
fireauth.authenum.Error.INTERNAL_ERROR);
assertEquals(expected.code, error.code);
// User data unchanged.
for (var key in accountInfo) {
// Metadata is structured differently in user compared to accountInfo.
if (key == 'lastLoginAt') {
assertEquals(
fireauth.util.utcTimestampToDateString(accountInfo[key]),
user['metadata']['lastSignInTime']);
} else if (key == 'createdAt') {
assertEquals(
fireauth.util.utcTimestampToDateString(accountInfo[key]),
user['metadata']['creationTime']);
} else {
assertEquals(accountInfo[key], user[key]);
}
}
asyncTestCase.signal();
});
}
function testUser_reload_success() {
user = new fireauth.AuthUser(config1, tokenResponse, accountInfo2);
user.addStateChangeListener(function(user) {
asyncTestCase.signal();
return goog.Promise.resolve();
});
assertNoTokenEvents(user);
assertNoUserInvalidatedEvents(user);
stubs.replace(
fireauth.RpcHandler.prototype,
'getAccountInfoByIdToken',
function(idToken) {
assertEquals(jwt, idToken);
user.copy(updatedUs