diff --git a/.pylintrc b/.pylintrc index 2155853c7..9618299ac 100644 --- a/.pylintrc +++ b/.pylintrc @@ -301,7 +301,7 @@ single-line-if-stmt=no no-space-check=trailing-comma,dict-separator # Maximum number of lines in a module -max-module-lines=1000 +max-module-lines=1200 # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 # tab). diff --git a/firebase_admin/messaging.py b/firebase_admin/messaging.py index 84134a950..c178848e1 100644 --- a/firebase_admin/messaging.py +++ b/firebase_admin/messaging.py @@ -273,14 +273,16 @@ class WebpushConfig(object): data: A dictionary of data fields (optional). All keys and values in the dictionary must be strings. When specified, overrides any data fields set via ``Message.data``. notification: A ``messaging.WebpushNotification`` to be included in the message (optional). + fcm_options: A ``messaging.WebpushFcmOptions`` (optional). .. _Webpush Specification: https://tools.ietf.org/html/rfc8030#section-5 """ - def __init__(self, headers=None, data=None, notification=None): + def __init__(self, headers=None, data=None, notification=None, fcm_options=None): self.headers = headers self.data = data self.notification = notification + self.fcm_options = fcm_options class WebpushNotificationAction(object): @@ -355,6 +357,18 @@ def __init__(self, title=None, body=None, icon=None, actions=None, badge=None, d self.custom_data = custom_data +class WebpushFcmOptions(object): + """Options for features provided by the FCM SDK for Web. + + Args: + link: The link to open when the user clicks on the notification. + For all URL values, HTTPS is required. + """ + + def __init__(self, link=None): + self.link = link + + class APNSConfig(object): """APNS-specific options that can be included in a message. @@ -622,6 +636,7 @@ def encode_webpush(cls, webpush): 'headers': _Validators.check_string_dict( 'WebpushConfig.headers', webpush.headers), 'notification': cls.encode_webpush_notification(webpush.notification), + 'fcm_options': cls.encode_webpush_fcm_options(webpush.fcm_options) } return cls.remove_null_values(result) @@ -672,6 +687,21 @@ def encode_webpush_notification(cls, notification): result[key] = value return cls.remove_null_values(result) + @classmethod + def encode_webpush_fcm_options(cls, fcm_options): + """Encodes an WebpushFcmOptions instance into JSON.""" + if fcm_options is None: + return None + if not isinstance(fcm_options, WebpushFcmOptions): + raise ValueError('WebpushConfig.fcm_options must be an instance of ' + 'WebFcmOptions class.') + result = { + 'link': _Validators.check_string( + 'WebpushFcmOptions.link', fcm_options.link), + } + return cls.remove_null_values(result) + + @classmethod def encode_webpush_notification_actions(cls, actions): """Encodes a list of WebpushNotificationActions into JSON.""" diff --git a/tests/test_messaging.py b/tests/test_messaging.py index 31c08c856..c3cb5fa93 100644 --- a/tests/test_messaging.py +++ b/tests/test_messaging.py @@ -616,6 +616,29 @@ def test_invalid_action_icon(self, data): assert str(excinfo.value) == 'WebpushNotificationAction.icon must be a string.' +class TestWebpushFcmOptionsEncoder(object): + + def _check_fcm_options(self, fcm_options): + with pytest.raises(ValueError) as excinfo: + check_encoding(messaging.Message( + topic='topic', webpush=messaging.WebpushConfig(fcm_options=fcm_options))) + return excinfo + + @pytest.mark.parametrize('data', NON_OBJECT_ARGS) + def test_invalid_webpush_fcm_options(self, data): + with pytest.raises(ValueError) as excinfo: + check_encoding(messaging.Message( + topic='topic', webpush=messaging.WebpushConfig(fcm_options=data))) + expected = 'WebpushConfig.fcm_options must be an instance of WebFcmOptions class.' + assert str(excinfo.value) == expected + + @pytest.mark.parametrize('data', NON_STRING_ARGS) + def test_invalid_link(self, data): + notification = messaging.WebpushFcmOptions(link=data) + excinfo = self._check_fcm_options(notification) + assert str(excinfo.value) == 'WebpushFcmOptions.link must be a string.' + + class TestAPNSConfigEncoder(object): @pytest.mark.parametrize('data', NON_OBJECT_ARGS)