diff --git a/spec/GCM.spec.js b/spec/GCM.spec.js index 0ddfe27..daefcea 100644 --- a/spec/GCM.spec.js +++ b/spec/GCM.spec.js @@ -20,89 +20,117 @@ describe('GCM', () => { it('can generate GCM Payload without expiration time', (done) => { //Mock request data - var data = { - 'alert': 'alert' + var requestData = { + data: { + 'alert': 'alert' + }, + notification: { + 'title': 'I am a title', + 'body': 'I am a body' + } }; var pushId = 'pushId'; var timeStamp = 1454538822113; var timeStampISOStr = new Date(timeStamp).toISOString(); - var payload = GCM.generateGCMPayload(data, pushId, timeStamp); + var payload = GCM.generateGCMPayload(requestData, pushId, timeStamp); - expect(payload.priority).toEqual('normal'); + expect(payload.priority).toEqual('high'); expect(payload.timeToLive).toEqual(undefined); var dataFromPayload = payload.data; expect(dataFromPayload.time).toEqual(timeStampISOStr); + expect(payload.notification).toEqual(requestData.notification); expect(dataFromPayload['push_id']).toEqual(pushId); - var dataFromUser = JSON.parse(dataFromPayload.data); - expect(dataFromUser).toEqual(data); + var dataFromUser = dataFromPayload.data; + expect(dataFromUser).toEqual(requestData.data); done(); }); it('can generate GCM Payload with valid expiration time', (done) => { //Mock request data - var data = { - 'alert': 'alert' + var requestData = { + data: { + 'alert': 'alert' + }, + notification: { + 'title': 'I am a title', + 'body': 'I am a body' + } }; var pushId = 'pushId'; var timeStamp = 1454538822113; var timeStampISOStr = new Date(timeStamp).toISOString(); var expirationTime = 1454538922113 - var payload = GCM.generateGCMPayload(data, pushId, timeStamp, expirationTime); + var payload = GCM.generateGCMPayload(requestData, pushId, timeStamp, expirationTime); - expect(payload.priority).toEqual('normal'); + expect(payload.priority).toEqual('high'); expect(payload.timeToLive).toEqual(Math.floor((expirationTime - timeStamp) / 1000)); var dataFromPayload = payload.data; expect(dataFromPayload.time).toEqual(timeStampISOStr); + expect(payload.notification).toEqual(requestData.notification); expect(dataFromPayload['push_id']).toEqual(pushId); - var dataFromUser = JSON.parse(dataFromPayload.data); - expect(dataFromUser).toEqual(data); + var dataFromUser = dataFromPayload.data; + expect(dataFromUser).toEqual(requestData.data); done(); }); it('can generate GCM Payload with too early expiration time', (done) => { //Mock request data - var data = { - 'alert': 'alert' + var requestData = { + data: { + 'alert': 'alert' + }, + notification: { + 'title': 'I am a title', + 'body': 'I am a body' + } }; var pushId = 'pushId'; var timeStamp = 1454538822113; var timeStampISOStr = new Date(timeStamp).toISOString(); var expirationTime = 1454538822112; - var payload = GCM.generateGCMPayload(data, pushId, timeStamp, expirationTime); + var payload = GCM.generateGCMPayload(requestData, pushId, timeStamp, expirationTime); - expect(payload.priority).toEqual('normal'); + expect(payload.priority).toEqual('high'); expect(payload.timeToLive).toEqual(0); var dataFromPayload = payload.data; expect(dataFromPayload.time).toEqual(timeStampISOStr); + expect(payload.notification).toEqual(requestData.notification); expect(dataFromPayload['push_id']).toEqual(pushId); - var dataFromUser = JSON.parse(dataFromPayload.data); - expect(dataFromUser).toEqual(data); + var dataFromUser = dataFromPayload.data; + expect(dataFromUser).toEqual(requestData.data); done(); }); it('can generate GCM Payload with too late expiration time', (done) => { //Mock request data - var data = { - 'alert': 'alert' + var requestData = { + data: { + 'alert': 'alert' + }, + notification: { + 'title': 'I am a title', + 'body': 'I am a body' + } }; var pushId = 'pushId'; var timeStamp = 1454538822113; var timeStampISOStr = new Date(timeStamp).toISOString(); var expirationTime = 2454538822113; - var payload = GCM.generateGCMPayload(data, pushId, timeStamp, expirationTime); + var payload = GCM.generateGCMPayload(requestData, pushId, timeStamp, expirationTime); - expect(payload.priority).toEqual('normal'); + expect(payload.priority).toEqual('high'); // Four week in second expect(payload.timeToLive).toEqual(4 * 7 * 24 * 60 * 60); var dataFromPayload = payload.data; expect(dataFromPayload.time).toEqual(timeStampISOStr); + expect(payload.notification).toEqual(requestData.notification); expect(dataFromPayload['push_id']).toEqual(pushId); - var dataFromUser = JSON.parse(dataFromPayload.data); - expect(dataFromUser).toEqual(data); + var dataFromUser = dataFromPayload.data; + expect(dataFromUser).toEqual(requestData.data); done(); }); diff --git a/spec/ParsePushAdapter.spec.js b/spec/ParsePushAdapter.spec.js index a8d6413..69712ef 100644 --- a/spec/ParsePushAdapter.spec.js +++ b/spec/ParsePushAdapter.spec.js @@ -54,13 +54,13 @@ describe('ParsePushAdapter', () => { it('can get valid push types', (done) => { var parsePushAdapter = new ParsePushAdapter(); - expect(parsePushAdapter.getValidPushTypes()).toEqual(['ios', 'android']); + expect(parsePushAdapter.getValidPushTypes()).toEqual(['ios', 'android', 'fcm']); done(); }); it('can classify installation', (done) => { // Mock installations - var validPushTypes = ['ios', 'android']; + var validPushTypes = ['ios', 'android', 'fcm']; var installations = [ { deviceType: 'android', diff --git a/src/GCM.js b/src/GCM.js index ea6bcc0..1aa551f 100644 --- a/src/GCM.js +++ b/src/GCM.js @@ -57,7 +57,7 @@ GCM.prototype.send = function(data, devices) { } // Generate gcm payload // PushId is not a formal field of GCM, but Parse Android SDK uses this field to deduplicate push notifications - let gcmPayload = generateGCMPayload(data.data, pushId, timestamp, expirationTime); + let gcmPayload = generateGCMPayload(data, pushId, timestamp, expirationTime); // Make and send gcm request let message = new gcm.Message(gcmPayload); @@ -114,22 +114,27 @@ GCM.prototype.send = function(data, devices) { /** * Generate the gcm payload from the data we get from api request. - * @param {Object} coreData The data field under api request body + * @param {Object} requestData The request body * @param {String} pushId A random string * @param {Number} timeStamp A number whose format is the Unix Epoch * @param {Number|undefined} expirationTime A number whose format is the Unix Epoch or undefined * @returns {Object} A promise which is resolved after we get results from gcm */ -function generateGCMPayload(coreData, pushId, timeStamp, expirationTime) { - let payloadData = { - 'time': new Date(timeStamp).toISOString(), - 'push_id': pushId, - 'data': JSON.stringify(coreData) - } +function generateGCMPayload(requestData, pushId, timeStamp, expirationTime) { let payload = { - priority: 'normal', - data: payloadData + priority: 'high' }; + payload.data = { + data: requestData.data, + push_id: pushId, + time: new Date(timeStamp).toISOString() + } + if (requestData.content_available) { + payload.content_available = requestData.content_available; + } + if (requestData.notification) { + payload.notification = requestData.notification; + } if (expirationTime) { // The timeStamp and expiration is in milliseconds but gcm requires second let timeToLive = Math.floor((expirationTime - timeStamp) / 1000); diff --git a/src/ParsePushAdapter.js b/src/ParsePushAdapter.js index f40c08e..0b30a16 100644 --- a/src/ParsePushAdapter.js +++ b/src/ParsePushAdapter.js @@ -12,7 +12,7 @@ export class ParsePushAdapter { supportsPushTracking = true; constructor(pushConfig = {}) { - this.validPushTypes = ['ios', 'android']; + this.validPushTypes = ['ios', 'android', 'fcm']; this.senderMap = {}; // used in PushController for Dashboard Features this.feature = { @@ -30,6 +30,7 @@ export class ParsePushAdapter { this.senderMap[pushType] = new APNS(pushConfig[pushType]); break; case 'android': + case 'fcm': this.senderMap[pushType] = new GCM(pushConfig[pushType]); break; }