Skip to content

Commit

Permalink
add setFlows so that node being tested can modify flows
Browse files Browse the repository at this point in the history
bumps version to 0.3.0
adds test in lower-case_spec.js
updates readme with API and example
  • Loading branch information
Steve-Mcl committed Jun 20, 2022
1 parent 229c5fb commit 2a82d32
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 15 deletions.
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,44 @@ Loads a flow then starts the flow. This function has the following arguments:
* testNode: (object|array of objects) Module object of a node to be tested returned by require function. This node will be registered, and can be used in testFlows.
* testFlow: (array of objects) Flow data to test a node. If you want to use flow data exported from Node-RED editor, export the flow to the clipboard and paste the content into your test scripts.
* testCredentials: (object) Optional node credentials.
* cb: (function) Function to call back when testFlows has been started.
* cb: (function) Function to call back when testFlows has been started (not required when called wih `await`)

### setFlows(testFlow, type, testCredentials, cb)

Updates the currently loaded flow. This function has the following arguments:

* testFlow: (array of objects) Flow data to test a node. If you want to use flow data exported from Node-RED editor, export the flow to the clipboard and paste the content into your test scripts.
* type: (string) Flow data to test a node. If you want to use flow data exported from Node-RED editor, export the flow to the clipboard and paste the content into your test scripts.
* testCredentials: (object) Optional node credentials.
* cb: (function) Function to call back when testFlows has been loaded (not required when called wih `await`)

#### Example

```js
it('should modify the flow then lower case of payload', async function () {
const flow = [
{ id: "n2", type: "helper" }
]
await helper.load(lowerNode, flow)
const newFlow = [...flow]
newFlow.push( { id: "n1", type: "lower-case", name: "lower-case", wires:[['n2']] },)
await helper.setFlows(newFlow, "nodes") //update flows
const n1 = helper.getNode('n1')
n1.should.have.a.property('name', 'lower-case')
await new Promise((resolve, reject) => {
const n2 = helper.getNode('n2')
n2.on('input', function (msg) {
try {
msg.should.have.property('payload', 'hello');
resolve()
} catch (err) {
reject(err);
}
});
n1.receive({ payload: 'HELLO' });
});
});
```

### unload()

Expand Down
24 changes: 24 additions & 0 deletions examples/lower-case_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,28 @@ describe('lower-case Node', function () {
n1.receive({ payload: "UpperCase" });
});
});
it('should modify the flow then lower case of payload', async function () {
const flow = [
{ id: "n2", type: "helper" }
]
await helper.load(lowerNode, flow)

const newFlow = [...flow]
newFlow.push( { id: "n1", type: "lower-case", name: "lower-case", wires:[['n2']] },)
await helper.setFlows(newFlow)
const n1 = helper.getNode('n1')
n1.should.have.a.property('name', 'lower-case')
await new Promise((resolve, reject) => {
const n2 = helper.getNode('n2')
n2.on('input', function (msg) {
try {
msg.should.have.property('payload', 'hello');
resolve()
} catch (err) {
reject(err);
}
});
n1.receive({ payload: 'HELLO' });
});
});
});
57 changes: 52 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,15 +199,19 @@ class NodeTestHelper extends EventEmitter {
});



if (typeof testCredentials === 'function') {
cb = testCredentials;
testCredentials = {};
}

var storage = {
const conf = {flows:testFlow,credentials:testCredentials|| {}}
const storage = {
conf: conf,
getFlows: function () {
return Promise.resolve({flows:testFlow,credentials:testCredentials});
return Promise.resolve(conf);
},
saveFlows: function(conf) {
storage.conf = conf;
return Promise.resolve();
}
};
// this._settings.logging = {console:{level:'off'}};
Expand Down Expand Up @@ -281,7 +285,7 @@ class NodeTestHelper extends EventEmitter {
unload() {
// TODO: any other state to remove between tests?
this._redNodes.clearRegistry();
this._logSpy.restore();
this._logSpy && this._logSpy.restore();
this._sandbox.restore();

// internal API
Expand All @@ -302,6 +306,49 @@ class NodeTestHelper extends EventEmitter {
return this._redNodes.stopFlows();
}

/**
* Update flows
* @param {object|object[]} testFlow Flow data to test a node
* @param {"full"|"flows"|"nodes"} type The type of deploy mode "full", "flows" or "nodes" (defaults to "full")
* @param {object} [testCredentials] Optional node credentials
* @param {function} [cb] Optional callback (not required when called with await)
* @returns {Promise}
*/
setFlows(testFlow, type, testCredentials, cb) {
const helper = this;
if (typeof testCredentials === 'string' ) {
cb = testCredentials;
testCredentials = {};
}
if(!type || typeof type != "string") {
type = "full"
}
async function waitStarted() {
return new Promise((resolve, reject) => {
let timeover = setTimeout(() => {
if (timeover) {
timeover = null
reject(Error("timeout waiting event"))
}
}, 300);
function hander() {
clearTimeout(timeover)
helper._events.off('flows:started', hander)
if (timeover) {
timeover = null
resolve()
}
}
helper._events.on('flows:started', hander); // call resolve when its done
});
}
return this._redNodes.setFlows(testFlow, testCredentials || {}, type)
.then(waitStarted)
.then(() => {
if(cb) cb();
});
}

request() {
return request(this._httpAdmin);
}
Expand Down
19 changes: 10 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
{
"name": "node-red-node-test-helper",
"version": "0.2.7",
"version": "0.3.0",
"description": "A test framework for Node-RED nodes",
"main": "index.js",
"scripts": {
"test": "mocha \"test/**/*_spec.js\"",
"examples": "mocha \"examples/**/*_spec.js\""
"examples": "mocha \"examples/**/*_spec.js\"",
"examples2": "set NODE_PATH=C:\\Users\\Stephen\\repos\\github\\node-red&& mocha \"examples/**/*_spec.js\""
},
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/node-red/node-red-node-test-helper.git"
},
"dependencies": {
"express": "4.17.1",
"body-parser": "1.19.0",
"body-parser": "1.20.0",
"express": "4.18.1",
"read-pkg-up": "7.0.1",
"semver": "7.3.4",
"semver": "7.3.7",
"should": "^13.2.3",
"should-sinon": "0.0.6",
"sinon": "9.2.4",
"sinon": "11.1.2",
"stoppable": "1.1.0",
"supertest": "4.0.2"
"supertest": "6.2.3"
},
"devDependencies": {
"mocha": "~7.1.2"
"mocha": "9.2.2"
},
"contributors": [
{
Expand All @@ -46,6 +47,6 @@
"node-red"
],
"engines": {
"node": ">=8"
"node": ">=14"
}
}

0 comments on commit 2a82d32

Please sign in to comment.