# Need help debugging a unittest

**URL:** https://discourse.nodered.org/t/need-help-debugging-a-unittest/72413
**Category:** Developing Nodes
**Tags:** function-node, node-red-node-test-helper
**Created:** [19 December 2022 10:16 UTC](https://discourse.nodered.org/t/need-help-debugging-a-unittest/72413 "2022-12-19T10:16:31Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![kakyoism](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kakyoism/32/46283_2.png) [@kakyoism](https://discourse.nodered.org/u/kakyoism)
#### Post date: [19 December 2022 10:16 UTC](https://discourse.nodered.org/t/need-help-debugging-a-unittest/72413/1 "2022-12-19T10:16:31Z")

</div>

I build a custom node and want to unittest it using `node-red-node-test-helper`.

I first make a custom flow in Node-RED and exported it. Then I follow the examples to turn that flow json object into a pure node array. Finally, I use helper routines to load the head and the tail node for input and output. But `helper.getNode(headID)` and `helper.getNode(tailID)` keep giving me `null`.  
I stepped into the `getNode()` but found that my `activeFlows` is empty.

I can't figure out why since I assume the helper can run a defined node list literal without a problem. Here is my test routine:

```nohighlight
async function testFlow(nodeRuntime, helper, wiredNodes, inputMsg, expectation) {
// usage:
// - nodeRuntime: require(service/node/node.js)
// - wiredNodes: simplified node list from standard Node-RED flow json object
// - e.g., [
// {id: "my.node.id", type: "service_a", "wires": ["next.node.id", ...]},
// {id: "next.node.id", type: "service_b", "wires": ["3rd.node.id", ...]},
// ...
// ]
// - inputMsg: Node-RED message fed to the first node of the flow
// - e.g., { topic: "my.topic", payload: obj, miaservice: "service_name" }
// - expectation: assertion wrapper; can be one of:
// - (outMsg) => { expect(outMsg).to....(); }
// - (outMsg) => { expect(customCondition()).to...(); }
// e.g., if your flow has no output, but writes to a file, then simply test then file content and ignore the outMsg argument
	let tail = wiredNodes.slice(-1)[0];
	// lazy-append helper to user flow 
	let tailID = "flowtest.tail";
	let helperName = 'helper';
	let userAddedHelperAsTail = tail.type === helperName;
	if ( !userAddedHelperAsTail ) {
	    // assume: tail has only one flow path,
		// wire up help node as new tail
		wiredNodes.slice(-1)[0].wires[0].push(tailID);
		wiredNodes.push({id: tailID, type: helperName});
	}
	await helper.load(nodeRuntime, wiredNodes);
	var tailNode = helper.getNode(tailID);
	var headNode = helper.getNode(wiredNodes[0].id);
        #
        # expected headNode to be valid, but got null! 
        #
	headNode.receive(inputMsg);
	await asyncAssertFlowOutput(tailNode, expectation);
};

```

Using this routine, in the debugger I can see that my `wiredNodes` are all valid according to helper's user guide: They all have `id`, `type`, `wires`, and other custom fields.

Help is much appreciated!

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [19 December 2022 10:19 UTC](https://discourse.nodered.org/t/need-help-debugging-a-unittest/72413/2 "2022-12-19T10:19:35Z")

</div>

> [@kakyoism](#):
>
> `"wires": ["3rd.node.id", ...]`

wires is an array of arrays `[[] ]`

See any of the test in any src e.g...

> <https://github.com/node-red/node-red/blob/master/test/nodes/core/storage/10-file_spec.js#L80>

---

<div class="post-metadata">

### Author: ![kakyoism](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kakyoism/32/46283_2.png) [@kakyoism](https://discourse.nodered.org/u/kakyoism)
#### Post date: [19 December 2022 10:29 UTC](https://discourse.nodered.org/t/need-help-debugging-a-unittest/72413/3 "2022-12-19T10:29:46Z")

</div>

> [@Steve-Mcl](#):
>
> ```auto
>               
> 
> ```

hmm, that's a good catch, but I believe it's a doc error on my part. The implementation notices that the `wires` is an array of array, e.g.,

```auto
// assume: tail has only one flow path,
// wire up help node as new tail
wiredNodes.slice(-1)[0].wires[0].push(tailID);

```

here I lazy-append a helper node to the node's first wire-array.

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [19 December 2022 10:34 UTC](https://discourse.nodered.org/t/need-help-debugging-a-unittest/72413/4 "2022-12-19T10:34:46Z")

</div>

what other nodes are in your `wiredNodes` argument other than `service_x` types?

---

<div class="post-metadata">

### Author: ![kakyoism](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kakyoism/32/46283_2.png) [@kakyoism](https://discourse.nodered.org/u/kakyoism)
#### Post date: [19 December 2022 10:55 UTC](https://discourse.nodered.org/t/need-help-debugging-a-unittest/72413/5 "2022-12-19T10:55:26Z")

</div>

@Steve-Mcl  
Here is the flow i'm trying to load:

```json
[
    {
        "id": "a7a60eb01af1bc26",
        "type": "tab",
        "label": "Flow 2",
        "disabled": false,
        "info": ""
    },
    {
        "id": "32e5afc70baae91f",
        "type": "inject",
        "z": "a7a60eb01af1bc26",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            },
            {
                "p": "my_service_type",
                "v": "inject",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "inject",
        "payload": "{\"pathlist\":\"roots.list\"}",
        "payloadType": "json",
        "x": 550,
        "y": 140,
        "wires": [
            [
                "70c49ab97918cdb2"
            ]
        ]
    },
    {
        "id": "70c49ab97918cdb2",
        "type": "find_files_folders",
        "z": "a7a60eb01af1bc26",
        "rootlist": "",
        "includes": [
            "*.js"
        ],
        "excludes": [],
        "caseinsensitive": false,
        "useregex": false,
        "targettype": "file",
        "_pathlist": true,
        "saveconfig": true,
        "cfgfile": "",
        "dryrun": false,
        "x": 746,
        "y": 140,
        "wires": [
            []
        ]
    }
]

```

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [19 December 2022 11:16 UTC](https://discourse.nodered.org/t/need-help-debugging-a-unittest/72413/6 "2022-12-19T11:16:38Z")

</div>

I would slim that down to bare minimum. Remove tab nodes, remove `x`, `y`, and `z` and properties

e.g...

```auto
[
    {
        "id": "32e5afc70baae91f",
        "type": "inject",
        "name": "",
        "props": [ { "p": "payload" },
            {"p": "topic","vt": "str" },
            { "p": "my_service_type", "v": "inject", "vt": "str" }
        ],
        "topic": "inject",
        "payload": "{\"pathlist\":\"roots.list\"}",
        "payloadType": "json",
        "wires": [[ "70c49ab97918cdb2"] ]
    },
    {
        "id": "70c49ab97918cdb2",
        "type": "find_files_folders",
        "rootlist": "",
        "includes": ["*.js"],
        "excludes": [],
        "caseinsensitive": false,
        "useregex": false,
        "targettype": "file",
        "_pathlist": true,
        "saveconfig": true,
        "cfgfile": "",
        "dryrun": false,
        "wires": [[] ]
    }
]

```

Q: I assume `find_files_folders` is one of your custom nodes and is `require`d and passed in via `nodeRuntime` arg?

Also, depending on your env it might be necessary to pass in the inject node e.g. `require` the inject node and pass it along with your custom node, as an array to `helper.load` in the first arg.

---

<div class="post-metadata">

### Author: ![kakyoism](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kakyoism/32/46283_2.png) [@kakyoism](https://discourse.nodered.org/u/kakyoism)
#### Post date: [19 December 2022 11:57 UTC](https://discourse.nodered.org/t/need-help-debugging-a-unittest/72413/7 "2022-12-19T11:57:36Z")

</div>

> Also, depending on your env it might be necessary to pass in the inject node e.g. `require` the inject node and pass it along with your custom node, as an array to `helper.load` in the first arg.

OK. That sounds like the issue. I didn't realize I needed to explicitly load the runtime of the buildin nodes. But come to think of it, the helper node itself was `require`ed, so it makes sense.

Just tried an naive loading like this

```js
let injectRuntime = require("D:\\Downloads\\node-red\\packages\\node_modules\\@node-red\\nodes\\core\\common\\20-inject.js");
await helper.load(injectRuntime, wiredNodes);
 await helper.load(nodeRuntime, wiredNodes);

```

and I got the error

```auto
 TypeError: Attempted to wrap log which is already wrapped

      113 | let injectRuntime = require("D:\\Downloads\\node-red\\packages\\node_modules\\@node-red\\nodes\\core\\common\\20-inject.js");
      114 | await helper.load(injectRuntime, wiredNodes);
    > 115 | await helper.load(nodeRuntime, wiredNodes);

```

I also tried to follow your linked example

```js
var fileNode = require("nr-test-utils").require("@node-red/nodes/core/storage/10-file.js");

```

Which gives me

```auto
TypeError: Attempted to wrap log which is already wrapped

      114 | injectRuntime = require('D:\\Downloads\\node-red\\test\\node_modules\\nr-test-utils').require('@node-red\\nodes\\core\\common\\20-inject.js');
      115 | await helper.load(injectRuntime, wiredNodes);
    > 116 | await helper.load(nodeRuntime, wiredNodes);

```

As for removing extra properties, I was successful the other day loading a flow that includes only one node (my own node). That exported flow has the whole bag of extra properries including the x/y/z.

---

<div class="post-metadata">

### Author: ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)
#### Post date: [19 December 2022 13:08 UTC](https://discourse.nodered.org/t/need-help-debugging-a-unittest/72413/8 "2022-12-19T13:08:19Z")

</div>

Why are you calling helper.load twice?

> [@Steve-Mcl](#):
>
> pass it along with your custom node, as an array to `helper.load` in the first arg

e.g...

```javascript
await helper.load([nodeRuntime, injectRuntime], wiredNodes)

```

---

<div class="post-metadata">

### Author: ![kakyoism](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kakyoism/32/46283_2.png) [@kakyoism](https://discourse.nodered.org/u/kakyoism)
#### Post date: [20 December 2022 02:11 UTC](https://discourse.nodered.org/t/need-help-debugging-a-unittest/72413/9 "2022-12-20T02:11:23Z")

</div>

Sorry. I missed that detail.

```nohighlight
	let injectRuntime = require('D:\\Downloads\\node-red\\test\\node_modules\\nr-test-utils').require('@node-red\\nodes\\core\\common\\20-inject.js');
	await helper.load([injectRuntime, nodeRuntime], wiredNodes);

```

This time the loading seems to get stuck:

```auto
    thrown: "Exceeded timeout of 5000 ms for a test.
    Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

      78 | defineFlowTest(description, wiredNodes, inputMsg, expectation, timeoutMs=5000) {
      79 | // help: test a flow using its simplified json object
    > 80 | it(description, async () => {
         | ^
      81 | await testFlow(this.nodeRuntime, this.helper, wiredNodes, inputMsg, expectation);
      82 | }, timeoutMs);
      83 | }

```

Not sure if my way of loading the `inject` node runtime is correct.

---

<div class="post-metadata">

### Author: ![kakyoism](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/kakyoism/32/46283_2.png) [@kakyoism](https://discourse.nodered.org/u/kakyoism)
#### Post date: [23 December 2022 09:23 UTC](https://discourse.nodered.org/t/need-help-debugging-a-unittest/72413/10 "2022-12-23T09:23:19Z")

</div>

Finally got this problem resolved. It was my own bugs somewhere in the node implementation.

Previously, the biggest confusion came from JEST's error message on async calls. **JEST only shows meaningful results about its assertions.** ANY OTHER errors before reaching its assertions will be reported as timeouts with the message:

```auto
"Exceeded timeout of 5000 ms for a test.
    Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

```

This message is essentially JEST saying "I was unable to reach any expect().toBe() and errored out". So any syntax error or exception counts, but they won't show up in the log! So you are on your own to debug the entire test at this point.

I must apologize for waisting time of others for looking at this.  
But at least now I won't get distracted by the false log.

---

<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: [6 January 2023 09:23 UTC](https://discourse.nodered.org/t/need-help-debugging-a-unittest/72413/11 "2023-01-06T09:23:52Z")

</div>

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