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

test: Converted the api unit tests to node:test #2516

Merged
merged 1 commit into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading