Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Converted collector unit tests to node:test #2510

Merged
merged 12 commits into from
Sep 4, 2024
57 changes: 57 additions & 0 deletions test/lib/assert-metrics.js
bizob2828 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2024 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

'use strict'

module.exports = {
assertMetricValues
}

const assert = require('node:assert')

/**
* @param {Transaction} transaction Nodejs agent transaction
* @param {Array} expected Array of metric data where metric data is in this form:
* [
* {
* “name”:”name of metric”,
* “scope”:”scope of metric”,
* },
* [count,
* total time,
* exclusive time,
* min time,
* max time,
* sum of squares]
* ]
* @param {boolean} exact When true, found and expected metric lengths should match
*/
function assertMetricValues(transaction, expected, exact) {
const metrics = transaction.metrics

for (let i = 0; i < expected.length; ++i) {
let expectedMetric = Object.assign({}, expected[i])
let name = null
let scope = null

if (typeof expectedMetric === 'string') {
name = expectedMetric
expectedMetric = {}
} else {
name = expectedMetric[0].name
scope = expectedMetric[0].scope
}

const metric = metrics.getMetric(name, scope)
assert.ok(metric, 'should have expected metric name')

assert.deepStrictEqual(metric.toJSON(), expectedMetric[1], 'metric values should match')
}

if (exact) {
const metricsJSON = metrics.toJSON()
assert.equal(metricsJSON.length, expected.length, 'metrics length should match')
}
}
53 changes: 46 additions & 7 deletions test/lib/test-collector.js
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of quality-of-life improvements to increase the usefulness of this tool.

Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ class Collector {
#handlers = new Map()
#server
#address
#runId

constructor() {
constructor({ runId = 42 } = {}) {
this.#runId = runId
this.#server = https.createServer({
key: fakeCert.privateKey,
cert: fakeCert.certificate
Expand All @@ -37,6 +39,27 @@ class Collector {
this.end(JSON.stringify(payload))
}

req.body = function () {
let resolve
let reject
const promise = new Promise((res, rej) => {
resolve = res
reject = rej
})

let data = ''
this.on('data', (d) => {
data += d
})
this.on('end', () => {
resolve(data)
})
this.on('error', (error) => {
reject(error)
})
return promise
}

handler.isDone = true
handler(req, res)
})
Expand Down Expand Up @@ -104,6 +127,19 @@ class Collector {
}
}

/**
* the most basic `connect` handler. Useful when you do not need to
* customize the handler.
*
* @returns {function}
*/
get connectHandler() {
const runId = this.#runId
return function (req, res) {
res.json({ payload: { return_value: { agent_run_id: runId } } })
}
}

/**
* The most basic `preconnect` handler. Useful when you do not need to
* customize the handler.
Expand Down Expand Up @@ -135,7 +171,9 @@ class Collector {
* requests.
* @param {function} handler A typical `(req, res) => {}` handler. For
* convenience, `res` is extended with a `json({ payload, code = 200 })`
* method for easily sending JSON responses.
* method for easily sending JSON responses. Also, `req` is extended with
* a `body()` method that returns a promise which resolves to the string
* data supplied via POST-like requests.
*/
addHandler(endpoint, handler) {
const qs = querystring.decode(endpoint.slice(endpoint.indexOf('?') + 1))
Expand Down Expand Up @@ -181,11 +219,12 @@ class Collector {
// Add handlers for the required agent startup connections. These should
// be overwritten by tests that exercise the startup phase, but adding these
// stubs makes it easier to test other connection events.
this.addHandler(helper.generateCollectorPath('preconnect', 42), this.preconnectHandler)
this.addHandler(helper.generateCollectorPath('connect', 42), (req, res) => {
res.json({ payload: { return_value: { agent_run_id: 42 } } })
})
this.addHandler(helper.generateCollectorPath('agent_settings', 42), this.agentSettingsHandler)
this.addHandler(helper.generateCollectorPath('preconnect', this.#runId), this.preconnectHandler)
this.addHandler(helper.generateCollectorPath('connect', this.#runId), this.connectHandler)
this.addHandler(
helper.generateCollectorPath('agent_settings', this.#runId),
this.agentSettingsHandler
)

return address
}
Expand Down
Loading
Loading