diff --git a/test/lib/agent_helper.js b/test/lib/agent_helper.js index f1a9d964a5..2c55f736bc 100644 --- a/test/lib/agent_helper.js +++ b/test/lib/agent_helper.js @@ -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 diff --git a/test/lib/custom-assertions.js b/test/lib/custom-assertions.js index 78be0f138c..ac67506a82 100644 --- a/test/lib/custom-assertions.js +++ b/test/lib/custom-assertions.js @@ -4,11 +4,7 @@ */ '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 @@ -16,7 +12,7 @@ function assertExactClmAttrs(segmentStub, expectedAttrs) { obj[key] = value return obj }, {}) - this.same(attrsObj, expectedAttrs, 'CLM attrs should match') + assert.deepEqual(attrsObj, expectedAttrs, 'CLM attrs should match') } /** @@ -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') } }) } @@ -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') } } @@ -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 +} diff --git a/test/lib/custom-tap-assertions.js b/test/lib/custom-tap-assertions.js new file mode 100644 index 0000000000..78be0f138c --- /dev/null +++ b/test/lib/custom-tap-assertions.js @@ -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') + }) +} diff --git a/test/unit/api/api-add-ignoring-rule.test.js b/test/unit/api/api-add-ignoring-rule.test.js index f6e2fdc03a..c6259aa288 100644 --- a/test/unit/api/api-add-ignoring-rule.test.js +++ b/test/unit/api/api-add-ignoring-rule.test.js @@ -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) { diff --git a/test/unit/api/api-add-naming-rule.test.js b/test/unit/api/api-add-naming-rule.test.js index c9136341ba..07eec4c3bb 100644 --- a/test/unit/api/api-add-naming-rule.test.js +++ b/test/unit/api/api-add-naming-rule.test.js @@ -5,97 +5,103 @@ '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 - addNamingRule', (t) => { - t.autoend() - - let agent = null - let api = null - +test('Agent API - addNamingRule', 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 adding naming rules', (t) => { - t.ok(api.addNamingRule) - t.type(api.addNamingRule, 'function') + await t.test('exports a function for adding naming rules', (t, end) => { + const { api } = t.nr + assert.ok(api.addNamingRule) + assert.equal(typeof api.addNamingRule, 'function') - t.end() + end() }) - 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, end) => { + const { agent, api } = t.nr + assert.equal(agent.userNormalizer.rules.length, 1) // default ignore rule api.addNamingRule('^/simple.*', 'API') - t.equal(agent.userNormalizer.rules.length, 2) + assert.equal(agent.userNormalizer.rules.length, 2) - t.end() + end() }) - 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 addNamingRuleGoldenPath(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 addNamingRuleGoldenPath(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 addNamingRuleGoldenPath(agent, api, (mine) => { - t.equal(mine.replacement, '/Test') - t.end() + assert.equal(mine.replacement, '/Test') + 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 addNamingRuleGoldenPath(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 addNamingRuleGoldenPath(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 addNamingRuleGoldenPath(agent, api, (mine) => { - t.equal(mine.eachSegment, false) - t.end() + assert.equal(mine.eachSegment, false) + 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.addNamingRule('^/test/.*', 'Test') agent.on('transactionFinished', function (transaction) { transaction.finalizeNameFromUri(TEST_URL, 200) - t.equal(transaction.name, 'WebTransaction/NormalizedUri/Test') + assert.equal(transaction.name, 'WebTransaction/NormalizedUri/Test') - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { @@ -107,15 +113,16 @@ tap.test('Agent API - addNamingRule', (t) => { }) }) - t.test('applies a regex pattern with capture groups correctly', (t) => { + await t.test('applies a regex pattern with capture groups correctly', (t, end) => { + const { agent, api } = t.nr api.addNamingRule(/^\/test\/(.*)\/(.*)/, 'Test/$2') agent.on('transactionFinished', function (transaction) { transaction.finalizeNameFromUri('/test/31337/related', 200) - t.equal(transaction.name, 'WebTransaction/NormalizedUri/Test/related') + assert.equal(transaction.name, 'WebTransaction/NormalizedUri/Test/related') - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { diff --git a/test/unit/api/api-custom-attributes.test.js b/test/unit/api/api-custom-attributes.test.js index 0bbcb4c8e4..ba50a38d0e 100644 --- a/test/unit/api/api-custom-attributes.test.js +++ b/test/unit/api/api-custom-attributes.test.js @@ -4,58 +4,59 @@ */ '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') const SpanEvent = require('../../../lib/spans/span-event') const DESTINATIONS = require('../../../lib/config/attribute-filter').DESTINATIONS -tap.test('Agent API - custom attributes', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() +test('Agent API - custom attributes', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.loadMockedAgent() agent.config.attributes.enabled = true agent.config.distributed_tracing.enabled = true - api = new API(agent) + 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 adding multiple custom attributes at once', (t) => { - t.ok(api.addCustomAttributes) - t.type(api.addCustomAttributes, 'function') - t.end() + await t.test('exports a function for adding multiple custom attributes at once', (t, end) => { + const { api } = t.nr + assert.ok(api.addCustomAttributes) + assert.equal(typeof api.addCustomAttributes, 'function') + end() }) - t.test("shouldn't blow up without a transaction", (t) => { - // should not throw - api.addCustomAttribute('TestName', 'TestValue') - t.end() + await t.test("shouldn't blow up without a transaction", (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { + api.addCustomAttribute('TestName', 'TestValue') + }) + end() }) - t.test('should properly add custom attributes', (t) => { + await t.test('should properly add custom attributes', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function (transaction) { api.addCustomAttribute('test', 1) const attributes = transaction.trace.custom.get(DESTINATIONS.TRANS_TRACE) - t.equal(attributes.test, 1) + assert.equal(attributes.test, 1) transaction.end() - t.end() + end() }) }) - t.test('should skip if attribute key length limit is exceeded', (t) => { + await t.test('should skip if attribute key length limit is exceeded', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function (transaction) { const tooLong = [ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', @@ -68,14 +69,15 @@ tap.test('Agent API - custom attributes', (t) => { const attributes = transaction.trace.custom.get(DESTINATIONS.TRANS_TRACE) const hasTooLong = Object.hasOwnProperty.call(attributes, 'tooLong') - t.notOk(hasTooLong) + assert.ok(!hasTooLong) transaction.end() - t.end() + end() }) }) - t.test('should properly add multiple custom attributes', (t) => { + await t.test('should properly add multiple custom attributes', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function (transaction) { api.addCustomAttributes({ one: 1, @@ -83,30 +85,32 @@ tap.test('Agent API - custom attributes', (t) => { }) const attributes = transaction.trace.custom.get(DESTINATIONS.TRANS_TRACE) - t.equal(attributes.one, 1) - t.equal(attributes.two, 2) + assert.equal(attributes.one, 1) + assert.equal(attributes.two, 2) transaction.end() - t.end() + end() }) }) - t.test('should not add custom attributes when disabled', (t) => { + await t.test('should not add custom attributes when disabled', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function (transaction) { agent.config.api.custom_attributes_enabled = false api.addCustomAttribute('test', 1) const attributes = transaction.trace.custom.get(DESTINATIONS.TRANS_TRACE) const hasTest = Object.hasOwnProperty.call(attributes, 'test') - t.notOk(hasTest) + assert.ok(!hasTest) agent.config.api.custom_attributes_enabled = true transaction.end() - t.end() + end() }) }) - t.test('should not add multiple custom attributes when disabled', (t) => { + await t.test('should not add multiple custom attributes when disabled', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function (transaction) { agent.config.api.custom_attributes_enabled = false api.addCustomAttributes({ @@ -117,31 +121,33 @@ tap.test('Agent API - custom attributes', (t) => { const hasOne = Object.hasOwnProperty.call(attributes, 'one') const hasTwo = Object.hasOwnProperty.call(attributes, 'two') - t.notOk(hasOne) - t.notOk(hasTwo) + assert.ok(!hasOne) + assert.ok(!hasTwo) agent.config.api.custom_attributes_enabled = true transaction.end() - t.end() + end() }) }) - t.test('should not add custom attributes in high security mode', (t) => { + await t.test('should not add custom attributes in high security mode', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function (transaction) { agent.config.high_security = true api.addCustomAttribute('test', 1) const attributes = transaction.trace.custom.get(DESTINATIONS.TRANS_TRACE) const hasTest = Object.hasOwnProperty.call(attributes, 'test') - t.notOk(hasTest) + assert.ok(!hasTest) agent.config.high_security = false transaction.end() - t.end() + end() }) }) - t.test('should not add multiple custom attributes in high security mode', (t) => { + await t.test('should not add multiple custom attributes in high security mode', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function (transaction) { agent.config.high_security = true api.addCustomAttributes({ @@ -152,21 +158,22 @@ tap.test('Agent API - custom attributes', (t) => { const hasOne = Object.hasOwnProperty.call(attributes, 'one') const hasTwo = Object.hasOwnProperty.call(attributes, 'two') - t.notOk(hasOne) - t.notOk(hasTwo) + assert.ok(!hasOne) + assert.ok(!hasTwo) agent.config.high_security = false transaction.end() - t.end() + end() }) }) - t.test('should keep the most-recently seen value', (t) => { + await t.test('should keep the most-recently seen value', (t, end) => { + const { agent, api } = t.nr agent.on('transactionFinished', function (transaction) { const attributes = transaction.trace.custom.get(DESTINATIONS.TRANS_TRACE) - t.equal(attributes.TestName, 'Third') + assert.equal(attributes.TestName, 'Third') - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { @@ -178,7 +185,8 @@ tap.test('Agent API - custom attributes', (t) => { }) }) - t.test('should roll with it if custom attributes are gone', (t) => { + await t.test('should roll with it if custom attributes are gone', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function (transaction) { const trace = transaction.trace delete trace.custom @@ -186,11 +194,12 @@ tap.test('Agent API - custom attributes', (t) => { // should not throw api.addCustomAttribute('TestName', 'TestValue') - t.end() + end() }) }) - t.test('should not allow setting of excluded attributes', (t) => { + await t.test('should not allow setting of excluded attributes', (t, end) => { + const { agent, api } = t.nr agent.config.attributes.exclude.push('ignore_me') agent.config.emit('attributes.exclude') @@ -198,9 +207,9 @@ tap.test('Agent API - custom attributes', (t) => { const attributes = transaction.trace.custom.get(DESTINATIONS.TRANS_TRACE) const hasIgnore = Object.hasOwnProperty.call(attributes, 'ignore_me') - t.notOk(hasIgnore) + assert.ok(!hasIgnore) - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { @@ -210,7 +219,8 @@ tap.test('Agent API - custom attributes', (t) => { }) }) - t.test('should properly add custom span attribute', (t) => { + await t.test('should properly add custom span attribute', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function (transaction) { transaction.name = 'test' api.startSegment('foobar', false, function () { @@ -219,15 +229,16 @@ tap.test('Agent API - custom attributes', (t) => { const span = SpanEvent.fromSegment(segment, 'parent') const attributes = span.customAttributes - t.equal(attributes.spannnnnny, 1) + assert.equal(attributes.spannnnnny, 1) }) transaction.end() - t.end() + end() }) }) - t.test('should properly add multiple custom span attributes', (t) => { + await t.test('should properly add multiple custom span attributes', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function (transaction) { api.startSegment('foo', false, () => { api.addCustomSpanAttributes({ @@ -238,8 +249,8 @@ tap.test('Agent API - custom attributes', (t) => { const span = SpanEvent.fromSegment(segment, 'parent') const attributes = span.customAttributes - t.equal(attributes.one, 1) - t.equal(attributes.two, 2) + assert.equal(attributes.one, 1) + assert.equal(attributes.two, 2) }) api.addCustomAttributes({ one: 1, @@ -247,7 +258,7 @@ tap.test('Agent API - custom attributes', (t) => { }) transaction.end() - t.end() + end() }) }) }) diff --git a/test/unit/api/api-custom-metrics.test.js b/test/unit/api/api-custom-metrics.test.js index e16c3230a3..354f57a2b3 100644 --- a/test/unit/api/api-custom-metrics.test.js +++ b/test/unit/api/api-custom-metrics.test.js @@ -4,56 +4,55 @@ */ '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 - custom metrics', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - api = new API(agent) +test('Agent API - custom metrics', async (t) => { + 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('should prepend "Custom" in front of name', (t) => { + await t.test('should prepend "Custom" in front of name', (t, end) => { + const { api } = t.nr api.recordMetric('metric/thing', 3) api.recordMetric('metric/thing', 4) api.recordMetric('metric/thing', 5) const metric = api.agent.metrics.getMetric('Custom/metric/thing') - t.ok(metric) + assert.ok(metric) - t.end() + end() }) - t.test('it should aggregate metric values', (t) => { + await t.test('it should aggregate metric values', (t, end) => { + const { api } = t.nr api.recordMetric('metric/thing', 3) api.recordMetric('metric/thing', 4) api.recordMetric('metric/thing', 5) const metric = api.agent.metrics.getMetric('Custom/metric/thing') - t.equal(metric.total, 12) - t.equal(metric.totalExclusive, 12) - t.equal(metric.min, 3) - t.equal(metric.max, 5) - t.equal(metric.sumOfSquares, 50) - t.equal(metric.callCount, 3) + assert.equal(metric.total, 12) + assert.equal(metric.totalExclusive, 12) + assert.equal(metric.min, 3) + assert.equal(metric.max, 5) + assert.equal(metric.sumOfSquares, 50) + assert.equal(metric.callCount, 3) - t.end() + end() }) - t.test('it should merge metrics', (t) => { + await t.test('it should merge metrics', (t, end) => { + const { api } = t.nr api.recordMetric('metric/thing', 3) api.recordMetric('metric/thing', { total: 9, @@ -65,40 +64,41 @@ tap.test('Agent API - custom metrics', (t) => { const metric = api.agent.metrics.getMetric('Custom/metric/thing') - t.equal(metric.total, 12) - t.equal(metric.totalExclusive, 12) - t.equal(metric.min, 3) - t.equal(metric.max, 5) - t.equal(metric.sumOfSquares, 50) - t.equal(metric.callCount, 3) + assert.equal(metric.total, 12) + assert.equal(metric.totalExclusive, 12) + assert.equal(metric.min, 3) + assert.equal(metric.max, 5) + assert.equal(metric.sumOfSquares, 50) + assert.equal(metric.callCount, 3) - t.end() + end() }) - t.test('it should increment properly', (t) => { + await t.test('it should increment properly', (t, end) => { + const { api } = t.nr api.incrementMetric('metric/thing') api.incrementMetric('metric/thing') api.incrementMetric('metric/thing') const metric = api.agent.metrics.getMetric('Custom/metric/thing') - t.equal(metric.total, 0) - t.equal(metric.totalExclusive, 0) - t.equal(metric.min, 0) - t.equal(metric.max, 0) - t.equal(metric.sumOfSquares, 0) - t.equal(metric.callCount, 3) + assert.equal(metric.total, 0) + assert.equal(metric.totalExclusive, 0) + assert.equal(metric.min, 0) + assert.equal(metric.max, 0) + assert.equal(metric.sumOfSquares, 0) + assert.equal(metric.callCount, 3) api.incrementMetric('metric/thing', 4) api.incrementMetric('metric/thing', 5) - t.equal(metric.total, 0) - t.equal(metric.totalExclusive, 0) - t.equal(metric.min, 0) - t.equal(metric.max, 0) - t.equal(metric.sumOfSquares, 0) - t.equal(metric.callCount, 12) + assert.equal(metric.total, 0) + assert.equal(metric.totalExclusive, 0) + assert.equal(metric.min, 0) + assert.equal(metric.max, 0) + assert.equal(metric.sumOfSquares, 0) + assert.equal(metric.callCount, 12) - t.end() + end() }) }) diff --git a/test/unit/api/api-get-linking-metadata.test.js b/test/unit/api/api-get-linking-metadata.test.js index d85e34c365..9e41c78f89 100644 --- a/test/unit/api/api-get-linking-metadata.test.js +++ b/test/unit/api/api-get-linking-metadata.test.js @@ -4,102 +4,108 @@ */ '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 - getLinkingMetadata', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.instrumentMockedAgent() - api = new API(agent) +test('Agent API - getLinkingMetadata', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.instrumentMockedAgent() + 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('should return available fields, no DT data, when DT disabled in transaction', (t) => { - agent.config.distributed_tracing.enabled = false + await t.test( + 'should return available fields, no DT data, when DT disabled in transaction', + (t, end) => { + const { agent, api } = t.nr + agent.config.distributed_tracing.enabled = false + + helper.runInTransaction(agent, function () { + const metadata = api.getLinkingMetadata() + + // trace and span id are omitted when dt is disabled + assert.ok(!metadata['trace.id']) + assert.ok(!metadata['span.id']) + assert.equal(metadata['entity.name'], 'New Relic for Node.js tests') + assert.equal(metadata['entity.type'], 'SERVICE') + assert.ok(!metadata['entity.guid']) + assert.equal(metadata.hostname, agent.config.getHostnameSafe()) + + end() + }) + } + ) + + await t.test( + 'should return available fields, no DT data, when DT enabled - no transaction', + (t, end) => { + const { agent, api } = t.nr + agent.config.distributed_tracing.enabled = true - helper.runInTransaction(agent, function () { const metadata = api.getLinkingMetadata() - // trace and span id are omitted when dt is disabled - t.notOk(metadata['trace.id']) - t.notOk(metadata['span.id']) - t.equal(metadata['entity.name'], 'New Relic for Node.js tests') - t.equal(metadata['entity.type'], 'SERVICE') - t.notOk(metadata['entity.guid']) - t.equal(metadata.hostname, agent.config.getHostnameSafe()) + // Trace and span id are omitted when there is no active transaction + assert.ok(!metadata['trace.id']) + assert.ok(!metadata['span.id']) + assert.equal(metadata['entity.name'], 'New Relic for Node.js tests') + assert.equal(metadata['entity.type'], 'SERVICE') + assert.ok(!metadata['entity.guid']) + assert.equal(metadata.hostname, agent.config.getHostnameSafe()) - t.end() - }) - }) - - t.test('should return available fields, no DT data, when DT enabled - no transaction', (t) => { - agent.config.distributed_tracing.enabled = true - - const metadata = api.getLinkingMetadata() - - // Trace and span id are omitted when there is no active transaction - t.notOk(metadata['trace.id']) - t.notOk(metadata['span.id']) - t.equal(metadata['entity.name'], 'New Relic for Node.js tests') - t.equal(metadata['entity.type'], 'SERVICE') - t.notOk(metadata['entity.guid']) - t.equal(metadata.hostname, agent.config.getHostnameSafe()) - - t.end() - }) + end() + } + ) - t.test('should return all data, when DT enabled in transaction', (t) => { + await t.test('should return all data, when DT enabled in transaction', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function () { const metadata = api.getLinkingMetadata() - t.ok(metadata['trace.id']) - t.type(metadata['trace.id'], 'string') + assert.ok(metadata['trace.id']) + assert.equal(typeof metadata['trace.id'], 'string') - t.ok(metadata['span.id']) - t.type(metadata['span.id'], 'string') + assert.ok(metadata['span.id']) + assert.equal(typeof metadata['span.id'], 'string') - t.equal(metadata['entity.name'], 'New Relic for Node.js tests') - t.equal(metadata['entity.type'], 'SERVICE') - t.notOk(metadata['entity.guid']) - t.equal(metadata.hostname, agent.config.getHostnameSafe()) + assert.equal(metadata['entity.name'], 'New Relic for Node.js tests') + assert.equal(metadata['entity.type'], 'SERVICE') + assert.ok(!metadata['entity.guid']) + assert.equal(metadata.hostname, agent.config.getHostnameSafe()) - t.end() + end() }) }) - t.test('should include entity_guid when set and DT enabled in transaction', (t) => { + await t.test('should include entity_guid when set and DT enabled in transaction', (t, end) => { + const { agent, api } = t.nr const expectedEntityGuid = 'test' agent.config.entity_guid = expectedEntityGuid helper.runInTransaction(agent, function () { const metadata = api.getLinkingMetadata() - t.ok(metadata['trace.id']) - t.type(metadata['trace.id'], 'string') + assert.ok(metadata['trace.id']) + assert.equal(typeof metadata['trace.id'], 'string') - t.ok(metadata['span.id']) - t.type(metadata['span.id'], 'string') + assert.ok(metadata['span.id']) + assert.equal(typeof metadata['span.id'], 'string') - t.equal(metadata['entity.name'], 'New Relic for Node.js tests') - t.equal(metadata['entity.type'], 'SERVICE') + assert.equal(metadata['entity.name'], 'New Relic for Node.js tests') + assert.equal(metadata['entity.type'], 'SERVICE') - t.ok(metadata['entity.guid']) - t.equal(metadata['entity.guid'], expectedEntityGuid) + assert.ok(metadata['entity.guid']) + assert.equal(metadata['entity.guid'], expectedEntityGuid) - t.equal(metadata.hostname, agent.config.getHostnameSafe()) + assert.equal(metadata.hostname, agent.config.getHostnameSafe()) - t.end() + end() }) }) }) diff --git a/test/unit/api/api-get-trace-metadata.test.js b/test/unit/api/api-get-trace-metadata.test.js index 0d8a309128..d993e8fb58 100644 --- a/test/unit/api/api-get-trace-metadata.test.js +++ b/test/unit/api/api-get-trace-metadata.test.js @@ -4,72 +4,71 @@ */ '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 - trace metadata', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() +test('Agent API - trace metadata', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.loadMockedAgent() agent.config.distributed_tracing.enabled = true - api = new API(agent) + 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 trace metadata function', (t) => { + await t.test('exports a trace metadata function', (t, end) => { + const { api, agent } = t.nr helper.runInTransaction(agent, function (txn) { - t.type(api.getTraceMetadata, 'function') + assert.equal(typeof api.getTraceMetadata, 'function') const metadata = api.getTraceMetadata() - t.type(metadata, 'object') + assert.equal(typeof metadata, 'object') - t.type(metadata.traceId, 'string') - t.equal(metadata.traceId, txn.traceId) + assert.equal(typeof metadata.traceId, 'string') + assert.equal(metadata.traceId, txn.traceId) - t.type(metadata.spanId, 'string') - t.equal(metadata.spanId, txn.agent.tracer.getSegment().id) + assert.equal(typeof metadata.spanId, 'string') + assert.equal(metadata.spanId, txn.agent.tracer.getSegment().id) - t.end() + end() }) }) - t.test('should return empty object with DT disabled', (t) => { + await t.test('should return empty object with DT disabled', (t, end) => { + const { api, agent } = t.nr agent.config.distributed_tracing.enabled = false helper.runInTransaction(agent, function () { const metadata = api.getTraceMetadata() - t.type(metadata, 'object') + assert.equal(typeof metadata, 'object') - t.same(metadata, {}) - t.end() + assert.deepEqual(metadata, {}) + end() }) }) - t.test('should not include spanId property with span events disabled', (t) => { + await t.test('should not include spanId property with span events disabled', (t, end) => { + const { api, agent } = t.nr agent.config.span_events.enabled = false helper.runInTransaction(agent, function (txn) { const metadata = api.getTraceMetadata() - t.type(metadata, 'object') + assert.equal(typeof metadata, 'object') - t.type(metadata.traceId, 'string') - t.equal(metadata.traceId, txn.traceId) + assert.equal(typeof metadata.traceId, 'string') + assert.equal(metadata.traceId, txn.traceId) const hasProperty = Object.hasOwnProperty.call(metadata, 'spanId') - t.notOk(hasProperty) + assert.ok(!hasProperty) - t.end() + end() }) }) }) diff --git a/test/unit/api/api-ignore-apdex.test.js b/test/unit/api/api-ignore-apdex.test.js index 5f7f555971..c35a238a54 100644 --- a/test/unit/api/api-ignore-apdex.test.js +++ b/test/unit/api/api-ignore-apdex.test.js @@ -4,8 +4,8 @@ */ 'use strict' - -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const sinon = require('sinon') const proxyquire = require('proxyquire') const loggerMock = require('../mocks/logger')() @@ -17,42 +17,41 @@ const API = proxyquire('../../../api', { } }) -tap.test('Agent API = ignore apdex', (t) => { - let agent = null - let api - - t.beforeEach(() => { +test('Agent API = ignore apdex', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} loggerMock.warn.reset() - agent = helper.loadMockedAgent({ + const agent = helper.loadMockedAgent({ attributes: { enabled: true } }) - api = new API(agent) + ctx.nr.api = new API(agent) + ctx.nr.agent = agent }) - t.afterEach(() => { - helper.unloadAgent(agent) + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - t.test('should set ignoreApdex on active transaction', (t) => { + await t.test('should set ignoreApdex on active transaction', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, (tx) => { api.ignoreApdex() - t.equal(tx.ignoreApdex, true) - t.equal(loggerMock.warn.callCount, 0) - t.end() + assert.equal(tx.ignoreApdex, true) + assert.equal(loggerMock.warn.callCount, 0) + end() }) }) - t.test('should log warning if not in active transaction', (t) => { + await t.test('should log warning if not in active transaction', (t, end) => { + const { api } = t.nr api.ignoreApdex() - t.equal(loggerMock.warn.callCount, 1) - t.equal( + assert.equal(loggerMock.warn.callCount, 1) + assert.equal( loggerMock.warn.args[0][0], 'Apdex will not be ignored. ignoreApdex must be called within the scope of a transaction.' ) - t.end() + end() }) - - t.end() }) diff --git a/test/unit/api/api-instrument-conglomerate.test.js b/test/unit/api/api-instrument-conglomerate.test.js index 371ad1ff33..46acfbdcff 100644 --- a/test/unit/api/api-instrument-conglomerate.test.js +++ b/test/unit/api/api-instrument-conglomerate.test.js @@ -4,59 +4,56 @@ */ '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') const sinon = require('sinon') const shimmer = require('../../../lib/shimmer') -tap.test('Agent API - instrumentConglomerate', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - api = new API(agent) +test('Agent API - instrumentConglomerate', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.loadMockedAgent() + ctx.nr.api = new API(agent) sinon.spy(shimmer, 'registerInstrumentation') + ctx.nr.agent = agent }) - t.afterEach(() => { - helper.unloadAgent(agent) - agent = null - + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) shimmer.registerInstrumentation.restore() }) - t.test('should register the instrumentation with shimmer', (t) => { + await t.test('should register the instrumentation with shimmer', (t, end) => { + const { api } = t.nr const opts = { moduleName: 'foobar', onRequire: () => {} } api.instrumentConglomerate(opts) - t.ok(shimmer.registerInstrumentation.calledOnce) + assert.ok(shimmer.registerInstrumentation.calledOnce) const args = shimmer.registerInstrumentation.getCall(0).args const [actualOpts] = args - t.equal(actualOpts, opts) - t.equal(actualOpts.type, 'conglomerate') + assert.equal(actualOpts, opts) + assert.equal(actualOpts.type, 'conglomerate') - t.end() + end() }) - t.test('should convert separate args into an options object', (t) => { + await t.test('should convert separate args into an options object', (t, end) => { + const { api } = t.nr function onRequire() {} function onError() {} api.instrumentConglomerate('foobar', onRequire, onError) const opts = shimmer.registerInstrumentation.getCall(0).args[0] - t.equal(opts.moduleName, 'foobar') - t.equal(opts.onRequire, onRequire) - t.equal(opts.onError, onError) + assert.equal(opts.moduleName, 'foobar') + assert.equal(opts.onRequire, onRequire) + assert.equal(opts.onError, onError) - t.end() + end() }) }) diff --git a/test/unit/api/api-instrument-datastore.test.js b/test/unit/api/api-instrument-datastore.test.js index 76ed2bb5a3..9be0cedba8 100644 --- a/test/unit/api/api-instrument-datastore.test.js +++ b/test/unit/api/api-instrument-datastore.test.js @@ -4,60 +4,57 @@ */ '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') const sinon = require('sinon') const shimmer = require('../../../lib/shimmer') -tap.test('Agent API - instrumentDatastore', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - api = new API(agent) +test('Agent API - instrumentDatastore', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.loadMockedAgent() + ctx.nr.api = new API(agent) sinon.spy(shimmer, 'registerInstrumentation') + ctx.nr.agent = agent }) - t.afterEach(() => { - helper.unloadAgent(agent) - agent = null - + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) shimmer.registerInstrumentation.restore() }) - t.test('should register the instrumentation with shimmer', (t) => { + await t.test('should register the instrumentation with shimmer', (t, end) => { + const { api } = t.nr const opts = { moduleName: 'foobar', onRequire: function () {} } api.instrumentDatastore(opts) - t.ok(shimmer.registerInstrumentation.calledOnce) + assert.ok(shimmer.registerInstrumentation.calledOnce) const args = shimmer.registerInstrumentation.getCall(0).args const [actualOpts] = args - t.equal(actualOpts, opts) - t.equal(actualOpts.type, 'datastore') + assert.equal(actualOpts, opts) + assert.equal(actualOpts.type, 'datastore') - t.end() + end() }) - t.test('should convert separate args into an options object', (t) => { + await t.test('should convert separate args into an options object', (t, end) => { + const { api } = t.nr function onRequire() {} function onError() {} api.instrumentDatastore('foobar', onRequire, onError) const opts = shimmer.registerInstrumentation.getCall(0).args[0] - t.equal(opts.moduleName, 'foobar') - t.equal(opts.onRequire, onRequire) - t.equal(opts.onError, onError) + assert.equal(opts.moduleName, 'foobar') + assert.equal(opts.onRequire, onRequire) + assert.equal(opts.onError, onError) - t.end() + end() }) }) diff --git a/test/unit/api/api-instrument-loaded-module.test.js b/test/unit/api/api-instrument-loaded-module.test.js index 43bfb28fb9..8b9a3c0011 100644 --- a/test/unit/api/api-instrument-loaded-module.test.js +++ b/test/unit/api/api-instrument-loaded-module.test.js @@ -4,91 +4,94 @@ */ 'use strict' - -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const API = require('../../../api') const agentHelper = require('../../lib/agent_helper') const symbols = require('../../../lib/symbols') -tap.test('Agent API - instrumentLoadedModule', (t) => { - t.autoend() - - let agent - let api - let expressMock +test('Agent API - instrumentLoadedModule', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = agentHelper.instrumentMockedAgent() - t.beforeEach(() => { - agent = agentHelper.instrumentMockedAgent() + ctx.nr.api = new API(agent) - api = new API(agent) - - expressMock = {} - expressMock.application = {} - expressMock.application.use = function use() {} - expressMock.Router = {} + const expressMock = { + application: { + use: function use() {} + }, + Router: {} + } + ctx.nr.agent = agent + ctx.nr.expressMock = expressMock }) - t.afterEach(() => { - agentHelper.unloadAgent(agent) - agent = null - api = null - expressMock = null + t.afterEach((ctx) => { + agentHelper.unloadAgent(ctx.nr.agent) }) - t.test('should be callable without an error', (t) => { + await t.test('should be callable without an error', (t, end) => { + const { api, expressMock } = t.nr api.instrumentLoadedModule('express', expressMock) - t.end() + end() }) - t.test('should return true when a function is instrumented', (t) => { + await t.test('should return true when a function is instrumented', (t, end) => { + const { api, expressMock } = t.nr const didInstrument = api.instrumentLoadedModule('express', expressMock) - t.equal(didInstrument, true) + assert.equal(didInstrument, true) - t.end() + end() }) - t.test('should wrap express.application.use', (t) => { + await t.test('should wrap express.application.use', (t, end) => { + const { api, expressMock } = t.nr api.instrumentLoadedModule('express', expressMock) - t.type(expressMock, 'object') + assert.equal(typeof expressMock, 'object') const shim = expressMock[symbols.shim] const isWrapped = shim.isWrapped(expressMock.application.use) - t.ok(isWrapped) + assert.ok(isWrapped) - t.end() + end() }) - t.test('should return false when it cannot resolve module', (t) => { + await t.test('should return false when it cannot resolve module', (t, end) => { + const { api } = t.nr const result = api.instrumentLoadedModule('myTestModule') - t.equal(result, false) + assert.equal(result, false) - t.end() + end() }) - t.test('should return false when no instrumentation exists', (t) => { + await t.test('should return false when no instrumentation exists', (t, end) => { + const { api } = t.nr const result = api.instrumentLoadedModule('tap', {}) - t.equal(result, false) + assert.equal(result, false) - t.end() + end() }) - t.test('should not instrument/wrap multiple times on multiple invocations', (t) => { + await t.test('should not instrument/wrap multiple times on multiple invocations', (t, end) => { + const { api, expressMock } = t.nr const originalUse = expressMock.application.use api.instrumentLoadedModule('express', expressMock) api.instrumentLoadedModule('express', expressMock) const nrOriginal = expressMock.application.use[symbols.original] - t.equal(nrOriginal, originalUse) + assert.equal(nrOriginal, originalUse) - t.end() + end() }) - t.test('should not throw if supported module is not installed', function (t) { + await t.test('should not throw if supported module is not installed', function (t, end) { + const { api } = t.nr // We need a supported module in our test. We need that module _not_ to be // installed. We'll use mysql. This first bit ensures const EMPTY_MODULE = {} @@ -97,14 +100,13 @@ tap.test('Agent API - instrumentLoadedModule', (t) => { // eslint-disable-next-line node/no-missing-require mod = require('mysql') } catch (e) {} - t.ok(mod === EMPTY_MODULE, 'mysql is not installed') + assert.ok(mod === EMPTY_MODULE, 'mysql is not installed') // attempt to instrument -- if nothing throws we're good - try { + assert.doesNotThrow(() => { api.instrumentLoadedModule('mysql', mod) - } catch (e) { - t.error(e) - } - t.end() + }) + + end() }) }) diff --git a/test/unit/api/api-instrument-messages.test.js b/test/unit/api/api-instrument-messages.test.js index becc3ebeaa..299120b66e 100644 --- a/test/unit/api/api-instrument-messages.test.js +++ b/test/unit/api/api-instrument-messages.test.js @@ -4,34 +4,30 @@ */ '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') const sinon = require('sinon') const shimmer = require('../../../lib/shimmer') -tap.test('Agent API - instrumentMessages', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - api = new API(agent) +test('Agent API - instrumentMessages', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.loadMockedAgent() + ctx.nr.api = new API(agent) sinon.spy(shimmer, 'registerInstrumentation') + ctx.nr.agent = agent }) - t.afterEach(() => { - helper.unloadAgent(agent) - agent = null - + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) shimmer.registerInstrumentation.restore() }) - t.test('should register the instrumentation with shimmer', (t) => { + await t.test('should register the instrumentation with shimmer', (t, end) => { + const { api } = t.nr const opts = { moduleName: 'foobar', absolutePath: `${__dirname}/foobar`, @@ -39,26 +35,27 @@ tap.test('Agent API - instrumentMessages', (t) => { } api.instrumentMessages(opts) - t.ok(shimmer.registerInstrumentation.calledOnce) + assert.ok(shimmer.registerInstrumentation.calledOnce) const args = shimmer.registerInstrumentation.getCall(0).args const [actualOpts] = args - t.same(actualOpts, opts) - t.equal(actualOpts.type, 'message') + assert.deepEqual(actualOpts, opts) + assert.equal(actualOpts.type, 'message') - t.end() + end() }) - t.test('should convert separate args into an options object', (t) => { + await t.test('should convert separate args into an options object', (t, end) => { + const { api } = t.nr function onRequire() {} function onError() {} api.instrumentMessages('foobar', onRequire, onError) const opts = shimmer.registerInstrumentation.getCall(0).args[0] - t.equal(opts.moduleName, 'foobar') - t.equal(opts.onRequire, onRequire) - t.equal(opts.onError, onError) + assert.equal(opts.moduleName, 'foobar') + assert.equal(opts.onRequire, onRequire) + assert.equal(opts.onError, onError) - t.end() + end() }) }) diff --git a/test/unit/api/api-instrument-webframework.test.js b/test/unit/api/api-instrument-webframework.test.js index bfc2d82d41..0c2f5514a6 100644 --- a/test/unit/api/api-instrument-webframework.test.js +++ b/test/unit/api/api-instrument-webframework.test.js @@ -4,60 +4,57 @@ */ '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') const sinon = require('sinon') const shimmer = require('../../../lib/shimmer') -tap.test('Agent API - instrumentWebframework', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - api = new API(agent) +test('Agent API - instrumentWebframework', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.loadMockedAgent() + ctx.nr.api = new API(agent) sinon.spy(shimmer, 'registerInstrumentation') + ctx.nr.agent = agent }) - t.afterEach(() => { - helper.unloadAgent(agent) - agent = null - + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) shimmer.registerInstrumentation.restore() }) - t.test('should register the instrumentation with shimmer', (t) => { + await t.test('should register the instrumentation with shimmer', (t, end) => { + const { api } = t.nr const opts = { moduleName: 'foobar', onRequire: function () {} } api.instrumentWebframework(opts) - t.ok(shimmer.registerInstrumentation.calledOnce) + assert.ok(shimmer.registerInstrumentation.calledOnce) const args = shimmer.registerInstrumentation.getCall(0).args const [actualOpts] = args - t.equal(actualOpts, opts) - t.equal(actualOpts.type, 'web-framework') + assert.equal(actualOpts, opts) + assert.equal(actualOpts.type, 'web-framework') - t.end() + end() }) - t.test('should convert separate args into an options object', (t) => { + await t.test('should convert separate args into an options object', (t, end) => { + const { api } = t.nr function onRequire() {} function onError() {} api.instrumentWebframework('foobar', onRequire, onError) const opts = shimmer.registerInstrumentation.getCall(0).args[0] - t.equal(opts.moduleName, 'foobar') - t.equal(opts.onRequire, onRequire) - t.equal(opts.onError, onError) + assert.equal(opts.moduleName, 'foobar') + assert.equal(opts.onRequire, onRequire) + assert.equal(opts.onError, onError) - t.end() + end() }) }) diff --git a/test/unit/api/api-instrument.test.js b/test/unit/api/api-instrument.test.js index 1c44a74aba..9152a9279c 100644 --- a/test/unit/api/api-instrument.test.js +++ b/test/unit/api/api-instrument.test.js @@ -4,64 +4,62 @@ */ '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') const sinon = require('sinon') const shimmer = require('../../../lib/shimmer') -tap.test('Agent API - instrument', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - api = new API(agent) +test('Agent API - instrument', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.loadMockedAgent() + ctx.nr.api = new API(agent) sinon.spy(shimmer, 'registerInstrumentation') + ctx.nr.agent = agent }) - t.afterEach(() => { - helper.unloadAgent(agent) - agent = null - + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) shimmer.registerInstrumentation.restore() }) - t.test('exports a function for adding custom instrumentation', (t) => { - t.ok(api.instrument) - t.type(api.instrument, 'function') + await t.test('exports a function for adding custom instrumentation', (t, end) => { + const { api } = t.nr + assert.ok(api.instrument) + assert.equal(typeof api.instrument, 'function') - t.end() + end() }) - t.test('should register the instrumentation with shimmer', (t) => { + await t.test('should register the instrumentation with shimmer', (t, end) => { + const { api } = t.nr const opts = { moduleName: 'foobar', onRequire: function () {} } api.instrument(opts) - t.ok(shimmer.registerInstrumentation.calledOnce) + assert.ok(shimmer.registerInstrumentation.calledOnce) const args = shimmer.registerInstrumentation.getCall(0).args - t.equal(args[0], opts) + assert.equal(args[0], opts) - t.end() + end() }) - t.test('should convert separate args into an options object', (t) => { + await t.test('should convert separate args into an options object', (t, end) => { + const { api } = t.nr function onRequire() {} function onError() {} api.instrument('foobar', onRequire, onError) const opts = shimmer.registerInstrumentation.getCall(0).args[0] - t.equal(opts.moduleName, 'foobar') - t.equal(opts.onRequire, onRequire) - t.equal(opts.onError, onError) + assert.equal(opts.moduleName, 'foobar') + assert.equal(opts.onRequire, onRequire) + assert.equal(opts.onError, onError) - t.end() + end() }) }) diff --git a/test/unit/api/api-llm.test.js b/test/unit/api/api-llm.test.js index 26eab92c81..96d5fc6afe 100644 --- a/test/unit/api/api-llm.test.js +++ b/test/unit/api/api-llm.test.js @@ -4,57 +4,52 @@ */ 'use strict' - -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const sinon = require('sinon') const proxyquire = require('proxyquire') const helper = require('../../lib/agent_helper') -tap.test('Agent API LLM methods', (t) => { - t.autoend() - let loggerMock - let API - - t.before(() => { - loggerMock = require('../mocks/logger')() - API = proxyquire('../../../api', { - './lib/logger': { - child: sinon.stub().callsFake(() => loggerMock) - } - }) +test('Agent API LLM methods', async (t) => { + const loggerMock = require('../mocks/logger')() + const API = proxyquire('../../../api', { + './lib/logger': { + child: sinon.stub().callsFake(() => loggerMock) + } }) - t.beforeEach((t) => { + t.beforeEach((ctx) => { + ctx.nr = {} loggerMock.warn.reset() const agent = helper.loadMockedAgent() - t.context.api = new API(agent) + ctx.nr.api = new API(agent) agent.config.ai_monitoring.enabled = true - t.context.agent = agent + ctx.nr.agent = agent }) - t.afterEach((t) => { - helper.unloadAgent(t.context.api.agent) + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - t.test('recordLlmFeedbackEvent is no-op when no traceId is provided', async (t) => { - const { api } = t.context + await t.test('recordLlmFeedbackEvent is no-op when no traceId is provided', async (t) => { + const { api } = t.nr - helper.runInTransaction(api.agent, () => { + await helper.runInTransaction(api.agent, () => { const result = api.recordLlmFeedbackEvent({ category: 'test', rating: 'test' }) - t.equal(result, undefined) - t.equal(loggerMock.warn.callCount, 1) - t.equal( + assert.equal(result, undefined) + assert.equal(loggerMock.warn.callCount, 1) + assert.equal( loggerMock.warn.args[0][0], 'A feedback event will not be recorded. recordLlmFeedbackEvent must be called with a traceId.' ) }) }) - t.test('recordLlmFeedbackEvent is no-op when ai_monitoring is disabled', async (t) => { - const { api } = t.context + await t.test('recordLlmFeedbackEvent is no-op when ai_monitoring is disabled', async (t) => { + const { api } = t.nr api.agent.config.ai_monitoring.enabled = false const result = api.recordLlmFeedbackEvent({ @@ -62,32 +57,32 @@ tap.test('Agent API LLM methods', (t) => { category: 'test', rating: 'test' }) - t.equal(result, undefined) - t.equal(loggerMock.warn.callCount, 1) - t.equal( + assert.equal(result, undefined) + assert.equal(loggerMock.warn.callCount, 1) + assert.equal( loggerMock.warn.args[0][0], 'recordLlmFeedbackEvent invoked but ai_monitoring is disabled.' ) }) - t.test('recordLlmFeedbackEvent is no-op when no transaction is available', async (t) => { - const { api } = t.context + await t.test('recordLlmFeedbackEvent is no-op when no transaction is available', async (t) => { + const { api } = t.nr const result = api.recordLlmFeedbackEvent({ traceId: 'trace-id', category: 'test', rating: 'test' }) - t.equal(result, undefined) - t.equal(loggerMock.warn.callCount, 1) - t.equal( + assert.equal(result, undefined) + assert.equal(loggerMock.warn.callCount, 1) + assert.equal( loggerMock.warn.args[0][0], 'A feedback events will not be recorded. recordLlmFeedbackEvent must be called within the scope of a transaction.' ) }) - t.test('recordLlmFeedbackEvent returns undefined on success', async (t) => { - const { api } = t.context + await t.test('recordLlmFeedbackEvent returns undefined on success', async (t) => { + const { api } = t.nr const rce = api.recordCustomEvent let event @@ -95,22 +90,24 @@ tap.test('Agent API LLM methods', (t) => { event = { name, data } return rce.call(api, name, data) } - t.teardown(() => { + t.after(() => { api.recordCustomEvent = rce }) - helper.runInTransaction(api.agent, () => { + await helper.runInTransaction(api.agent, () => { const result = api.recordLlmFeedbackEvent({ traceId: 'trace-id', category: 'test-cat', rating: '5 star', metadata: { foo: 'foo' } }) - t.equal(result, undefined) - t.equal(loggerMock.warn.callCount, 0) - t.equal(event.name, 'LlmFeedbackMessage') - t.match(event.data, { - id: /[\w\d]{32}/, + assert.equal(result, undefined) + assert.equal(loggerMock.warn.callCount, 0) + assert.equal(event.name, 'LlmFeedbackMessage') + assert.match(event.data.id, /[\w\d]{32}/) + // remove from object as it was just asserted via regex + delete event.data.id + assert.deepEqual(event.data, { trace_id: 'trace-id', category: 'test-cat', rating: '5 star', @@ -121,51 +118,51 @@ tap.test('Agent API LLM methods', (t) => { }) }) - t.test('withLlmCustomAttributes should handle no active transaction', (t) => { - const { api } = t.context - t.equal( + await t.test('withLlmCustomAttributes should handle no active transaction', (t, end) => { + const { api } = t.nr + assert.equal( api.withLlmCustomAttributes({ test: 1 }, () => { - t.equal(loggerMock.warn.callCount, 1) + assert.equal(loggerMock.warn.callCount, 1) return 1 }), 1 ) - t.end() + end() }) - t.test('withLlmCustomAttributes should handle an empty store', (t) => { - const { api } = t.context + await t.test('withLlmCustomAttributes should handle an empty store', (t, end) => { + const { api } = t.nr const agent = api.agent helper.runInTransaction(api.agent, (tx) => { agent.tracer.getTransaction = () => { return tx } - t.equal( + assert.equal( api.withLlmCustomAttributes(null, () => { return 1 }), 1 ) - t.end() + end() }) }) - t.test('withLlmCustomAttributes should handle no callback', (t) => { - const { api } = t.context + await t.test('withLlmCustomAttributes should handle no callback', (t, end) => { + const { api } = t.nr const agent = api.agent helper.runInTransaction(api.agent, (tx) => { agent.tracer.getTransaction = () => { return tx } api.withLlmCustomAttributes({ test: 1 }, null) - t.equal(loggerMock.warn.callCount, 1) - t.end() + assert.equal(loggerMock.warn.callCount, 1) + end() }) }) - t.test('withLlmCustomAttributes should normalize attributes', (t) => { - const { api } = t.context + await t.test('withLlmCustomAttributes should normalize attributes', (t, end) => { + const { api } = t.nr const agent = api.agent helper.runInTransaction(api.agent, (tx) => { agent.tracer.getTransaction = () => { @@ -183,22 +180,22 @@ tap.test('Agent API LLM methods', (t) => { () => { const contextManager = tx._llmContextManager const parentContext = contextManager.getStore() - t.equal(parentContext['llm.toRename'], 'value1') - t.notOk(parentContext.toDelete) - t.notOk(parentContext.toDelete2) - t.notOk(parentContext.toDelete3) - t.equal(parentContext['llm.number'], 1) - t.equal(parentContext['llm.boolean'], true) - t.end() + assert.equal(parentContext['llm.toRename'], 'value1') + assert.ok(!parentContext.toDelete) + assert.ok(!parentContext.toDelete2) + assert.ok(!parentContext.toDelete3) + assert.equal(parentContext['llm.number'], 1) + assert.equal(parentContext['llm.boolean'], true) + end() } ) }) }) - t.test('withLlmCustomAttributes should support branching', (t) => { - const { api } = t.context + await t.test('withLlmCustomAttributes should support branching', (t, end) => { + const { api } = t.nr const agent = api.agent - t.autoend() + helper.runInTransaction(api.agent, (tx) => { agent.tracer.getTransaction = () => { return tx @@ -208,31 +205,31 @@ tap.test('Agent API LLM methods', (t) => { () => { const contextManager = tx._llmContextManager const context = contextManager.getStore() - t.equal(context[`llm.step`], '1') - t.equal(context['llm.path'], 'root') - t.equal(context['llm.name'], 'root') + assert.equal(context[`llm.step`], '1') + assert.equal(context['llm.path'], 'root') + assert.equal(context['llm.name'], 'root') api.withLlmCustomAttributes({ 'llm.step': '1.1', 'llm.path': 'root/1' }, () => { - const contextManager = tx._llmContextManager - const context = contextManager.getStore() - t.equal(context[`llm.step`], '1.1') - t.equal(context['llm.path'], 'root/1') - t.equal(context['llm.name'], 'root') + const contextManager2 = tx._llmContextManager + const context2 = contextManager2.getStore() + assert.equal(context2[`llm.step`], '1.1') + assert.equal(context2['llm.path'], 'root/1') + assert.equal(context2['llm.name'], 'root') }) api.withLlmCustomAttributes({ 'llm.step': '1.2', 'llm.path': 'root/2' }, () => { - const contextManager = tx._llmContextManager - const context = contextManager.getStore() - t.equal(context[`llm.step`], '1.2') - t.equal(context['llm.path'], 'root/2') - t.equal(context['llm.name'], 'root') - t.end() + const contextManager3 = tx._llmContextManager + const context3 = contextManager3.getStore() + assert.equal(context3[`llm.step`], '1.2') + assert.equal(context3['llm.path'], 'root/2') + assert.equal(context3['llm.name'], 'root') + end() }) } ) }) }) - t.test('setLlmTokenCount should register callback to calculate token counts', async (t) => { - const { api, agent } = t.context + await t.test('setLlmTokenCount should register callback to calculate token counts', async (t) => { + const { api, agent } = t.nr function callback(model, content) { if (model === 'foo' && content === 'bar') { return 10 @@ -241,11 +238,11 @@ tap.test('Agent API LLM methods', (t) => { return 1 } api.setLlmTokenCountCallback(callback) - t.same(agent.llm.tokenCountCallback, callback) + assert.deepEqual(agent.llm.tokenCountCallback, callback) }) - t.test('should not store token count callback if it is async', async (t) => { - const { api, agent } = t.context + await t.test('should not store token count callback if it is async', async (t) => { + const { api, agent } = t.nr async function callback(model, content) { return await new Promise((resolve) => { if (model === 'foo' && content === 'bar') { @@ -254,22 +251,22 @@ tap.test('Agent API LLM methods', (t) => { }) } api.setLlmTokenCountCallback(callback) - t.same(agent.llm.tokenCountCallback, undefined) - t.equal(loggerMock.warn.callCount, 1) - t.equal( + assert.deepEqual(agent.llm.tokenCountCallback, undefined) + assert.equal(loggerMock.warn.callCount, 1) + assert.equal( loggerMock.warn.args[0][0], 'Llm token count callback must be a synchronous function, callback will not be registered.' ) }) - t.test( + await t.test( 'should not store token count callback if callback is not actually a function', async (t) => { - const { api, agent } = t.context + const { api, agent } = t.nr api.setLlmTokenCountCallback({ unit: 'test' }) - t.same(agent.llm.tokenCountCallback, undefined) - t.equal(loggerMock.warn.callCount, 1) - t.equal( + assert.deepEqual(agent.llm.tokenCountCallback, undefined) + assert.equal(loggerMock.warn.callCount, 1) + assert.equal( loggerMock.warn.args[0][0], 'Llm token count callback must be a synchronous function, callback will not be registered.' ) diff --git a/test/unit/api/api-notice-error.test.js b/test/unit/api/api-notice-error.test.js index b049f4d4a2..c3b5e18ff8 100644 --- a/test/unit/api/api-notice-error.test.js +++ b/test/unit/api/api-notice-error.test.js @@ -4,104 +4,110 @@ */ '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 - noticeError', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - api = new API(agent) +test('Agent API - noticeError', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.loadMockedAgent() + ctx.nr.api = new API(agent) agent.config.attributes.enabled = true + ctx.nr.agent = agent }) - t.afterEach(() => { - helper.unloadAgent(agent) - agent = null + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - t.test('should add the error even without a transaction', (t) => { - t.equal(agent.errors.traceAggregator.errors.length, 0) + await t.test('should add the error even without a transaction', (t, end) => { + const { agent, api } = t.nr + assert.equal(agent.errors.traceAggregator.errors.length, 0) api.noticeError(new TypeError('this test is bogus, man')) - t.equal(agent.errors.traceAggregator.errors.length, 1) + assert.equal(agent.errors.traceAggregator.errors.length, 1) - t.end() + end() }) - t.test('should still add errors in high security mode', (t) => { + await t.test('should still add errors in high security mode', (t, end) => { + const { agent, api } = t.nr agent.config.high_security = true - t.equal(agent.errors.traceAggregator.errors.length, 0) + assert.equal(agent.errors.traceAggregator.errors.length, 0) api.noticeError(new TypeError('this test is bogus, man')) - t.equal(agent.errors.traceAggregator.errors.length, 1) + assert.equal(agent.errors.traceAggregator.errors.length, 1) agent.config.high_security = false - t.end() + end() }) - t.test('should not track custom attributes if custom_attributes_enabled is false', (t) => { - agent.config.api.custom_attributes_enabled = false - t.equal(agent.errors.traceAggregator.errors.length, 0) + await t.test( + 'should not track custom attributes if custom_attributes_enabled is false', + (t, end) => { + const { agent, api } = t.nr + agent.config.api.custom_attributes_enabled = false + assert.equal(agent.errors.traceAggregator.errors.length, 0) - api.noticeError(new TypeError('this test is bogus, man'), { crucial: 'attribute' }) + api.noticeError(new TypeError('this test is bogus, man'), { crucial: 'attribute' }) - t.equal(agent.errors.traceAggregator.errors.length, 1) - const attributes = agent.errors.traceAggregator.errors[0][4] - t.same(attributes.userAttributes, {}) - agent.config.api.custom_attributes_enabled = true + assert.equal(agent.errors.traceAggregator.errors.length, 1) + const attributes = agent.errors.traceAggregator.errors[0][4] + assert.deepEqual(attributes.userAttributes, {}) + agent.config.api.custom_attributes_enabled = true - t.end() - }) + end() + } + ) - t.test('should not track custom attributes in high security mode', (t) => { + await t.test('should not track custom attributes in high security mode', (t, end) => { + const { agent, api } = t.nr agent.config.high_security = true - t.equal(agent.errors.traceAggregator.errors.length, 0) + assert.equal(agent.errors.traceAggregator.errors.length, 0) api.noticeError(new TypeError('this test is bogus, man'), { crucial: 'attribute' }) - t.equal(agent.errors.traceAggregator.errors.length, 1) + assert.equal(agent.errors.traceAggregator.errors.length, 1) const attributes = agent.errors.traceAggregator.errors[0][4] - t.same(attributes.userAttributes, {}) + assert.deepEqual(attributes.userAttributes, {}) agent.config.high_security = false - t.end() + end() }) - t.test('should not add errors when noticeErrors is disabled', (t) => { + await t.test('should not add errors when noticeErrors is disabled', (t, end) => { + const { agent, api } = t.nr agent.config.api.notice_error_enabled = false - t.equal(agent.errors.traceAggregator.errors.length, 0) + assert.equal(agent.errors.traceAggregator.errors.length, 0) api.noticeError(new TypeError('this test is bogus, man')) - t.equal(agent.errors.traceAggregator.errors.length, 0) + assert.equal(agent.errors.traceAggregator.errors.length, 0) agent.config.api.notice_error_enabled = true - t.end() + end() }) - t.test('should track custom parameters on error without a transaction', (t) => { - t.equal(agent.errors.traceAggregator.errors.length, 0) + await t.test('should track custom parameters on error without a transaction', (t, end) => { + const { agent, api } = t.nr + assert.equal(agent.errors.traceAggregator.errors.length, 0) api.noticeError(new TypeError('this test is bogus, man'), { present: 'yep' }) - t.equal(agent.errors.traceAggregator.errors.length, 1) + assert.equal(agent.errors.traceAggregator.errors.length, 1) const params = agent.errors.traceAggregator.errors[0][4] - t.equal(params.userAttributes.present, 'yep') + assert.equal(params.userAttributes.present, 'yep') - t.end() + end() }) - t.test('should omit improper types of attributes', (t) => { - t.equal(agent.errors.traceAggregator.errors.length, 0) + await t.test('should omit improper types of attributes', (t, end) => { + const { agent, api } = t.nr + assert.equal(agent.errors.traceAggregator.errors.length, 0) api.noticeError(new TypeError('this test is bogus, man'), { string: 'yep', @@ -114,54 +120,56 @@ tap.test('Agent API - noticeError', (t) => { boolean: true }) - t.equal(agent.errors.traceAggregator.errors.length, 1) + assert.equal(agent.errors.traceAggregator.errors.length, 1) const params = agent.errors.traceAggregator.errors[0][4] - t.equal(params.userAttributes.string, 'yep') - t.equal(params.userAttributes.number, 1234) - t.equal(params.userAttributes.boolean, true) + assert.equal(params.userAttributes.string, 'yep') + assert.equal(params.userAttributes.number, 1234) + assert.equal(params.userAttributes.boolean, true) const hasAttribute = Object.hasOwnProperty.bind(params.userAttributes) - t.notOk(hasAttribute('object')) - t.notOk(hasAttribute('array')) - t.notOk(hasAttribute('function')) - t.notOk(hasAttribute('undef')) - t.notOk(hasAttribute('symbol')) + assert.ok(!hasAttribute('object')) + assert.ok(!hasAttribute('array')) + assert.ok(!hasAttribute('function')) + assert.ok(!hasAttribute('undef')) + assert.ok(!hasAttribute('symbol')) - t.end() + end() }) - t.test('should respect attribute filter rules', (t) => { + await t.test('should respect attribute filter rules', (t, end) => { + const { agent, api } = t.nr agent.config.attributes.exclude.push('unwanted') agent.config.emit('attributes.exclude') - t.equal(agent.errors.traceAggregator.errors.length, 0) + assert.equal(agent.errors.traceAggregator.errors.length, 0) api.noticeError(new TypeError('this test is bogus, man'), { present: 'yep', unwanted: 'nope' }) - t.equal(agent.errors.traceAggregator.errors.length, 1) + assert.equal(agent.errors.traceAggregator.errors.length, 1) const params = agent.errors.traceAggregator.errors[0][4] - t.equal(params.userAttributes.present, 'yep') - t.notOk(params.userAttributes.unwanted) + assert.equal(params.userAttributes.present, 'yep') + assert.ok(!params.userAttributes.unwanted) - t.end() + end() }) - t.test('should add the error associated to a transaction', (t) => { - t.equal(agent.errors.traceAggregator.errors.length, 0) + await t.test('should add the error associated to a transaction', (t, end) => { + const { agent, api } = t.nr + assert.equal(agent.errors.traceAggregator.errors.length, 0) agent.on('transactionFinished', function (transaction) { - t.equal(agent.errors.traceAggregator.errors.length, 1) + assert.equal(agent.errors.traceAggregator.errors.length, 1) const caught = agent.errors.traceAggregator.errors[0] const [, transactionName, message, type] = caught - t.equal(transactionName, 'Unknown') - t.equal(message, 'test error') - t.equal(type, 'TypeError') + assert.equal(transactionName, 'Unknown') + assert.equal(message, 'test error') + assert.equal(type, 'TypeError') - t.equal(transaction.ignore, false) + assert.equal(transaction.ignore, false) - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { @@ -170,26 +178,27 @@ tap.test('Agent API - noticeError', (t) => { }) }) - t.test('should notice custom attributes associated with an error', (t) => { - t.equal(agent.errors.traceAggregator.errors.length, 0) + await t.test('should notice custom attributes associated with an error', (t, end) => { + const { agent, api } = t.nr + assert.equal(agent.errors.traceAggregator.errors.length, 0) const orig = agent.config.attributes.exclude agent.config.attributes.exclude = ['ignored'] agent.config.emit('attributes.exclude') agent.on('transactionFinished', function (transaction) { - t.equal(agent.errors.traceAggregator.errors.length, 1) + assert.equal(agent.errors.traceAggregator.errors.length, 1) const caught = agent.errors.traceAggregator.errors[0] - t.equal(caught[1], 'Unknown') - t.equal(caught[2], 'test error') - t.equal(caught[3], 'TypeError') - t.equal(caught[4].userAttributes.hi, 'yo') - t.equal(caught[4].ignored, undefined) + assert.equal(caught[1], 'Unknown') + assert.equal(caught[2], 'test error') + assert.equal(caught[3], 'TypeError') + assert.equal(caught[4].userAttributes.hi, 'yo') + assert.equal(caught[4].ignored, undefined) - t.equal(transaction.ignore, false) + assert.equal(transaction.ignore, false) agent.config.attributes.exclude = orig - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { @@ -198,19 +207,20 @@ tap.test('Agent API - noticeError', (t) => { }) }) - t.test('should add an error-alike with a message but no stack', (t) => { - t.equal(agent.errors.traceAggregator.errors.length, 0) + await t.test('should add an error-alike with a message but no stack', (t, end) => { + const { agent, api } = t.nr + assert.equal(agent.errors.traceAggregator.errors.length, 0) agent.on('transactionFinished', function (transaction) { - t.equal(agent.errors.traceAggregator.errors.length, 1) + assert.equal(agent.errors.traceAggregator.errors.length, 1) const caught = agent.errors.traceAggregator.errors[0] - t.equal(caught[1], 'Unknown') - t.equal(caught[2], 'not an Error') - t.equal(caught[3], 'Object') + assert.equal(caught[1], 'Unknown') + assert.equal(caught[2], 'not an Error') + assert.equal(caught[3], 'Object') - t.equal(transaction.ignore, false) + assert.equal(transaction.ignore, false) - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { @@ -219,19 +229,20 @@ tap.test('Agent API - noticeError', (t) => { }) }) - t.test('should add an error-alike with a stack but no message', (t) => { - t.equal(agent.errors.traceAggregator.errors.length, 0) + await t.test('should add an error-alike with a stack but no message', (t, end) => { + const { agent, api } = t.nr + assert.equal(agent.errors.traceAggregator.errors.length, 0) agent.on('transactionFinished', function (transaction) { - t.equal(agent.errors.traceAggregator.errors.length, 1) + assert.equal(agent.errors.traceAggregator.errors.length, 1) const caught = agent.errors.traceAggregator.errors[0] - t.equal(caught[1], 'Unknown') - t.equal(caught[2], '') - t.equal(caught[3], 'Error') + assert.equal(caught[1], 'Unknown') + assert.equal(caught[2], '') + assert.equal(caught[3], 'Error') - t.equal(transaction.ignore, false) + assert.equal(transaction.ignore, false) - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { @@ -240,35 +251,37 @@ tap.test('Agent API - noticeError', (t) => { }) }) - t.test("shouldn't throw on (or capture) a useless error object", (t) => { - t.equal(agent.errors.traceAggregator.errors.length, 0) + await t.test("shouldn't throw on (or capture) a useless error object", (t, end) => { + const { agent, api } = t.nr + assert.equal(agent.errors.traceAggregator.errors.length, 0) agent.on('transactionFinished', function (transaction) { - t.equal(agent.errors.traceAggregator.errors.length, 0) - t.equal(transaction.ignore, false) + assert.equal(agent.errors.traceAggregator.errors.length, 0) + assert.equal(transaction.ignore, false) - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { - t.doesNotThrow(() => api.noticeError({})) + assert.doesNotThrow(() => api.noticeError({})) transaction.end() }) }) - t.test('should add a string error associated to a transaction', (t) => { - t.equal(agent.errors.traceAggregator.errors.length, 0) + await t.test('should add a string error associated to a transaction', (t, end) => { + const { agent, api } = t.nr + assert.equal(agent.errors.traceAggregator.errors.length, 0) agent.on('transactionFinished', function (transaction) { - t.equal(agent.errors.traceAggregator.errors.length, 1) + assert.equal(agent.errors.traceAggregator.errors.length, 1) const caught = agent.errors.traceAggregator.errors[0] - t.equal(caught[1], 'Unknown') - t.equal(caught[2], 'busted, bro') - t.equal(caught[3], 'Error') + assert.equal(caught[1], 'Unknown') + assert.equal(caught[2], 'busted, bro') + assert.equal(caught[3], 'Error') - t.equal(transaction.ignore, false) + assert.equal(transaction.ignore, false) - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { @@ -277,19 +290,20 @@ tap.test('Agent API - noticeError', (t) => { }) }) - t.test('should allow custom parameters to be added to string errors', (t) => { - t.equal(agent.errors.traceAggregator.errors.length, 0) + await t.test('should allow custom parameters to be added to string errors', (t, end) => { + const { agent, api } = t.nr + assert.equal(agent.errors.traceAggregator.errors.length, 0) agent.on('transactionFinished', function (transaction) { - t.equal(agent.errors.traceAggregator.errors.length, 1) + assert.equal(agent.errors.traceAggregator.errors.length, 1) const caught = agent.errors.traceAggregator.errors[0] - t.equal(caught[2], 'busted, bro') - t.equal(caught[4].userAttributes.a, 1) - t.equal(caught[4].userAttributes.steak, 'sauce') + assert.equal(caught[2], 'busted, bro') + assert.equal(caught[4].userAttributes.a, 1) + assert.equal(caught[4].userAttributes.steak, 'sauce') - t.equal(transaction.ignore, false) + assert.equal(transaction.ignore, false) - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { diff --git a/test/unit/api/api-obfuscate-sql.test.js b/test/unit/api/api-obfuscate-sql.test.js index e3fefd9bd4..dca517abc4 100644 --- a/test/unit/api/api-obfuscate-sql.test.js +++ b/test/unit/api/api-obfuscate-sql.test.js @@ -4,21 +4,21 @@ */ '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 - obfuscateSql', (t) => { +test('Agent API - obfuscateSql', (t, end) => { const agent = helper.instrumentMockedAgent() const api = new API(agent) - t.teardown(() => { + t.after(() => { helper.unloadAgent(agent) }) const sql = `select * from foo where a='b' and c=100;` const obfuscated = api.obfuscateSql(sql, 'postgres') - t.equal(obfuscated, 'select * from foo where a=? and c=?;') - t.end() + assert.equal(obfuscated, 'select * from foo where a=? and c=?;') + end() }) diff --git a/test/unit/api/api-record-custom-event.test.js b/test/unit/api/api-record-custom-event.test.js index 7089c6959c..afee90ec99 100644 --- a/test/unit/api/api-record-custom-event.test.js +++ b/test/unit/api/api-record-custom-event.test.js @@ -4,79 +4,80 @@ */ 'use strict' - -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const helper = require('../../lib/agent_helper.js') const API = require('../../../api.js') const MAX_CUSTOM_EVENTS = 2 -tap.test('Agent API - recordCustomEvent', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent({ +test('Agent API - recordCustomEvent', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.loadMockedAgent({ custom_insights_events: { max_samples_stored: MAX_CUSTOM_EVENTS } }) - api = new API(agent) + ctx.nr.api = new API(agent) + ctx.nr.agent = agent }) - t.afterEach(() => { - helper.unloadAgent(agent) - agent = null - api = null + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - t.test('can be called without exploding', (t) => { - t.doesNotThrow(() => { + await t.test('can be called without exploding', (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { api.recordCustomEvent('EventName', { key: 'value' }) }) - t.end() + end() }) - t.test('does not throw an exception on invalid name', (t) => { - t.doesNotThrow(() => { + await t.test('does not throw an exception on invalid name', (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { api.recordCustomEvent('éventñame', { key: 'value' }) }) - t.end() + end() }) - t.test('pushes the event into the customEvents pool', (t) => { + await t.test('pushes the event into the customEvents pool', (t, end) => { + const { agent, api } = t.nr api.recordCustomEvent('EventName', { key: 'value' }) const myEvent = popTopCustomEvent(agent) - t.ok(myEvent) + assert.ok(myEvent) - t.end() + end() }) - t.test('does not collect events when high security mode is on', (t) => { + await t.test('does not collect events when high security mode is on', (t, end) => { + const { agent, api } = t.nr agent.config.high_security = true api.recordCustomEvent('EventName', { key: 'value' }) const events = getCustomEvents(agent) - t.equal(events.length, 0) + assert.equal(events.length, 0) - t.end() + end() }) - t.test('does not collect events when the endpoint is disabled in the config', (t) => { + await t.test('does not collect events when the endpoint is disabled in the config', (t, end) => { + const { agent, api } = t.nr agent.config.api.custom_events_enabled = false api.recordCustomEvent('EventName', { key: 'value' }) const events = getCustomEvents(agent) - t.equal(events.length, 0) + assert.equal(events.length, 0) - t.end() + end() }) - t.test('creates the proper intrinsic values when recorded', (t) => { + await t.test('creates the proper intrinsic values when recorded', (t, end) => { + const { agent, api } = t.nr const when = Date.now() api.recordCustomEvent('EventName', { key: 'value' }) @@ -84,14 +85,15 @@ tap.test('Agent API - recordCustomEvent', (t) => { const myEvent = popTopCustomEvent(agent) const [intrinsics] = myEvent - t.ok(intrinsics) - t.equal(intrinsics.type, 'EventName') - t.ok(intrinsics.timestamp >= when) + assert.ok(intrinsics) + assert.equal(intrinsics.type, 'EventName') + assert.ok(intrinsics.timestamp >= when) - t.end() + end() }) - t.test('adds the attributes the user asks for', (t) => { + await t.test('adds the attributes the user asks for', (t, end) => { + const { agent, api } = t.nr const data = { string: 'value', bool: true, @@ -102,12 +104,13 @@ tap.test('Agent API - recordCustomEvent', (t) => { const myEvent = popTopCustomEvent(agent) const userAttributes = myEvent[1] - t.same(userAttributes, data) + assert.deepEqual(userAttributes, data) - t.end() + end() }) - t.test('filters object type values from user attributes', (t) => { + await t.test('filters object type values from user attributes', (t, end) => { + const { agent, api } = t.nr const data = { string: 'value', object: {}, @@ -122,164 +125,180 @@ tap.test('Agent API - recordCustomEvent', (t) => { const myEvent = popTopCustomEvent(agent) const userAttributes = myEvent[1] - t.equal(userAttributes.string, 'value') + assert.equal(userAttributes.string, 'value') const hasOwnAttribute = Object.hasOwnProperty.bind(userAttributes) - t.notOk(hasOwnAttribute('object')) - t.notOk(hasOwnAttribute('array')) - t.notOk(hasOwnAttribute('function')) - t.notOk(hasOwnAttribute('undef')) - t.notOk(hasOwnAttribute('symbol')) + assert.ok(!hasOwnAttribute('object')) + assert.ok(!hasOwnAttribute('array')) + assert.ok(!hasOwnAttribute('function')) + assert.ok(!hasOwnAttribute('undef')) + assert.ok(!hasOwnAttribute('symbol')) - t.end() + end() }) - t.test('does not add events with invalid names', (t) => { + await t.test('does not add events with invalid names', (t, end) => { + const { agent, api } = t.nr api.recordCustomEvent('éventñame', { key: 'value' }) const myEvent = popTopCustomEvent(agent) - t.notOk(myEvent) + assert.ok(!myEvent) - t.end() + end() }) - t.test('does not collect events when disabled', (t) => { + await t.test('does not collect events when disabled', (t, end) => { + const { agent, api } = t.nr agent.config.custom_insights_events = false api.recordCustomEvent('SomeEvent', { key: 'value' }) const myEvent = popTopCustomEvent(agent) - t.notOk(myEvent) + assert.ok(!myEvent) agent.config.custom_insights_events = true - t.end() + end() }) - t.test('should sample after the limit of events', (t) => { + await t.test('should sample after the limit of events', (t, end) => { + const { agent, api } = t.nr api.recordCustomEvent('MaybeBumped', { a: 1 }) api.recordCustomEvent('MaybeBumped', { b: 2 }) api.recordCustomEvent('MaybeBumped', { c: 3 }) const customEvents = getCustomEvents(agent) - t.equal(customEvents.length, MAX_CUSTOM_EVENTS) + assert.equal(customEvents.length, MAX_CUSTOM_EVENTS) - t.end() + end() }) - t.test('should not throw an exception with too few arguments', (t) => { - t.doesNotThrow(() => { + await t.test('should not throw an exception with too few arguments', (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { api.recordCustomEvent() }) - t.doesNotThrow(() => { + assert.doesNotThrow(() => { api.recordCustomEvent('SomeThing') }) - t.end() + end() }) - t.test('should reject events with object first arg', (t) => { + await t.test('should reject events with object first arg', (t, end) => { + const { agent, api } = t.nr api.recordCustomEvent({}, { alpha: 'beta' }) const customEvent = popTopCustomEvent(agent) - t.notOk(customEvent) + assert.ok(!customEvent) - t.end() + end() }) - t.test('should reject events with array first arg', (t) => { + await t.test('should reject events with array first arg', (t, end) => { + const { agent, api } = t.nr api.recordCustomEvent([], { alpha: 'beta' }) const customEvent = popTopCustomEvent(agent) - t.notOk(customEvent) + assert.ok(!customEvent) - t.end() + end() }) - t.test('should reject events with number first arg', (t) => { + await t.test('should reject events with number first arg', (t, end) => { + const { agent, api } = t.nr api.recordCustomEvent(1, { alpha: 'beta' }) const customEvent = popTopCustomEvent(agent) - t.notOk(customEvent) + assert.ok(!customEvent) - t.end() + end() }) - t.test('should reject events with undfined first arg', (t) => { + await t.test('should reject events with undefined first arg', (t, end) => { + const { agent, api } = t.nr api.recordCustomEvent(undefined, { alpha: 'beta' }) const customEvent = popTopCustomEvent(agent) - t.notOk(customEvent) + assert.ok(!customEvent) - t.end() + end() }) - t.test('should reject events with null first arg', (t) => { + await t.test('should reject events with null first arg', (t, end) => { + const { agent, api } = t.nr api.recordCustomEvent(null, { alpha: 'beta' }) const customEvent = popTopCustomEvent(agent) - t.notOk(customEvent) + assert.ok(!customEvent) - t.end() + end() }) - t.test('should reject events with string second arg', (t) => { + await t.test('should reject events with string second arg', (t, end) => { + const { agent, api } = t.nr api.recordCustomEvent('EventThing', 'thing') const customEvent = popTopCustomEvent(agent) - t.notOk(customEvent) + assert.ok(!customEvent) - t.end() + end() }) - t.test('should reject events with array second arg', (t) => { + await t.test('should reject events with array second arg', (t, end) => { + const { agent, api } = t.nr api.recordCustomEvent('EventThing', []) const customEvent = popTopCustomEvent(agent) - t.notOk(customEvent) + assert.ok(!customEvent) - t.end() + end() }) - t.test('should reject events with number second arg', (t) => { + await t.test('should reject events with number second arg', (t, end) => { + const { agent, api } = t.nr api.recordCustomEvent('EventThing', 1) const customEvent = popTopCustomEvent(agent) - t.notOk(customEvent) + assert.ok(!customEvent) - t.end() + end() }) - t.test('should reject events with undefined second arg', (t) => { + await t.test('should reject events with undefined second arg', (t, end) => { + const { agent, api } = t.nr api.recordCustomEvent('EventThing', undefined) const customEvent = popTopCustomEvent(agent) - t.notOk(customEvent) + assert.ok(!customEvent) - t.end() + end() }) - t.test('should reject events with null second arg', (t) => { + await t.test('should reject events with null second arg', (t, end) => { + const { agent, api } = t.nr api.recordCustomEvent('EventThing', null) const customEvent = popTopCustomEvent(agent) - t.notOk(customEvent) + assert.ok(!customEvent) - t.end() + end() }) - t.test('should reject events with a type greater than 255 chars', (t) => { + await t.test('should reject events with a type greater than 255 chars', (t, end) => { + const { agent, api } = t.nr const badType = new Array(257).join('a') api.recordCustomEvent(badType, { ship: 'every week' }) const customEvent = popTopCustomEvent(agent) - t.notOk(customEvent) + assert.ok(!customEvent) - t.end() + end() }) - t.test('should reject events with an attribute key greater than 255 chars', (t) => { + await t.test('should reject events with an attribute key greater than 255 chars', (t, end) => { + const { agent, api } = t.nr const badKey = new Array(257).join('b') const attributes = {} attributes[badKey] = true @@ -287,9 +306,9 @@ tap.test('Agent API - recordCustomEvent', (t) => { api.recordCustomEvent('MyType', attributes) const customEvent = popTopCustomEvent(agent) - t.notOk(customEvent) + assert.ok(!customEvent) - t.end() + end() }) }) diff --git a/test/unit/api/api-record-log-events.test.js b/test/unit/api/api-record-log-events.test.js index 86a07dd57a..4ca47566f5 100644 --- a/test/unit/api/api-record-log-events.test.js +++ b/test/unit/api/api-record-log-events.test.js @@ -4,32 +4,28 @@ */ 'use strict' - -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const helper = require('../../lib/agent_helper.js') const API = require('../../../api.js') const { SUPPORTABILITY, LOGGING } = require('../../../lib/metrics/names') const API_METRIC = SUPPORTABILITY.API + '/recordLogEvent' - -tap.test('Agent API - recordCustomEvent', (t) => { - t.autoend() - - let agent = null - let api = null - const message = 'just logging a log in the logger' - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - api = new API(agent) +const message = 'just logging a log in the logger' + +test('Agent API - recordCustomEvent', async (t) => { + 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 - api = null + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - t.test('can handle a singular log message', (t) => { + await t.test('can handle a singular log message', (t, end) => { + const { agent, api } = t.nr const now = Date.now() const error = new Error('testing error') api.recordLogEvent({ @@ -38,37 +34,38 @@ tap.test('Agent API - recordCustomEvent', (t) => { }) const logMessage = popTopLogMessage(agent) - t.ok(logMessage, 'we have a log message') - t.equal(logMessage.message, message, 'it has the right log message') - t.equal(logMessage.level, 'UNKNOWN', 'it has UNKNOWN severity') - t.ok(logMessage.timestamp >= now, 'its timestamp is current') - t.ok(logMessage.hostname, 'a hostname was set') - t.notOk(logMessage['trace.id'], 'it does not have a trace id') - t.notOk(logMessage['span.id'], 'it does not have a span id') - t.equal(logMessage['error.message'], 'testing error', 'it has the right error.message') - t.equal( + assert.ok(logMessage, 'we have a log message') + assert.equal(logMessage.message, message, 'it has the right log message') + assert.equal(logMessage.level, 'UNKNOWN', 'it has UNKNOWN severity') + assert.ok(logMessage.timestamp >= now, 'its timestamp is current') + assert.ok(logMessage.hostname, 'a hostname was set') + assert.ok(!logMessage['trace.id'], 'it does not have a trace id') + assert.ok(!logMessage['span.id'], 'it does not have a span id') + assert.equal(logMessage['error.message'], 'testing error', 'it has the right error.message') + assert.equal( logMessage['error.stack'].substring(0, 1021), error.stack.substring(0, 1021), 'it has the right error.stack' ) - t.equal(logMessage['error.class'], 'Error', 'it has the right error.class') + assert.equal(logMessage['error.class'], 'Error', 'it has the right error.class') const lineMetric = agent.metrics.getMetric(LOGGING.LINES) - t.ok(lineMetric, 'line logging metric exists') - t.equal(lineMetric.callCount, 1, 'ensure a single log line was counted') + assert.ok(lineMetric, 'line logging metric exists') + assert.equal(lineMetric.callCount, 1, 'ensure a single log line was counted') const unknownLevelMetric = agent.metrics.getMetric(LOGGING.LEVELS.UNKNOWN) - t.ok(unknownLevelMetric, 'unknown level logging metric exists') - t.equal(unknownLevelMetric.callCount, 1, 'ensure a single log line was counted') + assert.ok(unknownLevelMetric, 'unknown level logging metric exists') + assert.equal(unknownLevelMetric.callCount, 1, 'ensure a single log line was counted') const apiMetric = agent.metrics.getMetric(API_METRIC) - t.ok(apiMetric, 'API logging metric exists') - t.equal(apiMetric.callCount, 1, 'ensure one API call was counted') + assert.ok(apiMetric, 'API logging metric exists') + assert.equal(apiMetric.callCount, 1, 'ensure one API call was counted') - t.end() + end() }) - t.test('adds the proper linking data in a transaction', (t) => { + await t.test('adds the proper linking data in a transaction', (t, end) => { + const { agent, api } = t.nr agent.config.entity_guid = 'api-guid' const birthday = 365515200000 const birth = 'a new jordi is here' @@ -79,105 +76,106 @@ tap.test('Agent API - recordCustomEvent', (t) => { }) const logMessage = popTopLogMessage(agent) - t.ok(logMessage, 'we have a log message') - t.equal(logMessage.message, birth, 'it has the right log message') - t.equal(logMessage.level, 'info', 'it has `info` severity') - t.equal(logMessage.timestamp, birthday, 'its timestamp is correct') - t.ok(logMessage.hostname, 'a hostname was set') - t.ok(logMessage['trace.id'], 'it has a trace id') - t.ok(logMessage['span.id'], 'it has a span id') - t.ok(logMessage['entity.type'], 'it has an entity type') - t.ok(logMessage['entity.name'], 'it has an entity name') - t.equal(logMessage['entity.guid'], 'api-guid', 'it has the right entity guid') + assert.ok(logMessage, 'we have a log message') + assert.equal(logMessage.message, birth, 'it has the right log message') + assert.equal(logMessage.level, 'info', 'it has `info` severity') + assert.equal(logMessage.timestamp, birthday, 'its timestamp is correct') + assert.ok(logMessage.hostname, 'a hostname was set') + assert.ok(logMessage['trace.id'], 'it has a trace id') + assert.ok(logMessage['span.id'], 'it has a span id') + assert.ok(logMessage['entity.type'], 'it has an entity type') + assert.ok(logMessage['entity.name'], 'it has an entity name') + assert.equal(logMessage['entity.guid'], 'api-guid', 'it has the right entity guid') const lineMetric = agent.metrics.getMetric(LOGGING.LINES) - t.ok(lineMetric, 'line logging metric exists') - t.equal(lineMetric.callCount, 1, 'ensure a single log line was counted') + assert.ok(lineMetric, 'line logging metric exists') + assert.equal(lineMetric.callCount, 1, 'ensure a single log line was counted') const infoLevelMetric = agent.metrics.getMetric(LOGGING.LEVELS.INFO) - t.ok(infoLevelMetric, 'info level logging metric exists') - t.equal(infoLevelMetric.callCount, 1, 'ensure a single log line was counted') - - const apiMetric = agent.metrics.getMetric(API_METRIC) - t.ok(apiMetric, 'API logging metric exists') - t.equal(apiMetric.callCount, 1, 'ensure one API call was counted') - - t.end() - }) - - t.test('does not collect logs when high security mode is on', (t) => { - // We need to go through all of the config logic, as HSM disables - // log forwarding as one of its configs, can't just directly set - // the HSM config after the agent has been created. - helper.unloadAgent(agent) - agent = helper.loadMockedAgent({ high_security: true }) - api = new API(agent) - - api.recordLogEvent({ message }) - - const logs = getLogMessages(agent) - t.equal(logs.length, 0, 'no log messages in queue') + assert.ok(infoLevelMetric, 'info level logging metric exists') + assert.equal(infoLevelMetric.callCount, 1, 'ensure a single log line was counted') const apiMetric = agent.metrics.getMetric(API_METRIC) - t.ok(apiMetric, 'API logging metric exists anyway') - t.equal(apiMetric.callCount, 1, 'ensure one API call was counted anyway') + assert.ok(apiMetric, 'API logging metric exists') + assert.equal(apiMetric.callCount, 1, 'ensure one API call was counted') - t.end() + end() }) - t.test('does not collect logs when log forwarding is disabled in the config', (t) => { + await t.test('does not collect logs when log forwarding is disabled in the config', (t, end) => { + const { agent, api } = t.nr agent.config.application_logging.forwarding.enabled = false api.recordLogEvent({ message }) const logs = getLogMessages(agent) - t.equal(logs.length, 0, 'no log messages in queue') + assert.equal(logs.length, 0, 'no log messages in queue') const apiMetric = agent.metrics.getMetric(API_METRIC) - t.ok(apiMetric, 'API logging metric exists anyway') - t.equal(apiMetric.callCount, 1, 'ensure one API call was counted anyway') + assert.ok(apiMetric, 'API logging metric exists anyway') + assert.equal(apiMetric.callCount, 1, 'ensure one API call was counted anyway') - t.end() + end() }) - t.test('it does not collect logs if the user sends a malformed message', (t) => { - t.doesNotThrow(() => { + await t.test('it does not collect logs if the user sends a malformed message', (t, end) => { + const { agent, api } = t.nr + assert.doesNotThrow(() => { api.recordLogEvent(message) }, 'no erroring out if passing in a string instead of an object') - t.doesNotThrow(() => { + assert.doesNotThrow(() => { api.recordLogEvent({ msg: message }) }, 'no erroring out if passing in an object missing a "message" attribute') const logs = getLogMessages(agent) - t.equal(logs.length, 0, 'no log messages in queue') + assert.equal(logs.length, 0, 'no log messages in queue') const apiMetric = agent.metrics.getMetric(API_METRIC) - t.ok(apiMetric, 'API logging metric exists anyway') - t.equal(apiMetric.callCount, 2, 'ensure two API calls were counted anyway') + assert.ok(apiMetric, 'API logging metric exists anyway') + assert.equal(apiMetric.callCount, 2, 'ensure two API calls were counted anyway') - t.end() + end() }) - t.test('log line metrics are not collected if the setting is disabled', (t) => { + await t.test('log line metrics are not collected if the setting is disabled', (t, end) => { + const { agent, api } = t.nr agent.config.application_logging.metrics.enabled = false api.recordLogEvent({ message }) const logMessage = popTopLogMessage(agent) - t.ok(logMessage, 'we have a log message') + assert.ok(logMessage, 'we have a log message') const lineMetric = agent.metrics.getMetric(LOGGING.LINES) - t.notOk(lineMetric, 'line logging metric does not exist') + assert.ok(!lineMetric, 'line logging metric does not exist') const unknownLevelMetric = agent.metrics.getMetric(LOGGING.LEVELS.UNKNOWN) - t.notOk(unknownLevelMetric, 'unknown level logging metric does not exist') + assert.ok(!unknownLevelMetric, 'unknown level logging metric does not exist') const apiMetric = agent.metrics.getMetric(API_METRIC) - t.ok(apiMetric, 'but API logging metric does exist') - t.equal(apiMetric.callCount, 1, 'and one API call was counted anyway') - t.end() + assert.ok(apiMetric, 'but API logging metric does exist') + assert.equal(apiMetric.callCount, 1, 'and one API call was counted anyway') + end() }) }) +test('does not collect logs when high security mode is on', (_t, end) => { + // We need to go through all of the config logic, as HSM disables + // log forwarding as one of its configs, can't just directly set + // the HSM config after the agent has been created. + const agent = helper.loadMockedAgent({ high_security: true }) + const api = new API(agent) + + api.recordLogEvent({ message }) + + const logs = getLogMessages(agent) + assert.equal(logs.length, 0, 'no log messages in queue') + + const apiMetric = agent.metrics.getMetric(API_METRIC) + assert.ok(apiMetric, 'API logging metric exists anyway') + assert.equal(apiMetric.callCount, 1, 'ensure one API call was counted anyway') + end() +}) + function popTopLogMessage(agent) { return getLogMessages(agent).pop() } diff --git a/test/unit/api/api-set-controller-name.test.js b/test/unit/api/api-set-controller-name.test.js index b429534862..46b7323b6a 100644 --- a/test/unit/api/api-set-controller-name.test.js +++ b/test/unit/api/api-set-controller-name.test.js @@ -4,64 +4,58 @@ */ '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 - setControllerName', (t) => { - t.autoend() - - const TEST_URL = '/test/path/31337' - const NAME = 'WebTransaction/Uri/test/path/31337' - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - api = new API(agent) +const TEST_URL = '/test/path/31337' +const NAME = 'WebTransaction/Uri/test/path/31337' + +test('Agent API - setControllerName', async (t) => { + 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 controller naming function', (t) => { - t.ok(api.setControllerName) - t.type(api.setControllerName, 'function') + await t.test('exports a controller naming function', (t, end) => { + const { api } = t.nr + assert.ok(api.setControllerName) + assert.equal(typeof api.setControllerName, 'function') - t.end() + end() }) - t.test('sets the controller in the transaction name', (t) => { - goldenPathRenameControllerInTransaction((transaction) => { - t.equal(transaction.name, 'WebTransaction/Controller/Test/POST') - t.end() - }) + await t.test('sets the controller in the transaction name', async (t) => { + const { agent, api } = t.nr + const { transaction } = await goldenPathRenameControllerInTransaction({ agent, api }) + assert.equal(transaction.name, 'WebTransaction/Controller/Test/POST') }) - t.test('names the web trace segment after the controller', (t) => { - goldenPathRenameControllerInTransaction((transaction, segment) => { - t.equal(segment.name, 'WebTransaction/Controller/Test/POST') - t.end() - }) + await t.test('names the web trace segment after the controller', async (t) => { + const { agent, api } = t.nr + const { segment } = await goldenPathRenameControllerInTransaction({ agent, api }) + assert.equal(segment.name, 'WebTransaction/Controller/Test/POST') }) - t.test('leaves the request URL alone', (t) => { - goldenPathRenameControllerInTransaction((transaction) => { - t.equal(transaction.url, TEST_URL) - t.end() - }) + await t.test('leaves the request URL alone', async (t) => { + const { agent, api } = t.nr + const { transaction } = await goldenPathRenameControllerInTransaction({ agent, api }) + assert.equal(transaction.url, TEST_URL) }) - t.test('uses the HTTP verb for the default action', (t) => { + await t.test('uses the HTTP verb for the default action', (t, end) => { + const { agent, api } = t.nr agent.on('transactionFinished', function (transaction) { transaction.finalizeNameFromUri(TEST_URL, 200) - t.equal(transaction.name, 'WebTransaction/Controller/Test/DELETE') + assert.equal(transaction.name, 'WebTransaction/Controller/Test/DELETE') - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { @@ -78,13 +72,14 @@ tap.test('Agent API - setControllerName', (t) => { }) }) - t.test('allows a custom action', (t) => { + await t.test('allows a custom action', (t, end) => { + const { agent, api } = t.nr agent.on('transactionFinished', function (transaction) { transaction.finalizeNameFromUri(TEST_URL, 200) - t.equal(transaction.name, 'WebTransaction/Controller/Test/index') + assert.equal(transaction.name, 'WebTransaction/Controller/Test/index') - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { @@ -99,13 +94,14 @@ tap.test('Agent API - setControllerName', (t) => { }) }) - t.test('uses the last controller set when called multiple times', (t) => { + await t.test('uses the last controller set when called multiple times', (t, end) => { + const { agent, api } = t.nr agent.on('transactionFinished', function (transaction) { transaction.finalizeNameFromUri(TEST_URL, 200) - t.equal(transaction.name, 'WebTransaction/Controller/Test/list') + assert.equal(transaction.name, 'WebTransaction/Controller/Test/list') - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { @@ -122,14 +118,16 @@ tap.test('Agent API - setControllerName', (t) => { transaction.end() }) }) +}) - function goldenPathRenameControllerInTransaction(cb) { - let segment = null +function goldenPathRenameControllerInTransaction({ agent, api }) { + let segment = null + return new Promise((resolve) => { agent.on('transactionFinished', function (finishedTransaction) { finishedTransaction.finalizeNameFromUri(TEST_URL, 200) segment.markAsWeb(TEST_URL) - cb(finishedTransaction, segment) + resolve({ transaction: finishedTransaction, segment }) }) helper.runInTransaction(agent, function (tx) { @@ -146,5 +144,5 @@ tap.test('Agent API - setControllerName', (t) => { tx.end() }) }) - } -}) + }) +} diff --git a/test/unit/api/api-set-dispatcher.test.js b/test/unit/api/api-set-dispatcher.test.js index e94bbc6080..41d4b5681a 100644 --- a/test/unit/api/api-set-dispatcher.test.js +++ b/test/unit/api/api-set-dispatcher.test.js @@ -4,68 +4,68 @@ */ '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 - dispatch setter', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - api = new API(agent) +test('Agent API - dispatch setter', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.loadMockedAgent() + ctx.nr.api = new API(agent) + ctx.nr.agent = agent }) - t.afterEach(() => { + t.afterEach((ctx) => { + const { agent } = ctx.nr agent.environment.clearDispatcher() - helper.unloadAgent(agent) - agent = null }) - t.test('exports a dispatcher setter', (t) => { - t.ok(api.setDispatcher) - t.type(api.setDispatcher, 'function') + await t.test('exports a dispatcher setter', (t, end) => { + const { api } = t.nr + assert.ok(api.setDispatcher) + assert.equal(typeof api.setDispatcher, 'function') - t.end() + end() }) - t.test('sets the dispatcher', (t) => { + await t.test('sets the dispatcher', (t, end) => { + const { agent, api } = t.nr api.setDispatcher('test') const dispatcher = agent.environment.get('Dispatcher') - t.ok(dispatcher.includes('test')) + assert.ok(dispatcher.includes('test')) - t.end() + end() }) - t.test('sets the dispatcher and version', (t) => { + await t.test('sets the dispatcher and version', (t, end) => { + const { agent, api } = t.nr api.setDispatcher('test', 2) - t.ok(dispatcherIncludes(agent, 'test')) - t.ok(dispatcherVersionIncludes(agent, '2')) + assert.ok(dispatcherIncludes(agent, 'test')) + assert.ok(dispatcherVersionIncludes(agent, '2')) - t.end() + end() }) - t.test('does not allow internal calls to setDispatcher to override', (t) => { + await t.test('does not allow internal calls to setDispatcher to override', (t, end) => { + const { agent, api } = t.nr agent.environment.setDispatcher('internal', '3') - t.ok(dispatcherIncludes(agent, 'internal')) - t.ok(dispatcherVersionIncludes(agent, '3')) + assert.ok(dispatcherIncludes(agent, 'internal')) + assert.ok(dispatcherVersionIncludes(agent, '3')) api.setDispatcher('test', 2) - t.ok(dispatcherIncludes(agent, 'test')) - t.ok(dispatcherVersionIncludes(agent, '2')) + assert.ok(dispatcherIncludes(agent, 'test')) + assert.ok(dispatcherVersionIncludes(agent, '2')) agent.environment.setDispatcher('internal', '3') - t.ok(dispatcherIncludes(agent, 'test')) - t.ok(dispatcherVersionIncludes(agent, '2')) + assert.ok(dispatcherIncludes(agent, 'test')) + assert.ok(dispatcherVersionIncludes(agent, '2')) - t.end() + end() }) }) diff --git a/test/unit/api/api-set-error-group-callback.test.js b/test/unit/api/api-set-error-group-callback.test.js index defdf8e6df..bc0d8bfa79 100644 --- a/test/unit/api/api-set-error-group-callback.test.js +++ b/test/unit/api/api-set-error-group-callback.test.js @@ -4,8 +4,8 @@ */ 'use strict' - -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const sinon = require('sinon') const proxyquire = require('proxyquire') const loggerMock = require('../mocks/logger')() @@ -18,72 +18,74 @@ const API = proxyquire('../../../api', { }) const NAMES = require('../../../lib/metrics/names') -tap.test('Agent API = set Error Group callback', (t) => { - t.autoend() - let agent = null - let api - - t.beforeEach(() => { +test('Agent API = set Error Group callback', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} loggerMock.warn.reset() - agent = helper.loadMockedAgent({ + const agent = helper.loadMockedAgent({ attributes: { enabled: true } }) - api = new API(agent) + ctx.nr.api = new API(agent) + ctx.nr.agent = agent }) - t.afterEach(() => { - helper.unloadAgent(agent) + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - t.test('should have a setErrorGroupCallback method', (t) => { - t.ok(api.setErrorGroupCallback) - t.equal(typeof api.setErrorGroupCallback, 'function') - t.end() + await t.test('should have a setErrorGroupCallback method', (t, end) => { + const { api } = t.nr + assert.ok(api.setErrorGroupCallback) + assert.equal(typeof api.setErrorGroupCallback, 'function') + end() }) - t.test('should attach callback function when a function', (t) => { + await t.test('should attach callback function when a function', (t, end) => { + const { api } = t.nr const callback = function myTestCallback() { return 'test-error-group-1' } api.setErrorGroupCallback(callback) - t.equal(loggerMock.warn.callCount, 0, 'should not log warnings when successful') - t.equal( + assert.equal(loggerMock.warn.callCount, 0, 'should not log warnings when successful') + assert.equal( api.agent.errors.errorGroupCallback, callback, 'should attach the callback on the error collector' ) - t.equal(api.agent.errors.errorGroupCallback(), 'test-error-group-1') - t.equal( + assert.equal(api.agent.errors.errorGroupCallback(), 'test-error-group-1') + assert.equal( api.agent.metrics.getOrCreateMetric(NAMES.SUPPORTABILITY.API + '/setErrorGroupCallback') .callCount, 1, 'should increment the API tracking metric' ) - t.end() + end() }) - t.test('should not attach the callback when not a function', (t) => { + await t.test('should not attach the callback when not a function', (t, end) => { + const { api } = t.nr const callback = 'test-error-group-2' api.setErrorGroupCallback(callback) - t.equal(loggerMock.warn.callCount, 1, 'should log warning when failed') - t.notOk( - api.agent.errors.errorGroupCallback, + assert.equal(loggerMock.warn.callCount, 1, 'should log warning when failed') + assert.ok( + !api.agent.errors.errorGroupCallback, 'should not attach the callback on the error collector' ) - t.equal( + assert.equal( api.agent.metrics.getOrCreateMetric(NAMES.SUPPORTABILITY.API + '/setErrorGroupCallback') .callCount, 1, 'should increment the API tracking metric' ) - t.end() + end() }) - t.test('should not attach the callback when async function', (t) => { + await t.test('should not attach the callback when async function', (t, end) => { + const { api } = t.nr async function callback() { return await new Promise((resolve) => { setTimeout(() => { @@ -93,17 +95,17 @@ tap.test('Agent API = set Error Group callback', (t) => { } api.setErrorGroupCallback(callback()) - t.equal(loggerMock.warn.callCount, 1, 'should log warning when failed') - t.notOk( - api.agent.errors.errorGroupCallback, + assert.equal(loggerMock.warn.callCount, 1, 'should log warning when failed') + assert.ok( + !api.agent.errors.errorGroupCallback, 'should not attach the callback on the error collector' ) - t.equal( + assert.equal( api.agent.metrics.getOrCreateMetric(NAMES.SUPPORTABILITY.API + '/setErrorGroupCallback') .callCount, 1, 'should increment the API tracking metric' ) - t.end() + end() }) }) diff --git a/test/unit/api/api-set-transaction-name.test.js b/test/unit/api/api-set-transaction-name.test.js index b99a568943..644b7e96be 100644 --- a/test/unit/api/api-set-transaction-name.test.js +++ b/test/unit/api/api-set-transaction-name.test.js @@ -4,65 +4,59 @@ */ '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 - setTranasactionName', (t) => { - t.autoend() - - let agent = null - let api = null - - const TEST_URL = '/test/path/31337' - const NAME = 'WebTransaction/Uri/test/path/31337' - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - api = new API(agent) +const TEST_URL = '/test/path/31337' +const NAME = 'WebTransaction/Uri/test/path/31337' + +test('Agent API - setTransactionName', async (t) => { + 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 transaction naming function', (t) => { - t.ok(api.setTransactionName) - t.type(api.setTransactionName, 'function') + await t.test('exports a transaction naming function', (t, end) => { + const { api } = t.nr + assert.ok(api.setTransactionName) + assert.equal(typeof api.setTransactionName, 'function') - t.end() + end() }) - t.test('sets the transaction name to the custom name', (t) => { - setTranasactionNameGoldenPath((transaction) => { - t.equal(transaction.name, 'WebTransaction/Custom/Test') - t.end() - }) + await t.test('sets the transaction name to the custom name', async (t) => { + const { agent, api } = t.nr + const { transaction } = await setTranasactionNameGoldenPath({ agent, api }) + assert.equal(transaction.name, 'WebTransaction/Custom/Test') }) - t.test('names the web trace segment after the custom name', (t) => { - setTranasactionNameGoldenPath((transaction, segment) => { - t.equal(segment.name, 'WebTransaction/Custom/Test') - t.end() - }) + await t.test('names the web trace segment after the custom name', async (t) => { + const { agent, api } = t.nr + const { segment } = await setTranasactionNameGoldenPath({ agent, api }) + assert.equal(segment.name, 'WebTransaction/Custom/Test') }) - t.test('leaves the request URL alone', (t) => { - setTranasactionNameGoldenPath((transaction) => { - t.equal(transaction.url, TEST_URL) - t.end() - }) + await t.test('leaves the request URL alone', async (t) => { + const { agent, api } = t.nr + const { transaction } = await setTranasactionNameGoldenPath({ agent, api }) + assert.equal(transaction.url, TEST_URL) }) - t.test('uses the last name set when called multiple times', (t) => { + await t.test('uses the last name set when called multiple times', (t, end) => { + const { agent, api } = t.nr agent.on('transactionFinished', function (transaction) { transaction.finalizeNameFromUri(TEST_URL, 200) - t.equal(transaction.name, 'WebTransaction/Custom/List') + assert.equal(transaction.name, 'WebTransaction/Custom/List') - t.end() + end() }) helper.runInTransaction(agent, function (transaction) { @@ -79,14 +73,15 @@ tap.test('Agent API - setTranasactionName', (t) => { transaction.end() }) }) +}) - function setTranasactionNameGoldenPath(cb) { - let segment = null - +function setTranasactionNameGoldenPath({ agent, api }) { + let segment = null + return new Promise((resolve) => { agent.on('transactionFinished', function (finishedTransaction) { finishedTransaction.finalizeNameFromUri(TEST_URL, 200) segment.markAsWeb(TEST_URL) - cb(finishedTransaction, segment) + resolve({ transaction: finishedTransaction, segment }) }) helper.runInTransaction(agent, function (tx) { @@ -104,5 +99,5 @@ tap.test('Agent API - setTranasactionName', (t) => { tx.end() }) }) - } -}) + }) +} diff --git a/test/unit/api/api-set-user-id.test.js b/test/unit/api/api-set-user-id.test.js index 9bc603573b..aaebd43b02 100644 --- a/test/unit/api/api-set-user-id.test.js +++ b/test/unit/api/api-set-user-id.test.js @@ -4,8 +4,8 @@ */ 'use strict' - -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const sinon = require('sinon') const proxyquire = require('proxyquire') const loggerMock = require('../mocks/logger')() @@ -19,53 +19,58 @@ const API = proxyquire('../../../api', { const { createError, Exception } = require('../../../lib/errors') const { DESTINATIONS } = require('../../../lib/config/attribute-filter') -tap.test('Agent API = set user id', (t) => { - t.autoend() - let agent = null - let api - - t.beforeEach(() => { +test('Agent API = set user id', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} loggerMock.warn.reset() - agent = helper.loadMockedAgent({ + const agent = helper.loadMockedAgent({ attributes: { enabled: true } }) - api = new API(agent) + ctx.nr.api = new API(agent) + ctx.nr.agent = agent }) - t.afterEach(() => { - helper.unloadAgent(agent) + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - t.test('should have a setUserID method', (t) => { - t.ok(api.setUserID) - t.equal(typeof api.setUserID, 'function', 'api.setUserID should be a function') - t.end() + await t.test('should have a setUserID method', (t, end) => { + const { api } = t.nr + assert.ok(api.setUserID) + assert.equal(typeof api.setUserID, 'function', 'api.setUserID should be a function') + end() }) - t.test('should set the enduser.id on transaction attributes', (t) => { + await t.test('should set the enduser.id on transaction attributes', (t, end) => { + const { agent, api } = t.nr const id = 'anonymizedUser123456' helper.runInTransaction(agent, (tx) => { api.setUserID(id) - t.equal(loggerMock.warn.callCount, 0, 'should not log warnings when setUserID succeeds') + assert.equal(loggerMock.warn.callCount, 0, 'should not log warnings when setUserID succeeds') const attrs = tx.trace.attributes.get(DESTINATIONS.TRANS_EVENT) - t.equal(attrs['enduser.id'], id, 'should set enduser.id attribute on transaction') + assert.equal(attrs['enduser.id'], id, 'should set enduser.id attribute on transaction') const traceAttrs = tx.trace.attributes.get(DESTINATIONS.TRANS_TRACE) - t.equal(traceAttrs['enduser.id'], id, 'should set enduser.id attribute on transaction') - t.end() + assert.equal(traceAttrs['enduser.id'], id, 'should set enduser.id attribute on transaction') + end() }) }) - t.test('should set enduser.id attribute on error event when in a transaction', (t) => { + await t.test('should set enduser.id attribute on error event when in a transaction', (t, end) => { + const { agent, api } = t.nr const id = 'anonymizedUser567890' helper.runInTransaction(agent, (tx) => { api.setUserID(id) const exception = new Exception(new Error('Test error.')) const [...data] = createError(tx, exception, agent.config) const params = data.at(-2) - t.equal(params.agentAttributes['enduser.id'], id, 'should set enduser.id attribute on error') - t.end() + assert.equal( + params.agentAttributes['enduser.id'], + id, + 'should set enduser.id attribute on error' + ) + end() }) }) @@ -73,19 +78,23 @@ tap.test('Agent API = set user id', (t) => { 'User id is empty or not in a transaction, not assigning `enduser.id` attribute to transaction events, trace events, and/or errors.' const emptyOptions = [null, undefined, ''] - emptyOptions.forEach((value) => { - t.test(`should not assign enduser.id if id is '${value}'`, (t) => { - api.setUserID(value) - t.equal(loggerMock.warn.callCount, 1, 'should warn not id is present') - t.equal(loggerMock.warn.args[0][0], WARN_MSG) - t.end() + await Promise.all( + emptyOptions.map(async (value) => { + await t.test(`should not assign enduser.id if id is '${value}'`, (t, end) => { + const { api } = t.nr + api.setUserID(value) + assert.equal(loggerMock.warn.callCount, 1, 'should warn not id is present') + assert.equal(loggerMock.warn.args[0][0], WARN_MSG) + end() + }) }) - }) + ) - t.test('should not assign enduser.id if no transaction is present', (t) => { + await t.test('should not assign enduser.id if no transaction is present', (t, end) => { + const { api } = t.nr api.setUserID('my-unit-test-id') - t.equal(loggerMock.warn.callCount, 1, 'should warn not id is present') - t.equal(loggerMock.warn.args[0][0], WARN_MSG) - t.end() + assert.equal(loggerMock.warn.callCount, 1, 'should warn not id is present') + assert.equal(loggerMock.warn.args[0][0], WARN_MSG) + end() }) }) diff --git a/test/unit/api/api-shutdown.test.js b/test/unit/api/api-shutdown.test.js index c02e9e9222..de4f2cdb08 100644 --- a/test/unit/api/api-shutdown.test.js +++ b/test/unit/api/api-shutdown.test.js @@ -4,60 +4,44 @@ */ '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') const sinon = require('sinon') -tap.test('Agent API - shutdown', (t) => { - t.autoend() - - let agent = null - let api = null - - function setupAgentApi() { - agent = helper.loadMockedAgent() - api = new API(agent) +test('Agent API - shutdown', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.loadMockedAgent() + ctx.nr.api = new API(agent) agent.config.attributes.enabled = true - } - - function cleanupAgentApi() { - helper.unloadAgent(agent) - agent = null - } - - t.test('exports a shutdown function', (t) => { - setupAgentApi() - t.teardown(() => { - cleanupAgentApi() - }) - - t.ok(api.shutdown) - t.type(api.shutdown, 'function') + ctx.nr.agent = agent + }) - t.end() + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - t.test('calls agent stop', (t) => { - setupAgentApi() - t.teardown(() => { - cleanupAgentApi() - }) + await t.test('exports a shutdown function', (t, end) => { + const { api } = t.nr + assert.ok(api.shutdown) + assert.equal(typeof api.shutdown, 'function') + end() + }) + await t.test('calls agent stop', (t, end) => { + const { agent, api } = t.nr const mock = sinon.mock(agent) mock.expects('stop').once() api.shutdown() mock.verify() - - t.end() + end() }) - t.test('accepts callback as second argument', (t) => { - setupAgentApi() - t.teardown(cleanupAgentApi) - + await t.test('accepts callback as second argument', (t, end) => { + const { agent, api } = t.nr agent.stop = function (cb) { cb() } @@ -65,14 +49,12 @@ tap.test('Agent API - shutdown', (t) => { const callback = sinon.spy() api.shutdown({}, callback) - t.equal(callback.called, true) - t.end() + assert.equal(callback.called, true) + end() }) - t.test('accepts callback as first argument', (t) => { - setupAgentApi() - t.teardown(cleanupAgentApi) - + await t.test('accepts callback as first argument', (t, end) => { + const { agent, api } = t.nr agent.stop = function (cb) { cb() } @@ -80,120 +62,109 @@ tap.test('Agent API - shutdown', (t) => { const callback = sinon.spy() api.shutdown(callback) - t.equal(callback.called, true) - t.end() + assert.equal(callback.called, true) + end() }) - t.test('does not error when no callback is provided', (t) => { - setupAgentApi() - t.teardown(cleanupAgentApi) - - // should not throw - api.shutdown() - - t.end() + await t.test('does not error when no callback is provided', (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { + api.shutdown() + }) + end() }) - t.test('when `options.collectPendingData` is `true`', (t) => { - t.autoend() - - t.beforeEach(setupAgentApi) - t.afterEach(cleanupAgentApi) - - t.test('calls forceHarvestAll when state is `started`', (t) => { - const mock = sinon.mock(agent) - agent.setState('started') - mock.expects('forceHarvestAll').once() - api.shutdown({ collectPendingData: true }) - mock.verify() + await t.test('calls forceHarvestAll when state is `started`', (t, end) => { + const { agent, api } = t.nr + const mock = sinon.mock(agent) + agent.setState('started') + mock.expects('forceHarvestAll').once() + api.shutdown({ collectPendingData: true }) + mock.verify() - t.end() - }) + end() + }) - t.test('calls forceHarvestAll when state changes to "started"', (t) => { - const mock = sinon.mock(agent) - agent.setState('starting') - mock.expects('forceHarvestAll').once() - api.shutdown({ collectPendingData: true }) - agent.setState('started') - mock.verify() + await t.test('calls forceHarvestAll when state changes to "started"', (t, end) => { + const { agent, api } = t.nr + const mock = sinon.mock(agent) + agent.setState('starting') + mock.expects('forceHarvestAll').once() + api.shutdown({ collectPendingData: true }) + agent.setState('started') + mock.verify() - t.end() - }) + end() + }) - t.test('does not call forceHarvestAll when state is not "started"', (t) => { - const mock = sinon.mock(agent) - agent.setState('starting') - mock.expects('forceHarvestAll').never() - api.shutdown({ collectPendingData: true }) - mock.verify() + await t.test('does not call forceHarvestAll when state is not "started"', (t, end) => { + const { agent, api } = t.nr + const mock = sinon.mock(agent) + agent.setState('starting') + mock.expects('forceHarvestAll').never() + api.shutdown({ collectPendingData: true }) + mock.verify() - t.end() - }) + end() + }) - t.test('calls stop when timeout is not given and state changes to "errored"', (t) => { - const mock = sinon.mock(agent) - agent.setState('starting') - mock.expects('stop').once() - api.shutdown({ collectPendingData: true }) - agent.setState('errored') - mock.verify() + await t.test('calls stop when timeout is not given and state changes to "errored"', (t, end) => { + const { agent, api } = t.nr + const mock = sinon.mock(agent) + agent.setState('starting') + mock.expects('stop').once() + api.shutdown({ collectPendingData: true }) + agent.setState('errored') + mock.verify() - t.end() - }) + end() + }) - t.test('calls stop when timeout is given and state changes to "errored"', (t) => { - const mock = sinon.mock(agent) - agent.setState('starting') - mock.expects('stop').once() - api.shutdown({ collectPendingData: true, timeout: 1000 }) - agent.setState('errored') - mock.verify() + await t.test('calls stop when timeout is given and state changes to "errored"', (t, end) => { + const { agent, api } = t.nr + const mock = sinon.mock(agent) + agent.setState('starting') + mock.expects('stop').once() + api.shutdown({ collectPendingData: true, timeout: 1000 }) + agent.setState('errored') + mock.verify() - t.end() - }) + end() }) - t.test('when `options.waitForIdle` is `true`', (t) => { - t.autoend() + await t.test('calls stop when there are no active transactions', (t, end) => { + const { agent, api } = t.nr + const mock = sinon.mock(agent) + agent.setState('started') + mock.expects('stop').once() + api.shutdown({ waitForIdle: true }) + mock.verify() - t.beforeEach(setupAgentApi) - t.afterEach(cleanupAgentApi) + end() + }) - t.test('calls stop when there are no active transactions', (t) => { - const mock = sinon.mock(agent) - agent.setState('started') - mock.expects('stop').once() + await t.test('calls stop after transactions complete when there are some', (t, end) => { + const { agent, api } = t.nr + let mock = sinon.mock(agent) + agent.setState('started') + mock.expects('stop').never() + helper.runInTransaction(agent, (tx) => { api.shutdown({ waitForIdle: true }) mock.verify() + mock.restore() - t.end() - }) - - t.test('calls stop after transactions complete when there are some', (t) => { - let mock = sinon.mock(agent) - agent.setState('started') - mock.expects('stop').never() - helper.runInTransaction(agent, (tx) => { - api.shutdown({ waitForIdle: true }) + mock = sinon.mock(agent) + mock.expects('stop').once() + tx.end() + setImmediate(() => { mock.verify() - mock.restore() - - mock = sinon.mock(agent) - mock.expects('stop').once() - tx.end() - setImmediate(() => { - mock.verify() - t.end() - }) + end() }) }) }) - t.test('calls forceHarvestAll when a timeout is given and not reached', (t) => { - setupAgentApi() - t.teardown(cleanupAgentApi) - + await t.test('calls forceHarvestAll when a timeout is given and not reached', (t, end) => { + const { agent, api } = t.nr const mock = sinon.mock(agent) agent.setState('starting') mock.expects('forceHarvestAll').once() @@ -201,12 +172,11 @@ tap.test('Agent API - shutdown', (t) => { agent.setState('started') mock.verify() - t.end() + end() }) - t.test('calls stop when timeout is reached and does not forceHarvestAll', (t) => { - setupAgentApi() - + await t.test('calls stop when timeout is reached and does not forceHarvestAll', (t, end) => { + const { agent, api } = t.nr const originalSetTimeout = setTimeout let timeoutHandle = null global.setTimeout = function patchedSetTimeout() { @@ -221,11 +191,10 @@ tap.test('Agent API - shutdown', (t) => { return timeoutHandle } - t.teardown(() => { + t.after(() => { timeoutHandle.unref() timeoutHandle = null global.setTimeout = originalSetTimeout - cleanupAgentApi() }) let didCallForceHarvestAll = false @@ -244,17 +213,15 @@ tap.test('Agent API - shutdown', (t) => { agent.setState('starting') api.shutdown({ collectPendingData: true, timeout: 1000 }, function sdCallback() { - t.notOk(didCallForceHarvestAll) - t.equal(stopCallCount, 1) + assert.ok(!didCallForceHarvestAll) + assert.equal(stopCallCount, 1) - t.end() + end() }) }) - t.test('calls forceHarvestAll when timeout is not a number', (t) => { - setupAgentApi() - t.teardown(cleanupAgentApi) - + await t.test('calls forceHarvestAll when timeout is not a number', (t, end) => { + const { agent, api } = t.nr agent.setState('starting') agent.stop = function mockedStop(cb) { @@ -270,17 +237,16 @@ tap.test('Agent API - shutdown', (t) => { } api.shutdown({ collectPendingData: true, timeout: 'xyz' }, function () { - t.equal(forceHarvestCallCount, 1) - t.end() + assert.equal(forceHarvestCallCount, 1) + end() }) // Waits for agent to start before harvesting and shutting down agent.setState('started') }) - t.test('calls stop after harvest', (t) => { - setupAgentApi() - t.teardown(cleanupAgentApi) + await t.test('calls stop after harvest', (t, end) => { + const { agent, api } = t.nr agent.setState('starting') @@ -292,22 +258,21 @@ tap.test('Agent API - shutdown', (t) => { } agent.forceHarvestAll = function mockedForceHarvest(cb) { - t.equal(stopCallCount, 0) + assert.equal(stopCallCount, 0) setImmediate(cb) } api.shutdown({ collectPendingData: true }, function () { - t.equal(stopCallCount, 1) - t.end() + assert.equal(stopCallCount, 1) + end() }) // Waits for agent to start before harvesting and shutting down agent.setState('started') }) - t.test('calls stop when harvest errors', (t) => { - setupAgentApi() - t.teardown(cleanupAgentApi) + await t.test('calls stop when harvest errors', (t, end) => { + const { agent, api } = t.nr agent.setState('starting') @@ -319,7 +284,7 @@ tap.test('Agent API - shutdown', (t) => { } agent.forceHarvestAll = function mockedForceHarvest(cb) { - t.equal(stopCallCount, 0) + assert.equal(stopCallCount, 0) setImmediate(() => { cb(new Error('some error')) @@ -327,8 +292,8 @@ tap.test('Agent API - shutdown', (t) => { } api.shutdown({ collectPendingData: true }, function () { - t.equal(stopCallCount, 1) - t.end() + assert.equal(stopCallCount, 1) + end() }) // Waits for agent to start before harvesting and shutting down diff --git a/test/unit/api/api-start-background-transaction.test.js b/test/unit/api/api-start-background-transaction.test.js index 03a9f61647..822bd22bd0 100644 --- a/test/unit/api/api-start-background-transaction.test.js +++ b/test/unit/api/api-start-background-transaction.test.js @@ -4,81 +4,80 @@ */ '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 - startBackgroundTransaction', (t) => { - t.autoend() - - let agent = null - let contextManager = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - contextManager = helper.getContextManager() - api = new API(agent) +const { assertCLMAttrs } = require('../../lib/custom-assertions') + +function nested({ api }) { + api.startBackgroundTransaction('nested', function nestedHandler() {}) +} + +test('Agent API - startBackgroundTransaction', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.loadMockedAgent() + ctx.nr.contextManager = helper.getContextManager() + ctx.nr.api = new API(agent) + ctx.nr.agent = agent }) - t.afterEach(() => { - helper.unloadAgent(agent) - agent = null - contextManager = null + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - function nested() { - api.startBackgroundTransaction('nested', function nestedHandler() {}) - } - - t.test('should not throw when transaction cannot be created', (t) => { + await t.test('should not throw when transaction cannot be created', (t, end) => { + const { agent, api } = t.nr agent.setState('stopped') api.startBackgroundTransaction('test', () => { const transaction = agent.tracer.getTransaction() - t.notOk(transaction) + assert.ok(!transaction) - t.end() + end() }) }) - t.test('should add nested transaction as segment to parent transaction', (t) => { + await t.test('should add nested transaction as segment to parent transaction', (t, end) => { + const { agent, api, contextManager } = t.nr let transaction = null api.startBackgroundTransaction('test', function () { - nested() + nested({ api }) transaction = agent.tracer.getTransaction() - t.equal(transaction.type, 'bg') - t.equal(transaction.getFullName(), 'OtherTransaction/Nodejs/test') - t.ok(transaction.isActive()) + assert.equal(transaction.type, 'bg') + assert.equal(transaction.getFullName(), 'OtherTransaction/Nodejs/test') + assert.ok(transaction.isActive()) const currentSegment = contextManager.getContext() const nestedSegment = currentSegment.children[0] - t.equal(nestedSegment.name, 'Nodejs/nested') + assert.equal(nestedSegment.name, 'Nodejs/nested') }) - t.notOk(transaction.isActive()) + assert.ok(!transaction.isActive()) - t.end() + end() }) - t.test('should end the transaction after the handle returns by default', (t) => { + await t.test('should end the transaction after the handle returns by default', (t, end) => { + const { agent, api } = t.nr let transaction = null api.startBackgroundTransaction('test', function () { transaction = agent.tracer.getTransaction() - t.equal(transaction.type, 'bg') - t.equal(transaction.getFullName(), 'OtherTransaction/Nodejs/test') - t.ok(transaction.isActive()) + assert.equal(transaction.type, 'bg') + assert.equal(transaction.getFullName(), 'OtherTransaction/Nodejs/test') + assert.ok(transaction.isActive()) }) - t.notOk(transaction.isActive()) + assert.ok(!transaction.isActive()) - t.end() + end() }) - t.test('should be namable with setTransactionName', (t) => { + await t.test('should be namable with setTransactionName', (t, end) => { + const { agent, api } = t.nr let handle = null let transaction = null api.startBackgroundTransaction('test', function () { @@ -86,148 +85,162 @@ tap.test('Agent API - startBackgroundTransaction', (t) => { handle = api.getTransaction() api.setTransactionName('custom name') - t.equal(transaction.type, 'bg') - t.equal(transaction.getFullName(), 'OtherTransaction/Custom/custom name') - t.ok(transaction.isActive()) + assert.equal(transaction.type, 'bg') + assert.equal(transaction.getFullName(), 'OtherTransaction/Custom/custom name') + assert.ok(transaction.isActive()) }) process.nextTick(function () { handle.end() - t.notOk(transaction.isActive()) - t.equal(transaction.getFullName(), 'OtherTransaction/Custom/custom name') + assert.ok(!transaction.isActive()) + assert.equal(transaction.getFullName(), 'OtherTransaction/Custom/custom name') - t.end() + end() }) }) - t.test('should start a background txn with the given name as the name and group', (t) => { - let transaction = null - api.startBackgroundTransaction('test', 'group', function () { - transaction = agent.tracer.getTransaction() - t.ok(transaction) - - t.equal(transaction.type, 'bg') - t.equal(transaction.getFullName(), 'OtherTransaction/group/test') - t.ok(transaction.isActive()) - }) - - t.notOk(transaction.isActive()) + await t.test( + 'should start a background txn with the given name as the name and group', + (t, end) => { + const { agent, api } = t.nr + let transaction = null + api.startBackgroundTransaction('test', 'group', function () { + transaction = agent.tracer.getTransaction() + assert.ok(transaction) + + assert.equal(transaction.type, 'bg') + assert.equal(transaction.getFullName(), 'OtherTransaction/group/test') + assert.ok(transaction.isActive()) + }) - t.end() - }) + assert.ok(!transaction.isActive()) - t.test('should end the txn after a promise returned by the txn function resolves', (t) => { - let thenCalled = false - const FakePromise = { - then: function (f) { - thenCalled = true - f() - return this - } + end() } + ) + + await t.test( + 'should end the txn after a promise returned by the txn function resolves', + (t, end) => { + const { agent, api } = t.nr + let thenCalled = false + const FakePromise = { + then: function (f) { + thenCalled = true + f() + return this + } + } - let transaction = null - api.startBackgroundTransaction('test', function () { - transaction = agent.tracer.getTransaction() + let transaction = null + api.startBackgroundTransaction('test', function () { + transaction = agent.tracer.getTransaction() - t.equal(transaction.type, 'bg') - t.equal(transaction.getFullName(), 'OtherTransaction/Nodejs/test') - t.ok(transaction.isActive()) + assert.equal(transaction.type, 'bg') + assert.equal(transaction.getFullName(), 'OtherTransaction/Nodejs/test') + assert.ok(transaction.isActive()) - t.notOk(thenCalled) - return FakePromise - }) + assert.ok(!thenCalled) + return FakePromise + }) - t.ok(thenCalled) + assert.ok(thenCalled) - t.notOk(transaction.isActive()) + assert.ok(!transaction.isActive()) - t.end() - }) + end() + } + ) - t.test('should not end the txn if the txn is being handled externally', (t) => { + await t.test('should not end the txn if the txn is being handled externally', (t, end) => { + const { agent, api } = t.nr let transaction = null api.startBackgroundTransaction('test', function () { transaction = agent.tracer.getTransaction() - t.equal(transaction.type, 'bg') - t.equal(transaction.getFullName(), 'OtherTransaction/Nodejs/test') - t.ok(transaction.isActive()) + assert.equal(transaction.type, 'bg') + assert.equal(transaction.getFullName(), 'OtherTransaction/Nodejs/test') + assert.ok(transaction.isActive()) transaction.handledExternally = true }) - t.ok(transaction.isActive()) + assert.ok(transaction.isActive()) transaction.end() - t.end() + end() }) - t.test('should call the handler if no name is supplied', (t) => { + await t.test('should call the handler if no name is supplied', (t, end) => { + const { agent, api } = t.nr api.startBackgroundTransaction(null, function () { const transaction = agent.tracer.getTransaction() - t.notOk(transaction) + assert.ok(!transaction) - t.end() + end() }) }) - t.test('should not throw when no handler is supplied', (t) => { - t.doesNotThrow(() => api.startBackgroundTransaction('test')) - t.doesNotThrow(() => api.startBackgroundTransaction('test', 'asdf')) - t.doesNotThrow(() => api.startBackgroundTransaction('test', 'asdf', 'not a function')) + await t.test('should not throw when no handler is supplied', (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => api.startBackgroundTransaction('test')) + assert.doesNotThrow(() => api.startBackgroundTransaction('test', 'asdf')) + assert.doesNotThrow(() => api.startBackgroundTransaction('test', 'asdf', 'not a function')) - t.end() + end() }) const clmEnabled = [true, false] - clmEnabled.forEach((enabled) => { - t.test(`should ${enabled ? 'add' : 'not add'} CLM attributes to segment`, (t) => { - agent.config.code_level_metrics.enabled = enabled - api.startBackgroundTransaction('clm-tx', function handler() { - const segment = api.shim.getSegment() - t.clmAttrs({ - segments: [ - { - segment, - name: 'handler', - filepath: 'test/unit/api/api-start-background-transaction.test.js' - } - ], - enabled - }) - t.end() - }) - }) - - t.test( - `should ${enabled ? 'add' : 'not add'} CLM attributes to nested web transactions`, - (t) => { + await Promise.all( + clmEnabled.map(async (enabled) => { + await t.test(`should ${enabled ? 'add' : 'not add'} CLM attributes to segment`, (t, end) => { + const { agent, api } = t.nr agent.config.code_level_metrics.enabled = enabled - api.startBackgroundTransaction('nested-clm-test', function () { - nested() - const currentSegment = contextManager.getContext() - const nestedSegment = currentSegment.children[0] - t.clmAttrs({ + api.startBackgroundTransaction('clm-tx', function handler() { + const segment = api.shim.getSegment() + assertCLMAttrs({ segments: [ { - segment: currentSegment, - name: '(anonymous)', - filepath: 'test/unit/api/api-start-background-transaction.test.js' - }, - { - segment: nestedSegment, - name: 'nestedHandler', + segment, + name: 'handler', filepath: 'test/unit/api/api-start-background-transaction.test.js' } ], enabled }) + end() }) + }) - t.end() - } - ) - }) + await t.test( + `should ${enabled ? 'add' : 'not add'} CLM attributes to nested web transactions`, + (t, end) => { + const { agent, api, contextManager } = t.nr + agent.config.code_level_metrics.enabled = enabled + api.startBackgroundTransaction('nested-clm-test', function () { + nested({ api }) + const currentSegment = contextManager.getContext() + const nestedSegment = currentSegment.children[0] + assertCLMAttrs({ + segments: [ + { + segment: currentSegment, + name: '(anonymous)', + filepath: 'test/unit/api/api-start-background-transaction.test.js' + }, + { + segment: nestedSegment, + name: 'nestedHandler', + filepath: 'test/unit/api/api-start-background-transaction.test.js' + } + ], + enabled + }) + end() + }) + } + ) + }) + ) }) diff --git a/test/unit/api/api-start-segment.test.js b/test/unit/api/api-start-segment.test.js index 4d83164605..b8efac74b4 100644 --- a/test/unit/api/api-start-segment.test.js +++ b/test/unit/api/api-start-segment.test.js @@ -4,98 +4,100 @@ */ '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 - startSegment', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - api = new API(agent) +const { assertCLMAttrs } = require('../../lib/custom-assertions') + +test('Agent API - startSegment', async (t) => { + 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('should name the segment as provided', (t) => { + await t.test('should name the segment as provided', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function () { api.startSegment('foobar', false, function () { const segment = api.shim.getSegment() - t.ok(segment) - t.equal(segment.name, 'foobar') + assert.ok(segment) + assert.equal(segment.name, 'foobar') - t.end() + end() }) }) }) - t.test('should return the return value of the handler', (t) => { + await t.test('should return the return value of the handler', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function () { const obj = {} const ret = api.startSegment('foobar', false, function () { return obj }) - t.equal(ret, obj) - t.end() + assert.equal(ret, obj) + end() }) }) - t.test('should not record a metric when `record` is `false`', (t) => { + await t.test('should not record a metric when `record` is `false`', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function (tx) { tx.name = 'test' api.startSegment('foobar', false, function () { const segment = api.shim.getSegment() - t.ok(segment) - t.equal(segment.name, 'foobar') + assert.ok(segment) + assert.equal(segment.name, 'foobar') }) tx.end() const hasNameMetric = Object.hasOwnProperty.call(tx.metrics.scoped, tx.name) - t.notOk(hasNameMetric) + assert.ok(!hasNameMetric) const hasCustomMetric = Object.hasOwnProperty.call(tx.metrics.unscoped, 'Custom/foobar') - t.notOk(hasCustomMetric) + assert.ok(!hasCustomMetric) - t.end() + end() }) }) - t.test('should record a metric when `record` is `true`', (t) => { + await t.test('should record a metric when `record` is `true`', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function (tx) { tx.name = 'test' api.startSegment('foobar', true, function () { const segment = api.shim.getSegment() - t.ok(segment) - t.equal(segment.name, 'foobar') + assert.ok(segment) + assert.equal(segment.name, 'foobar') }) tx.end() const transactionNameMetric = tx.metrics.scoped[tx.name] - t.ok(transactionNameMetric) + assert.ok(transactionNameMetric) const transactionScopedCustomMetric = transactionNameMetric['Custom/foobar'] - t.ok(transactionScopedCustomMetric) + assert.ok(transactionScopedCustomMetric) const unscopedCustomMetric = tx.metrics.unscoped['Custom/foobar'] - t.ok(unscopedCustomMetric) + assert.ok(unscopedCustomMetric) - t.end() + end() }) }) - t.test('should time the segment from the callback if provided', (t) => { + await t.test('should time the segment from the callback if provided', (t, end) => { + const { agent, api } = t.nr helper.runInTransaction(agent, function () { api.startSegment( 'foobar', @@ -105,20 +107,21 @@ tap.test('Agent API - startSegment', (t) => { setTimeout(cb, 150, null, segment) }, function (err, segment) { - t.notOk(err) - t.ok(segment) + assert.ok(!err) + assert.ok(segment) const duration = segment.getDurationInMillis() const isExpectedRange = duration >= 100 && duration < 200 - t.ok(isExpectedRange) + assert.ok(isExpectedRange) - t.end() + end() } ) }) }) - t.test('should time the segment from a returned promise', (t) => { + await t.test('should time the segment from a returned promise', (t) => { + const { agent, api } = t.nr return helper.runInTransaction(agent, function () { return api .startSegment('foobar', false, function () { @@ -128,37 +131,38 @@ tap.test('Agent API - startSegment', (t) => { }) }) .then(function (segment) { - t.ok(segment) + assert.ok(segment) const duration = segment.getDurationInMillis() const isExpectedRange = duration >= 100 && duration < 200 - t.ok(isExpectedRange) - - t.end() + assert.ok(isExpectedRange) }) }) }) const clmEnabled = [true, false] - clmEnabled.forEach((enabled) => { - t.test(`should ${enabled ? 'add' : 'not add'} CLM attributes to segment`, (t) => { - agent.config.code_level_metrics.enabled = enabled - helper.runInTransaction(agent, function () { - api.startSegment('foobar', false, function segmentRecorder() { - const segment = api.shim.getSegment() - t.clmAttrs({ - segments: [ - { - segment, - name: 'segmentRecorder', - filepath: 'test/unit/api/api-start-segment.test.js' - } - ], - enabled + await Promise.all( + clmEnabled.map(async (enabled) => { + await t.test(`should ${enabled ? 'add' : 'not add'} CLM attributes to segment`, (t, end) => { + const { agent, api } = t.nr + agent.config.code_level_metrics.enabled = enabled + helper.runInTransaction(agent, function () { + api.startSegment('foobar', false, function segmentRecorder() { + const segment = api.shim.getSegment() + assertCLMAttrs({ + segments: [ + { + segment, + name: 'segmentRecorder', + filepath: 'test/unit/api/api-start-segment.test.js' + } + ], + enabled + }) + end() }) - t.end() }) }) }) - }) + ) }) diff --git a/test/unit/api/api-start-web-transaction.test.js b/test/unit/api/api-start-web-transaction.test.js index 03a77286ee..fd89ded5ee 100644 --- a/test/unit/api/api-start-web-transaction.test.js +++ b/test/unit/api/api-start-web-transaction.test.js @@ -4,192 +4,199 @@ */ '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 - startWebTransaction', (t) => { - t.autoend() - - let agent = null - let contextManager = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - contextManager = helper.getContextManager() - api = new API(agent) +const { assertCLMAttrs } = require('../../lib/custom-assertions') +function nested({ api }) { + api.startWebTransaction('nested', function nestedHandler() {}) +} + +test('Agent API - startWebTransaction', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + const agent = helper.loadMockedAgent() + ctx.nr.contextManager = helper.getContextManager() + ctx.nr.api = new API(agent) + ctx.nr.agent = agent }) - t.afterEach(() => { - helper.unloadAgent(agent) - agent = null - contextManager = null + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - /** - * Helper run a web transaction within an existing one - */ - function nested() { - api.startWebTransaction('nested', function nestedHandler() {}) - } - - t.test('should not throw when transaction cannot be created', (t) => { + await t.test('should not throw when transaction cannot be created', (t, end) => { + const { agent, api } = t.nr agent.setState('stopped') api.startWebTransaction('test', () => { const transaction = agent.tracer.getTransaction() - t.notOk(transaction) + assert.ok(!transaction) - t.end() + end() }) }) - t.test('should add nested transaction as segment to parent transaction', (t) => { + await t.test('should add nested transaction as segment to parent transaction', (t, end) => { + const { agent, api, contextManager } = t.nr let transaction = null api.startWebTransaction('test', function () { - nested() + nested({ api }) transaction = agent.tracer.getTransaction() - t.equal(transaction.type, 'web') - t.equal(transaction.getFullName(), 'WebTransaction/Custom//test') - t.ok(transaction.isActive()) + assert.equal(transaction.type, 'web') + assert.equal(transaction.getFullName(), 'WebTransaction/Custom//test') + assert.ok(transaction.isActive()) const currentSegment = contextManager.getContext() const nestedSegment = currentSegment.children[0] - t.equal(nestedSegment.name, 'nested') + assert.equal(nestedSegment.name, 'nested') }) - t.notOk(transaction.isActive()) + assert.ok(!transaction.isActive()) - t.end() + end() }) - t.test('should end the transaction after the handle returns by default', (t) => { + await t.test('should end the transaction after the handle returns by default', (t, end) => { + const { agent, api } = t.nr let transaction = null api.startWebTransaction('test', function () { transaction = agent.tracer.getTransaction() - t.equal(transaction.type, 'web') - t.equal(transaction.getFullName(), 'WebTransaction/Custom//test') - t.ok(transaction.isActive()) + assert.equal(transaction.type, 'web') + assert.equal(transaction.getFullName(), 'WebTransaction/Custom//test') + assert.ok(transaction.isActive()) }) - t.notOk(transaction.isActive()) - t.end() + assert.ok(!transaction.isActive()) + end() }) - t.test('should end the txn after a promise returned by the txn function resolves', (t) => { - let thenCalled = false - const FakePromise = { - then: function (f) { - thenCalled = true - f() - return this + await t.test( + 'should end the txn after a promise returned by the txn function resolves', + (t, end) => { + const { agent, api } = t.nr + let thenCalled = false + const FakePromise = { + then: function (f) { + thenCalled = true + f() + return this + } } - } - let transaction = null + let transaction = null - api.startWebTransaction('test', function () { - transaction = agent.tracer.getTransaction() - t.equal(transaction.type, 'web') - t.equal(transaction.getFullName(), 'WebTransaction/Custom//test') - t.ok(transaction.isActive()) + api.startWebTransaction('test', function () { + transaction = agent.tracer.getTransaction() + assert.equal(transaction.type, 'web') + assert.equal(transaction.getFullName(), 'WebTransaction/Custom//test') + assert.ok(transaction.isActive()) - t.notOk(thenCalled) - return FakePromise - }) + assert.ok(!thenCalled) + return FakePromise + }) - t.ok(thenCalled) - t.notOk(transaction.isActive()) + assert.ok(thenCalled) + assert.ok(!transaction.isActive()) - t.end() - }) + end() + } + ) - t.test('should not end the txn if the txn is being handled externally', (t) => { + await t.test('should not end the txn if the txn is being handled externally', (t, end) => { + const { agent, api } = t.nr let transaction = null api.startWebTransaction('test', function () { transaction = agent.tracer.getTransaction() - t.equal(transaction.type, 'web') - t.equal(transaction.getFullName(), 'WebTransaction/Custom//test') - t.ok(transaction.isActive()) + assert.equal(transaction.type, 'web') + assert.equal(transaction.getFullName(), 'WebTransaction/Custom//test') + assert.ok(transaction.isActive()) transaction.handledExternally = true }) - t.ok(transaction.isActive()) + assert.ok(transaction.isActive()) transaction.end() - t.end() + end() }) - t.test('should call the handler if no url is supplied', (t) => { + await t.test('should call the handler if no url is supplied', (t, end) => { + const { agent, api } = t.nr let transaction = null api.startWebTransaction(null, function () { transaction = agent.tracer.getTransaction() - t.notOk(transaction) + assert.ok(!transaction) - t.end() + end() }) }) - t.test('should not throw when no handler is supplied', (t) => { + await t.test('should not throw when no handler is supplied', (t, end) => { + const { api } = t.nr // should not throw - api.startWebTransaction('test') + assert.doesNotThrow(() => { + api.startWebTransaction('test') + }) - t.end() + end() }) const clmEnabled = [true, false] - clmEnabled.forEach((enabled) => { - t.test(`should ${enabled ? 'add' : 'not add'} CLM attributes to segment`, (t) => { - agent.config.code_level_metrics.enabled = enabled - api.startWebTransaction('clm-tx', function handler() { - const segment = api.shim.getSegment() - t.clmAttrs({ - segments: [ - { - segment, - name: 'handler', - filepath: 'test/unit/api/api-start-web-transaction.test.js' - } - ], - enabled - }) - t.end() - }) - }) - - t.test( - `should ${enabled ? 'add' : 'not add'} CLM attributes to nested web transactions`, - (t) => { + await Promise.all( + clmEnabled.map(async (enabled) => { + await t.test(`should ${enabled ? 'add' : 'not add'} CLM attributes to segment`, (t, end) => { + const { agent, api } = t.nr agent.config.code_level_metrics.enabled = enabled - api.startWebTransaction('clm-nested-test', function () { - nested() - const currentSegment = contextManager.getContext() - const nestedSegment = currentSegment.children[0] - t.clmAttrs({ + api.startWebTransaction('clm-tx', function handler() { + const segment = api.shim.getSegment() + assertCLMAttrs({ segments: [ { - segment: currentSegment, - name: '(anonymous)', - filepath: 'test/unit/api/api-start-web-transaction.test.js' - }, - { - segment: nestedSegment, - name: 'nestedHandler', + segment, + name: 'handler', filepath: 'test/unit/api/api-start-web-transaction.test.js' } ], enabled }) + end() }) + }) - t.end() - } - ) - }) + await t.test( + `should ${enabled ? 'add' : 'not add'} CLM attributes to nested web transactions`, + (t, end) => { + const { agent, api, contextManager } = t.nr + agent.config.code_level_metrics.enabled = enabled + api.startWebTransaction('clm-nested-test', function () { + nested({ api }) + const currentSegment = contextManager.getContext() + const nestedSegment = currentSegment.children[0] + assertCLMAttrs({ + segments: [ + { + segment: currentSegment, + name: '(anonymous)', + filepath: 'test/unit/api/api-start-web-transaction.test.js' + }, + { + segment: nestedSegment, + name: 'nestedHandler', + filepath: 'test/unit/api/api-start-web-transaction.test.js' + } + ], + enabled + }) + }) + + end() + } + ) + }) + ) }) diff --git a/test/unit/api/api-supportability-metrics.test.js b/test/unit/api/api-supportability-metrics.test.js index f7d2bc5547..78e282f3d5 100644 --- a/test/unit/api/api-supportability-metrics.test.js +++ b/test/unit/api/api-supportability-metrics.test.js @@ -4,46 +4,43 @@ */ 'use strict' - -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const helper = require('../../lib/agent_helper') const API = require('../../../api') const NAMES = require('../../../lib/metrics/names') -tap.test('The API supportability metrics', (t) => { - t.autoend() - - let agent = null - let api = null - +test('The API supportability metrics', async (t) => { const apiCalls = Object.keys(API.prototype) - 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) + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - for (let i = 0; i < apiCalls.length; i++) { - testMetricCalls(apiCalls[i]) + for (const key of apiCalls) { + await testMetricCalls(key) } - function testMetricCalls(name) { - const testName = 'should create a metric for API#' + name - t.test(testName, (t) => { + async function testMetricCalls(name) { + await t.test(`should create a metric for API#${name}`, (t, end) => { + const { agent, api } = t.nr const beforeMetric = agent.metrics.getOrCreateMetric(NAMES.SUPPORTABILITY.API + '/' + name) - t.equal(beforeMetric.callCount, 0) + assert.equal(beforeMetric.callCount, 0) // Some api calls required a name to be given rather than just an empty string api[name]('test') const afterMetric = agent.metrics.getOrCreateMetric(NAMES.SUPPORTABILITY.API + '/' + name) - t.equal(afterMetric.callCount, 1) + assert.equal(afterMetric.callCount, 1) - t.end() + end() }) } }) diff --git a/test/unit/api/api-transaction-handle.test.js b/test/unit/api/api-transaction-handle.test.js index 859f70a2e2..6bea8df7ea 100644 --- a/test/unit/api/api-transaction-handle.test.js +++ b/test/unit/api/api-transaction-handle.test.js @@ -4,138 +4,147 @@ */ '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 - transaction handle', (t) => { - t.autoend() - - let agent = null - let api = null - - t.beforeEach(() => { - agent = helper.loadMockedAgent() - api = new API(agent) +test('Agent API - transaction handle', async (t) => { + 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 getting a transaction handle', (t) => { - t.ok(api.getTransaction) - t.type(api.getTransaction, 'function') + await t.test('exports a function for getting a transaction handle', (t, end) => { + const { api } = t.nr + assert.ok(api.getTransaction) + assert.equal(typeof api.getTransaction, 'function') - t.end() + end() }) - t.test('shoud return a stub when running outside of a transaction', (t) => { + await t.test('should return a stub when running outside of a transaction', (t, end) => { + const { api } = t.nr const handle = api.getTransaction() - t.type(handle.end, 'function') - t.type(handle.ignore, 'function') + assert.equal(typeof handle.end, 'function') + assert.equal(typeof handle.ignore, 'function') - t.type(handle.acceptDistributedTraceHeaders, 'function') - t.type(handle.insertDistributedTraceHeaders, 'function') - t.type(handle.isSampled, 'function') + assert.equal(typeof handle.acceptDistributedTraceHeaders, 'function') + assert.equal(typeof handle.insertDistributedTraceHeaders, 'function') + assert.equal(typeof handle.isSampled, 'function') - t.end() + end() }) - t.test('should mark the transaction as externally handled', (t) => { + await t.test('should mark the transaction as externally handled', (t, end) => { + const { api, agent } = t.nr helper.runInTransaction(agent, function (txn) { const handle = api.getTransaction() - t.ok(txn.handledExternally) - t.type(handle.end, 'function') + assert.ok(txn.handledExternally) + assert.equal(typeof handle.end, 'function') handle.end() - t.end() + end() }) }) - t.test('should return a method to ignore the transaction', (t) => { + await t.test('should return a method to ignore the transaction', (t, end) => { + const { api, agent } = t.nr helper.runInTransaction(agent, function (txn) { const handle = api.getTransaction() - t.type(handle.ignore, 'function') + assert.equal(typeof handle.ignore, 'function') handle.ignore() - t.ok(txn.forceIgnore) - t.type(handle.end, 'function') + assert.ok(txn.forceIgnore) + assert.equal(typeof handle.end, 'function') handle.end() - t.end() + end() }) }) - t.test('should have a method to insert distributed trace headers', (t) => { + await t.test('should have a method to insert distributed trace headers', (t, end) => { + const { api, agent } = t.nr helper.runInTransaction(agent, function () { const handle = api.getTransaction() - t.type(handle.insertDistributedTraceHeaders, 'function') + assert.equal(typeof handle.insertDistributedTraceHeaders, 'function') agent.config.cross_process_id = '1234#5678' const headers = {} handle.insertDistributedTraceHeaders(headers) - t.type(headers.traceparent, 'string') + assert.equal(typeof headers.traceparent, 'string') - t.end() + end() }) }) - t.test('should have a method for accepting distributed trace headers', (t) => { + await t.test('should have a method for accepting distributed trace headers', (t, end) => { + const { api, agent } = t.nr helper.runInTransaction(agent, function () { const handle = api.getTransaction() - t.type(handle.acceptDistributedTraceHeaders, 'function') - t.end() + assert.equal(typeof handle.acceptDistributedTraceHeaders, 'function') + end() }) }) - t.test('should return a handle with a method to end the transaction', (t) => { + await t.test('should return a handle with a method to end the transaction', (t, end) => { + const { api, agent } = t.nr let transaction agent.on('transactionFinished', function (finishedTransaction) { - t.equal(finishedTransaction.id, transaction.id) - t.end() + assert.equal(finishedTransaction.id, transaction.id) + end() }) helper.runInTransaction(agent, function (txn) { transaction = txn const handle = api.getTransaction() - t.type(handle.end, 'function') + assert.equal(typeof handle.end, 'function') handle.end() }) }) - t.test('should call a callback when handle end is called', (t) => { + await t.test('should call a callback when handle end is called', (t, end) => { + const { api, agent } = t.nr helper.runInTransaction(agent, function () { const handle = api.getTransaction() handle.end(function () { - t.end() + end() }) }) }) - t.test('does not blow up when end is called without a callback', (t) => { + await t.test('does not blow up when end is called without a callback', (t, end) => { + const { api, agent } = t.nr helper.runInTransaction(agent, function () { const handle = api.getTransaction() handle.end() - t.end() + end() }) }) - t.test('should have a method for reporting whether the transaction is sampled', (t) => { - helper.runInTransaction(agent, function () { - const handle = api.getTransaction() - t.type(handle.isSampled, 'function') - t.equal(handle.isSampled(), true) + await t.test( + 'should have a method for reporting whether the transaction is sampled', + (t, end) => { + const { api, agent } = t.nr + helper.runInTransaction(agent, function () { + const handle = api.getTransaction() + assert.equal(typeof handle.isSampled, 'function') + assert.equal(handle.isSampled(), true) - t.end() - }) - }) + end() + }) + } + ) }) diff --git a/test/unit/api/stub.test.js b/test/unit/api/stub.test.js index f31f0e9d07..6419188477 100644 --- a/test/unit/api/stub.test.js +++ b/test/unit/api/stub.test.js @@ -4,360 +4,228 @@ */ 'use strict' - -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const API = require('../../../stub_api') -const EXPECTED_API_COUNT = 37 - -tap.test('Agent API - Stubbed Agent API', (t) => { - t.autoend() - - let api = null - - t.beforeEach(() => { - api = new API() - }) - - t.test(`should export ${EXPECTED_API_COUNT - 1} API calls`, (t) => { - const apiKeys = Object.keys(api.constructor.prototype) - t.equal(apiKeys.length, EXPECTED_API_COUNT) - t.end() - }) - - t.test('exports a transaction naming function', (t) => { - t.ok(api.setTransactionName) - t.type(api.setTransactionName, 'function') - - t.end() - }) - - t.test('exports a dispatcher naming function', (t) => { - t.ok(api.setDispatcher) - - t.type(api.setDispatcher, 'function') - - t.end() - }) - - t.test("shouldn't throw when transaction is named", (t) => { - t.doesNotThrow(() => { - api.setTransactionName('TEST/*') - }) - - t.end() - }) - - t.test('exports a controller naming function', (t) => { - t.ok(api.setControllerName) - t.type(api.setControllerName, 'function') - - t.end() - }) - - t.test("shouldn't throw when controller is named without an action", (t) => { - t.doesNotThrow(() => { - api.setControllerName('TEST/*') - }) - - t.end() - }) - - t.test("shouldn't throw when controller is named with an action", (t) => { - t.doesNotThrow(() => { - api.setControllerName('TEST/*', 'test') - }) - - t.end() - }) - - t.test('exports a function to get the current transaction handle', (t) => { - t.ok(api.getTransaction) - t.type(api.getTransaction, 'function') - - t.end() - }) - - t.test('exports a function for adding naming rules', (t) => { - t.ok(api.addNamingRule) - t.type(api.addNamingRule, 'function') - - t.end() - }) - - t.test("shouldn't throw when a naming rule is added", (t) => { - t.doesNotThrow(() => { - api.addNamingRule(/^foo/, '/foo/*') - }) - - t.end() - }) - - t.test('exports a function for ignoring certain URLs', (t) => { - t.ok(api.addIgnoringRule) - t.type(api.addIgnoringRule, 'function') - - t.end() +test('Agent API - Stubbed Agent API', async (t) => { + const apiCalls = Object.keys(API.prototype) + t.beforeEach((ctx) => { + ctx.nr = { + api: new API() + } }) - t.test("shouldn't throw when an ignoring rule is added", (t) => { - t.doesNotThrow(() => { - api.addIgnoringRule(/^foo/, '/foo/*') + for (const key of apiCalls) { + await testApiStubMethod(key) + } + + /** + * This tests that every API method is a function and + * does not throw when calling it + */ + async function testApiStubMethod(name) { + await t.test(`should export a stub of API#${name}`, (t, end) => { + const { api } = t.nr + assert.ok(api[name]) + assert.equal(typeof api[name], 'function') + assert.doesNotThrow(() => { + api[name]('arg') + }) + end() }) + } - t.end() - }) - - t.test('exports a function for getting linking metadata', (t) => { - t.ok(api.getLinkingMetadata) - t.type(api.getTraceMetadata, 'function') + /** + * All tests below test bespoke behavior of smoe of the stubbed API methods. + */ + await t.test('exports a function for getting linking metadata', (t, end) => { + const { api } = t.nr const metadata = api.getLinkingMetadata() - t.type(metadata, 'object') + assert.equal(typeof metadata, 'object') - t.end() + end() }) - t.test('exports a function for getting trace metadata', (t) => { - t.ok(api.getTraceMetadata) - t.type(api.getTraceMetadata, 'function') + await t.test('exports a function for getting trace metadata', (t, end) => { + const { api } = t.nr + assert.ok(api.getTraceMetadata) + assert.equal(typeof api.getTraceMetadata, 'function') const metadata = api.getTraceMetadata() - t.type(metadata, 'object') - t.type(metadata.traceId, 'string') - t.equal(metadata.traceId, '') - t.type(metadata.spanId, 'string') - t.equal(metadata.spanId, '') - - t.end() - }) - - t.test('exports a function for capturing errors', (t) => { - t.ok(api.noticeError) - t.type(api.noticeError, 'function') - - t.end() - }) - - t.test("shouldn't throw when an error is added", (t) => { - t.doesNotThrow(() => { - api.noticeError(new Error()) - }) + assert.equal(typeof metadata, 'object') + assert.equal(typeof metadata.traceId, 'string') + assert.equal(metadata.traceId, '') + assert.equal(typeof metadata.spanId, 'string') + assert.equal(metadata.spanId, '') - t.end() + end() }) - t.test('should return an empty string when requesting browser monitoring', (t) => { + await t.test('should return an empty string when requesting browser monitoring', (t, end) => { + const { api } = t.nr const header = api.getBrowserTimingHeader() - t.equal(header, '') + assert.equal(header, '') - t.end() + end() }) - t.test("shouldn't throw when a custom parameter is added", (t) => { - t.doesNotThrow(() => { - api.addCustomAttribute('test', 'value') - }) - - t.end() - }) - - t.test('exports a function for adding multiple custom parameters at once', (t) => { - t.ok(api.addCustomAttributes) - t.type(api.addCustomAttributes, 'function') - - t.end() - }) - - t.test("shouldn't throw when multiple custom parameters are added", (t) => { - t.doesNotThrow(() => { - api.addCustomAttributes({ test: 'value', test2: 'value2' }) - }) - - t.end() - }) - - t.test('should return a function when calling setLambdaHandler', (t) => { + await t.test('should return a function when calling setLambdaHandler', (t, end) => { + const { api } = t.nr function myNop() {} const retVal = api.setLambdaHandler(myNop) - t.equal(retVal, myNop) + assert.equal(retVal, myNop) - t.end() + end() }) - t.test('should call the function passed into `startSegment`', (t) => { + await t.test('should call the function passed into `startSegment`', (t, end) => { + const { api } = t.nr api.startSegment('foo', false, () => { - t.end() + end() }) }) - t.test('should not throw when a non-function is passed to `startSegment`', (t) => { - t.doesNotThrow(() => { + await t.test('should not throw when a non-function is passed to `startSegment`', (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { api.startSegment('foo', false, null) }) - t.end() + end() }) - t.test('should return the return value of the handler', (t) => { + await t.test('should return the return value of the handler', (t, end) => { + const { api } = t.nr const obj = {} const ret = api.startSegment('foo', false, function () { return obj }) - t.equal(obj, ret) + assert.equal(obj, ret) - t.end() + end() }) - t.test("shouldn't throw when a custom web transaction is started", (t) => { - t.doesNotThrow(() => { + await t.test("shouldn't throw when a custom web transaction is started", (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { api.startWebTransaction('test', function nop() {}) }) - t.end() + end() }) - t.test('should call the function passed into startWebTransaction', (t) => { + await t.test('should call the function passed into startWebTransaction', (t, end) => { + const { api } = t.nr api.startWebTransaction('test', function nop() { - t.end() + end() }) }) - t.test("shouldn't throw when a callback isn't passed into startWebTransaction", (t) => { - t.doesNotThrow(() => { - api.startWebTransaction('test') - }) + await t.test( + "shouldn't throw when a callback isn't passed into startWebTransaction", + (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { + api.startWebTransaction('test') + }) - t.end() - }) + end() + } + ) - t.test("shouldn't throw when a non-function callback is passed into startWebTransaction", (t) => { - t.doesNotThrow(() => { - api.startWebTransaction('test', 'asdf') - }) + await t.test( + "shouldn't throw when a non-function callback is passed into startWebTransaction", + (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { + api.startWebTransaction('test', 'asdf') + }) - t.end() - }) + end() + } + ) - t.test("shouldn't throw when a custom background transaction is started", (t) => { - t.doesNotThrow(() => { + await t.test("shouldn't throw when a custom background transaction is started", (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { api.startBackgroundTransaction('test', 'group', function nop() {}) }) - t.end() + end() }) - t.test('should call the function passed into startBackgroundTransaction', (t) => { + await t.test('should call the function passed into startBackgroundTransaction', (t, end) => { + const { api } = t.nr api.startBackgroundTransaction('test', 'group', function nop() { - t.end() + end() }) }) - t.test("shouldn't throw when a callback isn't passed into startBackgroundTransaction", (t) => { - t.doesNotThrow(() => { - api.startBackgroundTransaction('test', 'group') - }) + await t.test( + "shouldn't throw when a callback isn't passed into startBackgroundTransaction", + (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { + api.startBackgroundTransaction('test', 'group') + }) - t.end() - }) + end() + } + ) - t.test( + await t.test( "shouldn't throw when non-function callback is passed to startBackgroundTransaction", - (t) => { - t.doesNotThrow(() => { + (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { api.startBackgroundTransaction('test', 'group', 'asdf') }) - t.end() + end() } ) - t.test("shouldn't throw when a custom background transaction is started with no group", (t) => { - t.doesNotThrow(() => { - api.startBackgroundTransaction('test', function nop() {}) - }) + await t.test( + "shouldn't throw when a custom background transaction is started with no group", + (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { + api.startBackgroundTransaction('test', function nop() {}) + }) - t.end() - }) + end() + } + ) - t.test('should call the function passed into startBackgroundTransaction with no group', (t) => { - api.startBackgroundTransaction('test', function nop() { - t.end() - }) - }) + await t.test( + 'should call the function passed into startBackgroundTransaction with no group', + (t, end) => { + const { api } = t.nr + api.startBackgroundTransaction('test', function nop() { + end() + }) + } + ) - t.test( + await t.test( "shouldn't throw when a callback isn't passed into startBackgroundTransaction " + 'with no group', - (t) => { - t.doesNotThrow(() => { + (t, end) => { + const { api } = t.nr + assert.doesNotThrow(() => { api.startBackgroundTransaction('test') }) - t.end() + end() } ) - t.test("shouldn't throw when a transaction is ended", (t) => { - t.doesNotThrow(() => { - api.endTransaction() - }) - - t.end() - }) - - t.test('exports a metric recording function', (t) => { - t.ok(api.recordMetric) - t.type(api.recordMetric, 'function') - - t.end() - }) - - t.test('should not throw when calling the metric recorder', (t) => { - t.doesNotThrow(() => { - api.recordMetric('metricname', 1) - }) - - t.end() - }) - - t.test('exports a metric increment function', (t) => { - t.ok(api.incrementMetric) - t.type(api.incrementMetric, 'function') - - t.end() - }) - - t.test('should not throw when calling a metric incrementor', (t) => { - t.doesNotThrow(() => { - api.incrementMetric('metric name') - }) - - t.end() - }) - - t.test('exports a record custom event function', (t) => { - t.ok(api.recordCustomEvent) - t.type(api.recordCustomEvent, 'function') - - t.end() - }) - - t.test('should not throw when calling the custom metric recorder', (t) => { - t.doesNotThrow(() => { - api.recordCustomEvent('EventName', { id: 10 }) - }) - - t.end() - }) - - t.test('exports llm message api', (t) => { - t.type(api.recordLlmFeedbackEvent, 'function') - t.end() - }) - - t.test('exports ignoreApdex', (t) => { - t.type(api.ignoreApdex, 'function') - t.end() + await t.test('returns a TransactionHandle stub on getTransaction', (t, end) => { + const { api } = t.nr + const Stub = api.getTransaction() + assert.equal(Stub.constructor.name, 'TransactionHandleStub') + end() }) }) diff --git a/test/unit/util/code-level-metrics.test.js b/test/unit/util/code-level-metrics.test.js index e6985c2f45..b311553985 100644 --- a/test/unit/util/code-level-metrics.test.js +++ b/test/unit/util/code-level-metrics.test.js @@ -12,7 +12,7 @@ const path = require('path') const helperPath = path.resolve(`${__dirname}/../../lib/clm-helper.js`) const sinon = require('sinon') const symbols = require('../../../lib/symbols') -require('../../lib/custom-assertions') +require('../../lib/custom-tap-assertions') /** * Helper to generate a long string