prepare.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. const sinon = require('sinon');
  2. describe('perpareToken', function () {
  3. let fakes, prepareToken;
  4. beforeEach(function () {
  5. fakes = {
  6. sign: sinon.stub(),
  7. resolve: sinon.stub(),
  8. decode: sinon.stub(),
  9. };
  10. prepareToken = require('../../../lib/credentials/token/prepare')(fakes);
  11. });
  12. const testOptions = {
  13. key: 'key.pem',
  14. keyId: '123KeyId',
  15. teamId: 'abcTeamId',
  16. };
  17. context('with valid options', function () {
  18. let token;
  19. beforeEach(function () {
  20. fakes.resolve.withArgs('key.pem').returns('keyData');
  21. fakes.sign.returns('generated-token');
  22. token = prepareToken(testOptions);
  23. });
  24. describe('return value', function () {
  25. describe('`current` property', function () {
  26. it('is initialized to a signed token', function () {
  27. expect(token.current).to.have.equal('generated-token');
  28. });
  29. });
  30. describe('`generation` property', function () {
  31. it('is initialized to 0', function () {
  32. expect(token.generation).to.equal(0);
  33. });
  34. });
  35. context('`regenerate` called with the current `generation` value', function () {
  36. let generation;
  37. beforeEach(function () {
  38. generation = Math.floor(Math.random() * 10) + 2;
  39. token.generation = generation;
  40. fakes.sign.reset();
  41. fakes.sign.onCall(0).returns('second-token');
  42. token.regenerate(generation);
  43. });
  44. it('increments `generation` property', function () {
  45. expect(token.generation).to.equal(generation + 1);
  46. });
  47. it('invokes the sign method with the correct arguments', function () {
  48. expect(fakes.sign).to.have.been.calledWith(
  49. sinon.match({}), // empty payload
  50. 'keyData',
  51. sinon.match({
  52. algorithm: 'ES256',
  53. issuer: 'abcTeamId',
  54. header: sinon.match({
  55. kid: '123KeyId',
  56. }),
  57. })
  58. );
  59. });
  60. it('updates the `current` property to the return value of the sign method', function () {
  61. expect(token.current).to.equal('second-token');
  62. });
  63. });
  64. context('`regenerate` called with a lower `generation` value', function () {
  65. let generation;
  66. beforeEach(function () {
  67. generation = Math.floor(Math.random() * 10) + 2;
  68. token.generation = generation;
  69. fakes.sign.reset();
  70. fakes.sign.onCall(0).returns('second-token');
  71. token.regenerate(generation - 1);
  72. });
  73. it('does not increment `generation` property', function () {
  74. expect(token.generation).to.equal(generation);
  75. });
  76. it('does not invoke the sign method', function () {
  77. expect(fakes.sign).to.have.not.been.called;
  78. });
  79. it('does not change the `current` property', function () {
  80. expect(token.current).to.equal('generated-token');
  81. });
  82. });
  83. context('`isExpired` called with expired token', function () {
  84. let token;
  85. beforeEach(function () {
  86. fakes.resolve.withArgs('key.pem').returns('keyData');
  87. fakes.decode.onCall(0).returns({ iat: Math.floor(Date.now() / 1000) - 1 });
  88. token = prepareToken(testOptions);
  89. });
  90. it('token is not expired', function () {
  91. expect(token.isExpired(0)).to.equal(true);
  92. });
  93. });
  94. context('`isExpired` called with valid token', function () {
  95. let token;
  96. beforeEach(function () {
  97. fakes.resolve.withArgs('key.pem').returns('keyData');
  98. fakes.decode.onCall(0).returns({ iat: Math.floor(Date.now() / 1000) });
  99. token = prepareToken(testOptions);
  100. });
  101. it('token is not expired', function () {
  102. expect(token.isExpired(5)).to.equal(false);
  103. });
  104. });
  105. });
  106. });
  107. context('with bad `key` parameter', function () {
  108. context('key resolution fails', function () {
  109. it('throws a wrapped error', function () {
  110. fakes.resolve.withArgs('key.pem').throws(new Error('ENOENT: Unable to read file key.pem'));
  111. expect(() => prepareToken(testOptions)).to.throw(
  112. /Failed loading token key: ENOENT: Unable to read file key.pem/
  113. );
  114. });
  115. });
  116. context('key cannot be used for signing', function () {
  117. it('throws a wrapped error from jwt.sign', function () {
  118. fakes.sign.throws(new Error('Unable to sign token'));
  119. expect(() => prepareToken(testOptions)).to.throw(
  120. /Failed to generate token: Unable to sign token/
  121. );
  122. });
  123. });
  124. });
  125. });