diff --git a/src/messaging/messaging-types.ts b/src/messaging/messaging-types.ts index c6958cefe9..a848969a16 100644 --- a/src/messaging/messaging-types.ts +++ b/src/messaging/messaging-types.ts @@ -179,6 +179,12 @@ export interface DataMessagePayload { [key: string]: string; } +/* Payload for fcmOptions messages */ +export interface FcmOptionsPayload { + analyticsLabel?: string; + [key: string]: string; +} + /* Payload for notification messages */ export interface NotificationMessagePayload { tag?: string; @@ -196,9 +202,10 @@ export interface NotificationMessagePayload { [other: string]: string; } -/* Composite messaging payload (data and notification payloads are both optional) */ +/* Composite messaging payload (data, fcmOptions, and notification payloads are all optional) */ export interface MessagingPayload { data?: DataMessagePayload; + fcmOptions?: FcmOptionsPayload; notification?: NotificationMessagePayload; } diff --git a/src/messaging/messaging.ts b/src/messaging/messaging.ts index 6dc0e26006..086e050366 100644 --- a/src/messaging/messaging.ts +++ b/src/messaging/messaging.ts @@ -735,7 +735,7 @@ export class Messaging implements FirebaseServiceInterface { const payloadCopy: MessagingPayload = deepCopy(payload); const payloadKeys = Object.keys(payloadCopy); - const validPayloadKeys = ['data', 'notification']; + const validPayloadKeys = ['data', 'fcmOptions', 'notification']; let containsDataOrNotificationKey = false; payloadKeys.forEach((payloadKey) => { @@ -744,7 +744,7 @@ export class Messaging implements FirebaseServiceInterface { throw new FirebaseMessagingError( MessagingClientErrorCode.INVALID_PAYLOAD, `Messaging payload contains an invalid "${ payloadKey }" property. Valid properties are ` + - `"data" and "notification".`, + `"data", "fcmOptions", and "notification".`, ); } else { containsDataOrNotificationKey = true; diff --git a/test/resources/mocks.ts b/test/resources/mocks.ts index 822cd68ff0..20e9e6ffe7 100644 --- a/test/resources/mocks.ts +++ b/test/resources/mocks.ts @@ -258,6 +258,11 @@ const mockPayloadNotificationValue = { body: 'Mock body.', }; +const payload = { + data: mockPayloadDataValue, + notification: mockPayloadNotificationValue, +}; + export const messaging = { topic: 'mock-topic', topicWithPrefix: '/topics/mock-topic', @@ -273,9 +278,12 @@ export const messaging = { payloadNotificationOnly: { notification: mockPayloadNotificationValue, }, - payload: { - data: mockPayloadDataValue, - notification: mockPayloadNotificationValue, + payload, + payloadWithFcmOptions: { + ...payload, + fcmOptions: { + analyticsLabel: 'test.analytics', + }, }, options: { collapseKey: 'foo', diff --git a/test/unit/messaging/messaging.spec.ts b/test/unit/messaging/messaging.spec.ts index ef8ffa29b4..1c917ce0c1 100644 --- a/test/unit/messaging/messaging.spec.ts +++ b/test/unit/messaging/messaging.spec.ts @@ -2710,6 +2710,16 @@ describe('Messaging', () => { ); }); + it('should be fulfilled given an options object containing only whitelisted properties with fcmOptions', () => { + mockedRequests.push(mockSendToDeviceStringRequest()); + + return messaging.sendToTopic( + mocks.messaging.topic, + mocks.messaging.payloadWithFcmOptions, + mocks.messaging.options, + ); + }); + it('should be fulfilled given an options object containing non-whitelisted properties', () => { mockedRequests.push(mockSendToDeviceStringRequest());