diff --git a/firebase_admin/project_management.py b/firebase_admin/project_management.py index 74696dfb..0c9eb637 100644 --- a/firebase_admin/project_management.py +++ b/firebase_admin/project_management.py @@ -101,18 +101,20 @@ def create_android_app(package_name, display_name=None, app=None): return _get_project_management_service(app).create_android_app(package_name, display_name) -def create_ios_app(bundle_id, display_name=None, app=None): +def create_ios_app(bundle_id, display_name=None, app=None, app_store_id=None): """Creates a new iOS app in the associated Firebase project. Args: bundle_id: The bundle ID of the iOS app to be created. display_name: A nickname for this iOS app (optional). app: An App instance (optional). + app_store_id: The Apple App Store ID of this iOS app (optional). Returns: IOSApp: An ``IOSApp`` instance that is a reference to the newly created app. """ - return _get_project_management_service(app).create_ios_app(bundle_id, display_name) + return _get_project_management_service(app).create_ios_app( + bundle_id, display_name, app_store_id) def _check_is_string_or_none(obj, field_name): @@ -569,13 +571,14 @@ def create_android_app(self, package_name, display_name=None): display_name=display_name, app_class=AndroidApp) - def create_ios_app(self, bundle_id, display_name=None): + def create_ios_app(self, bundle_id, display_name=None, app_store_id=None): return self._create_app( platform_resource_name=_ProjectManagementService.IOS_APPS_RESOURCE_NAME, identifier_name=_ProjectManagementService.IOS_APP_IDENTIFIER_NAME, identifier=bundle_id, display_name=display_name, - app_class=IOSApp) + app_class=IOSApp, + app_store_id=app_store_id) def _create_app( self, @@ -583,13 +586,17 @@ def _create_app( identifier_name, identifier, display_name, - app_class): + app_class, + app_store_id=None): """Creates an Android or iOS app.""" _check_is_string_or_none(display_name, 'display_name') + _check_is_nonempty_string_or_none(app_store_id, 'app_store_id') path = f'/v1beta1/projects/{self._project_id}/{platform_resource_name}' request_body = {identifier_name: identifier} if display_name: request_body['displayName'] = display_name + if app_store_id: + request_body['appStoreId'] = app_store_id response = self._make_request('post', path, json=request_body) operation_name = response['name'] poll_response = self._poll_app_creation(operation_name) diff --git a/tests/test_project_management.py b/tests/test_project_management.py index 0536c291..9b0c32bc 100644 --- a/tests/test_project_management.py +++ b/tests/test_project_management.py @@ -721,6 +721,45 @@ def test_create_ios_app(self): self._assert_request_is_correct( recorder[2], 'GET', 'https://firebase.googleapis.com/v1/operations/abcdefg') + def test_create_ios_app_with_app_store_id(self): + recorder = self._instrument_service( + statuses=[200, 200, 200], + responses=[ + OPERATION_IN_PROGRESS_RESPONSE, # Request to create iOS app asynchronously. + OPERATION_IN_PROGRESS_RESPONSE, # Creation operation is still not done. + IOS_APP_OPERATION_SUCCESSFUL_RESPONSE, # Creation operation completed. + ]) + + ios_app = project_management.create_ios_app( + bundle_id='com.hello.world.ios', + display_name='My iOS App', + app_store_id='123456789') + + assert ios_app.app_id == '1:12345678:ios:ca5cade5' + assert len(recorder) == 3 + body = { + 'bundleId': 'com.hello.world.ios', + 'displayName': 'My iOS App', + 'appStoreId': '123456789', + } + self._assert_request_is_correct(recorder[0], 'POST', TestCreateIOSApp._CREATION_URL, body) + self._assert_request_is_correct( + recorder[1], 'GET', 'https://firebase.googleapis.com/v1/operations/abcdefg') + self._assert_request_is_correct( + recorder[2], 'GET', 'https://firebase.googleapis.com/v1/operations/abcdefg') + + @pytest.mark.parametrize('app_store_id', ['', 12345, ['123'], {'id': '123'}, True]) + def test_create_ios_app_invalid_app_store_id(self, app_store_id): + recorder = self._instrument_service(statuses=[], responses=[]) + + with pytest.raises(ValueError) as excinfo: + project_management.create_ios_app( + bundle_id='com.hello.world.ios', + app_store_id=app_store_id) + + assert str(excinfo.value) == 'app_store_id must be a non-empty string.' + assert len(recorder) == 0 + def test_create_ios_app_already_exists(self): recorder = self._instrument_service(statuses=[409], responses=[ALREADY_EXISTS_RESPONSE])