diff --git a/spec/PushController.spec.js b/spec/PushController.spec.js index 2f25fa1bed..059f0d6632 100644 --- a/spec/PushController.spec.js +++ b/spec/PushController.spec.js @@ -245,6 +245,84 @@ describe('PushController', () => { }); }); + it('properly increment badges by more than 1', (done) => { + const pushAdapter = { + send: function(body, installations) { + const badge = body.data.badge; + installations.forEach((installation) => { + expect(installation.badge).toEqual(badge); + expect(installation.originalBadge + 3).toEqual(installation.badge); + }) + return successfulTransmissions(body, installations); + }, + getValidPushTypes: function() { + return ["ios", "android"]; + } + } + const payload = {data:{ + alert: "Hello World!", + badge: { __op: 'Increment', amount: 3 }, + }} + const installations = []; + while(installations.length != 10) { + const installation = new Parse.Object("_Installation"); + installation.set("installationId", "installation_" + installations.length); + installation.set("deviceToken","device_token_" + installations.length) + installation.set("badge", installations.length); + installation.set("originalBadge", installations.length); + installation.set("deviceType", "ios"); + installations.push(installation); + } + + while(installations.length != 15) { + const installation = new Parse.Object("_Installation"); + installation.set("installationId", "installation_" + installations.length); + installation.set("deviceToken","device_token_" + installations.length); + installation.set("badge", installations.length); + installation.set("originalBadge", installations.length); + installation.set("deviceType", "android"); + installations.push(installation); + } + const config = Config.get(Parse.applicationId); + const auth = { + isMaster: true + } + + const pushController = new PushController(); + reconfigureServer({ + push: { adapter: pushAdapter } + }).then(() => { + return Parse.Object.saveAll(installations) + }).then(() => { + return pushController.sendPush(payload, {}, config, auth); + }).then(() => { + // Wait so the push is completed. + return new Promise((resolve) => { setTimeout(() => { resolve(); }, 1000); }); + }).then(() => { + // Check we actually sent 15 pushes. + const query = new Parse.Query('_PushStatus'); + return query.find({ useMasterKey: true }) + }).then((results) => { + expect(results.length).toBe(1); + const pushStatus = results[0]; + expect(pushStatus.get('numSent')).toBe(15); + }).then(() => { + // Check that the installations were actually updated. + const query = new Parse.Query('_Installation'); + return query.find({ useMasterKey: true }) + }).then((results) => { + expect(results.length).toBe(15); + for (let i = 0; i < 15; i++) { + const installation = results[i]; + expect(installation.get('badge')).toBe(parseInt(installation.get('originalBadge')) + 3); + } + done() + }).catch((err) => { + jfail(err); + done(); + }); + }); + it('properly set badges to 1', (done) => { const pushAdapter = { diff --git a/src/Controllers/PushController.js b/src/Controllers/PushController.js index 416b0ea4ff..8b645a3680 100644 --- a/src/Controllers/PushController.js +++ b/src/Controllers/PushController.js @@ -44,10 +44,13 @@ export class PushController { let restUpdate = {}; if (typeof badge == 'string' && badge.toLowerCase() === 'increment') { restUpdate = { badge: { __op: 'Increment', amount: 1 } } + } else if (typeof badge == 'object' && typeof badge.__op == 'string' && + badge.__op.toLowerCase() == 'increment' && Number(badge.amount)) { + restUpdate = { badge: { __op: 'Increment', amount: badge.amount } } } else if (Number(badge)) { restUpdate = { badge: badge } } else { - throw "Invalid value for badge, expected number or 'Increment'"; + throw "Invalid value for badge, expected number or 'Increment' or {increment: number}"; } // Force filtering on only valid device tokens diff --git a/src/Push/utils.js b/src/Push/utils.js index ed33a66a14..f9b1a4118f 100644 --- a/src/Push/utils.js +++ b/src/Push/utils.js @@ -2,10 +2,17 @@ import Parse from 'parse/node'; import deepcopy from 'deepcopy'; export function isPushIncrementing(body) { - return body.data && - body.data.badge && - typeof body.data.badge == 'string' && - body.data.badge.toLowerCase() == "increment" + if (!body.data || !body.data.badge) { + return false; + } + + const badge = body.data.badge; + if (typeof badge == 'string' && badge.toLowerCase() == "increment") { + return true; + } + + return typeof badge == 'object' && typeof badge.__op == 'string' && + badge.__op.toLowerCase() == "increment" && Number(badge.amount); } const localizableKeys = ['alert', 'title'];