From 83b80aca318e3193210857fbbca1d1855d0ab014 Mon Sep 17 00:00:00 2001 From: Shane O'Brien Date: Wed, 4 Dec 2024 14:53:13 -0500 Subject: [PATCH] Added some auth tests --- package-lock.json | 62 ++++++++++++++++++++++++++++++++++++++++++ package.json | 2 ++ src/auth/index.test.ts | 38 ++++++++++++++++---------- 3 files changed, 88 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 71a84d1..6239968 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@types/mocha": "^10.0.10", "@types/node": "^20.11.0", "@types/node-jose": "^1.1.10", + "@types/proxyquire": "^1.3.31", "@types/sinon": "^17.0.3", "@typescript-eslint/eslint-plugin": "^6.7.0", "@typescript-eslint/parser": "^6.7.0", @@ -34,6 +35,7 @@ "mocha": "^11.0.1", "prettier": "^3.0.3", "prettier-eslint": "^16.0.0", + "proxyquire": "^2.1.3", "rimraf": "^3.0.2", "sinon": "^19.0.2", "ts-node": "^10.9.2", @@ -800,6 +802,13 @@ "@types/node": "*" } }, + "node_modules/@types/proxyquire": { + "version": "1.3.31", + "resolved": "https://registry.npmjs.org/@types/proxyquire/-/proxyquire-1.3.31.tgz", + "integrity": "sha512-uALowNG2TSM1HNPMMOR0AJwv4aPYPhqB0xlEhkeRTMuto5hjoSPZkvgu1nbPUkz3gEPAHv4sy4DmKsurZiEfRQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/secp256k1": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", @@ -2539,6 +2548,20 @@ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" }, + "node_modules/fill-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", + "integrity": "sha512-tcgI872xXjwFF4xgQmLxi76GnwJG3g/3isB1l4/G5Z4zrbddGpBjqZCO9oEAcB5wX0Hj/5iQB3toxfO7in1hHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-object": "~1.0.1", + "merge-descriptors": "~1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -2995,6 +3018,16 @@ "node": ">=0.12.0" } }, + "node_modules/is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -3408,6 +3441,16 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3587,6 +3630,13 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/module-not-found-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "integrity": "sha512-pEk4ECWQXV6z2zjhRZUongnLJNUeGQJ3w6OQ5ctGwD+i5o93qjRQUk2Rt6VdNeu3sEP0AB4LcfvdebpxBRVr4g==", + "dev": true, + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4053,6 +4103,18 @@ "node": ">= 0.6.0" } }, + "node_modules/proxyquire": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", + "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-keys": "^1.0.2", + "module-not-found-error": "^1.0.1", + "resolve": "^1.11.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", diff --git a/package.json b/package.json index 57aedad..00017cf 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@types/mocha": "^10.0.10", "@types/node": "^20.11.0", "@types/node-jose": "^1.1.10", + "@types/proxyquire": "^1.3.31", "@types/sinon": "^17.0.3", "@typescript-eslint/eslint-plugin": "^6.7.0", "@typescript-eslint/parser": "^6.7.0", @@ -48,6 +49,7 @@ "mocha": "^11.0.1", "prettier": "^3.0.3", "prettier-eslint": "^16.0.0", + "proxyquire": "^2.1.3", "rimraf": "^3.0.2", "sinon": "^19.0.2", "ts-node": "^10.9.2", diff --git a/src/auth/index.test.ts b/src/auth/index.test.ts index eed8609..a7cf30d 100644 --- a/src/auth/index.test.ts +++ b/src/auth/index.test.ts @@ -1,18 +1,23 @@ import { expect } from 'chai'; import sinon from 'sinon'; -import * as fs from 'fs'; +import proxyquire from 'proxyquire'; import { JWK, JWS } from 'node-jose'; -import { buildJWT } from './index'; -describe('buildJWT', () => { +describe('BuildJWT', () => { let readFileSyncStub: sinon.SinonStub; let asKeyStub: sinon.SinonStub; let signStub: sinon.SinonStub; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let buildJWT: any; beforeEach(() => { - readFileSyncStub = sinon.stub(fs, 'readFileSync'); + readFileSyncStub = sinon.stub(); asKeyStub = sinon.stub(JWK, 'asKey'); signStub = sinon.stub(JWS, 'createSign'); + + buildJWT = proxyquire('./index', { + fs: { readFileSync: readFileSyncStub }, + }).buildJWT; }); afterEach(() => { @@ -23,9 +28,11 @@ describe('buildJWT', () => { const url = 'https://api.example.com/resource'; const method = 'POST'; const apiKeyName = 'test-api-key'; - const apiPrivateKey = 'test-private-key'; - const pemPrivateKey = + const apiPrivateKey = '-----BEGIN EC PRIVATE KEY-----\ntest-private-key\n-----END EC PRIVATE KEY-----'; + // The method strips the newline characters under the hood, so we've removed that from the expected value + const pemPrivateKey = + '-----BEGIN EC PRIVATE KEY-----test-private-key-----END EC PRIVATE KEY-----'; const privateKey = { kty: 'EC' }; asKeyStub.resolves(privateKey); @@ -46,10 +53,11 @@ describe('buildJWT', () => { const method = 'POST'; const apiKey = { name: 'test-api-key', - privateKey: 'test-private-key', + privateKey: + '-----BEGIN EC PRIVATE KEY-----test-private-key-----END EC PRIVATE KEY-----', }; const pemPrivateKey = - '-----BEGIN EC PRIVATE KEY-----\ntest-private-key\n-----END EC PRIVATE KEY-----'; + '-----BEGIN EC PRIVATE KEY-----test-private-key-----END EC PRIVATE KEY-----'; const privateKey = { kty: 'EC' }; readFileSyncStub.returns(JSON.stringify(apiKey)); @@ -75,9 +83,10 @@ describe('buildJWT', () => { const url = 'https://api.example.com/resource'; const method = 'POST'; const apiKeyName = 'test-api-key'; - const apiPrivateKey = 'test-private-key'; - const pemPrivateKey = + const apiPrivateKey = '-----BEGIN EC PRIVATE KEY-----\ntest-private-key\n-----END EC PRIVATE KEY-----'; + const pemPrivateKey = + '-----BEGIN EC PRIVATE KEY-----test-private-key-----END EC PRIVATE KEY-----'; const privateKey = { kty: 'RSA' }; asKeyStub.resolves(privateKey); @@ -86,7 +95,7 @@ describe('buildJWT', () => { await buildJWT(url, method, apiKeyName, apiPrivateKey); expect.fail('Expected buildJWT to throw an error'); } catch (error) { - expect((error as Error).message).to.equal('Not an EC private key'); + expect((error as Error).message).to.contain('Not an EC private key'); } expect(asKeyStub.calledOnceWithExactly(pemPrivateKey, 'pem')).to.be.true; @@ -97,9 +106,10 @@ describe('buildJWT', () => { const url = 'https://api.example.com/resource'; const method = 'POST'; const apiKeyName = 'test-api-key'; - const apiPrivateKey = 'test-private-key'; - const pemPrivateKey = + const apiPrivateKey = '-----BEGIN EC PRIVATE KEY-----\ntest-private-key\n-----END EC PRIVATE KEY-----'; + const pemPrivateKey = + '-----BEGIN EC PRIVATE KEY-----test-private-key-----END EC PRIVATE KEY-----'; asKeyStub.rejects(new Error('Invalid key')); @@ -108,7 +118,7 @@ describe('buildJWT', () => { expect.fail('Expected buildJWT to throw an error'); } catch (error) { expect((error as Error).message).to.include( - 'jwt: Could not decode or parse private key. Invalid key', + 'jwt: Could not decode or parse private key. Error: Invalid key', ); }