# Capturing input messages with node-red-node-test-helper not working

**URL:** https://discourse.nodered.org/t/capturing-input-messages-with-node-red-node-test-helper-not-working/43596
**Category:** Developing Nodes
**Created:** [3 April 2021 12:41 UTC](https://discourse.nodered.org/t/capturing-input-messages-with-node-red-node-test-helper-not-working/43596 "2021-04-03T12:41:25Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![jens\_rossbach](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jens_rossbach/32/98717_2.png) [@jens\_rossbach](https://discourse.nodered.org/u/jens_rossbach)
#### Post date: [3 April 2021 12:41 UTC](https://discourse.nodered.org/t/capturing-input-messages-with-node-red-node-test-helper-not-working/43596/1 "2021-04-03T12:41:25Z")

</div>

Hi,

recently I started writing unit tests for my Node-RED nodes. I'm using node-red-node-test-helper and already implemented a couple of tests which work just fine.

But now I got stuck implementing a test which involves sending a message from my node to the helper node. I just cannot get it working, the callback function for the "input" event is never called. But I'm sure that my node sends a message during the test. I verified this by instrumenting the code and saw that the `send` function is called. Additionally I faked the test to pass and measured the coverage and also here I saw that the `send` function was called.

The code of the node under test is available on GitHub:

> <https://github.com/jensrossbach/node-red-contrib-chronos/blob/master/nodes/scheduler.js>

This is my test code:

```javascript
const sinon = require("sinon");

const helper = require("node-red-node-test-helper");
const configNode = require("../nodes/config.js");
const schedulerNode = require("../nodes/scheduler.js");
const chronos = require("../nodes/common/chronos.js");
const moment = require("moment");

describe("scheduler node", function()
{
    context("node timers", function()
    {
        let clock = null;

        before(function(done)
        {
            helper.startServer(done);
        });

        after(function(done)
        {
            helper.stopServer(done);
        });

        beforeEach(function()
        {
            clock = sinon.useFakeTimers();
            sinon.stub(chronos, "getCurrentTime").returns(moment().utc());
        });

        afterEach(function()
        {
            helper.unload();
            sinon.restore();
            clock.restore();
        });

        it("should trigger at specified time", async function(done)
        {
            const flow = [{id: "sn1", type: "chronos-scheduler", name: "scheduler", config: "cn1", wires: [["hn1"]], schedule: [{trigger: {type: "time", value: "00:01", offset: 0, random: false}, output: {type: "msg", property: {name: "payload", type: "string", value: "test"}}}], outputs: 1},
                          {id: "hn1", type: "helper"},
                          {id: "cn1", type: "chronos-config", name: "config"}];
            const credentials = {"cn1": {latitude: "50", longitude: "10"}};

            await helper.load([schedulerNode, configNode], flow, credentials);
            const hn1 = helper.getNode("hn1");

            hn1.on("input", function(msg)
            {
                try
                {
                    msg.should.have.property("payload", "test");
                    done();
                }
                catch(e)
                {
                    done(e);
                }
            });

            clock.tick(60000);
        });
    });
});

```

I always get this error from mocha as the `done` function is never called:

`Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.`

Any idea what I'm doing wrong and how I can get this working?

Best regards,  
Jens

---

<div class="post-metadata">

### Author: ![jens\_rossbach](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jens_rossbach/32/98717_2.png) [@jens\_rossbach](https://discourse.nodered.org/u/jens_rossbach)
#### Post date: [10 April 2021 09:59 UTC](https://discourse.nodered.org/t/capturing-input-messages-with-node-red-node-test-helper-not-working/43596/2 "2021-04-10T09:59:29Z")

</div>

Any help? I know that node-red-node-test-helper is not used so widely outside of the Node-RED core development, but maybe someone from the Node-RED development team has an idea? Could it be related to the usage of sinonjs fake timers? Or maybe because of using a configuration node and credentials? There do not seem to exist comparable examples from the node-red-node-test-helper repository or the Node-RED unit tests.

---

<div class="post-metadata">

### Author: ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)
#### Post date: [10 April 2021 10:07 UTC](https://discourse.nodered.org/t/capturing-input-messages-with-node-red-node-test-helper-not-working/43596/3 "2021-04-10T10:07:41Z")

</div>

I'll try to take a look tonight. I can't see anything obvious from the code you've shared. As you note, there aren't comparable examples in the core tests - in particular, we`ve never used the fake timers provided by Sinon (although perhaps we should...).

---

<div class="post-metadata">

### Author: ![ncherry](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ncherry/32/27_2.png) [@ncherry](https://discourse.nodered.org/u/ncherry)
#### Post date: [10 April 2021 22:44 UTC](https://discourse.nodered.org/t/capturing-input-messages-with-node-red-node-test-helper-not-working/43596/4 "2021-04-10T22:44:36Z")

</div>

This was happening to my code also (the Timeout of 2000ms exceeded) and I had to approach the timer test a bit differently.

> **[linuxha/node-red-contrib-mytimeout](https://github.com/linuxha/node-red-contrib-mytimeout/tree/feature/dev-test)**
>
> feature/dev-test

I can't recall much about this as I'm currently working on other things. The main command:

```auto
  "scripts": {
    "pretest": "eslint *.js",
    "test": "mocha --exit \"test/*_spec.js\"",
     ...
  },

```

I think that 0000\_basic\_spec.js may have something interesting, Test Case 23 runs for 15 seconds. Just understand that I haven't completed all the tests but I think the basic test cases are all valid and correct.

---

<div class="post-metadata">

### Author: ![jens\_rossbach](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jens_rossbach/32/98717_2.png) [@jens\_rossbach](https://discourse.nodered.org/u/jens_rossbach)
#### Post date: [11 April 2021 13:52 UTC](https://discourse.nodered.org/t/capturing-input-messages-with-node-red-node-test-helper-not-working/43596/5 "2021-04-11T13:52:32Z")

</div>

I implemented another test without fake timers, this time checking the retrieval of an input message (which is independent of any timers). Also this test fails because the "input" event callback added in the test is never called. Again I instrumented the code of my node and could see that the message was received inside the node itself.

```javascript
    context("node input", function()
    {
        let clock = null;

        before(function(done)
        {
            helper.startServer(done);
        });

        after(function(done)
        {
            helper.stopServer(done);
        });

        beforeEach(function()
        {
        });

        afterEach(function()
        {
            helper.unload();
        });

        it("should switch off schedule", async function(done)
        {
            const flow = [{id: "sn1", type: "chronos-scheduler", name: "scheduler", config: "cn1", schedule: [{trigger: {type: "time", value: "00:01", offset: 0, random: false}, output: {type: "msg", property: {name: "payload", type: "string", value: "test"}}}], outputs: 1},
                          {id: "cn1", type: "chronos-config", name: "config"}];
            const credentials = {"cn1": {latitude: "50", longitude: "10"}};

            await helper.load([configNode, schedulerNode], flow, credentials);
            const sn1 = helper.getNode("sn1");

            sn1.on("input", function()
            {
                try
                {
                    sn1.disabledSchedule.should.be.false();
                    done();
                }
                catch(e)
                {
                    done(e);
                }
            });

            sn1.receive({payload: false});
        });
    });

```

As there are no Sinon fake timers involved this time, the problem must be caused by something else. The only difference compared to all the examples from node-red-node-test-helper and Node-RED unit tests I can see is the usage of a configuration node and the usage of credentials.

---

<div class="post-metadata">

### Author: ![jens\_rossbach](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jens_rossbach/32/98717_2.png) [@jens\_rossbach](https://discourse.nodered.org/u/jens_rossbach)
#### Post date: [18 April 2021 15:52 UTC](https://discourse.nodered.org/t/capturing-input-messages-with-node-red-node-test-helper-not-working/43596/6 "2021-04-18T15:52:29Z")

</div>

Regarding the above case, after walking through the code with a debugger, I found out that the fact of calling the `done` function inside of the input event listener of my node seems to prevent the second input event listener (defined in my test function) to be called. This is because there is a variable `c` inside the `_emitInput` function (the handler of the input event) which is decreased inside the `done` callback and therefore the for-loop is left after the node's input event listener.

Now I'm wondering how I could rewrite my test code so that I can still have some code which runs **after** the input event handler of my node and checks some post conditions.

---

<div class="post-metadata">

### Author: ![jens\_rossbach](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jens_rossbach/32/98717_2.png) [@jens\_rossbach](https://discourse.nodered.org/u/jens_rossbach)
#### Post date: [18 April 2021 17:16 UTC](https://discourse.nodered.org/t/capturing-input-messages-with-node-red-node-test-helper-not-working/43596/7 "2021-04-18T17:16:47Z")

</div>

Finally I solved my initial problem. This was indeed caused by the SinonJS fake timers, more precisely the faking of `setImmediate`. This function is used inside Node-RED runtime to schedule the sending of the message on the next iteration of the event loop and due to the fake, this somehow didn't work then. So by only faking the functions relevant for my test (`Date`, `setTimeout` and `clearTimeout`), I got it working. I still had to do a small modification in the test function itself because due to faking setTimeout, the callback and hence the execution of the test input event listener happens synchronously inside the `clock.tick` method call.

So here is the code that is now working:

```javascript
const sinon = require("sinon");

const helper = require("node-red-node-test-helper");
const configNode = require("../nodes/config.js");
const schedulerNode = require("../nodes/scheduler.js");
const chronos = require("../nodes/common/chronos.js");
const moment = require("moment");

describe("scheduler node", function()
{
    context("node timers", function()
    {
        let clock = null;

        before(function(done)
        {
            helper.startServer(done);
        });

        after(function(done)
        {
            helper.stopServer(done);
        });

        beforeEach(function()
        {
            clock = sinon.useFakeTimers({toFake: ["Date", "setTimeout", "clearTimeout"]});
            sinon.stub(chronos, "getCurrentTime").returns(moment().utc());
        });

        afterEach(function()
        {
            helper.unload();
            sinon.restore();
            clock.restore();
        });

        it("should trigger at specified time", async function()
        {
            const flow = [{id: "sn1", type: "chronos-scheduler", name: "scheduler", config: "cn1", wires: [["hn1"]], schedule: [{trigger: {type: "time", value: "00:01", offset: 0, random: false}, output: {type: "msg", property: {name: "payload", type: "string", value: "test"}}}], outputs: 1},
                          {id: "hn1", type: "helper"},
                          {id: "cn1", type: "chronos-config", name: "config"}];
            const credentials = {"cn1": {latitude: "50", longitude: "10"}};

            await helper.load([schedulerNode, configNode], flow, credentials);
            const hn1 = helper.getNode("hn1");

            hn1.on("input", function(msg)
            {
                msg.should.have.property("payload", "test");
            });

            clock.tick(60000);
        });
    });
});

```

However, I still have the other problem from my two posts before. Maybe anybody knows how to solve this one, thanks!

Best regards  
Jens

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [17 June 2021 17:17 UTC](https://discourse.nodered.org/t/capturing-input-messages-with-node-red-node-test-helper-not-working/43596/8 "2021-06-17T17:17:22Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
