Skip to content

Commit

Permalink
test: Converted the api unit tests to node:test (#2516)
Browse files Browse the repository at this point in the history
  • Loading branch information
bizob2828 authored Aug 27, 2024
1 parent 9363eb0 commit ab91576
Show file tree
Hide file tree
Showing 34 changed files with 1,936 additions and 1,940 deletions.
2 changes: 1 addition & 1 deletion test/lib/agent_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ let _agent = null
let _agentApi = null
const tasks = []
// Load custom tap assertions
require('./custom-assertions')
require('./custom-tap-assertions')

const helper = module.exports

Expand Down
41 changes: 22 additions & 19 deletions test/lib/custom-assertions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@
*/

'use strict'
const tap = require('tap')
tap.Test.prototype.addAssert('clmAttrs', 1, assertCLMAttrs)
tap.Test.prototype.addAssert('isNonWritable', 1, isNonWritable)
tap.Test.prototype.addAssert('compareSegments', 2, compareSegments)
tap.Test.prototype.addAssert('exactClmAttrs', 2, assertExactClmAttrs)
const assert = require('node:assert')

function assertExactClmAttrs(segmentStub, expectedAttrs) {
const attrs = segmentStub.addAttribute.args
const attrsObj = attrs.reduce((obj, [key, value]) => {
obj[key] = value
return obj
}, {})
this.same(attrsObj, expectedAttrs, 'CLM attrs should match')
assert.deepEqual(attrsObj, expectedAttrs, 'CLM attrs should match')
}

/**
Expand All @@ -31,21 +27,21 @@ function assertCLMAttrs({ segments, enabled: clmEnabled, skipFull = false }) {
segments.forEach((segment) => {
const attrs = segment.segment.getAttributes()
if (clmEnabled) {
this.equal(attrs['code.function'], segment.name, 'should have appropriate code.function')
this.ok(
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 (!skipFull) {
this.match(attrs['code.lineno'], /[\d]+/, 'lineno should be a number')
this.match(attrs['code.column'], /[\d]+/, 'column should be a number')
assert.equal(typeof attrs['code.lineno'], 'number', 'lineno should be a number')
assert.equal(typeof attrs['code.column'], 'number', 'column should be a number')
}
} else {
this.notOk(attrs['code.function'], 'function should not exist')
this.notOk(attrs['code.filepath'], 'filepath should not exist')
this.notOk(attrs['code.lineno'], 'lineno should not exist')
this.notOk(attrs['code.column'], 'column should not exist')
assert.ok(!attrs['code.function'], 'function should not exist')
assert.ok(!attrs['code.filepath'], 'filepath should not exist')
assert.ok(!attrs['code.lineno'], 'lineno should not exist')
assert.ok(!attrs['code.column'], 'column should not exist')
}
})
}
Expand All @@ -59,14 +55,14 @@ function assertCLMAttrs({ segments, enabled: clmEnabled, skipFull = false }) {
* @param {string} params.value expected value of obj[key]
*/
function isNonWritable({ obj, key, value }) {
this.throws(function () {
assert.throws(function () {
obj[key] = 'testNonWritable test value'
}, new RegExp("(read only property '" + key + "'|Cannot set property " + key + ')'))

if (value) {
this.equal(obj[key], value)
assert.equal(obj[key], value)
} else {
this.not(obj[key], 'testNonWritable test value', 'should not set value when non-writable')
assert.ok(!obj[key], 'testNonWritable test value', 'should not set value when non-writable')
}
}

Expand All @@ -78,8 +74,15 @@ function isNonWritable({ obj, key, value }) {
* @param {Array} segments list of expected segments
*/
function compareSegments(parent, segments) {
this.ok(parent.children.length, segments.length, 'should be the same amount of children')
assert.ok(parent.children.length, segments.length, 'should be the same amount of children')
segments.forEach((segment, index) => {
this.equal(parent.children[index].id, segment.id, 'should have same ids')
assert.equal(parent.children[index].id, segment.id, 'should have same ids')
})
}

module.exports = {
assertCLMAttrs,
assertExactClmAttrs,
compareSegments,
isNonWritable
}
85 changes: 85 additions & 0 deletions test/lib/custom-tap-assertions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright 2023 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

'use strict'
const tap = require('tap')
tap.Test.prototype.addAssert('clmAttrs', 1, assertCLMAttrs)
tap.Test.prototype.addAssert('isNonWritable', 1, isNonWritable)
tap.Test.prototype.addAssert('compareSegments', 2, compareSegments)
tap.Test.prototype.addAssert('exactClmAttrs', 2, assertExactClmAttrs)

function assertExactClmAttrs(segmentStub, expectedAttrs) {
const attrs = segmentStub.addAttribute.args
const attrsObj = attrs.reduce((obj, [key, value]) => {
obj[key] = value
return obj
}, {})
this.same(attrsObj, expectedAttrs, 'CLM attrs should match')
}

/**
* Asserts the appropriate Code Level Metrics attributes on a segment
*
* @param {object} params
* @param {object} params.segments list of segments to assert { segment, filepath, name }
* @param {boolean} params.enabled if CLM is enabled or not
* @param {boolean} params.skipFull flag to skip asserting `code.lineno` and `code.column`
*/
function assertCLMAttrs({ segments, enabled: clmEnabled, skipFull = false }) {
segments.forEach((segment) => {
const attrs = segment.segment.getAttributes()
if (clmEnabled) {
this.equal(attrs['code.function'], segment.name, 'should have appropriate code.function')
this.ok(
attrs['code.filepath'].endsWith(segment.filepath),
'should have appropriate code.filepath'
)

if (!skipFull) {
this.match(attrs['code.lineno'], /[\d]+/, 'lineno should be a number')
this.match(attrs['code.column'], /[\d]+/, 'column should be a number')
}
} else {
this.notOk(attrs['code.function'], 'function should not exist')
this.notOk(attrs['code.filepath'], 'filepath should not exist')
this.notOk(attrs['code.lineno'], 'lineno should not exist')
this.notOk(attrs['code.column'], 'column should not exist')
}
})
}

/**
* assertion to test if a property is non-writable
*
* @param {Object} params
* @param {Object} params.obj obj to assign value
* @param {string} params.key key to assign value
* @param {string} params.value expected value of obj[key]
*/
function isNonWritable({ obj, key, value }) {
this.throws(function () {
obj[key] = 'testNonWritable test value'
}, new RegExp("(read only property '" + key + "'|Cannot set property " + key + ')'))

if (value) {
this.equal(obj[key], value)
} else {
this.not(obj[key], 'testNonWritable test value', 'should not set value when non-writable')
}
}

/**
* Verifies the expected length of children segments and that every
* id matches between a segment array and the children
*
* @param {Object} parent trace
* @param {Array} segments list of expected segments
*/
function compareSegments(parent, segments) {
this.ok(parent.children.length, segments.length, 'should be the same amount of children')
segments.forEach((segment, index) => {
this.equal(parent.children[index].id, segment.id, 'should have same ids')
})
}
99 changes: 51 additions & 48 deletions test/unit/api/api-add-ignoring-rule.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,104 +5,107 @@

'use strict'

const tap = require('tap')
const test = require('node:test')
const assert = require('node:assert')
const API = require('../../../api')
const helper = require('../../lib/agent_helper')

tap.test('Agent API - addIgnoringRule', (t) => {
t.autoend()

let agent = null
let api = null

test('Agent API - addIgnoringRule', async (t) => {
const TEST_URL = '/test/path/31337'
const NAME = 'WebTransaction/Uri/test/path/31337'

t.beforeEach(() => {
agent = helper.loadMockedAgent()
api = new API(agent)
t.beforeEach((ctx) => {
ctx.nr = {}
const agent = helper.loadMockedAgent()
ctx.nr.api = new API(agent)
ctx.nr.agent = agent
})

t.afterEach(() => {
helper.unloadAgent(agent)
agent = null
t.afterEach((ctx) => {
helper.unloadAgent(ctx.nr.agent)
})

t.test('exports a function for ignoring certain URLs', (t) => {
t.ok(api.addIgnoringRule)
t.type(api.addIgnoringRule, 'function')

t.end()
await t.test('exports a function for ignoring certain URLs', (t) => {
const { api } = t.nr
assert.ok(api.addIgnoringRule)
assert.equal(typeof api.addIgnoringRule, 'function')
})

t.test("should add it to the agent's normalizer", (t) => {
t.equal(agent.userNormalizer.rules.length, 1) // default ignore rule
await t.test("should add it to the agent's normalizer", (t) => {
const { agent, api } = t.nr
assert.equal(agent.userNormalizer.rules.length, 1) // default ignore rule
api.addIgnoringRule('^/simple.*')
t.equal(agent.userNormalizer.rules.length, 2)

t.end()
assert.equal(agent.userNormalizer.rules.length, 2)
})

t.test("should add it to the agent's normalizer", (t) => {
await t.test("should add it to the agent's normalizer", (t, end) => {
const { agent, api } = t.nr
addIgnoringRuleGoldenPath(agent, api, () => {
t.equal(agent.urlNormalizer.rules.length, 3)
t.equal(agent.userNormalizer.rules.length, 1 + 1) // +1 default rule
assert.equal(agent.urlNormalizer.rules.length, 3)
assert.equal(agent.userNormalizer.rules.length, 1 + 1) // +1 default rule

t.end()
end()
})
})

t.test('should leave the passed-in pattern alone', (t) => {
await t.test('should leave the passed-in pattern alone', (t, end) => {
const { agent, api } = t.nr
addIgnoringRuleGoldenPath(agent, api, (mine) => {
t.equal(mine.pattern.source, '^\\/test\\/.*')
t.end()
assert.equal(mine.pattern.source, '^\\/test\\/.*')
end()
})
})

t.test('should have the correct replacement', (t) => {
await t.test('should have the correct replacement', (t, end) => {
const { agent, api } = t.nr
addIgnoringRuleGoldenPath(agent, api, (mine) => {
t.equal(mine.replacement, '$0')
t.end()
assert.equal(mine.replacement, '$0')
end()
})
})

t.test('should set it to highest precedence', (t) => {
await t.test('should set it to highest precedence', (t, end) => {
const { agent, api } = t.nr
addIgnoringRuleGoldenPath(agent, api, (mine) => {
t.equal(mine.precedence, 0)
t.end()
assert.equal(mine.precedence, 0)
end()
})
})

t.test('should end further normalization', (t) => {
await t.test('should end further normalization', (t, end) => {
const { agent, api } = t.nr
addIgnoringRuleGoldenPath(agent, api, (mine) => {
t.equal(mine.isTerminal, true)
t.end()
assert.equal(mine.isTerminal, true)
end()
})
})

t.test('should only apply it to the whole URL', (t) => {
await t.test('should only apply it to the whole URL', (t, end) => {
const { agent, api } = t.nr
addIgnoringRuleGoldenPath(agent, api, (mine) => {
t.equal(mine.eachSegment, false)
t.end()
assert.equal(mine.eachSegment, false)
end()
})
})

t.test('should ignore transactions related to that URL', (t) => {
await t.test('should ignore transactions related to that URL', (t, end) => {
const { agent, api } = t.nr
addIgnoringRuleGoldenPath(agent, api, (mine) => {
t.equal(mine.ignore, true)
t.end()
assert.equal(mine.ignore, true)
end()
})
})

t.test('applies a string pattern correctly', (t) => {
await t.test('applies a string pattern correctly', (t, end) => {
const { agent, api } = t.nr
api.addIgnoringRule('^/test/.*')

agent.on('transactionFinished', function (transaction) {
transaction.finalizeNameFromUri(TEST_URL, 200)

t.equal(transaction.ignore, true)
assert.equal(transaction.ignore, true)

t.end()
end()
})

helper.runInTransaction(agent, function (transaction) {
Expand Down
Loading

0 comments on commit ab91576

Please sign in to comment.