Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/utils/fcmMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ class FcmMessage {
}

static buildAndroidMessage(params, options) {
const message = buildGcmMessage(params, options);
// Mark as FCM so buildGcmMessage doesn't pollute custom data
const fcmOptions = { ...options, fcm: true };
const message = buildGcmMessage(params, fcmOptions);

const androidMessage = message.toJson();

Expand Down
14 changes: 9 additions & 5 deletions src/utils/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,15 @@ const buildGcmMessage = (data, options) => {
};
}

custom.title = custom.title || data.title;
custom.message = custom.message || data.body;
custom.sound = custom.sound || data.sound;
custom.icon = custom.icon || data.icon;
custom.msgcnt = custom.msgcnt || data.badge;
// Only add notification fields to custom data for GCM (not FCM)
// FCM uses separate notification and data fields
if (!options.fcm) {
custom.title = custom.title || data.title;
custom.message = custom.message || data.body;
custom.sound = custom.sound || data.sound;
custom.icon = custom.icon || data.icon;
custom.msgcnt = custom.msgcnt || data.badge;
}
if (options.phonegap === true && data.contentAvailable) {
custom['content-available'] = 1;
}
Expand Down
64 changes: 64 additions & 0 deletions test/send/sendFCM.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,68 @@ describe('push-notifications-fcm', () => {
.catch(done);
});
});

describe('send push notifications with custom data', () => {
const customDataMessage = {
title: 'Notification Title',
body: 'Notification Body',
custom: {
userId: '12345',
actionId: 'action-001',
deepLink: 'app://section/item',
},
};

let customDataSendMethod;

function sendCustomDataMethod() {
return sinon.stub(
fbMessaging.prototype,
'sendEachForMulticast',
function sendFCMWithCustomData(firebaseMessage) {
const { custom } = customDataMessage;

// Verify custom data is preserved in top-level data field
expect(firebaseMessage.data).to.deep.equal(custom);

// Verify custom data does NOT pollute the notification
// Note: normalizeDataParams converts all values to strings (FCM requirement)
expect(firebaseMessage.android.data).to.deep.equal(custom);
expect(firebaseMessage.android.data).to.not.have.property('title');
expect(firebaseMessage.android.data).to.not.have.property('body');

// Verify notification has proper fields (separate from data)
expect(firebaseMessage.android.notification).to.include({
title: customDataMessage.title,
body: customDataMessage.body,
});

return Promise.resolve({
successCount: 1,
failureCount: 0,
responses: [{ error: null }],
});
}
);
}

before(() => {
customDataSendMethod = sendCustomDataMethod();
});

after(() => {
customDataSendMethod.restore();
});

it('custom data should be preserved and not mixed with notification fields', (done) => {
pn.send(regIds, customDataMessage)
.then((results) => {
expect(results).to.be.an('array');
expect(results[0].method).to.equal('fcm');
expect(results[0].success).to.equal(1);
done();
})
.catch(done);
});
});
});