From 0f3d25252b2c22353af37c9e51248b8abebfdad8 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Thu, 24 Apr 2025 15:26:29 +0100 Subject: [PATCH] Add unit tests --- .../@node-red/runtime/lib/telemetry/index.js | 20 ++-- .../runtime/lib/telemetry/metrics/03-env.js | 2 +- .../runtime/lib/telemetry/index_spec.js | 96 +++++++++++++++++++ .../lib/telemetry/metrics/01-core_spec.js | 16 ++++ .../lib/telemetry/metrics/02-os_spec.js | 14 +++ .../lib/telemetry/metrics/03-env_spec.js | 17 ++++ 6 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 test/unit/@node-red/runtime/lib/telemetry/index_spec.js create mode 100644 test/unit/@node-red/runtime/lib/telemetry/metrics/01-core_spec.js create mode 100644 test/unit/@node-red/runtime/lib/telemetry/metrics/02-os_spec.js create mode 100644 test/unit/@node-red/runtime/lib/telemetry/metrics/03-env_spec.js diff --git a/packages/node_modules/@node-red/runtime/lib/telemetry/index.js b/packages/node_modules/@node-red/runtime/lib/telemetry/index.js index f389407a8..2836d407b 100644 --- a/packages/node_modules/@node-red/runtime/lib/telemetry/index.js +++ b/packages/node_modules/@node-red/runtime/lib/telemetry/index.js @@ -106,16 +106,16 @@ function isTelemetryEnabled () { return undefined } - // If there are telemetry settings, use what it says - if (telemetrySettings && telemetrySettings.enabled !== undefined) { - return telemetrySettings.enabled - } - // User has made a choice; defer to that if (runtimeTelemetryEnabled !== undefined) { return runtimeTelemetryEnabled } + // If there are telemetry settings, use what it says + if (telemetrySettings && telemetrySettings.enabled !== undefined) { + return telemetrySettings.enabled + } + // At this point, we have no sign the user has consented to telemetry, so // keep disabled - but return undefined as a false-like value to distinguish // it from the explicit disable above @@ -157,6 +157,7 @@ function stopTelemetry () { module.exports = { init: (_runtime) => { runtime = _runtime + if (isTelemetryEnabled()) { startTelemetry() } @@ -185,5 +186,12 @@ module.exports = { * Get telemetry enabled status * @returns {boolean} true if telemetry is enabled, false if disabled, undefined if not set */ - isEnabled: isTelemetryEnabled + isEnabled: isTelemetryEnabled, + + stop: () => { + if (scheduleTask) { + scheduleTask.stop() + scheduleTask = null + } + } } \ No newline at end of file diff --git a/packages/node_modules/@node-red/runtime/lib/telemetry/metrics/03-env.js b/packages/node_modules/@node-red/runtime/lib/telemetry/metrics/03-env.js index 812c3ee4e..173adc752 100644 --- a/packages/node_modules/@node-red/runtime/lib/telemetry/metrics/03-env.js +++ b/packages/node_modules/@node-red/runtime/lib/telemetry/metrics/03-env.js @@ -1,6 +1,6 @@ const process = require('process') -module.exports = async (runtime) => { +module.exports = (runtime) => { return { 'env.nodejs': process.version.replace(/^v/, ''), 'env.node-red': runtime.settings.version diff --git a/test/unit/@node-red/runtime/lib/telemetry/index_spec.js b/test/unit/@node-red/runtime/lib/telemetry/index_spec.js new file mode 100644 index 000000000..7ab1b89d1 --- /dev/null +++ b/test/unit/@node-red/runtime/lib/telemetry/index_spec.js @@ -0,0 +1,96 @@ +const should = require("should"); +const NR_TEST_UTILS = require("nr-test-utils"); + +const telemetryApi = NR_TEST_UTILS.require("@node-red/runtime/lib/telemetry/index"); + +describe("telemetry", function() { + + afterEach(function () { + telemetryApi.stop() + messages = [] + }) + + let messages = [] + + function getMockRuntime(settings) { + return { + settings: { + get: key => { return settings[key] }, + set: (key, value) => { settings[key] = value }, + available: () => true, + }, + log: { + debug: (msg) => { messages.push(msg)} + } + } + } + + // Principles to test: + // - No settings at all; disable telemetry + // - Runtime settings only; do what it says + // - User settings take precedence over runtime settings + + it('Disables telemetry with no settings present', function () { + telemetryApi.init(getMockRuntime({})) + messages.should.have.length(0) + // Returns undefined as we don't know either way + ;(telemetryApi.isEnabled() === undefined).should.be.true() + }) + it('Runtime settings - enable', function () { + // Enabled in runtime settings + telemetryApi.init(getMockRuntime({ + telemetry: { enabled: true } + })) + telemetryApi.isEnabled().should.be.true() + messages.should.have.length(1) + ;/Telemetry enabled/.test(messages[0]).should.be.true() + }) + it('Runtime settings - disable', function () { + telemetryApi.init(getMockRuntime({ + telemetry: { enabled: false }, + })) + // Returns false, not undefined + telemetryApi.isEnabled().should.be.false() + messages.should.have.length(0) + }) + + it('User settings - enable overrides runtime settings', function () { + telemetryApi.init(getMockRuntime({ + telemetry: { enabled: false }, + telemetryEnabled: true + })) + telemetryApi.isEnabled().should.be.true() + messages.should.have.length(1) + ;/Telemetry enabled/.test(messages[0]).should.be.true() + }) + + it('User settings - disable overrides runtime settings', function () { + telemetryApi.init(getMockRuntime({ + telemetry: { enabled: true }, + telemetryEnabled: false + })) + telemetryApi.isEnabled().should.be.false() + messages.should.have.length(0) + }) + + it('Can enable/disable telemetry', function () { + const settings = {} + telemetryApi.init(getMockRuntime(settings)) + ;(telemetryApi.isEnabled() === undefined).should.be.true() + + telemetryApi.enable() + + telemetryApi.isEnabled().should.be.true() + messages.should.have.length(1) + ;/Telemetry enabled/.test(messages[0]).should.be.true() + settings.should.have.property('telemetryEnabled', true) + + telemetryApi.disable() + + telemetryApi.isEnabled().should.be.false() + messages.should.have.length(2) + ;/Telemetry disabled/.test(messages[1]).should.be.true() + settings.should.have.property('telemetryEnabled', false) + + }) +}) \ No newline at end of file diff --git a/test/unit/@node-red/runtime/lib/telemetry/metrics/01-core_spec.js b/test/unit/@node-red/runtime/lib/telemetry/metrics/01-core_spec.js new file mode 100644 index 000000000..d1e012e5a --- /dev/null +++ b/test/unit/@node-red/runtime/lib/telemetry/metrics/01-core_spec.js @@ -0,0 +1,16 @@ +const should = require("should"); +const NR_TEST_UTILS = require("nr-test-utils"); + +const api = NR_TEST_UTILS.require("@node-red/runtime/lib/telemetry/metrics/01-core"); + +describe("telemetry metrics/01-core", function() { + + it('reports core metrics', function () { + const result = api({ + settings: { + get: key => { return {instanceId: "1234"}[key]} + } + }) + result.should.have.property("instanceId", "1234") + }) +}) \ No newline at end of file diff --git a/test/unit/@node-red/runtime/lib/telemetry/metrics/02-os_spec.js b/test/unit/@node-red/runtime/lib/telemetry/metrics/02-os_spec.js new file mode 100644 index 000000000..77a4b60af --- /dev/null +++ b/test/unit/@node-red/runtime/lib/telemetry/metrics/02-os_spec.js @@ -0,0 +1,14 @@ +const should = require("should"); +const NR_TEST_UTILS = require("nr-test-utils"); + +const api = NR_TEST_UTILS.require("@node-red/runtime/lib/telemetry/metrics/02-os"); + +describe("telemetry metrics/02-os", function() { + + it('reports os metrics', function () { + const result = api() + result.should.have.property("os.type") + result.should.have.property("os.release") + result.should.have.property("os.arch") + }) +}) \ No newline at end of file diff --git a/test/unit/@node-red/runtime/lib/telemetry/metrics/03-env_spec.js b/test/unit/@node-red/runtime/lib/telemetry/metrics/03-env_spec.js new file mode 100644 index 000000000..eff539270 --- /dev/null +++ b/test/unit/@node-red/runtime/lib/telemetry/metrics/03-env_spec.js @@ -0,0 +1,17 @@ +const should = require("should"); +const NR_TEST_UTILS = require("nr-test-utils"); + +const api = NR_TEST_UTILS.require("@node-red/runtime/lib/telemetry/metrics/03-env"); + +describe("telemetry metrics/03-env", function() { + + it('reports env metrics', function () { + const result = api({ + settings: { + version: '1.2.3' + } + }) + result.should.have.property("env.nodejs", process.version.replace(/^v/, '')) + result.should.have.property("env.node-red", '1.2.3') + }) +}) \ No newline at end of file