apn
Version:
An interface to the Apple Push Notification service for Node.js
159 lines (122 loc) • 4.65 kB
JavaScript
;
const sinon = require("sinon");
describe("perpareToken", function () {
let fakes, prepareToken;
beforeEach(function () {
fakes = {
sign: sinon.stub(),
resolve: sinon.stub(),
decode: sinon.stub(),
};
prepareToken = require("../../../lib/credentials/token/prepare")(fakes);
});
const testOptions = {
key: "key.pem",
keyId: "123KeyId",
teamId: "abcTeamId",
};
context("with valid options", function() {
let token;
beforeEach(function() {
fakes.resolve.withArgs("key.pem").returns("keyData");
fakes.sign.returns("generated-token");
token = prepareToken(testOptions);
});
describe("return value", function (){
describe("`current` property", function () {
it("is initialized to a signed token", function () {
expect(token.current).to.have.equal("generated-token");
});
});
describe("`generation` property", function () {
it("is initialized to 0", function () {
expect(token.generation).to.equal(0);
});
});
context("`regenerate` called with the current `generation` value", function () {
let generation;
beforeEach(function () {
generation = Math.floor(Math.random() * 10) + 2;
token.generation = generation;
fakes.sign.reset();
fakes.sign.onCall(0).returns("second-token");
token.regenerate(generation);
});
it("increments `generation` property", function () {
expect(token.generation).to.equal(generation + 1);
});
it("invokes the sign method with the correct arguments", function (){
expect(fakes.sign).to.have.been.calledWith(
sinon.match({}), // empty payload
"keyData",
sinon.match({
algorithm: "ES256",
issuer: "abcTeamId",
header: sinon.match({
kid: "123KeyId",
}),
})
);
});
it("updates the `current` property to the return value of the sign method", function () {
expect(token.current).to.equal("second-token");
});
});
context("`regenerate` called with a lower `generation` value", function () {
let generation;
beforeEach(function () {
generation = Math.floor(Math.random() * 10) + 2;
token.generation = generation;
fakes.sign.reset();
fakes.sign.onCall(0).returns("second-token");
token.regenerate(generation - 1);
});
it("does not increment `generation` property", function () {
expect(token.generation).to.equal(generation);
});
it("does not invoke the sign method", function () {
expect(fakes.sign).to.have.not.been.called;
});
it("does not change the `current` property", function () {
expect(token.current).to.equal("generated-token");
});
});
context("`isExpired` called with expired token", function () {
let token;
beforeEach(function () {
fakes.resolve.withArgs("key.pem").returns("keyData");
fakes.decode.onCall(0).returns({iat:Math.floor(Date.now() / 1000)-1});
token = prepareToken(testOptions);
});
it("token is not expired", function () {
expect(token.isExpired(0)).to.equal(true);
});
});
context("`isExpired` called with valid token", function () {
let token;
beforeEach(function () {
fakes.resolve.withArgs("key.pem").returns("keyData");
fakes.decode.onCall(0).returns({iat:Math.floor(Date.now() / 1000)});
token = prepareToken(testOptions);
});
it("token is not expired", function () {
expect(token.isExpired(5)).to.equal(false);
});
});
});
});
context("with bad `key` parameter", function () {
context("key resolution fails", function () {
it("throws a wrapped error", function () {
fakes.resolve.withArgs("key.pem").throws(new Error("ENOENT: Unable to read file key.pem"));
expect(() => prepareToken(testOptions)).to.throw(/Failed loading token key: ENOENT: Unable to read file key.pem/);
});
});
context("key cannot be used for signing", function () {
it("throws a wrapped error from jwt.sign", function () {
fakes.sign.throws(new Error("Unable to sign token"));
expect(() => prepareToken(testOptions)).to.throw(/Failed to generate token: Unable to sign token/);
});
});
});
});