Comparing version 1.5.2 to 1.6.0
## Changelog | ||
1.6.0: | ||
* Fixes #156: Retire a socket from the pool immediately instead of waiting for a "close" event. | ||
* Fixes #165: Introduced a connection retry limit to emit errors when fatal connection errors occur. | ||
* Fixes #152: Failure to attach an error handler would prevent exponential backoff from working. | ||
* Improved error handling for EPIPE write events to maximise chances of reading error info from Apple. | ||
* Fixed #181: Initial support for larger payloads for iOS 8 testing. | ||
* Fixed #187: Correctly trim notifications with escaped characters. | ||
* Merged #190: Always emit a feedback event when batch mode is enabled, even if there are no tokens. | ||
* Merged #189: Added support for iOS 8 Notification actions. | ||
* Display a warning when null parameters are passed during connection creation. | ||
* Fixed #171: Removed references to the unknown notification identifier. | ||
1.5.2: | ||
@@ -4,0 +17,0 @@ |
@@ -24,2 +24,5 @@ var apn = require ('../index.js'); | ||
console.error("Notification caused error: " + errCode + " for device ", device, notification); | ||
if (errCode == 8) { | ||
console.log("A error code of 8 indicates that the device token is invalid. This could be for a number of reasons - are you using the correct environment? i.e. Production vs. Sandbox"); | ||
} | ||
}); | ||
@@ -40,2 +43,3 @@ | ||
function pushNotificationToMany() { | ||
console.log("Sending the same notification each of the devices with one call to pushNotification."); | ||
var note = new apn.notification(); | ||
@@ -53,2 +57,3 @@ note.setAlertText("Hello, from node-apn!"); | ||
function pushSomeNotifications() { | ||
console.log("Sending a tailored notification to %d devices", tokens.length); | ||
for (var i in tokens) { | ||
@@ -55,0 +60,0 @@ var note = new apn.notification(); |
var Errors = require('./errors'); | ||
var fs = require('fs'); | ||
var q = require('q'); | ||
var tls = require('tls'); | ||
var net = require('net'); | ||
var sysu = require('util'); | ||
var util = require('./util'); | ||
var events = require('events'); | ||
var Device = require('./device'); | ||
var events = require('events'); | ||
var CredentialLoader = require('./credentials'); | ||
var createSocket = require('./socket'); | ||
var debug = function() {}; | ||
@@ -63,8 +64,17 @@ if(process.env.DEBUG) { | ||
connectionTimeout: 0, | ||
connectionRetryLimit: 10, | ||
buffersNotifications: true, | ||
fastMode: false, | ||
legacy: false, | ||
disableNagle: false | ||
disableNagle: false, | ||
disableEPIPEFix: false, | ||
largePayloads: false | ||
}; | ||
for (var key in options) { | ||
if (options[key] == null) { | ||
debug("Option [" + key + "] set to null. This may cause unexpected behaviour."); | ||
} | ||
} | ||
util.extend(this.options, options); | ||
@@ -82,2 +92,3 @@ | ||
this.options.address = "gateway.sandbox.push.apple.com"; | ||
this.options.largePayloads = true; | ||
} | ||
@@ -108,2 +119,4 @@ } | ||
this.terminated = false; | ||
events.EventEmitter.call(this); | ||
@@ -119,85 +132,10 @@ } | ||
Connection.prototype.initialize = function () { | ||
if (this.initializationPromise) { | ||
return this.initializationPromise; | ||
if (!this.initializationPromise) { | ||
debug("Initialising module"); | ||
this.initializationPromise = CredentialLoader(this.options); | ||
} | ||
debug("Initialising module"); | ||
var readFile = q.nfbind(fs.readFile); | ||
// Prepare PKCS#12 data if available | ||
var pfxPromise = null; | ||
if(this.options.pfx != null || this.options.pfxData != null) { | ||
if(this.options.pfxData) { | ||
pfxPromise = this.options.pfxData; | ||
} | ||
else if(Buffer.isBuffer(this.options.pfx)) { | ||
pfxPromise = this.options.pfx; | ||
} | ||
else { | ||
pfxPromise = readFile(this.options.pfx); | ||
} | ||
} | ||
// Prepare Certificate data if available. | ||
var certPromise = null; | ||
if (this.options.certData) { | ||
certPromise = this.options.certData; | ||
} | ||
else if(Buffer.isBuffer(this.options.cert) || checkPEMType(this.options.cert, "CERTIFICATE")) { | ||
certPromise = this.options.cert; | ||
} | ||
else if(this.options.cert){ | ||
// Nothing has matched so attempt to load from disk | ||
certPromise = readFile(this.options.cert); | ||
} | ||
// Prepare Key data if available | ||
var keyPromise = null; | ||
if (this.options.keyData) { | ||
keyPromise = this.options.keyData; | ||
} | ||
else if(Buffer.isBuffer(this.options.key) || checkPEMType(this.options.key, "PRIVATE KEY")) { | ||
keyPromise = this.options.key; | ||
} | ||
else if(this.options.key) { | ||
keyPromise = readFile(this.options.key); | ||
} | ||
// Prepare Certificate Authority data if available. | ||
var caPromises = []; | ||
if (this.options.ca != null && !sysu.isArray(this.options.ca)) { | ||
this.options.ca = [ this.options.ca ]; | ||
} | ||
for(var i in this.options.ca) { | ||
var ca = this.options.ca[i]; | ||
if(Buffer.isBuffer(ca) || checkPEMType(ca, "CERTIFICATE")) { | ||
caPromises.push(ca); | ||
} | ||
else if (ca){ | ||
caPromises.push(readFile(ca)); | ||
} | ||
} | ||
if (caPromises.length == 0) { | ||
caPromises = undefined; | ||
} | ||
else { | ||
caPromises = q.all(caPromises); | ||
} | ||
this.initializationPromise = q.all([pfxPromise, certPromise, keyPromise, caPromises]); | ||
return this.initializationPromise; | ||
}; | ||
function checkPEMType(input, type) { | ||
if (input == null) { | ||
return; | ||
} | ||
var matches = input.match(/\-\-\-\-\-BEGIN ([A-Z\s*]+)\-\-\-\-\-/); | ||
if (matches != null) { | ||
return matches[1].indexOf(type) >= 0; | ||
} | ||
return false; | ||
} | ||
/** | ||
@@ -217,2 +155,9 @@ * You should never need to call this method, initialisation and connection is handled by {@link Connection#pushNotification} | ||
socketOptions.port = this.options.port; | ||
socketOptions.host = this.options.address; | ||
socketOptions.disableEPIPEFix = this.options.disableEPIPEFix; | ||
socketOptions.disableNagle = this.options.disableNagle; | ||
socketOptions.connectionTimeout = this.options.connectionTimeout; | ||
socketOptions.pfx = pfxData; | ||
@@ -225,10 +170,3 @@ socketOptions.cert = certData; | ||
// We pass in our own Stream to delay connection until we have attached the | ||
// event listeners below. | ||
socketOptions.socket = new net.Socket(); | ||
this.socket = tls.connect( | ||
this.options['port'], | ||
this.options['address'], | ||
socketOptions, | ||
this.socket = createSocket(this, socketOptions, | ||
function () { | ||
@@ -240,23 +178,2 @@ debug("Connection established"); | ||
socketOptions.socket.setNoDelay(this.options.disableNagle); | ||
socketOptions.socket.setKeepAlive(true); | ||
if (this.options.connectionTimeout > 0) { | ||
socketOptions.socket.setTimeout(this.options.connectionTimeout); | ||
} | ||
this.socket.on("error", this.errorOccurred.bind(this, this.socket)); | ||
this.socket.on("timeout", this.socketTimeout.bind(this, this.socket)); | ||
this.socket.on("data", this.handleTransmissionError.bind(this, this.socket)); | ||
this.socket.on("drain", this.socketDrained.bind(this, this.socket, true)); | ||
this.socket.once("close", this.socketClosed.bind(this, this.socket)); | ||
// The actual connection is delayed until after all the event listeners have | ||
// been attached. | ||
if ("function" == typeof this.socket.connect ) { | ||
this.socket.connect(this.options['port'], this.options['address']); | ||
} | ||
else { | ||
socketOptions.socket.connect(this.options['port'], this.options['address']); | ||
} | ||
}.bind(this)).fail(function (error) { | ||
@@ -266,9 +183,5 @@ debug("Module initialisation error:", error); | ||
// This is a pretty fatal scenario, we don't have key/certificate to connect to APNS, there's not much we can do, so raise errors and clear the queue. | ||
while(this.notificationBuffer.length > 0) { | ||
var notification = this.notificationBuffer.shift(); | ||
this.raiseError(error, notification.notification, notification.recipient); | ||
this.emit('transmissionError', Errors['moduleInitialisationFailed'], notification.notification, notification.recipient); | ||
} | ||
this.rejectBuffer(Errors['moduleInitialisationFailed']); | ||
this.deferredConnection.reject(error); | ||
this.deferredConnection = null; | ||
this.terminated = true; | ||
}.bind(this)); | ||
@@ -294,5 +207,15 @@ | ||
var delay = Math.pow(2, this.failureCount++) * 1000; | ||
this.raiseError(error); | ||
this.emit('error', error); | ||
if (this.options.connectionRetryLimit > 0 | ||
&& this.failureCount > this.options.connectionRetryLimit | ||
&& this.sockets.length == 0) { | ||
this.rejectBuffer(Errors['connectionRetryLimitExceeded']); | ||
this.shutdown(); | ||
this.terminated = true; | ||
return; | ||
} | ||
return q.delay(delay); | ||
@@ -303,3 +226,3 @@ }.bind(this)).finally(function () { | ||
this.serviceBuffer(); | ||
}.bind(this)); | ||
}.bind(this)).done(); | ||
}; | ||
@@ -420,9 +343,6 @@ | ||
// ensuring "serviceBuffer" is only called once per loop. | ||
var nextRun = function() { this.runningOnNextTick = false; this.serviceBuffer(); }.bind(this); | ||
if('function' === typeof setImmediate) { | ||
setImmediate(nextRun); | ||
} | ||
else { | ||
process.nextTick(nextRun); | ||
} | ||
util.setImmediate(function() { | ||
this.runningOnNextTick = false; | ||
this.serviceBuffer(); | ||
}.bind(this)); | ||
this.runningOnNextTick = true; | ||
@@ -439,2 +359,4 @@ } | ||
this.destroyConnection(socket); | ||
this.serviceBuffer(); | ||
}; | ||
@@ -448,2 +370,3 @@ | ||
if (socket) { | ||
this.retireSocket(socket); | ||
socket.destroy(); | ||
@@ -464,7 +387,3 @@ } | ||
else { | ||
var index = this.sockets.indexOf(socket); | ||
if (index > -1) { | ||
this.sockets.splice(index, 1); | ||
} | ||
this.retireSocket(socket); | ||
this.emit('disconnected', this.sockets.length); | ||
@@ -477,2 +396,14 @@ } | ||
/** | ||
* @private | ||
*/ | ||
Connection.prototype.retireSocket = function(socket) { | ||
debug("Removing socket from pool", socket.socketId); | ||
var index = this.sockets.indexOf(socket); | ||
if (index > -1) { | ||
this.sockets.splice(index, 1); | ||
} | ||
} | ||
/** | ||
* Use this method to modify the cache length after initialisation. | ||
@@ -500,2 +431,13 @@ */ | ||
*/ | ||
Connection.prototype.rejectBuffer = function (errCode) { | ||
while(this.notificationBuffer.length > 0) { | ||
var notification = this.notificationBuffer.shift(); | ||
this.raiseError(errCode, notification.notification, notification.recipient); | ||
this.emit('transmissionError', errCode, notification.notification, notification.recipient); | ||
} | ||
} | ||
/** | ||
* @private | ||
*/ | ||
Connection.prototype.prepareNotification = function (notification, device) { | ||
@@ -505,3 +447,3 @@ var recipient = device; | ||
if (recipient === undefined) { | ||
process.nextTick(function () { | ||
util.setImmediate(function () { | ||
this.raiseError(Errors['missingDeviceToken'], notification); | ||
@@ -520,3 +462,3 @@ this.emit('transmissionError', Errors['missingDeviceToken'], notification); | ||
// If an exception has been thrown it's down to an invalid token. | ||
process.nextTick(function () { | ||
util.setImmediate(function () { | ||
this.raiseError(Errors['invalidToken'], notification, device); | ||
@@ -742,4 +684,4 @@ this.emit('transmissionError', Errors['invalidToken'], notification, device); | ||
if (messageLength > 256) { | ||
process.nextTick(function () { | ||
if (messageLength > (this.options.largePayloads ? 2048 : 256)) { | ||
util.setImmediate(function () { | ||
this.raiseError(Errors['invalidPayloadSize'], notification, recipient); | ||
@@ -761,2 +703,6 @@ this.emit('transmissionError', Errors['invalidPayloadSize'], notification, recipient); | ||
Connection.prototype.pushNotification = function (notification, recipient) { | ||
if (this.terminated) { | ||
this.emit('transmissionError', Errors['connectionTerminated'], notification, recipient); | ||
return false; | ||
} | ||
if (!this.validNotification(notification, recipient)) { | ||
@@ -763,0 +709,0 @@ return; |
@@ -19,5 +19,7 @@ /** | ||
'retryLimitExceeded': 512, | ||
'moduleInitialisationFailed': 513 | ||
'moduleInitialisationFailed': 513, | ||
'connectionRetryLimitExceeded': 514, // When a connection is unable to be established. Usually because of a network / SSL error this will be emitted | ||
'connectionTerminated': 515 | ||
}; | ||
module.exports = Errors; |
@@ -0,5 +1,5 @@ | ||
var CredentialLoader = require('./credentials'); | ||
var Device = require('./device'); | ||
var Errors = require('./errors'); | ||
var fs = require('fs'); | ||
var q = require('q'); | ||
@@ -57,2 +57,8 @@ var tls = require('tls'); | ||
for (var key in options) { | ||
if (options[key] == null) { | ||
debug("Option [" + key + "] set to null. This may cause unexpected behaviour."); | ||
} | ||
} | ||
util.extend(this.options, options); | ||
@@ -110,70 +116,7 @@ | ||
Feedback.prototype.initialize = function () { | ||
if (this.initializationPromise) { | ||
return this.initializationPromise; | ||
if (!this.initializationPromise) { | ||
debug("Initialising module"); | ||
this.initializationPromise = CredentialLoader(this.options); | ||
} | ||
debug("Initialising module"); | ||
var readFile = q.nfbind(fs.readFile); | ||
// Prepare PKCS#12 data if available | ||
var pfxPromise = null; | ||
if(this.options.pfx != null || this.options.pfxData != null) { | ||
if(this.options.pfxData) { | ||
pfxPromise = this.options.pfxData; | ||
} | ||
else if(Buffer.isBuffer(this.options.pfx)) { | ||
pfxPromise = this.options.pfx; | ||
} | ||
else { | ||
pfxPromise = readFile(this.options.pfx); | ||
} | ||
} | ||
// Prepare Certificate data if available. | ||
var certPromise = null; | ||
if (this.options.certData) { | ||
certPromise = this.options.certData; | ||
} | ||
else if(Buffer.isBuffer(this.options.cert) || checkPEMType(this.options.cert, "CERTIFICATE")) { | ||
certPromise = this.options.cert; | ||
} | ||
else if(this.options.cert) { | ||
// Nothing has matched so attempt to load from disk | ||
certPromise = readFile(this.options.cert); | ||
} | ||
// Prepare Key data if available | ||
var keyPromise = null; | ||
if (this.options.keyData) { | ||
keyPromise = this.options.keyData; | ||
} | ||
else if(Buffer.isBuffer(this.options.key) || checkPEMType(this.options.key, "PRIVATE KEY")) { | ||
keyPromise = this.options.key; | ||
} | ||
else if(this.options.key){ | ||
keyPromise = readFile(this.options.key); | ||
} | ||
// Prepare Certificate Authority data if available. | ||
var caPromises = []; | ||
if (this.options.ca != null && !sysu.isArray(this.options.ca)) { | ||
this.options.ca = [ this.options.ca ]; | ||
} | ||
for(var i in this.options.ca) { | ||
var ca = this.options.ca[i]; | ||
if(Buffer.isBuffer(ca) || checkPEMType(ca, "CERTIFICATE")) { | ||
caPromises.push(ca); | ||
} | ||
else if(ca) { | ||
caPromises.push(readFile(ca)); | ||
} | ||
} | ||
if (caPromises.length == 0) { | ||
caPromises = undefined; | ||
} | ||
else { | ||
caPromises = q.all(caPromises); | ||
} | ||
this.initializationPromise = q.all([pfxPromise, certPromise, keyPromise, caPromises]); | ||
return this.initializationPromise; | ||
@@ -296,4 +239,4 @@ }; | ||
if (this.options.batchFeedback && this.feedbackData.length > 0) { | ||
debug("Emitting all feedback tokens"); | ||
if (this.options.batchFeedback) { | ||
debug("Emitting " + this.feedbackData.length + " feedback tokens"); | ||
this.emit('feedback', this.feedbackData); | ||
@@ -300,0 +243,0 @@ this.feedbackData = []; |
@@ -10,3 +10,2 @@ /** | ||
this.expiry = 0; | ||
this.identifier = 0; | ||
this.priority = 10; | ||
@@ -34,2 +33,5 @@ | ||
this.urlArgs = undefined; | ||
/** iOS 8 notification actions **/ | ||
this.category = undefined; | ||
} | ||
@@ -50,3 +52,2 @@ | ||
notification.expiry = this.expiry; | ||
notification.identifier = this.identifier; | ||
notification.priority = this.priority; | ||
@@ -64,2 +65,4 @@ notification.device = device; | ||
notification.category = this.category; | ||
return notification; | ||
@@ -260,2 +263,11 @@ }; | ||
/** | ||
* Set the category for the notification | ||
* @param {String} [category] The category for the push notification action | ||
*/ | ||
Notification.prototype.setCategory = function (category) { | ||
this.category = category; | ||
return this; | ||
}; | ||
/** | ||
* If an alert object doesn't already exist create it and transfer any existing message into the .body property | ||
@@ -288,4 +300,4 @@ * @private | ||
*/ | ||
Notification.prototype.trim = function() { | ||
var tooLong = this.length() - 256; | ||
Notification.prototype.trim = function(length) { | ||
var tooLong = this.length() - (length || 256); | ||
if(tooLong <= 0) { | ||
@@ -296,19 +308,29 @@ return 0; | ||
var encoding = this.encoding || 'utf8'; | ||
var escaped; // Working variable for trimming string | ||
if(typeof this.alert == "string") { | ||
length = Buffer.byteLength(this.alert, encoding); | ||
if (length < tooLong) { | ||
return length - tooLong; | ||
} | ||
this.alert = this.truncateStringToLength(this.alert, length - tooLong); | ||
return tooLong; | ||
escaped = this.alert; | ||
} | ||
else if(typeof this.alert == "object" && typeof this.alert.body == "string") { | ||
length = Buffer.byteLength(this.alert.body, encoding); | ||
if (length < tooLong) { | ||
return length - tooLong; | ||
} | ||
this.alert.body = this.truncateStringToLength(this.alert.body, length - tooLong); | ||
return tooLong; | ||
escaped = this.alert.body; | ||
} | ||
return -tooLong; | ||
else { | ||
return -tooLong; | ||
} | ||
escaped = JSON.stringify(escaped).slice(1, -1); // trim quotes | ||
length = Buffer.byteLength(escaped, encoding); | ||
if (length < tooLong) { | ||
return length - tooLong; | ||
} | ||
escaped = this.truncateStringToLength(escaped, length - tooLong); | ||
escaped = escaped.replace(/(\\|\\x\d{0,1}|\\u\d{0,3})$/, ''); | ||
escaped = JSON.parse('"' + escaped + '"'); | ||
if (typeof this.alert == "string") { | ||
this.alert = escaped; | ||
} | ||
else { | ||
this.alert.body = escaped; | ||
} | ||
return tooLong; | ||
}; | ||
@@ -412,2 +434,6 @@ | ||
} | ||
if (typeof this.category == 'string') { | ||
this.payload.aps.category = this.category; | ||
apsSet = true; | ||
} | ||
@@ -414,0 +440,0 @@ if (!apsSet) { |
@@ -11,2 +11,12 @@ var extend = function(target) { | ||
module.exports.extend = extend; | ||
var apnSetImmediate = function (method) { | ||
if('function' === typeof setImmediate) { | ||
setImmediate(method); | ||
} | ||
else { | ||
process.nextTick(method); | ||
} | ||
}; | ||
module.exports.extend = extend; | ||
module.exports.setImmediate = apnSetImmediate; |
{ | ||
"name": "apn", | ||
"description": "An interface to the Apple Push Notification service for Node.js", | ||
"version": "1.5.2", | ||
"version": "1.6.0", | ||
"author": "Andrew Naylor <argon@mkbot.net>", | ||
@@ -41,5 +41,5 @@ "contributors": [ | ||
"engines": { | ||
"node": ">= 0.6.6" | ||
"node": ">= 0.6.14" | ||
}, | ||
"license": "MIT" | ||
} |
@@ -6,23 +6,29 @@ var apn = require("../"); | ||
describe('constructor', function () { | ||
var originalEnv; | ||
before(function() { | ||
originalEnv = process.env.NODE_ENV; | ||
}); | ||
after(function() { | ||
process.env.NODE_ENV = originalEnv; | ||
}) | ||
beforeEach(function() { | ||
process.env.NODE_ENV = ""; | ||
}) | ||
// Issue #50 | ||
it("should use gateway.sandbox.push.apple.com as the default connection address", function () { | ||
var existingEnv = process.env.NODE_ENV; | ||
process.env.NODE_ENV = ""; | ||
apn.Connection().options.address.should.equal("gateway.sandbox.push.apple.com"); | ||
process.env.NODE_ENV = existingEnv; | ||
}); | ||
it("should use gateway.push.apple.com when NODE_ENV=production", function () { | ||
var existingEnv = process.env.NODE_ENV; | ||
process.env.NODE_ENV = "production"; | ||
apn.Connection().options.address.should.equal("gateway.push.apple.com"); | ||
process.env.NODE_ENV = existingEnv; | ||
}); | ||
it("should give precedence to production flag over NODE_ENV=production", function () { | ||
var existingEnv = process.env.NODE_ENV; | ||
process.env.NODE_ENV = "production"; | ||
apn.Connection({ production: false }).options.address.should.equal("gateway.sandbox.push.apple.com"); | ||
process.env.NODE_ENV = existingEnv; | ||
}); | ||
@@ -40,106 +46,7 @@ | ||
describe('#initialize', function () { | ||
var pfx, cert, key, ca; | ||
before(function () { | ||
pfx = fs.readFileSync("test/support/initializeTest.pfx"); | ||
cert = fs.readFileSync("test/support/initializeTest.crt"); | ||
key = fs.readFileSync("test/support/initializeTest.key"); | ||
}); | ||
it("should eventually load a pfx file from disk", function () { | ||
it("should be fulfilled", function () { | ||
return apn.Connection({ pfx: "test/support/initializeTest.pfx" }) | ||
.initialize().get(0).post("toString") | ||
.should.eventually.equal(pfx.toString()); | ||
.initialize().should.be.fulfilled; | ||
}); | ||
it("should eventually provide pfx data from memory", function () { | ||
return apn.Connection({ pfx: pfx }).initialize().get(0).post("toString") | ||
.should.eventually.equal(pfx.toString()); | ||
}); | ||
it("should eventually provide pfx data explicitly passed in pfxData parameter", function () { | ||
return apn.Connection({ pfxData: pfx }).initialize().get(0).post("toString") | ||
.should.eventually.equal(pfx.toString()); | ||
}); | ||
it("should eventually load a certificate from disk", function () { | ||
return apn.Connection({ cert: "test/support/initializeTest.crt", key: null}) | ||
.initialize().get(1).post("toString") | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually provide a certificate from a Buffer", function () { | ||
return apn.Connection({ cert: cert, key: null}) | ||
.initialize().get(1).post("toString") | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually provide a certificate from a String", function () { | ||
return apn.Connection({ cert: cert.toString(), key: null}) | ||
.initialize().get(1) | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually provide certificate data explicitly passed in the certData parameter", function () { | ||
return apn.Connection({ certData: cert, key: null}) | ||
.initialize().get(1).post("toString") | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually load a key from disk", function () { | ||
return apn.Connection({ cert: null, key: "test/support/initializeTest.key"}) | ||
.initialize().get(2).post("toString") | ||
.should.eventually.equal(key.toString()); | ||
}); | ||
it("should eventually provide a key from a Buffer", function () { | ||
return apn.Connection({ cert: null, key: key}) | ||
.initialize().get(2).post("toString") | ||
.should.eventually.equal(key.toString()); | ||
}); | ||
it("should eventually provide a key from a String", function () { | ||
return apn.Connection({ cert: null, key: key.toString()}) | ||
.initialize().get(2) | ||
.should.eventually.equal(key.toString()); | ||
}) | ||
it("should eventually provide key data explicitly passed in the keyData parameter", function () { | ||
return apn.Connection({ cert: null, keyData: key}) | ||
.initialize().get(2).post("toString") | ||
.should.eventually.equal(key.toString()); | ||
}); | ||
it("should eventually load a single CA certificate from disk", function () { | ||
return apn.Connection({ cert: null, key: null, ca: "test/support/initializeTest.crt" }) | ||
.initialize().get(3).get(0).post("toString") | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually provide a single CA certificate from a Buffer", function () { | ||
return apn.Connection({ cert: null, key: null, ca: cert }) | ||
.initialize().get(3).get(0).post("toString") | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually provide a single CA certificate from a String", function () { | ||
return apn.Connection({ cert: null, key: null, ca: cert.toString() }) | ||
.initialize().get(3).get(0) | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually load an array of CA certificates", function (done) { | ||
apn.Connection({ cert: null, key: null, ca: ["test/support/initializeTest.crt", cert, cert.toString()] }) | ||
.initialize().get(3).spread(function(cert1, cert2, cert3) { | ||
var certString = cert.toString(); | ||
if (cert1.toString() == certString && | ||
cert2.toString() == certString && | ||
cert3.toString() == certString) { | ||
done(); | ||
} | ||
else { | ||
done(new Error("provided certificates did not match")); | ||
} | ||
}, done); | ||
}); | ||
}); | ||
}); |
@@ -6,3 +6,3 @@ var apn = require("../"); | ||
describe('constructor', function () { | ||
var requestMethod; | ||
var requestMethod, originalEnv; | ||
@@ -12,2 +12,4 @@ before(function() { | ||
apn.Feedback.prototype.request = function() { }; | ||
originalEnv = process.env.NODE_ENV; | ||
}); | ||
@@ -17,17 +19,17 @@ | ||
apn.Feedback.prototype.request = requestMethod; | ||
}) | ||
process.env.NODE_ENV = originalEnv; | ||
}); | ||
beforeEach(function() { | ||
process.env.NODE_ENV = ""; | ||
}); | ||
// Issue #50 | ||
it("should use feedback.sandbox.push.apple.com as the default Feedback address", function () { | ||
var existingEnv = process.env.NODE_ENV; | ||
process.env.NODE_ENV = ""; | ||
apn.Feedback().options.address.should.equal("feedback.sandbox.push.apple.com"); | ||
process.env.NODE_ENV = existingEnv; | ||
}); | ||
it("should use feedback.push.apple.com when NODE_ENV=production", function () { | ||
var existingEnv = process.env.NODE_ENV; | ||
process.env.NODE_ENV = "production"; | ||
apn.Feedback().options.address.should.equal("feedback.push.apple.com"); | ||
process.env.NODE_ENV = existingEnv; | ||
}); | ||
@@ -40,6 +42,4 @@ | ||
it("should give precedence to production flag over NODE_ENV=production", function () { | ||
var existingEnv = process.env.NODE_ENV; | ||
process.env.NODE_ENV = "production"; | ||
apn.Feedback({ production: false }).options.address.should.equal("feedback.sandbox.push.apple.com"); | ||
process.env.NODE_ENV = existingEnv; | ||
}); | ||
@@ -53,106 +53,8 @@ | ||
describe('#initialize', function () { | ||
var pfx, cert, key, ca; | ||
before(function () { | ||
pfx = fs.readFileSync("test/support/initializeTest.pfx"); | ||
cert = fs.readFileSync("test/support/initializeTest.crt"); | ||
key = fs.readFileSync("test/support/initializeTest.key"); | ||
}); | ||
it("should eventually load a pfx file from disk", function () { | ||
it("should be fulfilled", function () { | ||
return apn.Feedback({ pfx: "test/support/initializeTest.pfx" }) | ||
.initialize().get(0).post("toString") | ||
.should.eventually.equal(pfx.toString()); | ||
.initialize().should.be.fulfilled; | ||
}); | ||
it("should eventually provide pfx data from memory", function () { | ||
return apn.Feedback({ pfx: pfx }).initialize().get(0).post("toString") | ||
.should.eventually.equal(pfx.toString()); | ||
}); | ||
it("should eventually provide pfx data explicitly passed in pfxData parameter", function () { | ||
return apn.Feedback({ pfxData: pfx }).initialize().get(0).post("toString") | ||
.should.eventually.equal(pfx.toString()); | ||
}); | ||
it("should eventually load a certificate from disk", function () { | ||
return apn.Feedback({ cert: "test/support/initializeTest.crt", key: null}) | ||
.initialize().get(1).post("toString") | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually provide a certificate from a Buffer", function () { | ||
return apn.Feedback({ cert: cert, key: null}) | ||
.initialize().get(1).post("toString") | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually provide a certificate from a String", function () { | ||
return apn.Feedback({ cert: cert.toString(), key: null}) | ||
.initialize().get(1) | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually provide certificate data explicitly passed in the certData parameter", function () { | ||
return apn.Feedback({ certData: cert, key: null}) | ||
.initialize().get(1).post("toString") | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually load a key from disk", function () { | ||
return apn.Feedback({ cert: null, key: "test/support/initializeTest.key"}) | ||
.initialize().get(2).post("toString") | ||
.should.eventually.equal(key.toString()); | ||
}); | ||
it("should eventually provide a key from a Buffer", function () { | ||
return apn.Feedback({ cert: null, key: key}) | ||
.initialize().get(2).post("toString") | ||
.should.eventually.equal(key.toString()); | ||
}); | ||
it("should eventually provide a key from a String", function () { | ||
return apn.Feedback({ cert: null, key: key.toString()}) | ||
.initialize().get(2) | ||
.should.eventually.equal(key.toString()); | ||
}) | ||
it("should eventually provide key data explicitly passed in the keyData parameter", function () { | ||
return apn.Feedback({ cert: null, keyData: key}) | ||
.initialize().get(2).post("toString") | ||
.should.eventually.equal(key.toString()); | ||
}); | ||
it("should eventually load a single CA certificate from disk", function () { | ||
return apn.Feedback({ cert: null, key: null, ca: "test/support/initializeTest.crt" }) | ||
.initialize().get(3).get(0).post("toString") | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually provide a single CA certificate from a Buffer", function () { | ||
return apn.Feedback({ cert: null, key: null, ca: cert }) | ||
.initialize().get(3).get(0).post("toString") | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually provide a single CA certificate from a String", function () { | ||
return apn.Feedback({ cert: null, key: null, ca: cert.toString() }) | ||
.initialize().get(3).get(0) | ||
.should.eventually.equal(cert.toString()); | ||
}); | ||
it("should eventually load an array of CA certificates", function (done) { | ||
apn.Feedback({ cert: null, key: null, ca: ["test/support/initializeTest.crt", cert, cert.toString()] }) | ||
.initialize().get(3).spread(function(cert1, cert2, cert3) { | ||
var certString = cert.toString(); | ||
if (cert1.toString() == certString && | ||
cert2.toString() == certString && | ||
cert3.toString() == certString) { | ||
done(); | ||
} | ||
else { | ||
done(new Error("provided certificates did not match")); | ||
} | ||
}, done); | ||
}); | ||
}); | ||
}); |
var apn = require("../"); | ||
describe("Notification", function() { | ||
describe('constructor', function () { | ||
var note; | ||
beforeEach(function() { | ||
note = new apn.Notification(); | ||
}); | ||
}); | ||
it("should trim long alert strings", function () { | ||
note.alert = 'ㅂㅈ ㅐ: LONDON (AP) — E\\\veryone says there areare lots of hidden costs to owning a home. If you own a palace, the costs are royal.\n\nThat became evident when the Buckingham Palace released its accounts Thursday, which showed the monarchy cost British taxpayers 35.7 million pounds ($60.8 million) last year — 56 pence (just under $1) for everyone in the country.\n\nThat is 7.2 percent, or 2.4 million pounds, more than the year before and the increase is mainly explained by the British royal family\'s repair bills.\n\nTheir properties are hardly typical. Buckingham Palace, for example, has 240 bedrooms and 78 bathrooms. That\'s a lot of plumbing to fix when things go wrong.\n\nSo it\'s no surprise that more than a third of the money British taxpayers paid for the monarchy, led by Queen Elizabeth II, was spent on repairs, improvements and maintenance of aging but still opulent palaces.\n\n"We continue to focus on value for money," said Keeper of the Privy Purse Alan Reid, asserting that careful spending habits had allowed for more money to be used for important maintenance work.\n\n\nFILE - In this Saturday, June 14, 2014 file photo, Britain\'s Queen Elizabeth II, foreground, sur …\nA big part of the fixer-upper budget in the 12 months that ended on March 31 went to creating a suitable home for the young family of Prince William, his wife Kate and their toddler Prince George.\n\nSome 3.4 million pounds of taxpayer funds were used to refurbish part of London\'s Kensington Palace for the couple. The extensive work included removing asbestos, installing new heating and redecorating.\n\nThe couple, who have considerable personal financial resources in part because of the estate left by Princess Diana, paid for the carpets, curtains and furniture out of personal funds, the palace said.\n\nIn addition, Prince Charles\' private secretary, William Nye, suggested that Charles and his wife Camilla — who are supported by profits from the extensive Duchy of Cornwall estate — may have helped William and Kate set up their new home.\n\nThe palace accounts also showed the high cost of entertaining on a royal scale: 2 million pounds were spent on "housekeeping and hospitality" in the 12 months that ended on March 31.\n\nThat became evident when the Buckingham Palace released its accounts Thursday, which showed the monarchy cost British taxpayers 35.7 million pounds ($60.8 million) last year — 56 pence (just under $1) for everyone in the country.\n\nThat is 7.2 percent, or 2.4 million pounds, more than the year before and the increase is mainly explained by the British royal family\'s repair bills.\n\nTheir properties are hardly typical. Buckingham Palace, for example, has 240 bedrooms and 78 bathrooms. That\'s a lot of plumbing to fix when things go wrong. \n\nSo it\'s no surprise that more than a third of the money British taxpayers paid for the monarchy, led by Queen Elizabeth II, was spent on repairs, improvements and maintenance of aging but still opulent palaces.\n\n"We continue to focus on value for money," said Keeper of the Privy Purse Alan Reid, asserting that careful spending habits had allowed for more money to be used for important maintenance work\n\nThat became evident when the Buckingham Palace released its accounts Thursday, which showed the monarchy cost British taxpayers 35.7 million pounds ($60.8 million) last year — 56 pence (just under $1) for everyone in the country.\n\nThat is 7.2 percent, or 2.4 million pounds, more than the year before and the increase is mainly explained by the British royal family\'s repair bills.\n\nTheir properties are hardly typical. Buckingham Palace, for example, has 240 bedrooms and 78 bathrooms. That\'s a lot of plumbing to fix when things go wrong. \n\nSo it\'s no surprise that more than a third of the money British taxpayers paid for the monarchy, led by Queen Elizabeth II, was spent on repairs, improvements and maintenance of aging but still opulent palaces.\n\n"We continue to focus on value for money," said Keeper of the Privy Purse Alan Reid, asserting that careful spending habits had allowed for more money to be used for important maintenance work\n\n\nThat became evident when the Buckingham Palace released its accounts Thursday, which showed the monarchy cost British taxpayers 35.7 million pounds ($60.8 million) last year — 56 pence (just under $1) for everyone in the country.\n\nThat is 7.2 percent, or 2.4 million pounds, more than the year before and the increase is mainly explained by the British royal family\'s repair bills.\n\nTheir properties are hardly typical. Buckingham Palace, for example, has 240 bedrooms and 78 bathrooms. That\'s a lot of plumbing to fix when things go wrong. \n\nSo it\'s no surprise that more than a third of the money British taxpayers paid for the monarchy, led by Queen Elizabeth II, was spent on repairs, improvements and maintenance of aging but still opulent palaces.\n\n"We continue to focus on value for money," said Keeper of the Privy Purse Alan Reid, asserting that careful spending habits had allowed for more money to be used for important maintenance work\n\nThat became evident when the Buckingham Palace released its accounts Thursday, which showed the monarchy cost British taxpayers 35.7 million pounds ($60.8 million) last year — 56 pence (just under $1) for everyone in the country.\n\nThat is 7.2 percent, or 2.4 million pounds, more than the year before and the increase is mainly explained by the British royal family\'s repair bills.\n\nTheir properties are hardly typical. Buckingham Palace, for example, has 240 bedrooms and 78 bathrooms. That\'s a lot of plumbing to fix when things go wrong. \n\nSo it\'s no surprise that more than a third of the money British taxpayers paid for the monarchy, led by Queen Elizabeth II, was spent on repairs, improvements and maintenance of aging but still opulent palaces.\n\n"We continue to focus on value for money," said Keeper of the Privy Purse Alan Reid, asserting that careful spending habits had allowed for more money to be used for important maintenance work\n---ending ---\n\n' | ||
note.trim(); | ||
note.length().should.equal(256); | ||
}); | ||
it("should trim long alert bodies ", function () { | ||
note.alert = { | ||
body: 'ㅂㅈ ㅐ: LONDON (AP) — E\\\veryone says there areare lots of hidden costs to owning a home. If you own a palace, the costs are royal.\n\nThat became evident when the Buckingham Palace released its accounts Thursday, which showed the monarchy cost British taxpayers 35.7 million pounds ($60.8 million) last year — 56 pence (just under $1) for everyone in the country.\n\nThat is 7.2 percent, or 2.4 million pounds, more than the year before and the increase is mainly explained by the British royal family\'s repair bills.\n\nTheir properties are hardly typical. Buckingham Palace, for example, has 240 bedrooms and 78 bathrooms. That\'s a lot of plumbing to fix when things go wrong.\n\nSo it\'s no surprise that more than a third of the money British taxpayers paid for the monarchy, led by Queen Elizabeth II, was spent on repairs, improvements and maintenance of aging but still opulent palaces.\n\n"We continue to focus on value for money," said Keeper of the Privy Purse Alan Reid, asserting that careful spending habits had allowed for more money to be used for important maintenance work.\n\n\nFILE - In this Saturday, June 14, 2014 file photo, Britain\'s Queen Elizabeth II, foreground, sur …\nA big part of the fixer-upper budget in the 12 months that ended on March 31 went to creating a suitable home for the young family of Prince William, his wife Kate and their toddler Prince George.\n\nSome 3.4 million pounds of taxpayer funds were used to refurbish part of London\'s Kensington Palace for the couple. The extensive work included removing asbestos, installing new heating and redecorating.\n\nThe couple, who have considerable personal financial resources in part because of the estate left by Princess Diana, paid for the carpets, curtains and furniture out of personal funds, the palace said.\n\nIn addition, Prince Charles\' private secretary, William Nye, suggested that Charles and his wife Camilla — who are supported by profits from the extensive Duchy of Cornwall estate — may have helped William and Kate set up their new home.\n\nThe palace accounts also showed the high cost of entertaining on a royal scale: 2 million pounds were spent on "housekeeping and hospitality" in the 12 months that ended on March 31.\n\nThat became evident when the Buckingham Palace released its accounts Thursday, which showed the monarchy cost British taxpayers 35.7 million pounds ($60.8 million) last year — 56 pence (just under $1) for everyone in the country.\n\nThat is 7.2 percent, or 2.4 million pounds, more than the year before and the increase is mainly explained by the British royal family\'s repair bills.\n\nTheir properties are hardly typical. Buckingham Palace, for example, has 240 bedrooms and 78 bathrooms. That\'s a lot of plumbing to fix when things go wrong. \n\nSo it\'s no surprise that more than a third of the money British taxpayers paid for the monarchy, led by Queen Elizabeth II, was spent on repairs, improvements and maintenance of aging but still opulent palaces.\n\n"We continue to focus on value for money," said Keeper of the Privy Purse Alan Reid, asserting that careful spending habits had allowed for more money to be used for important maintenance work\n\nThat became evident when the Buckingham Palace released its accounts Thursday, which showed the monarchy cost British taxpayers 35.7 million pounds ($60.8 million) last year — 56 pence (just under $1) for everyone in the country.\n\nThat is 7.2 percent, or 2.4 million pounds, more than the year before and the increase is mainly explained by the British royal family\'s repair bills.\n\nTheir properties are hardly typical. Buckingham Palace, for example, has 240 bedrooms and 78 bathrooms. That\'s a lot of plumbing to fix when things go wrong. \n\nSo it\'s no surprise that more than a third of the money British taxpayers paid for the monarchy, led by Queen Elizabeth II, was spent on repairs, improvements and maintenance of aging but still opulent palaces.\n\n"We continue to focus on value for money," said Keeper of the Privy Purse Alan Reid, asserting that careful spending habits had allowed for more money to be used for important maintenance work\n\n\nThat became evident when the Buckingham Palace released its accounts Thursday, which showed the monarchy cost British taxpayers 35.7 million pounds ($60.8 million) last year — 56 pence (just under $1) for everyone in the country.\n\nThat is 7.2 percent, or 2.4 million pounds, more than the year before and the increase is mainly explained by the British royal family\'s repair bills.\n\nTheir properties are hardly typical. Buckingham Palace, for example, has 240 bedrooms and 78 bathrooms. That\'s a lot of plumbing to fix when things go wrong. \n\nSo it\'s no surprise that more than a third of the money British taxpayers paid for the monarchy, led by Queen Elizabeth II, was spent on repairs, improvements and maintenance of aging but still opulent palaces.\n\n"We continue to focus on value for money," said Keeper of the Privy Purse Alan Reid, asserting that careful spending habits had allowed for more money to be used for important maintenance work\n\nThat became evident when the Buckingham Palace released its accounts Thursday, which showed the monarchy cost British taxpayers 35.7 million pounds ($60.8 million) last year — 56 pence (just under $1) for everyone in the country.\n\nThat is 7.2 percent, or 2.4 million pounds, more than the year before and the increase is mainly explained by the British royal family\'s repair bills.\n\nTheir properties are hardly typical. Buckingham Palace, for example, has 240 bedrooms and 78 bathrooms. That\'s a lot of plumbing to fix when things go wrong. \n\nSo it\'s no surprise that more than a third of the money British taxpayers paid for the monarchy, led by Queen Elizabeth II, was spent on repairs, improvements and maintenance of aging but still opulent palaces.\n\n"We continue to focus on value for money," said Keeper of the Privy Purse Alan Reid, asserting that careful spending habits had allowed for more money to be used for important maintenance work\n---ending ---\n\n' | ||
}; | ||
note.trim(); | ||
note.length().should.equal(256); | ||
}); | ||
it("should trim long messages with escaped characters", function () { | ||
note.alert = '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'; | ||
note.trim(); | ||
note.length().should.equal(256); | ||
}); | ||
it("should trim long messages with escaped characters by chopping off the last backslash", function () { | ||
note.alert = ' \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'; | ||
note.trim(); | ||
note.length().should.equal(255); | ||
}); | ||
it("should trim long messages with uni characters", function () { | ||
note.alert = 'ㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐㅂㅈ ㅐ'; | ||
note.trim(); | ||
note.length().should.be.at.most(256); | ||
}); | ||
it("should trim long messages with unprintible characters", function () { | ||
note.alert = '\x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07\x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07\x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07\x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07\x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07\x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07\x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07\x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07\x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07\x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07\x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07 \x07'; | ||
note.trim(); | ||
note.length().should.be.at.most(256); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
134492
32
1847
20
4