1414
1515"""Test cases for the firebase_admin.tenant_mgt module."""
1616
17+ import json
18+
1719import pytest
1820
1921import firebase_admin
3638}"""
3739
3840INVALID_TENANT_IDS = [None , '' , 0 , 1 , True , False , list (), tuple (), dict ()]
41+ INVALID_BOOLEANS = ['' , 1 , 0 , list (), tuple (), dict ()]
3942
4043TENANT_MGT_URL_PREFIX = 'https://identitytoolkit.googleapis.com/v2beta1/projects/mock-project-id'
4144
@@ -98,11 +101,8 @@ def test_invalid_tenant_id(self, tenant_id):
98101 def test_get_tenant (self , tenant_mgt_app ):
99102 _ , recorder = _instrument_tenant_mgt (tenant_mgt_app , 200 , GET_TENANT_RESPONSE )
100103 tenant = tenant_mgt .get_tenant ('tenant-id' , app = tenant_mgt_app )
101- assert tenant .tenant_id == 'tenant-id'
102- assert tenant .display_name == 'Test Tenant'
103- assert tenant .allow_password_sign_up is True
104- assert tenant .enable_email_link_sign_in is True
105104
105+ _assert_tenant (tenant )
106106 assert len (recorder ) == 1
107107 req = recorder [0 ]
108108 assert req .method == 'GET'
@@ -120,6 +120,167 @@ def test_tenant_not_found(self, tenant_mgt_app):
120120 assert excinfo .value .cause is not None
121121
122122
123+ class TestCreateTenant :
124+
125+ @pytest .mark .parametrize ('display_name' , [True , False , 1 , 0 , list (), tuple (), dict ()])
126+ def test_invalid_display_name (self , display_name , tenant_mgt_app ):
127+ with pytest .raises (ValueError ) as excinfo :
128+ tenant_mgt .create_tenant (display_name = display_name , app = tenant_mgt_app )
129+ assert str (excinfo .value ).startswith ('Invalid type for displayName' )
130+
131+ @pytest .mark .parametrize ('allow' , INVALID_BOOLEANS )
132+ def test_invalid_allow_password_sign_up (self , allow , tenant_mgt_app ):
133+ with pytest .raises (ValueError ) as excinfo :
134+ tenant_mgt .create_tenant (allow_password_sign_up = allow , app = tenant_mgt_app )
135+ assert str (excinfo .value ).startswith ('Invalid type for allowPasswordSignup' )
136+
137+ @pytest .mark .parametrize ('enable' , INVALID_BOOLEANS )
138+ def test_invalid_enable_email_link_sign_in (self , enable , tenant_mgt_app ):
139+ with pytest .raises (ValueError ) as excinfo :
140+ tenant_mgt .create_tenant (enable_email_link_sign_in = enable , app = tenant_mgt_app )
141+ assert str (excinfo .value ).startswith ('Invalid type for enableEmailLinkSignin' )
142+
143+ def test_create_tenant (self , tenant_mgt_app ):
144+ _ , recorder = _instrument_tenant_mgt (tenant_mgt_app , 200 , GET_TENANT_RESPONSE )
145+ tenant = tenant_mgt .create_tenant (
146+ display_name = 'My Tenant' , allow_password_sign_up = True , enable_email_link_sign_in = True ,
147+ app = tenant_mgt_app )
148+
149+ _assert_tenant (tenant )
150+ self ._assert_request (recorder , {
151+ 'displayName' : 'My Tenant' ,
152+ 'allowPasswordSignup' : True ,
153+ 'enableEmailLinkSignin' : True ,
154+ })
155+
156+ def test_create_tenant_false_values (self , tenant_mgt_app ):
157+ _ , recorder = _instrument_tenant_mgt (tenant_mgt_app , 200 , GET_TENANT_RESPONSE )
158+ tenant = tenant_mgt .create_tenant (
159+ display_name = '' , allow_password_sign_up = False , enable_email_link_sign_in = False ,
160+ app = tenant_mgt_app )
161+
162+ _assert_tenant (tenant )
163+ self ._assert_request (recorder , {
164+ 'displayName' : '' ,
165+ 'allowPasswordSignup' : False ,
166+ 'enableEmailLinkSignin' : False ,
167+ })
168+
169+ def test_create_tenant_minimal (self , tenant_mgt_app ):
170+ _ , recorder = _instrument_tenant_mgt (tenant_mgt_app , 200 , GET_TENANT_RESPONSE )
171+ tenant = tenant_mgt .create_tenant (app = tenant_mgt_app )
172+
173+ _assert_tenant (tenant )
174+ self ._assert_request (recorder , {})
175+
176+ def test_error (self , tenant_mgt_app ):
177+ _instrument_tenant_mgt (tenant_mgt_app , 500 , '{}' )
178+ with pytest .raises (exceptions .InternalError ) as excinfo :
179+ tenant_mgt .create_tenant (app = tenant_mgt_app )
180+
181+ error_msg = 'Unexpected error response: {}'
182+ assert excinfo .value .code == exceptions .INTERNAL
183+ assert str (excinfo .value ) == error_msg
184+ assert excinfo .value .http_response is not None
185+ assert excinfo .value .cause is not None
186+
187+ def _assert_request (self , recorder , body ):
188+ assert len (recorder ) == 1
189+ req = recorder [0 ]
190+ assert req .method == 'POST'
191+ assert req .url == '{0}/tenants' .format (TENANT_MGT_URL_PREFIX )
192+ got = json .loads (req .body .decode ())
193+ assert got == body
194+
195+
196+ class TestUpdateTenant :
197+
198+ @pytest .mark .parametrize ('tenant_id' , INVALID_TENANT_IDS )
199+ def test_invalid_tenant_id (self , tenant_id , tenant_mgt_app ):
200+ with pytest .raises (ValueError ) as excinfo :
201+ tenant_mgt .update_tenant (tenant_id , display_name = 'My Tenant' , app = tenant_mgt_app )
202+ assert str (excinfo .value ).startswith ('Tenant ID must be a non-empty string' )
203+
204+ @pytest .mark .parametrize ('display_name' , [True , False , 1 , 0 , list (), tuple (), dict ()])
205+ def test_invalid_display_name (self , display_name , tenant_mgt_app ):
206+ with pytest .raises (ValueError ) as excinfo :
207+ tenant_mgt .update_tenant ('tenant-id' , display_name = display_name , app = tenant_mgt_app )
208+ assert str (excinfo .value ).startswith ('Invalid type for displayName' )
209+
210+ @pytest .mark .parametrize ('allow' , INVALID_BOOLEANS )
211+ def test_invalid_allow_password_sign_up (self , allow , tenant_mgt_app ):
212+ with pytest .raises (ValueError ) as excinfo :
213+ tenant_mgt .update_tenant ('tenant-id' , allow_password_sign_up = allow , app = tenant_mgt_app )
214+ assert str (excinfo .value ).startswith ('Invalid type for allowPasswordSignup' )
215+
216+ @pytest .mark .parametrize ('enable' , INVALID_BOOLEANS )
217+ def test_invalid_enable_email_link_sign_in (self , enable , tenant_mgt_app ):
218+ with pytest .raises (ValueError ) as excinfo :
219+ tenant_mgt .update_tenant (
220+ 'tenant-id' , enable_email_link_sign_in = enable , app = tenant_mgt_app )
221+ assert str (excinfo .value ).startswith ('Invalid type for enableEmailLinkSignin' )
222+
223+ def test_update_tenant (self , tenant_mgt_app ):
224+ _ , recorder = _instrument_tenant_mgt (tenant_mgt_app , 200 , GET_TENANT_RESPONSE )
225+ tenant = tenant_mgt .update_tenant (
226+ 'tenant-id' , display_name = 'My Tenant' , allow_password_sign_up = True ,
227+ enable_email_link_sign_in = True , app = tenant_mgt_app )
228+
229+ _assert_tenant (tenant )
230+ body = {
231+ 'displayName' : 'My Tenant' ,
232+ 'allowPasswordSignup' : True ,
233+ 'enableEmailLinkSignin' : True ,
234+ }
235+ mask = ['allowPasswordSignup' , 'displayName' , 'enableEmailLinkSignin' ]
236+ self ._assert_request (recorder , body , mask )
237+
238+ def test_update_tenant_false_values (self , tenant_mgt_app ):
239+ _ , recorder = _instrument_tenant_mgt (tenant_mgt_app , 200 , GET_TENANT_RESPONSE )
240+ tenant = tenant_mgt .update_tenant (
241+ 'tenant-id' , display_name = '' , allow_password_sign_up = False ,
242+ enable_email_link_sign_in = False , app = tenant_mgt_app )
243+
244+ _assert_tenant (tenant )
245+ body = {
246+ 'displayName' : '' ,
247+ 'allowPasswordSignup' : False ,
248+ 'enableEmailLinkSignin' : False ,
249+ }
250+ mask = ['allowPasswordSignup' , 'displayName' , 'enableEmailLinkSignin' ]
251+ self ._assert_request (recorder , body , mask )
252+
253+ def test_update_tenant_minimal (self , tenant_mgt_app ):
254+ _ , recorder = _instrument_tenant_mgt (tenant_mgt_app , 200 , GET_TENANT_RESPONSE )
255+ tenant = tenant_mgt .update_tenant (
256+ 'tenant-id' , display_name = 'My Tenant' , app = tenant_mgt_app )
257+
258+ _assert_tenant (tenant )
259+ body = {'displayName' : 'My Tenant' }
260+ mask = ['displayName' ]
261+ self ._assert_request (recorder , body , mask )
262+
263+ def test_tenant_not_found_error (self , tenant_mgt_app ):
264+ _instrument_tenant_mgt (tenant_mgt_app , 500 , TENANT_NOT_FOUND_RESPONSE )
265+ with pytest .raises (tenant_mgt .TenantNotFoundError ) as excinfo :
266+ tenant_mgt .update_tenant ('tenant' , display_name = 'My Tenant' , app = tenant_mgt_app )
267+
268+ error_msg = 'No tenant found for the given identifier (TENANT_NOT_FOUND).'
269+ assert excinfo .value .code == exceptions .NOT_FOUND
270+ assert str (excinfo .value ) == error_msg
271+ assert excinfo .value .http_response is not None
272+ assert excinfo .value .cause is not None
273+
274+ def _assert_request (self , recorder , body , mask ):
275+ assert len (recorder ) == 1
276+ req = recorder [0 ]
277+ assert req .method == 'PATCH'
278+ assert req .url == '{0}/tenants/tenant-id?updateMask={1}' .format (
279+ TENANT_MGT_URL_PREFIX , ',' .join (mask ))
280+ got = json .loads (req .body .decode ())
281+ assert got == body
282+
283+
123284class TestDeleteTenant :
124285
125286 @pytest .mark .parametrize ('tenant_id' , INVALID_TENANT_IDS )
@@ -146,3 +307,10 @@ def test_tenant_not_found(self, tenant_mgt_app):
146307 assert str (excinfo .value ) == error_msg
147308 assert excinfo .value .http_response is not None
148309 assert excinfo .value .cause is not None
310+
311+
312+ def _assert_tenant (tenant ):
313+ assert tenant .tenant_id == 'tenant-id'
314+ assert tenant .display_name == 'Test Tenant'
315+ assert tenant .allow_password_sign_up is True
316+ assert tenant .enable_email_link_sign_in is True
0 commit comments