diff --git a/spec/ParsePushAdapter.spec.js b/spec/ParsePushAdapter.spec.js index 69712ef..a2af8ad 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', 'fcm']); + expect(parsePushAdapter.getValidPushTypes()).toEqual(['ios', 'osx', 'tvos', 'android', 'fcm']); done(); }); it('can classify installation', (done) => { // Mock installations - var validPushTypes = ['ios', 'android', 'fcm']; + var validPushTypes = ['ios', 'osx', 'tvos', 'android', 'fcm']; var installations = [ { deviceType: 'android', @@ -70,6 +70,14 @@ describe('ParsePushAdapter', () => { deviceType: 'ios', deviceToken: 'iosToken' }, + { + deviceType: 'tvos', + deviceToken: 'tvosToken' + }, + { + deviceType: 'osx', + deviceToken: 'osxToken' + }, { deviceType: 'win', deviceToken: 'winToken' @@ -83,6 +91,8 @@ describe('ParsePushAdapter', () => { var deviceMap = ParsePushAdapter.classifyInstallations(installations, validPushTypes); expect(deviceMap['android']).toEqual([makeDevice('androidToken', 'android')]); expect(deviceMap['ios']).toEqual([makeDevice('iosToken', 'ios')]); + expect(deviceMap['osx']).toEqual([makeDevice('osxToken', 'osx')]); + expect(deviceMap['tvos']).toEqual([makeDevice('tvosToken', 'tvos')]); expect(deviceMap['win']).toBe(undefined); done(); }); @@ -90,14 +100,18 @@ describe('ParsePushAdapter', () => { it('can send push notifications', (done) => { var parsePushAdapter = new ParsePushAdapter(); - // Mock android ios senders + // Mock senders var androidSender = { send: jasmine.createSpy('send') }; var iosSender = { send: jasmine.createSpy('send') }; + var osxSender = { + send: jasmine.createSpy('send') + } var senderMap = { + osx: osxSender, ios: iosSender, android: androidSender }; @@ -112,6 +126,10 @@ describe('ParsePushAdapter', () => { deviceType: 'ios', deviceToken: 'iosToken' }, + { + deviceType: 'osx', + deviceToken: 'osxToken' + }, { deviceType: 'win', deviceToken: 'winToken' @@ -136,14 +154,21 @@ describe('ParsePushAdapter', () => { args = iosSender.send.calls.first().args; expect(args[0]).toEqual(data); expect(args[1]).toEqual([ - makeDevice('iosToken', 'ios') + makeDevice('iosToken', 'ios'), + ]); + // Check osx sender + expect(osxSender.send).toHaveBeenCalled(); + args = osxSender.send.calls.first().args; + expect(args[0]).toEqual(data); + expect(args[1]).toEqual([ + makeDevice('osxToken', 'osx') ]); done(); }); it('can send push notifications by pushType and failback by deviceType', (done) => { var parsePushAdapter = new ParsePushAdapter(); - // Mock android ios senders + // Mock senders var androidSender = { send: jasmine.createSpy('send') }; @@ -233,7 +258,15 @@ describe('ParsePushAdapter', () => { cert: 'cert.cer', key: 'key.pem', production: false, - bundleId: 'bundleId' + bundleId: 'iosbundleId' + } + ], + osx: [ + { + cert: 'cert.cer', + key: 'key.pem', + production: false, + bundleId: 'osxbundleId' } ] }; @@ -244,13 +277,23 @@ describe('ParsePushAdapter', () => { }, { deviceType: 'ios', - deviceToken: 'c5ee8fae0a1c', - appIdentifier: 'anotherBundle' + deviceToken: '0d72a1baa92a2febd9a254cbd6584f750c70b2350af5fc9052d1d12584b738e6', + appIdentifier: 'invalidiosbundleId' }, { deviceType: 'ios', - deviceToken: 'c5ee8fae0a1c5805e731cf15496d5b2b3f9b9c577353d3239429d3faaee01c79', - appIdentifier: 'anotherBundle' + deviceToken: 'ff3943ed0b2090c47e5d6f07d8f202a10427941d7897fda5a6b18c6d9fd07d48', + appIdentifier: 'invalidiosbundleId' + }, + { + deviceType: 'osx', + deviceToken: '5cda62a8d88eb48d9111a6c436f2e326a053eb0cd72dfc3a0893089342602235', + appIdentifier: 'invalidosxbundleId' + }, + { + deviceType: 'tvos', + deviceToken: '3e72a1baa92a2febd9a254cbd6584f750c70b2350af5fc9052d1d12584b738e6', + appIdentifier: 'invalidiosbundleId' // ios and tvos share the same bundleid }, { deviceType: 'win', @@ -266,8 +309,8 @@ describe('ParsePushAdapter', () => { parsePushAdapter.send({data: {alert: 'some'}}, installations).then((results) => { expect(Array.isArray(results)).toBe(true); - // 2x iOS, 1x android - expect(results.length).toBe(3); + // 2x iOS, 1x android, 1x osx, 1x tvos + expect(results.length).toBe(5); results.forEach((result) => { expect(result.transmitted).toBe(false); expect(typeof result.device).toBe('object'); diff --git a/src/APNS.js b/src/APNS.js index fee8b23..37f41c9 100644 --- a/src/APNS.js +++ b/src/APNS.js @@ -20,7 +20,6 @@ const LOG_PREFIX = 'parse-server-push-adapter APNS'; * @param {Boolean} args.production Specifies which environment to connect to: Production (if true) or Sandbox */ function APNS(args) { - // Since for ios, there maybe multiple cert/key pairs, // typePushConfig can be an array. let apnsArgsList = []; if (Array.isArray(args)) { @@ -74,7 +73,7 @@ function APNS(args) { notification: notification, transmitted: true, device: { - deviceType: 'ios', + deviceType: device.deviceType, deviceToken: device.token.toString('hex') } }); @@ -115,7 +114,7 @@ APNS.prototype.send = function(data, devices) { transmitted: false, device: { deviceToken: device.deviceToken, - deviceType: 'ios' + deviceType: device.deviceType }, result: {error: 'No connection available'} }); @@ -177,7 +176,7 @@ function handleTransmissionError(conns, errCode, notification, apnDevice) { status: errCode, transmitted: false, device: { - deviceType: 'ios', + deviceType: apnDevice.deviceType, deviceToken: apnDevice.token.toString('hex') } }); diff --git a/src/ParsePushAdapter.js b/src/ParsePushAdapter.js index 0b30a16..c3a007e 100644 --- a/src/ParsePushAdapter.js +++ b/src/ParsePushAdapter.js @@ -12,7 +12,7 @@ export class ParsePushAdapter { supportsPushTracking = true; constructor(pushConfig = {}) { - this.validPushTypes = ['ios', 'android', 'fcm']; + this.validPushTypes = ['ios', 'osx', 'tvos', 'android', 'fcm']; this.senderMap = {}; // used in PushController for Dashboard Features this.feature = { @@ -27,6 +27,8 @@ export class ParsePushAdapter { } switch (pushType) { case 'ios': + case 'tvos': + case 'osx': this.senderMap[pushType] = new APNS(pushConfig[pushType]); break; case 'android': @@ -51,8 +53,8 @@ export class ParsePushAdapter { for (let pushType in deviceMap) { let sender = this.senderMap[pushType]; let devices = deviceMap[pushType]; - if(Array.isArray(devices) && devices.length > 0) - { + + if(Array.isArray(devices) && devices.length > 0) { if (!sender) { log.verbose(LOG_PREFIX, `Can not find sender for push type ${pushType}, ${data}`) let results = devices.map((device) => {