diff --git a/.gitignore b/.gitignore index b24d71e..0fadbf1 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,5 @@ Thumbs.db *.mov *.wmv +.nyc_output + diff --git a/systacomfort2/systacomfort2.js b/systacomfort2/systacomfort2.js index bdce471..d96c74c 100644 --- a/systacomfort2/systacomfort2.js +++ b/systacomfort2/systacomfort2.js @@ -48,13 +48,13 @@ module.exports = function(RED) { const address = udpServer.address() node.status({ fill: 'green', shape: 'dot', text: `Server is listening: ${address.address}:${address.port}` }) }) - udpServer.bind(config.listenPort || PARADIGMA_UDP_PORT_DEFAULT) + udpServer.bind(config.listenPort || PARADIGMA_UDP_PORT_DEFAULT) // Cleanup hooks node.on('close', () => { if ( udpServer ) { udpServer.close() } - }) + }) } /** diff --git a/test/systacomfort2-spec.js b/test/systacomfort2-spec.js index ce294c5..1cdedab 100644 --- a/test/systacomfort2-spec.js +++ b/test/systacomfort2-spec.js @@ -6,13 +6,16 @@ * Copyright (c) captica GmbH est. 2022 / MIT License */ const { expect } = require('chai') +const dgram = require('node:dgram') const systaComfort2Node = require('../systacomfort2/systacomfort2') const { dataParser, SYSTACOMFORT_VALUES } = require('../systacomfort2/dataparser') +const { assert } = require('node:console') const MESSAGE_INIT = 'AJe+LI4NzW0JCQwAMtoAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWAIAAAEAAAACAAAAAAAAADIAAAAyAAAAMgAAAGQAAAC4MP4/APgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABqAwAAGgMAAE4DAAA8AwAAUgEAAAAAAAA5AAAAlwMAAA0AAAAAAAAAvAIAAIQDAAC8AgAAvAAAAC6TBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAy9tHAsmsAQBQAAAANwAAAAAAAAAEAAAAGgMAAGsDAABOAwAAUgEAAAAAAABrAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAruTDkA==' const MESSAGE_INIT_ANSWER = 'AJe+LI4NzW0AAAAAAQAAABGcjK0=' const MESSAGE_DATA = 'AJe+LI4NzG0JCQwAMtoAAAEAAAAAAAAAOgEAAFYBAADU/v//SwMAAEUDAABCAwAA1P7//9T+///U/v//AAAAAAAAAABrAwAAXwIAAFoCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgCAADNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAyAAAAOYAAACgAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAA+gAAAAAAAAAGAAAAAAAAACYCAADIAAAAZAAAABQAAAB4AAAAAAAAADIAAABQAAAAZAAAAAUAAAACAAAAMgAAAB4AAAAAAAAAAAAAAAAAAAADAAAAMgAAAPQBAAAEAAAAMgAAAHISAADYAQAAAAAAAAAAAAABAAAAyAAAANwAAACWAAAAAAAAAAAAAAAAAAAAIwcAACQHAAAAAAAAXgEAAAAAAAANAAAAAAAAALwCAADIAAAAZAAAABQAAAB4AAAAAAAAAAAAAADIAAAAZAAAAAUAAAACAAAAMgAAAB4AAAAAAAAAAAAAAAAAAAADAAAAMgAAAPQBAAAEAAAAMgAAACMHAAAAAAAAAAAAAAAAAAABAAAAyAAAANwAAACWAAAAAAAAAAAAAAAAAAAAIwcAACQHAABeAQAAAAAAAA0AAAAAAAAAvAIAAMgAAABkAAAAFAAAAHgAAAAAAAAAAAAAAMgAAABkAAAABQAAAAIAAAAAAAAAAAAAAAMAAAAyAAAA9AEAAAQAAAAyAAAAIwcAAAAAAABYAgAAigIAAAEAAABkAAAAZAAAAAAAAAAyAAAAUgMAAAAAAAAFAAAAtgMAAAAAAAAyAAAAAAAAAJABAABkAAAAAQAAAAEAAAADAAAAAwAAAAMAAAAPAAAAMgAAAKQAAAAAAAAAAAAAABMAAAAFAAAAAAAAAAAAAAAjHAAAIwAAAAVZAAANAAAAEgAAAB51AAAcAAAAAAAAAAAAAAAAAAAALAEAAIoCAABkAAAAGQAAAAAAAAAAAAAA+gAAABgBAAAAAAAAAAAAAAAAAAC8AgAAAAAAAMgAAABkAAAAAgAAAMgAAAAeAAAAAAAAABQAAAAeAAAAHgAAADIAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAQAAAAEAAAAHAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/h54Ug==' const TOPIC_PREFIX = 'my/custom/topic/prefix' +const CONFIG = { listenPort: 44556 } const OUTPUT_MESSAGE_PAYLOAD = { BOILER_START_COUNTER: 22789, BOILER_WORKING_HOURS: 7203, @@ -33,18 +36,54 @@ const OUTPUT_MESSAGE_PAYLOAD = { /** * Node-RED registration/handling */ -describe('SystaComfort2 - Node-RED node', () => { +describe('SystaComfort2 - Node-RED node', () => { + // Constructor will be announced on register. We have to keep the object for later tests + let testNodeConstructor = null + let closeCallback = null // Check node registration first. We fake the RED-objec to capture the registration part systaComfort2Node({ nodes: { - registerType: function(name, obj) { + registerType: function(name, nodeConstructor) { it('should be registered on node-RED as a new node type', () => { expect(name).to.equal('systacomfort2') - expect(obj).to.not.be.undefined + expect(nodeConstructor).to.not.be.undefined }) + testNodeConstructor = nodeConstructor + }, + createNode: function(context, config) { + // Extend context with additional special function (normally provided by node red context object) + context.on = function(eventName, callback) { + closeCallback = callback + } + context.status = function(statusObj) { + it('status object should be present', () => { + expect(configObj).to.not.be.undefined + }) + } + it('should be provided the same config object', () => { + expect(config).to.be.equal(CONFIG) + }) } } }) + /** + * Call the node constructor + */ + it('should be possible to call node constructor and access udp server', () => { + try { + testNodeConstructor(CONFIG) + // Create a udp client to connect to service + const client = dgram.createSocket('udp4') + client.connect(CONFIG.listenPort, (err) => { + expect(err).to.be.undefined + client.close() + }) + } + finally { + // Don't forget to send close event after tests + closeCallback() + } + }) }) /**