Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions spec/PushController.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {increment: 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 = {
Expand Down
4 changes: 3 additions & 1 deletion src/Controllers/PushController.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ export class PushController {
let restUpdate = {};
if (typeof badge == 'string' && badge.toLowerCase() === 'increment') {
restUpdate = { badge: { __op: 'Increment', amount: 1 } }
} else if (typeof badge == 'object' && 'increment' in badge && Number(badge.increment)) {
restUpdate = { badge: { __op: 'Increment', amount: badge.increment } }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rdbayer @dplewis what do you think if we use the __op form instead of the one I just suggested? This is more consistent with the rest of the API.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're talking about using it but only supporting the "increment" case, I'm happy to make the changes.

If you mean more broadly supporting all the same operations, I don't understand all the ramifications well enough myself to be confident in implementing that (I'm fairly new to the code base and likely don't have the time right now to get up to speed on all those different flows)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, for now that would be just for the increment. Sorry for the back and forths. I believe if we use the same JSON based objects as the rest of the API we’ll be happier on the long term

} 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
Expand Down
14 changes: 10 additions & 4 deletions src/Push/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ 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' && 'increment' in badge && Number(badge.increment);
}

const localizableKeys = ['alert', 'title'];
Expand Down