@ministryofjustice/fb-jwt-client-node
Advanced tools
Comparing version 0.0.26 to 0.0.27
@@ -15,6 +15,2 @@ const got = require('got') | ||
// values for metrics | ||
const labelNames = ['client_name', 'base_url', 'url', 'method', 'status_code', 'status_message', 'error_name'] | ||
const buckets = [0.1, 0.25, 0.5, 1, 2, 5, 10] | ||
const getResponseLabels = (response) => { | ||
@@ -103,24 +99,16 @@ const responseLabels = { | ||
/** | ||
* Create metrics buckets for requests | ||
* Add metrics recorders for requests | ||
* | ||
* @param {object} prometheusClient | ||
* Prometheus client | ||
* @param {object} apiMetrics | ||
* Prometheus histogram instance | ||
* | ||
* @param {object} requestMetrics | ||
* Prometheus histogram instance | ||
* | ||
* @return {undefined} | ||
* | ||
**/ | ||
setMetricsInstrumentation (prometheusClient) { | ||
this.apiMetrics = new prometheusClient.Histogram({ | ||
name: 'api_requests', | ||
help: 'API calls using FB JWT Client', | ||
labelNames, | ||
buckets | ||
}) | ||
this.requestMetrics = new prometheusClient.Histogram({ | ||
name: 'jwt_client_requests', | ||
help: 'HTTP requests using FB JWT Client', | ||
labelNames, | ||
buckets | ||
}) | ||
setMetricsInstrumentation (apiMetrics, requestMetrics) { | ||
this.apiMetrics = apiMetrics | ||
this.requestMetrics = requestMetrics | ||
} | ||
@@ -289,9 +277,10 @@ | ||
const errorResponse = error.error || error.body | ||
const errorObj = typeof errorResponse === 'object' ? JSON.stringify(errorResponse) : '' | ||
const errorResponseObj = typeof errorResponse === 'object' ? JSON.stringify(errorResponse) : '' | ||
if (error.gotOptions) { | ||
error.client_headers = error.gotOptions.headers | ||
} | ||
const logObject = Object.assign({}, labels, {error}) | ||
const excludes = ['gotOptions', 'url', 'path'] | ||
excludes.forEach(exclude => { | ||
delete logObject.error[exclude] | ||
}) | ||
logger.error(logObject, `JWT ${type} request error: ${this.constructor.name}: ${labels.method.toUpperCase()} ${labels.base_url}${labels.url} - ${error.name} - ${error.code ? error.code : ''} - ${error.statusCode ? error.statusCode : ''} - ${error.statusMessage ? error.statusMessage : ''} - ${errorObj}`) | ||
logger.error(logObject, `JWT ${type} request error: ${this.constructor.name}: ${labels.method.toUpperCase()} ${labels.base_url}${labels.url} - ${error.name} - ${error.code ? error.code : ''} - ${error.statusCode ? error.statusCode : ''} - ${error.statusMessage ? error.statusMessage : ''} - ${errorResponseObj}`) | ||
} | ||
@@ -298,0 +287,0 @@ |
@@ -46,7 +46,5 @@ const test = require('tape') | ||
const testInstantiation = (t, params, expectedCode, expectedMessage) => { | ||
t.plan(4) | ||
let failedClient | ||
try { | ||
failedClient = new FBJWTClient(...params) | ||
t.throws(failedClient = new FBJWTClient(...params)) | ||
} catch (e) { | ||
@@ -58,2 +56,3 @@ t.equal(e.name, 'FBJWTClientError', 'it should return an error of the correct type') | ||
t.equal(failedClient, undefined, 'it should not return an instantiated client') | ||
t.end() | ||
} | ||
@@ -78,10 +77,9 @@ | ||
test('When instantiating client with a custom error', t => { | ||
t.plan(1) | ||
class MyError extends FBJWTClient.prototype.ErrorClass { } | ||
try { | ||
const jwtClient = new FBJWTClient(null, serviceToken, serviceSlug, microserviceUrl, MyError) // eslint-disable-line no-unused-vars | ||
t.throws(new FBJWTClient(null, serviceToken, serviceSlug, microserviceUrl, MyError)) | ||
} catch (e) { | ||
t.equal(e.name, 'MyError', 'it should use the error class passed') | ||
} | ||
t.end() | ||
}) | ||
@@ -92,34 +90,13 @@ | ||
// Injecting mwtrics instrumentation | ||
test('When asking for endpoint urls', t => { | ||
const histogramStub = stub() | ||
const prometheusClient = { | ||
Histogram: histogramStub | ||
} | ||
// Injecting metrics instrumentation | ||
test('When injecting metrics instrumentation', t => { | ||
const apiMetrics = {} | ||
const requestMetrics = {} | ||
const jwtClient = new FBJWTClient(serviceSecret, serviceToken, serviceSlug, microserviceUrl) | ||
jwtClient.setMetricsInstrumentation(prometheusClient) | ||
const metricsClient = new FBJWTClient(serviceSecret, serviceToken, serviceSlug, microserviceUrl) | ||
metricsClient.setMetricsInstrumentation(apiMetrics, requestMetrics) | ||
const apiMetricsArgs = histogramStub.getCall(0).args[0] | ||
const requestMetricsArgs = histogramStub.getCall(1).args[0] | ||
t.equal(metricsClient.apiMetrics, apiMetrics, 'it should update the apiMetrics method') | ||
t.equal(metricsClient.requestMetrics, requestMetrics, 'it should update the apiMetrics method') | ||
const labelNames = ['client_name', 'base_url', 'url', 'method', 'status_code', 'status_message', 'error_name'] | ||
const buckets = [0.1, 0.25, 0.5, 1, 2, 5, 10] | ||
t.ok(histogramStub.calledTwice, 'it should have been called Histogram twice') | ||
t.deepEqual(apiMetricsArgs, { | ||
name: 'api_requests', | ||
help: 'API calls using FB JWT Client', | ||
labelNames, | ||
buckets | ||
}, 'it should set up the client api metrics histogram with the correct args') | ||
t.deepEqual(requestMetricsArgs, { | ||
name: 'jwt_client_requests', | ||
help: 'HTTP requests using FB JWT Client', | ||
labelNames, | ||
buckets | ||
}, 'it it should set up the client request metrics histogram with the correct args') | ||
t.end() | ||
@@ -182,6 +159,4 @@ }) | ||
test('When decrypting invalid data', async t => { | ||
t.plan(4) | ||
let invalidData | ||
try { | ||
invalidData = jwtClient.decrypt(userToken, 'invalid') | ||
t.throws(jwtClient.decrypt(userToken, 'invalid')) | ||
} catch (e) { | ||
@@ -192,3 +167,2 @@ t.equal(e.name, 'FBJWTClientError', 'it should return an error object of the correct type') | ||
} | ||
t.equal(invalidData, undefined, 'it should not return anything if data is invalid') | ||
@@ -243,6 +217,4 @@ t.end() | ||
test('When decrypting invalid user ID and token', async t => { | ||
t.plan(4) | ||
let invalidData | ||
try { | ||
invalidData = jwtClient.decryptUserIdAndToken(userToken, 'invalid') | ||
t.throws(jwtClient.decryptUserIdAndToken(userToken, 'invalid')) | ||
} catch (e) { | ||
@@ -253,3 +225,2 @@ t.equal(e.name, 'FBJWTClientError', 'it should return an error object of the correct type') | ||
} | ||
t.equal(invalidData, undefined, 'it should not return anything if data is invalid') | ||
@@ -261,4 +232,2 @@ t.end() | ||
test('When sending gets', async t => { | ||
t.plan(5) | ||
const stubAccessToken = stub(jwtClient, 'generateAccessToken') | ||
@@ -304,4 +273,2 @@ stubAccessToken.callsFake(() => 'testAccessToken') | ||
test('When sending posts', async t => { | ||
t.plan(4) | ||
const gotStub = stub(got, 'post') | ||
@@ -392,5 +359,5 @@ gotStub.callsFake(options => { | ||
try { | ||
await nockedClient.send('get', { | ||
t.throws(await nockedClient.send('get', { | ||
url: '/notfound' | ||
}, {error: () => {}}) | ||
}, {error: () => {}})) | ||
} catch (e) { | ||
@@ -442,6 +409,8 @@ // | ||
try { | ||
await retryClient.send('get', { | ||
t.throws(await retryClient.send('get', { | ||
url: '/missing', | ||
sendOptions: {retry: {retries}} | ||
}, {error: () => {}}) | ||
sendOptions: { | ||
retry: {retries} | ||
} | ||
}, {error: () => {}})) | ||
} catch (e) { | ||
@@ -579,6 +548,4 @@ // | ||
t.plan(4) | ||
let decryptedData | ||
try { | ||
decryptedData = await clientMethod() | ||
t.throws(await clientMethod()) | ||
} catch (e) { | ||
@@ -589,5 +556,5 @@ t.equal(e.name, 'FBJWTClientError', 'it should return an error object of the correct type') | ||
} | ||
t.equal(decryptedData, undefined, 'it should not return a value for the data') | ||
gotStub.restore() | ||
t.end() | ||
} | ||
@@ -683,3 +650,2 @@ | ||
test('When making a request and both a status code and an error object containing a name are present', async t => { | ||
t.plan(3) | ||
const gotStub = stub(got, 'get') | ||
@@ -698,5 +664,3 @@ gotStub.callsFake(options => { | ||
try { | ||
await jwtClient.sendGet({ | ||
url: '/url' | ||
}) | ||
t.throws(await jwtClient.sendGet({url: '/url'})) | ||
} catch (e) { | ||
@@ -707,7 +671,8 @@ t.equals(e.name, 'FBJWTClientError', 'it should use the name specified in the error object as the message') | ||
} | ||
gotStub.restore() | ||
t.end() | ||
}) | ||
test('When making a request and both a status code and an error object with a code but no name are present', async t => { | ||
t.plan(1) | ||
const gotStub = stub(got, 'get') | ||
@@ -724,13 +689,12 @@ gotStub.callsFake(options => { | ||
try { | ||
await jwtClient.sendGet({ | ||
url: '/url' | ||
}) | ||
t.throws(await jwtClient.sendGet({url: '/url'})) | ||
} catch (e) { | ||
t.equals(e.message, 409, 'it should use the code specified in the error object as the message') | ||
} | ||
gotStub.restore() | ||
t.end() | ||
}) | ||
test('When making a request and both a status code and an error object with no name and no code are present', async t => { | ||
t.plan(1) | ||
const gotStub = stub(got, 'get') | ||
@@ -747,9 +711,9 @@ gotStub.callsFake(options => { | ||
try { | ||
await jwtClient.sendGet({ | ||
url: '/url' | ||
}) | ||
t.throws(await jwtClient.sendGet({url: '/url'})) | ||
} catch (e) { | ||
t.equals(e.message, 'EUNSPECIFIED', 'it should use ‘EUNSPECIFIED‘ as the message') | ||
} | ||
gotStub.restore() | ||
t.end() | ||
}) | ||
@@ -762,6 +726,7 @@ | ||
try { | ||
jwtClient.handleRequestError(thrown) | ||
t.throws(jwtClient.handleRequestError(thrown)) | ||
} catch (e) { | ||
t.equal(e, thrown, 'it should rethrow the error as is') | ||
} | ||
t.end() | ||
@@ -773,3 +738,2 @@ }) | ||
test('When a get request results in an error and a logger instance has been provided', async t => { | ||
t.plan(3) | ||
const gotStub = stub(got, 'get') | ||
@@ -795,5 +759,3 @@ let error = new Error() | ||
try { | ||
await jwtClient.sendGet({ | ||
url: '/url' | ||
}, logger) | ||
t.throws(await jwtClient.sendGet({url: '/url'}, logger)) | ||
} catch (e) { | ||
@@ -812,10 +774,16 @@ const callArgs = logErrorStub.getCall(0).args | ||
} | ||
gotStub.restore() | ||
logErrorStub.resetHistory() | ||
t.end() | ||
}) | ||
test('When a post request results in an error and a logger instance has been provided', async t => { | ||
t.plan(3) | ||
const gotStub = stub(got, 'post') | ||
let error = new Error() | ||
error.gotOptions = { | ||
headers: { | ||
'x-something': 'x-something-value' | ||
} | ||
} | ||
gotStub.callsFake(options => { | ||
@@ -831,5 +799,3 @@ return Promise.reject(error) | ||
try { | ||
await jwtClient.sendPost({ | ||
url: '/url' | ||
}, logger) | ||
t.throws(await jwtClient.sendPost({url: '/url'}, logger)) | ||
} catch (e) { | ||
@@ -848,3 +814,5 @@ const callArgs = logErrorStub.getCall(0).args | ||
} | ||
gotStub.restore() | ||
t.end() | ||
}) |
{ | ||
"name": "@ministryofjustice/fb-jwt-client-node", | ||
"version": "0.0.26", | ||
"version": "0.0.27", | ||
"description": "Form Builder JSON Web Token Client (Node)", | ||
@@ -5,0 +5,0 @@ "main": "lib/fb-jwt-client.js", |
56754
1497