Function node: add `node.outputCount` property to sandbox (#2918)

* Function node: add `node.outputs` property to sandbox

https://discourse.nodered.org/t/expose-configured-output-count-to-function-node-i-can-pr/43848

* style: indetation for function node sanbox code

I guess this was unintentionally unindented in d51aefa156 (diff-24cd715c3b7405ea194bfdc0dc2a350ceb2f5d18696b8163c3e40105b981a666)

* Function node: tests for accessing node properties

consistently tests that `node.id`, `node.name` and `node.outputs`
are available in `init()`, `func()` and `finalize()` methods.

* Function node: rename `node.outputs` to `node.outputCount`

https://discourse.nodered.org/t/expose-configured-output-count-to-function-node-i-can-pr/43848/9?u=kristian
This commit is contained in:
Kristian Heljas 2021-04-08 16:52:02 +03:00 committed by GitHub
parent 0059f9475e
commit 7b8ed487e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 76 additions and 27 deletions

View File

@ -93,6 +93,7 @@ module.exports = function(RED) {
var node = this;
node.name = n.name;
node.func = n.func;
node.outputs = n.outputs;
node.ini = n.initialize ? n.initialize.trim() : "";
node.fin = n.finalize ? n.finalize.trim() : "";
node.libs = n.libs || [];
@ -112,21 +113,22 @@ module.exports = function(RED) {
var functionText = "var results = null;"+
"results = (async function(msg,__send__,__done__){ "+
"var __msgid__ = msg._msgid;"+
"var node = {"+
"id:__node__.id,"+
"name:__node__.name,"+
"log:__node__.log,"+
"error:__node__.error,"+
"warn:__node__.warn,"+
"debug:__node__.debug,"+
"trace:__node__.trace,"+
"on:__node__.on,"+
"status:__node__.status,"+
"send:function(msgs,cloneMsg){ __node__.send(__send__,__msgid__,msgs,cloneMsg);},"+
"done:__done__"+
"};\n"+
node.func+"\n"+
"var __msgid__ = msg._msgid;"+
"var node = {"+
"id:__node__.id,"+
"name:__node__.name,"+
"outputCount:__node__.outputCount,"+
"log:__node__.log,"+
"error:__node__.error,"+
"warn:__node__.warn,"+
"debug:__node__.debug,"+
"trace:__node__.trace,"+
"on:__node__.on,"+
"status:__node__.status,"+
"send:function(msgs,cloneMsg){ __node__.send(__send__,__msgid__,msgs,cloneMsg);},"+
"done:__done__"+
"};\n"+
node.func+"\n"+
"})(msg,__send__,__done__);";
var finScript = null;
var finOpt = null;
@ -146,6 +148,7 @@ module.exports = function(RED) {
__node__: {
id: node.id,
name: node.name,
outputCount: node.outputs,
log: function() {
node.log.apply(node, arguments);
},
@ -330,6 +333,7 @@ module.exports = function(RED) {
var node = {
id:__node__.id,
name:__node__.name,
outputCount:__node__.outputCount,
log:__node__.log,
error:__node__.error,
warn:__node__.warn,
@ -351,6 +355,7 @@ module.exports = function(RED) {
var node = {
id:__node__.id,
name:__node__.name,
outputCount:__node__.outputCount,
log:__node__.log,
error:__node__.error,
warn:__node__.warn,

View File

@ -132,6 +132,28 @@ describe('function node', function() {
});
});
it('should allow accessing node.id and node.name and node.outputCount', function(done) {
var flow = [{id:"n1",name:"test-function", outputs: 2, type:"function",wires:[["n2"]],func: "return [{ topic: node.name, payload:node.id, outputCount: node.outputCount }];"},
{id:"n2", type:"helper"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
try {
// Use this form of assert as `msg` is created inside
// the sandbox and doesn't get all the should.js monkey patching
should.equal(msg.payload, n1.id);
should.equal(msg.topic, n1.name);
should.equal(msg.outputCount, n1.outputs);
done();
} catch(err) {
done(err);
}
});
n1.receive({payload:""});
});
});
function testSendCloning(args,done) {
var flow = [{id:"n1",type:"function",wires:[["n2"],["n2"]],func:"node.send("+args+"); msg.payload = 'changed';"},
{id:"n2", type:"helper"}];
@ -1402,17 +1424,38 @@ describe('function node', function() {
});
});
it('should execute finalization', function(done) {
var flow = [{id:"n1",type:"function",wires:[],func:"return msg;",finalize:"global.set('X','bar');"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var ctx = n1.context().global;
helper.unload().then(function () {
ctx.get('X').should.equal("bar");
done();
describe("finalize function", function() {
it('should execute', function(done) {
var flow = [{id:"n1",type:"function",wires:[],func:"return msg;",finalize:"global.set('X','bar');"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var ctx = n1.context().global;
helper.unload().then(function () {
ctx.get('X').should.equal("bar");
done();
});
});
});
});
it('should allow accessing node.id and node.name and node.outputCount', function(done) {
var flow = [{id:"n1",name:"test-function", outputs: 2, type:"function",wires:[["n2"]],finalize:"global.set('finalize-data', { topic: node.name, payload:node.id, outputCount: node.outputCount});", func: "return msg;"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
var ctx = n1.context().global;
helper.unload().then(function () {
const finalizeData = ctx.get('finalize-data');
should.equal(finalizeData.payload, n1.id);
should.equal(finalizeData.topic, n1.name);
should.equal(finalizeData.outputCount, n1.outputs);
done();
});
});
});
})
describe('externalModules', function() {
afterEach(function() {
@ -1655,8 +1698,8 @@ describe('function node', function() {
});
});
it('should allow accessing node.id and node.name and sending message', function(done) {
var flow = [{id:"n1",name:"test-function", type:"function",wires:[["n2"]],initialize:"setTimeout(function() { node.send({ topic: node.name, payload:node.id})},10)", func: ""},
it('should allow accessing node.id and node.name and node.outputCount and sending message', function(done) {
var flow = [{id:"n1",name:"test-function", outputs: 1, type:"function",wires:[["n2"]],initialize:"setTimeout(function() { node.send({ topic: node.name, payload:node.id, outputCount: node.outputCount})},10)", func: ""},
{id:"n2", type:"helper"}];
helper.load(functionNode, flow, function() {
var n1 = helper.getNode("n1");
@ -1667,6 +1710,7 @@ describe('function node', function() {
// the sandbox and doesn't get all the should.js monkey patching
should.equal(msg.payload, n1.id);
should.equal(msg.topic, n1.name);
should.equal(msg.outputCount, n1.outputs);
done();
} catch(err) {
done(err);
@ -1675,5 +1719,5 @@ describe('function node', function() {
});
});
})
});
});