Skip to content

Commit

Permalink
chore: Migrate fastify tests to node:test (#2632)
Browse files Browse the repository at this point in the history
Co-authored-by: Bob Evans <robert.evans25@gmail.com>
  • Loading branch information
jsumners-nr and bizob2828 authored Oct 4, 2024
1 parent 7e34062 commit b522477
Show file tree
Hide file tree
Showing 19 changed files with 798 additions and 721 deletions.
16 changes: 12 additions & 4 deletions test/lib/custom-assertions.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,18 @@ function assertCLMAttrs({ segments, enabled: clmEnabled, skipFull = false }) {
const attrs = segment.segment.getAttributes()
if (clmEnabled) {
assert.equal(attrs['code.function'], segment.name, 'should have appropriate code.function')
assert.ok(
attrs['code.filepath'].endsWith(segment.filepath),
'should have appropriate code.filepath'
)
if (segment.filepath instanceof RegExp) {
assert.match(
attrs['code.filepath'],
segment.filepath,
'should have appropriate code.filepath'
)
} else {
assert.ok(
attrs['code.filepath'].endsWith(segment.filepath),
'should have appropriate code.filepath'
)
}

if (!skipFull) {
assert.equal(typeof attrs['code.lineno'], 'number', 'lineno should be a number')
Expand Down
178 changes: 0 additions & 178 deletions test/versioned/fastify/add-hook.tap.js

This file was deleted.

187 changes: 187 additions & 0 deletions test/versioned/fastify/add-hook.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/*
* Copyright 2024 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

'use strict'

const test = require('node:test')
const assert = require('node:assert')

const { removeModules } = require('../../lib/cache-buster')
const { assertSegments } = require('../../lib/custom-assertions')
const helper = require('../../lib/agent_helper')
const common = require('./common')

// all of these events fire before the route handler
// See: https://www.fastify.io/docs/latest/Lifecycle/
// for more info on sequence
const REQUEST_HOOKS = ['onRequest', 'preParsing', 'preValidation', 'preHandler']

// these events fire after the route
// handler. they are in separate arrays
// for segment relationship assertions later
const AFTER_HANDLER_HOOKS = ['preSerialization', 'onSend']

// the onResponse hook fires after a response
// is received by client which is out of context
// of the transaction
const AFTER_TX_HOOKS = ['onResponse']

const ALL_HOOKS = [...REQUEST_HOOKS, ...AFTER_HANDLER_HOOKS, ...AFTER_TX_HOOKS]

/**
* Helper to return the list of expected segments
*
* @param {Array} hooks lifecyle hook names to build segment names from
* @returns {Array} formatted list of expected segments
*/
function getExpectedSegments(hooks) {
return hooks.map((hookName) => {
return `Nodejs/Middleware/Fastify/${hookName}/testHook`
})
}

test.beforeEach((ctx) => {
ctx.nr = {}
ctx.nr.agent = helper.instrumentMockedAgent()

const fastify = require('fastify')()
common.setupRoutes(fastify)
ctx.nr.fastify = fastify
})

test.afterEach((ctx) => {
helper.unloadAgent(ctx.nr.agent)
ctx.nr.fastify.close()
removeModules(['fastify'])
})

test('non-error hooks', async (t) => {
const { fastify, agent } = t.nr

// setup hooks
const ok = ALL_HOOKS.reduce((all, hookName) => {
all[hookName] = false
return all
}, {})

ALL_HOOKS.forEach((hookName) => {
fastify.addHook(hookName, function testHook(...args) {
// lifecycle signatures vary between the events
// the last arg is always the next function though
const next = args[args.length - 1]
ok[hookName] = true
next()
})
})

let txPassed = false
agent.on('transactionFinished', (transaction) => {
assert.equal(
'WebFrameworkUri/Fastify/GET//add-hook',
transaction.getName(),
`transaction name matched`
)
// all the hooks are siblings of the route handler
// except the AFTER_HANDLER_HOOKS which are children of the route handler
let expectedSegments
if (helper.isSecurityAgentEnabled(agent)) {
expectedSegments = [
'WebTransaction/WebFrameworkUri/Fastify/GET//add-hook',
[
'Nodejs/Middleware/Fastify/onRequest/<anonymous>',
[
...getExpectedSegments(REQUEST_HOOKS),
'Nodejs/Middleware/Fastify/routeHandler//add-hook',
getExpectedSegments(AFTER_HANDLER_HOOKS)
]
]
]
} else {
expectedSegments = [
'WebTransaction/WebFrameworkUri/Fastify/GET//add-hook',
[
...getExpectedSegments(REQUEST_HOOKS),
'Nodejs/Middleware/Fastify/routeHandler//add-hook',
getExpectedSegments(AFTER_HANDLER_HOOKS)
]
]
}
assertSegments(transaction.trace.root, expectedSegments)

txPassed = true
})

await fastify.listen({ port: 0 })
const address = fastify.server.address()
const result = await common.makeRequest(address, '/add-hook')
assert.deepEqual(result, { hello: 'world' })

// verify every hook was called after response
for (const [hookName, isOk] of Object.entries(ok)) {
assert.equal(isOk, true, `${hookName} captured`)
}

assert.equal(txPassed, true, 'transactionFinished assertions passed')
})

test('error hook', async function errorHookTest(t) {
const { fastify, agent } = t.nr

const hookName = 'onError'
let ok = false

fastify.addHook(hookName, function testHook(req, reply, err, next) {
assert.equal(err.message, 'test onError hook', 'error message correct')
ok = true
next()
})

let txPassed = false
agent.on('transactionFinished', (transaction) => {
assert.equal(
'WebFrameworkUri/Fastify/GET//error',
transaction.getName(),
`transaction name matched`
)
// all the hooks are siblings of the route handler
let expectedSegments
if (helper.isSecurityAgentEnabled(agent)) {
expectedSegments = [
'WebTransaction/WebFrameworkUri/Fastify/GET//error',
[
'Nodejs/Middleware/Fastify/onRequest/<anonymous>',
[
'Nodejs/Middleware/Fastify/errorRoute//error',
[`Nodejs/Middleware/Fastify/${hookName}/testHook`]
]
]
]
} else {
expectedSegments = [
'WebTransaction/WebFrameworkUri/Fastify/GET//error',
[
'Nodejs/Middleware/Fastify/errorRoute//error',
[`Nodejs/Middleware/Fastify/${hookName}/testHook`]
]
]
}

assertSegments(transaction.trace.root, expectedSegments)

txPassed = true
})

await fastify.listen({ port: 0 })
const address = fastify.server.address()
const result = await common.makeRequest(address, '/error')
assert.ok(ok)
assert.deepEqual(result, {
statusCode: 500,
error: 'Internal Server Error',
message: 'test onError hook'
})

assert.equal(txPassed, true, 'transactionFinished assertions passed')
})
Loading

0 comments on commit b522477

Please sign in to comment.