Change APNS multiple certs handling

This commit is contained in:
wangmengyan95
2016-02-11 02:13:23 -08:00
parent 06b1ee2362
commit 273a20767b
6 changed files with 505 additions and 253 deletions

View File

@@ -1,6 +1,65 @@
var APNS = require('../src/APNS');
describe('APNS', () => {
it('can initialize with single cert', (done) => {
var args = {
cert: 'prodCert.pem',
key: 'prodKey.pem',
production: true,
bundleId: 'bundleId'
}
var apns = new APNS(args);
expect(apns.conns.length).toBe(1);
var apnsConnection = apns.conns[0];
expect(apnsConnection.index).toBe(0);
expect(apnsConnection.bundleId).toBe(args.bundleId);
// TODO: Remove this checking onec we inject APNS
var prodApnsOptions = apnsConnection.options;
expect(prodApnsOptions.cert).toBe(args.cert);
expect(prodApnsOptions.key).toBe(args.key);
expect(prodApnsOptions.production).toBe(args.production);
done();
});
it('can initialize with multiple certs', (done) => {
var args = [
{
cert: 'devCert.pem',
key: 'devKey.pem',
production: false,
bundleId: 'bundleId'
},
{
cert: 'prodCert.pem',
key: 'prodKey.pem',
production: true,
bundleId: 'bundleIdAgain'
}
]
var apns = new APNS(args);
expect(apns.conns.length).toBe(2);
var devApnsConnection = apns.conns[1];
expect(devApnsConnection.index).toBe(1);
var devApnsOptions = devApnsConnection.options;
expect(devApnsOptions.cert).toBe(args[0].cert);
expect(devApnsOptions.key).toBe(args[0].key);
expect(devApnsOptions.production).toBe(args[0].production);
expect(devApnsConnection.bundleId).toBe(args[0].bundleId);
var prodApnsConnection = apns.conns[0];
expect(prodApnsConnection.index).toBe(0);
// TODO: Remove this checking onec we inject APNS
var prodApnsOptions = prodApnsConnection.options;
expect(prodApnsOptions.cert).toBe(args[1].cert);
expect(prodApnsOptions.key).toBe(args[1].key);
expect(prodApnsOptions.production).toBe(args[1].production);
expect(prodApnsOptions.bundleId).toBe(args[1].bundleId);
done();
});
it('can generate APNS notification', (done) => {
//Mock request data
var data = {
@@ -29,12 +88,195 @@ describe('APNS', () => {
done();
});
it('can send APNS notification', (done) => {
var apns = new APNS();
var sender = {
pushNotification: jasmine.createSpy('send')
it('can choose conns for device without appIdentifier', (done) => {
// Mock conns
var conns = [
{
bundleId: 'bundleId'
},
{
bundleId: 'bundleIdAgain'
}
];
// Mock device
var device = {};
var qualifiedConns = APNS.chooseConns(conns, device);
expect(qualifiedConns).toEqual([0, 1]);
done();
});
it('can choose conns for device with valid appIdentifier', (done) => {
// Mock conns
var conns = [
{
bundleId: 'bundleId'
},
{
bundleId: 'bundleIdAgain'
}
];
// Mock device
var device = {
appIdentifier: 'bundleId'
};
apns.sender = sender;
var qualifiedConns = APNS.chooseConns(conns, device);
expect(qualifiedConns).toEqual([0]);
done();
});
it('can choose conns for device with invalid appIdentifier', (done) => {
// Mock conns
var conns = [
{
bundleId: 'bundleId'
},
{
bundleId: 'bundleIdAgain'
}
];
// Mock device
var device = {
appIdentifier: 'invalid'
};
var qualifiedConns = APNS.chooseConns(conns, device);
expect(qualifiedConns).toEqual([]);
done();
});
it('can handle transmission error when notification is not in cache or device is missing', (done) => {
// Mock conns
var conns = [];
var errorCode = 1;
var notification = undefined;
var device = {};
APNS.handleTransmissionError(conns, errorCode, notification, device);
var notification = {};
var device = undefined;
APNS.handleTransmissionError(conns, errorCode, notification, device);
done();
});
it('can handle transmission error when there are other qualified conns', (done) => {
// Mock conns
var conns = [
{
pushNotification: jasmine.createSpy('pushNotification'),
bundleId: 'bundleId1'
},
{
pushNotification: jasmine.createSpy('pushNotification'),
bundleId: 'bundleId1'
},
{
pushNotification: jasmine.createSpy('pushNotification'),
bundleId: 'bundleId2'
},
];
var errorCode = 1;
var notification = {};
var apnDevice = {
connIndex: 0,
appIdentifier: 'bundleId1'
};
APNS.handleTransmissionError(conns, errorCode, notification, apnDevice);
expect(conns[0].pushNotification).not.toHaveBeenCalled();
expect(conns[1].pushNotification).toHaveBeenCalled();
expect(conns[2].pushNotification).not.toHaveBeenCalled();
done();
});
it('can handle transmission error when there is no other qualified conns', (done) => {
// Mock conns
var conns = [
{
pushNotification: jasmine.createSpy('pushNotification'),
bundleId: 'bundleId1'
},
{
pushNotification: jasmine.createSpy('pushNotification'),
bundleId: 'bundleId1'
},
{
pushNotification: jasmine.createSpy('pushNotification'),
bundleId: 'bundleId1'
},
{
pushNotification: jasmine.createSpy('pushNotification'),
bundleId: 'bundleId2'
},
{
pushNotification: jasmine.createSpy('pushNotification'),
bundleId: 'bundleId1'
}
];
var errorCode = 1;
var notification = {};
var apnDevice = {
connIndex: 2,
appIdentifier: 'bundleId1'
};
APNS.handleTransmissionError(conns, errorCode, notification, apnDevice);
expect(conns[0].pushNotification).not.toHaveBeenCalled();
expect(conns[1].pushNotification).not.toHaveBeenCalled();
expect(conns[2].pushNotification).not.toHaveBeenCalled();
expect(conns[3].pushNotification).not.toHaveBeenCalled();
expect(conns[4].pushNotification).toHaveBeenCalled();
done();
});
it('can handle transmission error when device has no appIdentifier', (done) => {
// Mock conns
var conns = [
{
pushNotification: jasmine.createSpy('pushNotification'),
bundleId: 'bundleId1'
},
{
pushNotification: jasmine.createSpy('pushNotification'),
bundleId: 'bundleId2'
},
{
pushNotification: jasmine.createSpy('pushNotification'),
bundleId: 'bundleId3'
},
];
var errorCode = 1;
var notification = {};
var apnDevice = {
connIndex: 1,
};
APNS.handleTransmissionError(conns, errorCode, notification, apnDevice);
expect(conns[0].pushNotification).not.toHaveBeenCalled();
expect(conns[1].pushNotification).not.toHaveBeenCalled();
expect(conns[2].pushNotification).toHaveBeenCalled();
done();
});
it('can send APNS notification', (done) => {
var args = {
cert: 'prodCert.pem',
key: 'prodKey.pem',
production: true,
bundleId: 'bundleId'
}
var apns = new APNS(args);
var conn = {
pushNotification: jasmine.createSpy('send'),
bundleId: 'bundleId'
};
apns.conns = [ conn ];
// Mock data
var expirationTime = 1454571491354
var data = {
@@ -45,16 +287,21 @@ describe('APNS', () => {
}
// Mock devices
var devices = [
{ deviceToken: 'token' }
{
deviceToken: '112233',
appIdentifier: 'bundleId'
}
];
var promise = apns.send(data, devices);
expect(sender.pushNotification).toHaveBeenCalled();
var args = sender.pushNotification.calls.first().args;
expect(conn.pushNotification).toHaveBeenCalled();
var args = conn.pushNotification.calls.first().args;
var notification = args[0];
expect(notification.alert).toEqual(data.data.alert);
expect(notification.expiry).toEqual(data['expiration_time']);
expect(args[1]).toEqual(['token']);
var apnDevice = args[1]
expect(apnDevice.connIndex).toEqual(0);
expect(apnDevice.appIdentifier).toEqual('bundleId');
done();
});
});

View File

@@ -1,6 +1,23 @@
var GCM = require('../src/GCM');
describe('GCM', () => {
it('can initialize', (done) => {
var args = {
apiKey: 'apiKey'
};
var gcm = new GCM(args);
expect(gcm.sender.key).toBe(args.apiKey);
done();
});
it('can throw on initializing with invalid args', (done) => {
var args = 123
expect(function() {
new GCM(args);
}).toThrow();
done();
});
it('can generate GCM Payload without expiration time', (done) => {
//Mock request data
var data = {
@@ -90,7 +107,9 @@ describe('GCM', () => {
});
it('can send GCM request', (done) => {
var gcm = new GCM('apiKey');
var gcm = new GCM({
apiKey: 'apiKey'
});
// Mock gcm sender
var sender = {
send: jasmine.createSpy('send')
@@ -111,7 +130,7 @@ describe('GCM', () => {
}
];
var promise = gcm.send(data, devices);
gcm.send(data, devices);
expect(sender.send).toHaveBeenCalled();
var args = sender.send.calls.first().args;
// It is too hard to verify message of gcm library, we just verify tokens and retry times
@@ -120,24 +139,21 @@ describe('GCM', () => {
done();
});
it('can throw on sending when we have too many registration tokens', (done) => {
var gcm = new GCM('apiKey');
// Mock gcm sender
var sender = {
send: jasmine.createSpy('send')
};
gcm.sender = sender;
it('can slice devices', (done) => {
// Mock devices
var devices = [];
for (var i = 0; i <= 2000; i++) {
devices.push({
deviceToken: i.toString()
});
}
var devices = [makeDevice(1), makeDevice(2), makeDevice(3), makeDevice(4)];
expect(function() {
gcm.send({}, devices);
}).toThrow();
var chunkDevices = GCM.sliceDevices(devices, 3);
expect(chunkDevices).toEqual([
[makeDevice(1), makeDevice(2), makeDevice(3)],
[makeDevice(4)]
]);
done();
});
function makeDevice(deviceToken) {
return {
deviceToken: deviceToken
};
}
});

View File

@@ -1,4 +1,6 @@
var ParsePushAdapter = require('../src/Adapters/Push/ParsePushAdapter');
var APNS = require('../src/APNS');
var GCM = require('../src/GCM');
describe('ParsePushAdapter', () => {
it('can be initialized', (done) => {
@@ -12,35 +14,25 @@ describe('ParsePushAdapter', () => {
{
cert: 'prodCert.pem',
key: 'prodKey.pem',
production: true
production: true,
bundleId: 'bundleId'
},
{
cert: 'devCert.pem',
key: 'devKey.pem',
production: false
production: false,
bundleId: 'bundleIdAgain'
}
]
};
var parsePushAdapter = new ParsePushAdapter(pushConfig);
// Check ios
var iosSenders = parsePushAdapter.senders['ios'];
expect(iosSenders.length).toBe(2);
// TODO: Remove this checking onec we inject APNS
var prodApnsOptions = iosSenders[0].sender.options;
expect(prodApnsOptions.cert).toBe(pushConfig.ios[0].cert);
expect(prodApnsOptions.key).toBe(pushConfig.ios[0].key);
expect(prodApnsOptions.production).toBe(pushConfig.ios[0].production);
var devApnsOptions = iosSenders[1].sender.options;
expect(devApnsOptions.cert).toBe(pushConfig.ios[1].cert);
expect(devApnsOptions.key).toBe(pushConfig.ios[1].key);
expect(devApnsOptions.production).toBe(pushConfig.ios[1].production);
var iosSender = parsePushAdapter.senderMap['ios'];
expect(iosSender instanceof APNS).toBe(true);
// Check android
var androidSenders = parsePushAdapter.senders['android'];
expect(androidSenders.length).toBe(1);
var androidSender = androidSenders[0];
// TODO: Remove this checking onec we inject GCM
expect(androidSender.sender.key).toBe(pushConfig.android.apiKey);
var androidSender = parsePushAdapter.senderMap['android'];
expect(androidSender instanceof GCM).toBe(true);
done();
});
@@ -59,46 +51,6 @@ describe('ParsePushAdapter', () => {
done();
});
it('can throw on initializing with invalid pushConfig', (done) => {
// Make mock config
var pushConfig = {
android: 123
};
expect(function() {
new ParsePushAdapter(pushConfig);
}).toThrow();
done();
});
it('can get push senders', (done) => {
var parsePushAdapter = new ParsePushAdapter();
// Mock push senders
var androidSender = {};
var iosSender = {};
var iosSenderAgain = {};
parsePushAdapter.senders = {
android: [
androidSender
],
ios: [
iosSender,
iosSenderAgain
]
};
expect(parsePushAdapter.getPushSenders('android')).toEqual([androidSender]);
expect(parsePushAdapter.getPushSenders('ios')).toEqual([iosSender, iosSenderAgain]);
done();
});
it('can get empty push senders', (done) => {
var parsePushAdapter = new ParsePushAdapter();
expect(parsePushAdapter.getPushSenders('android')).toEqual([]);
done();
});
it('can get valid push types', (done) => {
var parsePushAdapter = new ParsePushAdapter();
@@ -128,31 +80,10 @@ describe('ParsePushAdapter', () => {
}
];
var deviceTokenMap = ParsePushAdapter.classifyInstallation(installations, validPushTypes);
expect(deviceTokenMap['android']).toEqual([makeDevice('androidToken')]);
expect(deviceTokenMap['ios']).toEqual([makeDevice('iosToken')]);
expect(deviceTokenMap['win']).toBe(undefined);
done();
});
it('can slice ios devices', (done) => {
// Mock devices
var devices = [makeDevice(1), makeDevice(2), makeDevice(3), makeDevice(4)];
var chunkDevices = ParsePushAdapter.sliceDevices('ios', devices, 2);
expect(chunkDevices).toEqual([devices]);
done();
});
it('can slice android devices', (done) => {
// Mock devices
var devices = [makeDevice(1), makeDevice(2), makeDevice(3), makeDevice(4)];
var chunkDevices = ParsePushAdapter.sliceDevices('android', devices, 3);
expect(chunkDevices).toEqual([
[makeDevice(1), makeDevice(2), makeDevice(3)],
[makeDevice(4)]
]);
var deviceMap = ParsePushAdapter.classifyInstallation(installations, validPushTypes);
expect(deviceMap['android']).toEqual([makeDevice('androidToken')]);
expect(deviceMap['ios']).toEqual([makeDevice('iosToken')]);
expect(deviceMap['win']).toBe(undefined);
done();
});
@@ -166,14 +97,11 @@ describe('ParsePushAdapter', () => {
var iosSender = {
send: jasmine.createSpy('send')
};
var iosSenderAgain = {
send: jasmine.createSpy('send')
var senderMap = {
ios: iosSender,
android: androidSender
};
var senders = {
ios: [iosSender, iosSenderAgain],
android: [androidSender]
};
parsePushAdapter.senders = senders;
parsePushAdapter.senderMap = senderMap;
// Mock installations
var installations = [
{
@@ -210,18 +138,13 @@ describe('ParsePushAdapter', () => {
expect(args[1]).toEqual([
makeDevice('iosToken')
]);
expect(iosSenderAgain.send).toHaveBeenCalled();
args = iosSenderAgain.send.calls.first().args;
expect(args[0]).toEqual(data);
expect(args[1]).toEqual([
makeDevice('iosToken')
]);
done();
});
function makeDevice(deviceToken) {
function makeDevice(deviceToken, appIdentifier) {
return {
deviceToken: deviceToken
deviceToken: deviceToken,
appIdentifier: appIdentifier
};
}
});