@@ -34,22 +34,40 @@ namespace FirebaseAdmin.Auth.Users.Tests
3434{
3535 public class FirebaseUserManagerTest
3636 {
37- public static readonly IEnumerable < object [ ] > TestConfigs = new List < object [ ] > ( )
37+ public static readonly TheoryData < TestConfig > TestConfigs = new TheoryData < TestConfig > ( )
3838 {
39- new object [ ] { TestConfig . ForFirebaseAuth ( ) } ,
40- new object [ ] { TestConfig . ForTenantAwareFirebaseAuth ( "tenant1" ) } ,
41- new object [ ] { TestConfig . ForFirebaseAuth ( ) . WithEmulator ( ) } ,
42- new object [ ] { TestConfig . ForTenantAwareFirebaseAuth ( "tenant1" ) . WithEmulator ( ) } ,
39+ TestConfig . ForFirebaseAuth ( ) ,
40+ TestConfig . ForTenantAwareFirebaseAuth ( "tenant1" ) ,
41+ TestConfig . ForFirebaseAuth ( ) . WithEmulator ( ) ,
42+ TestConfig . ForTenantAwareFirebaseAuth ( "tenant1" ) . WithEmulator ( ) ,
4343 } ;
4444
45- public static readonly IEnumerable < object [ ] > MainTenantTestConfigs = new List < object [ ] > ( )
45+ public static readonly TheoryData < TestConfig > MainTenantTestConfigs = new TheoryData < TestConfig > ( )
4646 {
47- new object [ ] { TestConfig . ForFirebaseAuth ( ) } ,
48- new object [ ] { TestConfig . ForFirebaseAuth ( ) . WithEmulator ( ) } ,
47+ TestConfig . ForFirebaseAuth ( ) ,
48+ TestConfig . ForFirebaseAuth ( ) . WithEmulator ( ) ,
4949 } ;
5050
5151 private const string CreateUserResponse = @"{""localId"": ""user1""}" ;
5252
53+ public static TheoryData < TestConfig , string , string > UpdateUserInvalidProviderToLinkTestData
54+ {
55+ get
56+ {
57+ var data = new TheoryData < TestConfig , string , string > ( ) ;
58+
59+ foreach ( var testConfigObj in TestConfigs )
60+ {
61+ var testConfig = ( TestConfig ) testConfigObj [ 0 ] ;
62+
63+ data . Add ( testConfig , "google_user1" , string . Empty ) ; // Empty provider ID
64+ data . Add ( testConfig , string . Empty , "google.com" ) ; // Empty provider UID
65+ }
66+
67+ return data ;
68+ }
69+ }
70+
5371 [ Theory ]
5472 [ MemberData ( nameof ( TestConfigs ) ) ]
5573 public async Task GetUserById ( TestConfig config )
@@ -1107,6 +1125,12 @@ public async Task UpdateUser(TestConfig config)
11071125 { "package" , "gold" } ,
11081126 } ;
11091127
1128+ var providerToLink = new ProviderUserInfoArgs ( )
1129+ {
1130+ Uid = "google_user1" ,
1131+ ProviderId = "google.com" ,
1132+ } ;
1133+
11101134 var user = await auth . UpdateUserAsync ( new UserRecordArgs ( )
11111135 {
11121136 CustomClaims = customClaims ,
@@ -1118,6 +1142,7 @@ public async Task UpdateUser(TestConfig config)
11181142 PhoneNumber = "+1234567890" ,
11191143 PhotoUrl = "https://example.com/user.png" ,
11201144 Uid = "user1" ,
1145+ ProviderToLink = providerToLink ,
11211146 } ) ;
11221147
11231148 Assert . Equal ( "user1" , user . Uid ) ;
@@ -1135,6 +1160,13 @@ public async Task UpdateUser(TestConfig config)
11351160 Assert . Equal ( "+1234567890" , request [ "phoneNumber" ] ) ;
11361161 Assert . Equal ( "https://example.com/user.png" , request [ "photoUrl" ] ) ;
11371162
1163+ var expectedProviderUserInfo = new JObject
1164+ {
1165+ { "Uid" , "google_user1" } ,
1166+ { "ProviderId" , "google.com" } ,
1167+ } ;
1168+ Assert . Equal ( expectedProviderUserInfo , request [ "linkProviderUserInfo" ] ) ;
1169+
11381170 var claims = NewtonsoftJsonSerializer . Instance . Deserialize < JObject > ( ( string ) request [ "customAttributes" ] ) ;
11391171 Assert . True ( ( bool ) claims [ "admin" ] ) ;
11401172 Assert . Equal ( 4L , claims [ "level" ] ) ;
@@ -1168,6 +1200,37 @@ public async Task UpdateUserPartial(TestConfig config)
11681200 Assert . True ( ( bool ) request [ "emailVerified" ] ) ;
11691201 }
11701202
1203+ [ Theory ]
1204+ [ MemberData ( nameof ( TestConfigs ) ) ]
1205+ public async Task UpdateUserLinkProvider ( TestConfig config )
1206+ {
1207+ var handler = new MockMessageHandler ( )
1208+ {
1209+ Response = new List < string > ( ) { CreateUserResponse , config . GetUserResponse ( ) } ,
1210+ } ;
1211+ var auth = config . CreateAuth ( handler ) ;
1212+
1213+ var user = await auth . UpdateUserAsync ( new UserRecordArgs ( )
1214+ {
1215+ Uid = "user1" ,
1216+ ProviderToLink = new ProviderUserInfoArgs ( )
1217+ {
1218+ Uid = "google_user1" ,
1219+ ProviderId = "google.com" ,
1220+ } ,
1221+ } ) ;
1222+
1223+ Assert . Equal ( "user1" , user . Uid ) ;
1224+ Assert . Equal ( 2 , handler . Requests . Count ) ;
1225+ var request = NewtonsoftJsonSerializer . Instance . Deserialize < JObject > ( handler . Requests [ 0 ] . Body ) ;
1226+ Assert . Equal ( 2 , request . Count ) ;
1227+ Assert . Equal ( "user1" , request [ "localId" ] ) ;
1228+ var expectedProviderUserInfo = new JObject ( ) ;
1229+ expectedProviderUserInfo . Add ( "Uid" , "google_user1" ) ;
1230+ expectedProviderUserInfo . Add ( "ProviderId" , "google.com" ) ;
1231+ Assert . Equal ( expectedProviderUserInfo , request [ "linkProviderUserInfo" ] ) ;
1232+ }
1233+
11711234 [ Theory ]
11721235 [ MemberData ( nameof ( TestConfigs ) ) ]
11731236 public async Task UpdateUserRemoveAttributes ( TestConfig config )
@@ -1212,6 +1275,7 @@ public async Task UpdateUserRemoveProviders(TestConfig config)
12121275 {
12131276 PhoneNumber = null ,
12141277 Uid = "user1" ,
1278+ ProvidersToDelete = new List < string > ( ) { "google.com" } ,
12151279 } ) ;
12161280
12171281 Assert . Equal ( "user1" , user . Uid ) ;
@@ -1223,7 +1287,7 @@ public async Task UpdateUserRemoveProviders(TestConfig config)
12231287 Assert . Equal ( 2 , request . Count ) ;
12241288 Assert . Equal ( "user1" , request [ "localId" ] ) ;
12251289 Assert . Equal (
1226- new JArray ( ) { "phone" } ,
1290+ new JArray ( ) { "phone" , "google.com" } ,
12271291 request [ "deleteProvider" ] ) ;
12281292 }
12291293
@@ -1485,6 +1549,110 @@ public async Task UpdateUserShortPassword(TestConfig config)
14851549 Assert . Empty ( handler . Requests ) ;
14861550 }
14871551
1552+ [ Theory ]
1553+ [ MemberData ( nameof ( UpdateUserInvalidProviderToLinkTestData ) ) ]
1554+ public async Task UpdateUserInvalidProviderToLink ( TestConfig config , string uid , string providerId )
1555+ {
1556+ var handler = new MockMessageHandler ( ) { Response = CreateUserResponse } ;
1557+ var auth = config . CreateAuth ( handler ) ;
1558+
1559+ var args = new UserRecordArgs ( )
1560+ {
1561+ ProviderToLink = new ProviderUserInfoArgs ( )
1562+ {
1563+ Uid = uid ,
1564+ ProviderId = providerId ,
1565+ } ,
1566+ Uid = "user1" ,
1567+ } ;
1568+ await Assert . ThrowsAsync < ArgumentException > (
1569+ async ( ) => await auth . UpdateUserAsync ( args ) ) ;
1570+ Assert . Empty ( handler . Requests ) ;
1571+ }
1572+
1573+ [ Theory ]
1574+ [ MemberData ( nameof ( TestConfigs ) ) ]
1575+ public async Task UpdateUserInvalidEmailProviderToLink ( TestConfig config )
1576+ {
1577+ var handler = new MockMessageHandler ( ) { Response = CreateUserResponse } ;
1578+ var auth = config . CreateAuth ( handler ) ;
1579+
1580+ // Phone provider updated in 2 places in the same request
1581+ var args = new UserRecordArgs ( )
1582+ {
1583+ ProviderToLink = new ProviderUserInfoArgs ( )
1584+ {
1585+ Uid = "foo@bar.com" ,
1586+ ProviderId = "email" ,
1587+ } ,
1588+ Uid = "user1" ,
1589+ Email = "foo@bar.com" ,
1590+ } ;
1591+ var exception = await Assert . ThrowsAsync < FirebaseAuthException > (
1592+ async ( ) => await auth . UpdateUserAsync ( args ) ) ;
1593+
1594+ const string expectedError = "Both UpdateRequest.Email and UpdateRequest.ProviderToLink.ProviderId='email' " +
1595+ "were set. To link to the email/password provider, only specify the " +
1596+ "UpdateRequest.Email field." ;
1597+
1598+ Assert . Equal ( expectedError , exception . Message ) ;
1599+ Assert . Empty ( handler . Requests ) ;
1600+ }
1601+
1602+ [ Theory ]
1603+ [ MemberData ( nameof ( TestConfigs ) ) ]
1604+ public async Task UpdateUserInvalidPhoneProviderToLink ( TestConfig config )
1605+ {
1606+ var handler = new MockMessageHandler ( ) { Response = CreateUserResponse } ;
1607+ var auth = config . CreateAuth ( handler ) ;
1608+
1609+ // Phone provider updated in 2 places in the same request
1610+ var args = new UserRecordArgs ( )
1611+ {
1612+ ProviderToLink = new ProviderUserInfoArgs ( )
1613+ {
1614+ Uid = "+11234567891" ,
1615+ ProviderId = "phone" ,
1616+ } ,
1617+ Uid = "user1" ,
1618+ PhoneNumber = "+11234567891" ,
1619+ } ;
1620+ var exception = await Assert . ThrowsAsync < FirebaseAuthException > (
1621+ async ( ) => await auth . UpdateUserAsync ( args ) ) ;
1622+
1623+ const string expectedError = "Both UpdateRequest.PhoneNumber and UpdateRequest.ProviderToLink.ProviderId='phone'" +
1624+ " were set. To link to a phone provider, only specify the " +
1625+ "UpdateRequest.PhoneNumber field." ;
1626+
1627+ Assert . Equal ( expectedError , exception . Message ) ;
1628+ Assert . Empty ( handler . Requests ) ;
1629+ }
1630+
1631+ [ Theory ]
1632+ [ MemberData ( nameof ( TestConfigs ) ) ]
1633+ public async Task UpdateUserInvalidProvidersToDelete ( TestConfig config )
1634+ {
1635+ var handler = new MockMessageHandler ( ) { Response = CreateUserResponse } ;
1636+ var auth = config . CreateAuth ( handler ) ;
1637+
1638+ // Empty provider ID
1639+ var args = new UserRecordArgs ( )
1640+ {
1641+ ProvidersToDelete = new List < string > ( ) { "google.com" , string . Empty } ,
1642+ Uid = "user1" ,
1643+ } ;
1644+ await Assert . ThrowsAsync < ArgumentException > (
1645+ async ( ) => await auth . UpdateUserAsync ( args ) ) ;
1646+ Assert . Empty ( handler . Requests ) ;
1647+
1648+ // Phone provider updates in two places
1649+ args . PhoneNumber = null ;
1650+ args . ProvidersToDelete = new List < string > ( ) { "google.com" , "phone" } ;
1651+ await Assert . ThrowsAsync < ArgumentException > (
1652+ async ( ) => await auth . UpdateUserAsync ( args ) ) ;
1653+ Assert . Empty ( handler . Requests ) ;
1654+ }
1655+
14881656 [ Theory ]
14891657 [ MemberData ( nameof ( TestConfigs ) ) ]
14901658 public void EmptyNameClaims ( TestConfig config )
0 commit comments