Skip to content

Commit 6465f51

Browse files
committed
Change APNS multiple certs handling
1 parent 06b1ee2 commit 6465f51

File tree

6 files changed

+486
-247
lines changed

6 files changed

+486
-247
lines changed

spec/APNS.spec.js

Lines changed: 245 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,65 @@
11
var APNS = require('../src/APNS');
22

33
describe('APNS', () => {
4+
5+
it('can initialize with single cert', (done) => {
6+
var args = {
7+
cert: 'prodCert.pem',
8+
key: 'prodKey.pem',
9+
production: true,
10+
bundleId: 'bundleId'
11+
}
12+
var apns = new APNS(args);
13+
14+
expect(apns.conns.length).toBe(1);
15+
var apnsConnection = apns.conns[0];
16+
expect(apnsConnection.index).toBe(0);
17+
expect(apnsConnection.bundleId).toBe(args.bundleId);
18+
// TODO: Remove this checking onec we inject APNS
19+
var prodApnsOptions = apnsConnection.options;
20+
expect(prodApnsOptions.cert).toBe(args.cert);
21+
expect(prodApnsOptions.key).toBe(args.key);
22+
expect(prodApnsOptions.production).toBe(args.production);
23+
done();
24+
});
25+
26+
it('can initialize with multiple certs', (done) => {
27+
var args = [
28+
{
29+
cert: 'devCert.pem',
30+
key: 'devKey.pem',
31+
production: false,
32+
bundleId: 'bundleId'
33+
},
34+
{
35+
cert: 'prodCert.pem',
36+
key: 'prodKey.pem',
37+
production: true,
38+
bundleId: 'bundleIdAgain'
39+
}
40+
]
41+
42+
var apns = new APNS(args);
43+
expect(apns.conns.length).toBe(2);
44+
var devApnsConnection = apns.conns[1];
45+
expect(devApnsConnection.index).toBe(1);
46+
var devApnsOptions = devApnsConnection.options;
47+
expect(devApnsOptions.cert).toBe(args[0].cert);
48+
expect(devApnsOptions.key).toBe(args[0].key);
49+
expect(devApnsOptions.production).toBe(args[0].production);
50+
expect(devApnsConnection.bundleId).toBe(args[0].bundleId);
51+
52+
var prodApnsConnection = apns.conns[0];
53+
expect(prodApnsConnection.index).toBe(0);
54+
// TODO: Remove this checking onec we inject APNS
55+
var prodApnsOptions = prodApnsConnection.options;
56+
expect(prodApnsOptions.cert).toBe(args[1].cert);
57+
expect(prodApnsOptions.key).toBe(args[1].key);
58+
expect(prodApnsOptions.production).toBe(args[1].production);
59+
expect(prodApnsOptions.bundleId).toBe(args[1].bundleId);
60+
done();
61+
});
62+
463
it('can generate APNS notification', (done) => {
564
//Mock request data
665
var data = {
@@ -29,12 +88,185 @@ describe('APNS', () => {
2988
done();
3089
});
3190

91+
it('can choose conns for device without appIdentifier', (done) => {
92+
// Mock conns
93+
var conns = [
94+
{
95+
bundleId: 'bundleId'
96+
},
97+
{
98+
bundleId: 'bundleIdAgain'
99+
}
100+
];
101+
// Mock device
102+
var device = {};
103+
104+
var qualifiedConns = APNS.chooseConns(conns, device);
105+
expect(qualifiedConns).toEqual([0, 1]);
106+
done();
107+
});
108+
109+
it('can choose conns for device with valid appIdentifier', (done) => {
110+
// Mock conns
111+
var conns = [
112+
{
113+
bundleId: 'bundleId'
114+
},
115+
{
116+
bundleId: 'bundleIdAgain'
117+
}
118+
];
119+
// Mock device
120+
var device = {
121+
appIdentifier: 'bundleId'
122+
};
123+
124+
var qualifiedConns = APNS.chooseConns(conns, device);
125+
expect(qualifiedConns).toEqual([0]);
126+
done();
127+
});
128+
129+
it('can choose conns for device with invalid appIdentifier', (done) => {
130+
// Mock conns
131+
var conns = [
132+
{
133+
bundleId: 'bundleId'
134+
},
135+
{
136+
bundleId: 'bundleIdAgain'
137+
}
138+
];
139+
// Mock device
140+
var device = {
141+
appIdentifier: 'invalid'
142+
};
143+
144+
var qualifiedConns = APNS.chooseConns(conns, device);
145+
expect(qualifiedConns).toEqual([]);
146+
done();
147+
});
148+
149+
it('can handle transmission error when notification is not in cache or device is missing', (done) => {
150+
// Mock conns
151+
var conns = [];
152+
var errorCode = 1;
153+
var notification = undefined;
154+
var device = {};
155+
156+
APNS.handleTransmissionError(conns, errorCode, notification, device);
157+
158+
var notification = {};
159+
var device = undefined;
160+
161+
APNS.handleTransmissionError(conns, errorCode, notification, device);
162+
done();
163+
});
164+
165+
it('can handle transmission error when there are other qualified conns', (done) => {
166+
// Mock conns
167+
var conns = [
168+
{
169+
pushNotification: jasmine.createSpy('pushNotification'),
170+
bundleId: 'bundleId1'
171+
},
172+
{
173+
pushNotification: jasmine.createSpy('pushNotification'),
174+
bundleId: 'bundleId1'
175+
},
176+
{
177+
pushNotification: jasmine.createSpy('pushNotification'),
178+
bundleId: 'bundleId2'
179+
},
180+
];
181+
var errorCode = 1;
182+
var notification = {};
183+
var apnDevice = {
184+
connIndex: 0,
185+
appIdentifier: 'bundleId1'
186+
};
187+
188+
APNS.handleTransmissionError(conns, errorCode, notification, apnDevice);
189+
190+
expect(conns[0].pushNotification).not.toHaveBeenCalled();
191+
expect(conns[1].pushNotification).toHaveBeenCalled();
192+
expect(conns[2].pushNotification).not.toHaveBeenCalled();
193+
done();
194+
});
195+
196+
it('can handle transmission error when there is no other qualified conns', (done) => {
197+
// Mock conns
198+
var conns = [
199+
{
200+
pushNotification: jasmine.createSpy('pushNotification'),
201+
bundleId: 'bundleId1'
202+
},
203+
{
204+
pushNotification: jasmine.createSpy('pushNotification'),
205+
bundleId: 'bundleId1'
206+
},
207+
{
208+
pushNotification: jasmine.createSpy('pushNotification'),
209+
bundleId: 'bundleId2'
210+
},
211+
];
212+
var errorCode = 1;
213+
var notification = {};
214+
var apnDevice = {
215+
connIndex: 1,
216+
appIdentifier: 'bundleId1'
217+
};
218+
219+
APNS.handleTransmissionError(conns, errorCode, notification, apnDevice);
220+
221+
expect(conns[0].pushNotification).not.toHaveBeenCalled();
222+
expect(conns[1].pushNotification).not.toHaveBeenCalled();
223+
expect(conns[2].pushNotification).not.toHaveBeenCalled();
224+
done();
225+
});
226+
227+
it('can handle transmission error when device has no appIdentifier', (done) => {
228+
// Mock conns
229+
var conns = [
230+
{
231+
pushNotification: jasmine.createSpy('pushNotification'),
232+
bundleId: 'bundleId1'
233+
},
234+
{
235+
pushNotification: jasmine.createSpy('pushNotification'),
236+
bundleId: 'bundleId2'
237+
},
238+
{
239+
pushNotification: jasmine.createSpy('pushNotification'),
240+
bundleId: 'bundleId3'
241+
},
242+
];
243+
var errorCode = 1;
244+
var notification = {};
245+
var apnDevice = {
246+
connIndex: 1,
247+
};
248+
249+
APNS.handleTransmissionError(conns, errorCode, notification, apnDevice);
250+
251+
expect(conns[0].pushNotification).not.toHaveBeenCalled();
252+
expect(conns[1].pushNotification).not.toHaveBeenCalled();
253+
expect(conns[2].pushNotification).toHaveBeenCalled();
254+
done();
255+
});
256+
32257
it('can send APNS notification', (done) => {
33-
var apns = new APNS();
34-
var sender = {
35-
pushNotification: jasmine.createSpy('send')
258+
var args = {
259+
cert: 'prodCert.pem',
260+
key: 'prodKey.pem',
261+
production: true,
262+
bundleId: 'bundleId'
263+
}
264+
var apns = new APNS(args);
265+
var conn = {
266+
pushNotification: jasmine.createSpy('send'),
267+
bundleId: 'bundleId'
36268
};
37-
apns.sender = sender;
269+
apns.conns = [ conn ];
38270
// Mock data
39271
var expirationTime = 1454571491354
40272
var data = {
@@ -45,16 +277,21 @@ describe('APNS', () => {
45277
}
46278
// Mock devices
47279
var devices = [
48-
{ deviceToken: 'token' }
280+
{
281+
deviceToken: '112233',
282+
appIdentifier: 'bundleId'
283+
}
49284
];
50285

51286
var promise = apns.send(data, devices);
52-
expect(sender.pushNotification).toHaveBeenCalled();
53-
var args = sender.pushNotification.calls.first().args;
287+
expect(conn.pushNotification).toHaveBeenCalled();
288+
var args = conn.pushNotification.calls.first().args;
54289
var notification = args[0];
55290
expect(notification.alert).toEqual(data.data.alert);
56291
expect(notification.expiry).toEqual(data['expiration_time']);
57-
expect(args[1]).toEqual(['token']);
292+
var apnDevice = args[1]
293+
expect(apnDevice.connIndex).toEqual(0);
294+
expect(apnDevice.appIdentifier).toEqual('bundleId');
58295
done();
59296
});
60297
});

spec/GCM.spec.js

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
var GCM = require('../src/GCM');
22

33
describe('GCM', () => {
4+
it('can initialize', (done) => {
5+
var args = {
6+
apiKey: 'apiKey'
7+
};
8+
var gcm = new GCM(args);
9+
expect(gcm.sender.key).toBe(args.apiKey);
10+
done();
11+
});
12+
13+
it('can throw on initializing with invalid args', (done) => {
14+
var args = 123
15+
expect(function() {
16+
new GCM(args);
17+
}).toThrow();
18+
done();
19+
});
20+
421
it('can generate GCM Payload without expiration time', (done) => {
522
//Mock request data
623
var data = {
@@ -90,7 +107,9 @@ describe('GCM', () => {
90107
});
91108

92109
it('can send GCM request', (done) => {
93-
var gcm = new GCM('apiKey');
110+
var gcm = new GCM({
111+
apiKey: 'apiKey'
112+
});
94113
// Mock gcm sender
95114
var sender = {
96115
send: jasmine.createSpy('send')
@@ -111,7 +130,7 @@ describe('GCM', () => {
111130
}
112131
];
113132

114-
var promise = gcm.send(data, devices);
133+
gcm.send(data, devices);
115134
expect(sender.send).toHaveBeenCalled();
116135
var args = sender.send.calls.first().args;
117136
// It is too hard to verify message of gcm library, we just verify tokens and retry times
@@ -120,24 +139,21 @@ describe('GCM', () => {
120139
done();
121140
});
122141

123-
it('can throw on sending when we have too many registration tokens', (done) => {
124-
var gcm = new GCM('apiKey');
125-
// Mock gcm sender
126-
var sender = {
127-
send: jasmine.createSpy('send')
128-
};
129-
gcm.sender = sender;
142+
it('can slice devices', (done) => {
130143
// Mock devices
131-
var devices = [];
132-
for (var i = 0; i <= 2000; i++) {
133-
devices.push({
134-
deviceToken: i.toString()
135-
});
136-
}
144+
var devices = [makeDevice(1), makeDevice(2), makeDevice(3), makeDevice(4)];
137145

138-
expect(function() {
139-
gcm.send({}, devices);
140-
}).toThrow();
146+
var chunkDevices = GCM.sliceDevices(devices, 3);
147+
expect(chunkDevices).toEqual([
148+
[makeDevice(1), makeDevice(2), makeDevice(3)],
149+
[makeDevice(4)]
150+
]);
141151
done();
142152
});
153+
154+
function makeDevice(deviceToken) {
155+
return {
156+
deviceToken: deviceToken
157+
};
158+
}
143159
});

0 commit comments

Comments
 (0)