@@ -1151,6 +1151,120 @@ AUTH_CONFIGS.forEach((testConfig) => {
11511151 } ) ;
11521152 } ) ;
11531153
1154+ describe ( 'getUserByProviderUid()' , ( ) => {
1155+ const providerId = 'google.com' ;
1156+ const providerUid = 'google_uid' ;
1157+ const tenantId = testConfig . supportsTenantManagement ? undefined : TENANT_ID ;
1158+ const expectedGetAccountInfoResult = getValidGetAccountInfoResponse ( tenantId ) ;
1159+ const expectedUserRecord = getValidUserRecord ( expectedGetAccountInfoResult ) ;
1160+ const expectedError = new FirebaseAuthError ( AuthClientErrorCode . USER_NOT_FOUND ) ;
1161+
1162+ // Stubs used to simulate underlying api calls.
1163+ let stubs : sinon . SinonStub [ ] = [ ] ;
1164+ beforeEach ( ( ) => sinon . spy ( validator , 'isEmail' ) ) ;
1165+ afterEach ( ( ) => {
1166+ ( validator . isEmail as any ) . restore ( ) ;
1167+ _ . forEach ( stubs , ( stub ) => stub . restore ( ) ) ;
1168+ stubs = [ ] ;
1169+ } ) ;
1170+
1171+ it ( 'should be rejected given no provider id' , ( ) => {
1172+ expect ( ( ) => ( auth as any ) . getUserByProviderUid ( ) )
1173+ . to . throw ( FirebaseAuthError )
1174+ . with . property ( 'code' , 'auth/invalid-provider-id' ) ;
1175+ } ) ;
1176+
1177+ it ( 'should be rejected given an invalid provider id' , ( ) => {
1178+ expect ( ( ) => auth . getUserByProviderUid ( '' , 'uid' ) )
1179+ . to . throw ( FirebaseAuthError )
1180+ . with . property ( 'code' , 'auth/invalid-provider-id' ) ;
1181+ } ) ;
1182+
1183+ it ( 'should be rejected given an invalid provider uid' , ( ) => {
1184+ expect ( ( ) => auth . getUserByProviderUid ( 'id' , '' ) )
1185+ . to . throw ( FirebaseAuthError )
1186+ . with . property ( 'code' , 'auth/invalid-provider-id' ) ;
1187+ } ) ;
1188+
1189+ it ( 'should be rejected given an app which returns null access tokens' , ( ) => {
1190+ return nullAccessTokenAuth . getUserByProviderUid ( providerId , providerUid )
1191+ . should . eventually . be . rejected . and . have . property ( 'code' , 'app/invalid-credential' ) ;
1192+ } ) ;
1193+
1194+ it ( 'should be rejected given an app which returns invalid access tokens' , ( ) => {
1195+ return malformedAccessTokenAuth . getUserByProviderUid ( providerId , providerUid )
1196+ . should . eventually . be . rejected . and . have . property ( 'code' , 'app/invalid-credential' ) ;
1197+ } ) ;
1198+
1199+ it ( 'should be rejected given an app which fails to generate access tokens' , ( ) => {
1200+ return rejectedPromiseAccessTokenAuth . getUserByProviderUid ( providerId , providerUid )
1201+ . should . eventually . be . rejected . and . have . property ( 'code' , 'app/invalid-credential' ) ;
1202+ } ) ;
1203+
1204+ it ( 'should resolve with a UserRecord on success' , ( ) => {
1205+ // Stub getAccountInfoByEmail to return expected result.
1206+ const stub = sinon . stub ( testConfig . RequestHandler . prototype , 'getAccountInfoByFederatedUid' )
1207+ . resolves ( expectedGetAccountInfoResult ) ;
1208+ stubs . push ( stub ) ;
1209+ return auth . getUserByProviderUid ( providerId , providerUid )
1210+ . then ( ( userRecord ) => {
1211+ // Confirm underlying API called with expected parameters.
1212+ expect ( stub ) . to . have . been . calledOnce . and . calledWith ( providerId , providerUid ) ;
1213+ // Confirm expected user record response returned.
1214+ expect ( userRecord ) . to . deep . equal ( expectedUserRecord ) ;
1215+ } ) ;
1216+ } ) ;
1217+
1218+ describe ( 'non-federated providers' , ( ) => {
1219+ let invokeRequestHandlerStub : sinon . SinonStub ;
1220+ beforeEach ( ( ) => {
1221+ invokeRequestHandlerStub = sinon . stub ( testConfig . RequestHandler . prototype , 'invokeRequestHandler' )
1222+ . resolves ( {
1223+ // nothing here is checked; we just need enough to not crash.
1224+ users : [ {
1225+ localId : 1 ,
1226+ } ] ,
1227+ } ) ;
1228+
1229+ } ) ;
1230+ afterEach ( ( ) => {
1231+ invokeRequestHandlerStub . restore ( ) ;
1232+ } ) ;
1233+
1234+ it ( 'phone lookups should use phoneNumber field' , async ( ) => {
1235+ await auth . getUserByProviderUid ( 'phone' , '+15555550001' ) ;
1236+ expect ( invokeRequestHandlerStub ) . to . have . been . calledOnce . and . calledWith (
1237+ sinon . match . any , sinon . match . any , {
1238+ phoneNumber : [ '+15555550001' ] ,
1239+ } ) ;
1240+ } ) ;
1241+
1242+ it ( 'email lookups should use email field' , async ( ) => {
1243+ await auth . getUserByProviderUid ( 'email' , '[email protected] ' ) ; 1244+ expect ( invokeRequestHandlerStub ) . to . have . been . calledOnce . and . calledWith (
1245+ sinon . match . any , sinon . match . any , {
1246+ 1247+ } ) ;
1248+ } ) ;
1249+ } ) ;
1250+
1251+ it ( 'should throw an error when the backend returns an error' , ( ) => {
1252+ // Stub getAccountInfoByFederatedUid to throw a backend error.
1253+ const stub = sinon . stub ( testConfig . RequestHandler . prototype , 'getAccountInfoByFederatedUid' )
1254+ . rejects ( expectedError ) ;
1255+ stubs . push ( stub ) ;
1256+ return auth . getUserByProviderUid ( providerId , providerUid )
1257+ . then ( ( ) => {
1258+ throw new Error ( 'Unexpected success' ) ;
1259+ } , ( error ) => {
1260+ // Confirm underlying API called with expected parameters.
1261+ expect ( stub ) . to . have . been . calledOnce . and . calledWith ( providerId , providerUid ) ;
1262+ // Confirm expected error returned.
1263+ expect ( error ) . to . equal ( expectedError ) ;
1264+ } ) ;
1265+ } ) ;
1266+ } ) ;
1267+
11541268 describe ( 'getUsers()' , ( ) => {
11551269 let stubs : sinon . SinonStub [ ] = [ ] ;
11561270
0 commit comments