mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Split node UI rework - WIP
This commit is contained in:
parent
762eb07dd4
commit
9f8c32ce8f
@ -150,7 +150,11 @@
|
|||||||
this.typeField = $("<input>",{type:'hidden'}).appendTo(this.uiSelect);
|
this.typeField = $("<input>",{type:'hidden'}).appendTo(this.uiSelect);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.selectTrigger = $('<a href="#"><i class="fa fa-sort-desc"></i></a>').prependTo(this.uiSelect);
|
this.selectTrigger = $('<a href="#"></a>').prependTo(this.uiSelect);
|
||||||
|
$('<i class="fa fa-sort-desc"></i>').appendTo(this.selectTrigger);
|
||||||
|
if (this.types.length === 1) {
|
||||||
|
this.selectTrigger.addClass("disabled");
|
||||||
|
}
|
||||||
this.selectLabel = $('<span></span>').appendTo(this.selectTrigger);
|
this.selectLabel = $('<span></span>').appendTo(this.selectTrigger);
|
||||||
|
|
||||||
this.element.on('focus', function() {
|
this.element.on('focus', function() {
|
||||||
@ -162,11 +166,17 @@
|
|||||||
this.element.on('change', function() {
|
this.element.on('change', function() {
|
||||||
that.validate();
|
that.validate();
|
||||||
})
|
})
|
||||||
|
if (this.types.length > 1) {
|
||||||
this.selectTrigger.click(function(event) {
|
this.selectTrigger.click(function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
that._showMenu(that.menu,that.selectTrigger);
|
that._showMenu(that.menu,that.selectTrigger);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
this.selectTrigger.click(function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
that.element.focus();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (hasSubOptions) {
|
if (hasSubOptions) {
|
||||||
|
@ -57,21 +57,26 @@
|
|||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
&.disabled {
|
||||||
|
cursor: default;
|
||||||
|
i {
|
||||||
|
color: #bbb;
|
||||||
|
}
|
||||||
|
}
|
||||||
span {
|
span {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 0 1px 0 5px;
|
padding: 0 1px 0 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:not(.disabled):hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
background: $typedInput-button-background-hover;
|
background: $typedInput-button-background-hover;
|
||||||
}
|
}
|
||||||
&:focus {
|
&:focus {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
&:active {
|
&:not(.disabled):active {
|
||||||
background: $typedInput-button-background-active;
|
background: $typedInput-button-background-active;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
164
nodes/core/logic/17-split.html
Normal file
164
nodes/core/logic/17-split.html
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--
|
||||||
|
Copyright 2016 IBM Corp.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="split">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-splt"><i class="fa fa-scissors"></i> Split</label>
|
||||||
|
<input type="text" id="node-input-splt" placeholder="character to split strings on : e.g. \n">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="split">
|
||||||
|
<p>A function that splits the <code>msg.payload</code> in various ways to create multiple messages out.</p>
|
||||||
|
<p><ul>
|
||||||
|
<li>splits an <b>array</b> into individual messages, one element per message.</li>
|
||||||
|
<li>splits a <b>string</b> on a character - default is <code>""</code>, split on every character. A typical
|
||||||
|
use would be <code>\n</code> to split on line breaks. Split is actually a regex value so use <code>\.</code> to
|
||||||
|
split on a full stop .</li>
|
||||||
|
<li>splits an <b>object</b> into individual messages, promoting each property value to the <code>msg.payload</code>,
|
||||||
|
and saving each property key name as <code>msg.parts.key</code>.
|
||||||
|
</ul></p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('split',{
|
||||||
|
category: 'function',
|
||||||
|
color:"#E2D96E",
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
splt: {value:""}
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:1,
|
||||||
|
icon: "switch.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||"split";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="join">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-out"><i class="fa fa-long-arrow-right"></i> Output</label>
|
||||||
|
<select id="node-input-out" style="width:70%; margin-right:5px;">
|
||||||
|
<option value="auto">automatic</option>
|
||||||
|
<option value="str">a String of joined properties</option>
|
||||||
|
<option value="arr">an Array of properties</option>
|
||||||
|
<option value="obj">an Object of key/property pairs</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row node-row-key">
|
||||||
|
<label for="node-input-key" style="padding-right: 10px; box-sizing: border-box; text-align: right;">Key</label>
|
||||||
|
<input type="text" id="node-input-key">
|
||||||
|
</div>
|
||||||
|
<div class="form-row node-row-property">
|
||||||
|
<label for="node-input-property" style="padding-right: 10px; box-sizing: border-box; text-align: right;">Property</label>
|
||||||
|
<input type="text" id="node-input-property">
|
||||||
|
<input type="hidden" id="node-input-propertyType">
|
||||||
|
</div>
|
||||||
|
<div class="form-row node-row-join">
|
||||||
|
<label for="node-input-join" style="padding-right: 10px; box-sizing: border-box; text-align: right;">joined using</label>
|
||||||
|
<input type="text" id="node-input-join" style="width: 40px">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row node-row-trigger">
|
||||||
|
<label style="width: auto;">Send the message:</label>
|
||||||
|
<div style="height: 40px;">
|
||||||
|
<label style="margin-left: 40px; width: auto;"><input type="checkbox" style="width: auto;margin-bottom: 5px;"> after a fixed number of messages: <input type="text" style="width: 75px;"></label>
|
||||||
|
</div>
|
||||||
|
<div style="height: 40px;">
|
||||||
|
<label style="margin-left: 40px; width: auto;"><input type="checkbox" style="width: auto;margin-bottom: 5px;"> after a timeout following the first message: <input placeholder="seconds" type="text" style="width: 75px;"></label>
|
||||||
|
</div>
|
||||||
|
<div style="height: 40px; padding-top: 6px;" class="node-row-accumulate">
|
||||||
|
<label style="margin-left: 40px; width: auto;"><input type="checkbox" style="width: auto;margin-bottom: 5px;"> whenever a property is updated</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-tips form-tips-auto hide">This mode assumes this node is either
|
||||||
|
paired with a <i>split</i> node or the received messages will have a properly
|
||||||
|
configured <code>msg.parts</code> property.</div>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="join">
|
||||||
|
<p>A function that joins <code>msg.payload</code> from multiple msgs to create a single msg out.</p>
|
||||||
|
<p>Other properties of the msg are not guaranteed as they could come from any of the incoming msgs.</p>
|
||||||
|
<p>An optional <i>count</i> can be set that waits for that many <code>payload</code> to arrive before passing on the new message.</p>
|
||||||
|
<p>An optional <i>timeout</i> can be set that can then send the incomplete message, drop the message or raise a catchable error.</p>
|
||||||
|
<p>An optional <i>join character</i> can be set that can be used for joining multiple payloads together and returns a
|
||||||
|
string rather than an array.</p>
|
||||||
|
<p>When used with a <b>split</b> node the <i>count</i> and <i>join character</i> are automatically set - but can be
|
||||||
|
overridden by values in the configuration.</p>
|
||||||
|
<p>Messages can be joined into an <i>array</i> or <i>object</i>. To be joined into an object the incoming message must
|
||||||
|
have either a <code>msg.key</code> or <code>msg.topic</code> property - or <code>msg.payload</code> should
|
||||||
|
be an object with properties.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('join',{
|
||||||
|
category: 'function',
|
||||||
|
color:"#E2D96E",
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
out: { value:"auto"},
|
||||||
|
property: { value: "payload"},
|
||||||
|
timeout: {value:""},
|
||||||
|
timerr: {value:"send"},
|
||||||
|
count: {value:""},
|
||||||
|
joiner: {value:""},
|
||||||
|
build: {value:"array"}
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:1,
|
||||||
|
icon: "join.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||"join";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
},
|
||||||
|
oneditprepare: function() {
|
||||||
|
$("#node-input-out").change(function(e) {
|
||||||
|
var val = $(this).val();
|
||||||
|
$(".node-row-key").toggle(val==='obj');
|
||||||
|
$(".node-row-property").toggle(val!=='auto');
|
||||||
|
$(".node-row-join").toggle(val==='str');
|
||||||
|
$(".node-row-trigger").toggle(val!=='auto');
|
||||||
|
$(".node-row-accumulate").toggle(val==='obj');
|
||||||
|
$(".form-tips-auto").toggle(val==='auto');
|
||||||
|
})
|
||||||
|
|
||||||
|
$("#node-input-property").typedInput({
|
||||||
|
typeField: $("#node-input-propertyType"),
|
||||||
|
types:['msg', {value:"full",label:"complete message",hasValue:false}]
|
||||||
|
})
|
||||||
|
$("#node-input-key").typedInput({
|
||||||
|
types:['msg']
|
||||||
|
})
|
||||||
|
|
||||||
|
$("#node-input-out").change();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
205
nodes/core/logic/17-split.js
Normal file
205
nodes/core/logic/17-split.js
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 IBM Corp.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
module.exports = function(RED) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function SplitNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.splt = n.splt || "";
|
||||||
|
this.split = new RegExp(this.splt);
|
||||||
|
var node = this;
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
if (msg.hasOwnProperty("payload")) {
|
||||||
|
var a = msg.payload;
|
||||||
|
if (msg.hasOwnProperty("parts")) { msg.parts = { parts:msg.parts }; } // push existing parts to a stack
|
||||||
|
else { msg.parts = {}; }
|
||||||
|
msg.parts.id = msg._msgid; // use the existing _msgid by default.
|
||||||
|
if (typeof msg.payload === "string") { // Split String into array
|
||||||
|
a = msg.payload.split(node.split);
|
||||||
|
msg.parts.ch = node.splt; // pass the split char to other end for rejoin
|
||||||
|
msg.parts.type = "string";
|
||||||
|
}
|
||||||
|
if (Array.isArray(a)) { // then split array into messages
|
||||||
|
msg.parts.type = msg.parts.type || "array"; // if it wasn't a string in the first place
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
msg.payload = a[i];
|
||||||
|
msg.parts.index = i;
|
||||||
|
msg.parts.count = a.length;
|
||||||
|
node.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((typeof msg.payload === "object") && !Buffer.isBuffer(msg.payload)) {
|
||||||
|
var j = 0;
|
||||||
|
var l = Object.keys(msg.payload).length;
|
||||||
|
var pay = msg.payload;
|
||||||
|
msg.parts.type = "object";
|
||||||
|
for (var p in pay) {
|
||||||
|
if (pay.hasOwnProperty(p)) {
|
||||||
|
msg.payload = pay[p];
|
||||||
|
msg.parts.key = p;
|
||||||
|
msg.parts.index = j;
|
||||||
|
msg.parts.count = l;
|
||||||
|
node.send(msg);
|
||||||
|
j += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO not handling Buffers at present...
|
||||||
|
//else { } // otherwise drop the message.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("split",SplitNode);
|
||||||
|
|
||||||
|
|
||||||
|
function JoinNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.timer = Number(n.timeout || 0);
|
||||||
|
this.timerr = n.timerr || "send";
|
||||||
|
this.count = Number(n.count || 0);
|
||||||
|
this.joiner = n.joiner;
|
||||||
|
this.build = n.build || "array";
|
||||||
|
var node = this;
|
||||||
|
var inflight = {};
|
||||||
|
var misc = (this.build === "array") ? [] : {};
|
||||||
|
var tout;
|
||||||
|
|
||||||
|
function isObject (item) {
|
||||||
|
return (typeof item === "object" && !Array.isArray(item)&& ! Buffer.isBuffer(item) && item !== null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if array came from a string then reassemble it and send it
|
||||||
|
var sendIt = function(m) {
|
||||||
|
if (inflight[m.parts.id].ch !== undefined) { // if it was a string - rejoin it using the split char
|
||||||
|
var jc = (node.joiner || inflight[m.parts.id].ch).replace(/\\n/,"\n").replace(/\\r/,"\r").replace(/\\t/,"\t").replace(/\\e/,"\e").replace(/\\f/,"\c").replace(/\\0/,"\0");
|
||||||
|
m.payload = inflight[m.parts.id].a.join(jc);
|
||||||
|
} else { // leave it as an array
|
||||||
|
m.payload = inflight[m.parts.id].a;
|
||||||
|
}
|
||||||
|
m._msgid = m.parts.id;
|
||||||
|
clearTimeout(inflight[m.parts.id].timeout); // unset any timer
|
||||||
|
delete inflight[m.parts.id]; // remove from the keep track object
|
||||||
|
if (m.parts.hasOwnProperty("parts")) {
|
||||||
|
m.parts = m.parts.parts; // pop existing parts
|
||||||
|
}
|
||||||
|
else { delete m.parts; } // remove the parts flags
|
||||||
|
node.send(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check all elements of the array are strings (or claim to be).
|
||||||
|
var onlyString = function(a) { // check if the array is all strings
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
if (typeof a[i] !== "string") { return false; }
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send array of misc message that arrived. (convert to string if all were strings and need joining)
|
||||||
|
var sendMisc = function(m) {
|
||||||
|
if (tout) { clearTimeout(tout); tout = null; }
|
||||||
|
m.payload = misc;
|
||||||
|
if (node.joiner && onlyString(misc)) { // if the array is all strings and there is a join char set
|
||||||
|
m.payload = misc.join(node.joiner.replace(/\\n/,"\n").replace(/\\r/,"\r").replace(/\\t/,"\t").replace(/\\e/,"\e").replace(/\\f/,"\c").replace(/\\0/,"\0"));
|
||||||
|
}
|
||||||
|
if (node.build === "array") { misc = []; }
|
||||||
|
if (node.build === "object") { misc = {}; }
|
||||||
|
node.send(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
if (msg.hasOwnProperty("payload")) {
|
||||||
|
if (msg.hasOwnProperty("parts")) { // only act if it has parts
|
||||||
|
var count = node.count || msg.parts.count || 1;
|
||||||
|
if (msg.parts.hasOwnProperty("index")) { // it's a numbered part (from a split node)
|
||||||
|
if (!inflight[msg.parts.id]) { // New message - create new empty array of correct size
|
||||||
|
if (msg.parts.type === "object") {
|
||||||
|
inflight[msg.parts.id] = {i:0, a:{}, c:msg.parts.count, ch:msg.parts.ch, t:msg.parts.type};
|
||||||
|
} else { // it's an array or string
|
||||||
|
inflight[msg.parts.id] = {i:0, a:new Array(msg.parts.count), ch:msg.parts.ch, t:msg.parts.type};
|
||||||
|
}
|
||||||
|
if (node.timer !== 0) { // If there is a timer to set start it now
|
||||||
|
inflight[msg.parts.id].timeout = setTimeout(function() {
|
||||||
|
if (node.timerr === "send") { sendIt(msg); }
|
||||||
|
if (node.timerr === "error") { node.error("Incomplete",msg); }
|
||||||
|
delete inflight[msg.parts.id];
|
||||||
|
}, node.timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (msg.parts.type === "object") {
|
||||||
|
inflight[msg.parts.id].a[msg.parts.key] = msg.payload; // Add to the tracking array
|
||||||
|
inflight[msg.parts.id].i = Object.keys(inflight[msg.parts.id].a).length;
|
||||||
|
} else { // it's an array or string
|
||||||
|
inflight[msg.parts.id].a[msg.parts.index] = msg.payload; // Add to the tracking array
|
||||||
|
inflight[msg.parts.id].i += 1; // Increment the count
|
||||||
|
}
|
||||||
|
if (inflight[msg.parts.id].i >= count) { sendIt(msg); } // All arrived - send
|
||||||
|
} // otherwise ignore it
|
||||||
|
if (msg.hasOwnProperty("complete")) { // if set then send right away anyway...
|
||||||
|
delete(msg.complete);
|
||||||
|
sendIt(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The case for any messages arriving without parts - ie random messages you want to join.
|
||||||
|
else {
|
||||||
|
var l;
|
||||||
|
if (node.build === "array") { // simple case of build the array
|
||||||
|
misc.push(msg.payload); // Add the payload to an array
|
||||||
|
l = misc.length;
|
||||||
|
} else { // OK so let's build an object
|
||||||
|
if ((msg.key === undefined) && ((msg.topic === undefined) || (msg.topic === ''))) {
|
||||||
|
if (isObject(msg.payload)) { // if it's already an object (and no topic or key) just append it
|
||||||
|
misc = Object.assign(misc,msg.payload);
|
||||||
|
l = Object.keys(misc).length;
|
||||||
|
}
|
||||||
|
else { // if no topic or key and not an object then warn and drop it.
|
||||||
|
node.warn("key or topic not defined");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // if it's got a msg.key or msg.topic then use key||topic as the property name
|
||||||
|
misc[ msg.key || msg.topic ] = msg.payload;
|
||||||
|
//if (msg.topic) { msg.topic = (msg.topic.split('/')).slice(0,-1).join('/'); }
|
||||||
|
l = Object.keys(misc).length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (l >= node.count) { sendMisc(msg); } // if it's long enough send it
|
||||||
|
else if (msg.hasOwnProperty("complete")) { // if set then send right away anyway...
|
||||||
|
delete(msg.complete);
|
||||||
|
sendMisc(msg);
|
||||||
|
}
|
||||||
|
else if ((node.timer !== 0) && !tout) { // if not start the timer if there is one.
|
||||||
|
tout = setTimeout(function() {
|
||||||
|
if (node.timerr === "send") { sendMisc(msg); }
|
||||||
|
if (node.timerr === "error") { node.error("Timeout",msg); }
|
||||||
|
if (node.build === "array") { misc = []; }
|
||||||
|
if (node.build === "object") { misc = {}; }
|
||||||
|
}, node.timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on("close", function() {
|
||||||
|
if (tout) { clearTimeout(tout); }
|
||||||
|
for (var i in inflight) {
|
||||||
|
if (inflight[i].timeout) { clearTimeout(inflight[i].timeout); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("join",JoinNode);
|
||||||
|
}
|
379
test/nodes/core/logic/17-split_spec.js
Normal file
379
test/nodes/core/logic/17-split_spec.js
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 IBM Corp.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var should = require("should");
|
||||||
|
var splitNode = require("../../../../nodes/core/logic/17-split.js");
|
||||||
|
var joinNode = require("../../../../nodes/core/logic/17-split.js");
|
||||||
|
var helper = require("../../helper.js");
|
||||||
|
|
||||||
|
describe('SPLIT node', function() {
|
||||||
|
|
||||||
|
before(function(done) {
|
||||||
|
helper.startServer(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
helper.unload();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be loaded', function(done) {
|
||||||
|
var flow = [{id:"splitNode1", type:"split", name:"splitNode" }];
|
||||||
|
helper.load(splitNode, flow, function() {
|
||||||
|
var splitNode1 = helper.getNode("splitNode1");
|
||||||
|
splitNode1.should.have.property('name', 'splitNode');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should split an array into multiple messages', function(done) {
|
||||||
|
var flow = [{id:"sn1", type:"split", wires:[["sn2"]]},
|
||||||
|
{id:"sn2", type:"helper"}];
|
||||||
|
helper.load(splitNode, flow, function() {
|
||||||
|
var sn1 = helper.getNode("sn1");
|
||||||
|
var sn2 = helper.getNode("sn2");
|
||||||
|
sn2.on("input", function(msg) {
|
||||||
|
msg.should.have.property("parts");
|
||||||
|
msg.parts.should.have.property("count",4);
|
||||||
|
msg.parts.should.have.property("type","array");
|
||||||
|
msg.parts.should.have.property("index");
|
||||||
|
if (msg.parts.index === 0) { msg.payload.should.equal(1); }
|
||||||
|
if (msg.parts.index === 1) { msg.payload.should.equal(2); }
|
||||||
|
if (msg.parts.index === 2) { msg.payload.should.equal(3); }
|
||||||
|
if (msg.parts.index === 3) { msg.payload.should.equal(4); done(); }
|
||||||
|
});
|
||||||
|
sn1.receive({payload:[1,2,3,4]});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should split a string into characters', function(done) {
|
||||||
|
var flow = [{id:"sn1", type:"split", wires:[["sn2"]]},
|
||||||
|
{id:"sn2", type:"helper"}];
|
||||||
|
helper.load(splitNode, flow, function() {
|
||||||
|
var sn1 = helper.getNode("sn1");
|
||||||
|
var sn2 = helper.getNode("sn2");
|
||||||
|
sn2.on("input", function(msg) {
|
||||||
|
msg.should.have.property("parts");
|
||||||
|
msg.parts.should.have.property("count",4);
|
||||||
|
msg.parts.should.have.property("type","string");
|
||||||
|
msg.parts.should.have.property("index");
|
||||||
|
if (msg.parts.index === 0) { msg.payload.should.equal("D"); }
|
||||||
|
if (msg.parts.index === 1) { msg.payload.should.equal("a"); }
|
||||||
|
if (msg.parts.index === 2) { msg.payload.should.equal("v"); }
|
||||||
|
if (msg.parts.index === 3) { msg.payload.should.equal("e"); done(); }
|
||||||
|
});
|
||||||
|
sn1.receive({payload:"Dave"});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should split a string on a specified char', function(done) {
|
||||||
|
var flow = [{id:"sn1", type:"split", wires:[["sn2"]], splt:"\n"},
|
||||||
|
{id:"sn2", type:"helper"}];
|
||||||
|
helper.load(splitNode, flow, function() {
|
||||||
|
var sn1 = helper.getNode("sn1");
|
||||||
|
var sn2 = helper.getNode("sn2");
|
||||||
|
sn2.on("input", function(msg) {
|
||||||
|
msg.should.have.property("parts");
|
||||||
|
msg.parts.should.have.property("count",3);
|
||||||
|
msg.parts.should.have.property("ch","\n");
|
||||||
|
msg.parts.should.have.property("index");
|
||||||
|
msg.parts.should.have.property("type","string");
|
||||||
|
if (msg.parts.index === 0) { msg.payload.should.equal("1"); }
|
||||||
|
if (msg.parts.index === 1) { msg.payload.should.equal("2"); }
|
||||||
|
if (msg.parts.index === 2) { msg.payload.should.equal("3"); done(); }
|
||||||
|
});
|
||||||
|
sn1.receive({payload:"1\n2\n3"});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should split an object into pieces', function(done) {
|
||||||
|
var flow = [{id:"sn1", type:"split", wires:[["sn2"]]},
|
||||||
|
{id:"sn2", type:"helper"}];
|
||||||
|
helper.load(splitNode, flow, function() {
|
||||||
|
var sn1 = helper.getNode("sn1");
|
||||||
|
var sn2 = helper.getNode("sn2");
|
||||||
|
var count = 0;
|
||||||
|
sn2.on("input", function(msg) {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
msg.should.have.property("parts");
|
||||||
|
msg.parts.should.have.property("type","object");
|
||||||
|
msg.parts.should.have.property("key");
|
||||||
|
msg.parts.should.have.property("count");
|
||||||
|
msg.parts.should.have.property("index");
|
||||||
|
if (msg.parts.index === 0) { msg.payload.should.equal(1); }
|
||||||
|
if (msg.parts.index === 1) { msg.payload.should.equal("2"); }
|
||||||
|
if (msg.parts.index === 2) { msg.payload.should.equal(true); done(); }
|
||||||
|
});
|
||||||
|
sn1.receive({payload:{a:1,b:"2",c:true}});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('JOIN node', function() {
|
||||||
|
|
||||||
|
before(function(done) {
|
||||||
|
helper.startServer(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
helper.unload();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be loaded', function(done) {
|
||||||
|
var flow = [{id:"joinNode1", type:"join", name:"joinNode" }];
|
||||||
|
helper.load(joinNode, flow, function() {
|
||||||
|
var joinNode1 = helper.getNode("joinNode1");
|
||||||
|
joinNode1.should.have.property('name', 'joinNode');
|
||||||
|
joinNode1.should.have.property('count', 0);
|
||||||
|
joinNode1.should.have.property('timer', 0);
|
||||||
|
joinNode1.should.have.property('timerr', 'send');
|
||||||
|
joinNode1.should.have.property('build', 'array');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should join things into an array after a count', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"join", wires:[["n2"]], count:3, joiner:","},
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(joinNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
msg.payload.should.be.an.Array;
|
||||||
|
msg.payload[0].should.equal(1);
|
||||||
|
msg.payload[1].should.equal(true);
|
||||||
|
//msg.payload[2].a.should.equal(1);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
catch(e) { }//console.log(e); }
|
||||||
|
});
|
||||||
|
n1.receive({payload:1});
|
||||||
|
n1.receive({payload:true});
|
||||||
|
n1.receive({payload:{a:1}});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should join things into an object after a count', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"join", wires:[["n2"]], count:5, build:"object"},
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(joinNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
msg.payload.should.have.property("a",1);
|
||||||
|
msg.payload.should.have.property("b","2");
|
||||||
|
msg.payload.should.have.property("c",true);
|
||||||
|
msg.payload.should.have.property("d");
|
||||||
|
msg.payload.d.should.have.property("e",5);
|
||||||
|
msg.payload.should.have.property("f",6);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
catch(e) { }//console.log(e); }
|
||||||
|
});
|
||||||
|
n1.receive({payload:1, topic:"a"});
|
||||||
|
n1.receive({payload:"2", topic:"b"});
|
||||||
|
n1.receive({payload:true, topic:"c"});
|
||||||
|
n1.receive({payload:{e:5}, topic:"d"});
|
||||||
|
n1.receive({payload:{f:6}});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should join strings with a specifed character after a timeout', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"join", wires:[["n2"]], timeout:50, count:10, joiner:","},
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(joinNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
msg.payload.should.equal("a,b,c");
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
catch(e) { console.log(e); }
|
||||||
|
});
|
||||||
|
n1.receive({payload:"a"});
|
||||||
|
n1.receive({payload:"b"});
|
||||||
|
n1.receive({payload:"c"});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should join strings with a specifed character and complete when told to', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"join", wires:[["n2"]], timeout:5000, count:100, joiner:"\n"},
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(joinNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
msg.payload.should.equal("Hello\nNodeRED\nWorld\n");
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
catch(e) { console.log(e); }
|
||||||
|
});
|
||||||
|
n1.receive({payload:"Hello"});
|
||||||
|
n1.receive({payload:"NodeRED"});
|
||||||
|
n1.receive({payload:"World"});
|
||||||
|
n1.receive({payload:'', complete:true});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should join split things back into an array', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"join", wires:[["n2"]]},
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(joinNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
msg.payload.should.be.an.Array;
|
||||||
|
msg.payload[0].should.equal(1);
|
||||||
|
msg.payload[1].should.equal(2);
|
||||||
|
msg.payload[2].should.equal(3);
|
||||||
|
msg.payload[3].should.equal(4);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
catch(e) { console.log(e); }
|
||||||
|
});
|
||||||
|
n1.receive({payload:3, parts:{index:2, count:4, id:111}});
|
||||||
|
n1.receive({payload:2, parts:{index:1, count:4, id:111}});
|
||||||
|
n1.receive({payload:4, parts:{index:3, count:4, id:111}});
|
||||||
|
n1.receive({payload:1, parts:{index:0, count:4, id:111}});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should join split things back into an object', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"join", wires:[["n2"]]},
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(joinNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
msg.payload.should.have.property("a",1);
|
||||||
|
msg.payload.should.have.property("b",2);
|
||||||
|
msg.payload.should.have.property("c",3);
|
||||||
|
msg.payload.should.have.property("d",4);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
catch(e) { console.log(e); }
|
||||||
|
});
|
||||||
|
n1.receive({payload:3, parts:{index:2, count:4, id:222, key:"c", type:"object"}});
|
||||||
|
n1.receive({payload:2, parts:{index:1, count:4, id:222, key:"b", type:"object"}});
|
||||||
|
n1.receive({payload:4, parts:{index:3, count:4, id:222, key:"d", type:"object"}});
|
||||||
|
n1.receive({payload:1, parts:{index:0, count:4, id:222, key:"a", type:"object"}});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip('should join split things, missing some after a timeout', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"join", wires:[["n2"]], timeout:50},
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(joinNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
msg.payload.should.be.an.Array;
|
||||||
|
(msg.payload[0] === undefined).should.be.true;
|
||||||
|
msg.payload[1].should.equal(2);
|
||||||
|
msg.payload[2].should.equal(3);
|
||||||
|
(msg.payload[3] === undefined).should.be.true;
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
catch(e) { console.log(e); }
|
||||||
|
});
|
||||||
|
n1.receive({payload:3, parts:{index:2, count:4, id:333}});
|
||||||
|
n1.receive({payload:2, parts:{index:1, count:4, id:333}});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should join split things, send when told complete', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"join", wires:[["n2"]], timeout:250},
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(joinNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
msg.payload.should.be.an.Array;
|
||||||
|
(msg.payload[0] === undefined).should.be.true;
|
||||||
|
msg.payload[1].should.equal(2);
|
||||||
|
msg.payload[2].should.equal(3);
|
||||||
|
msg.payload[3].should.equal(4);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
catch(e) { console.log(e); }
|
||||||
|
});
|
||||||
|
n1.receive({payload:3, parts:{index:2, count:4, id:444} });
|
||||||
|
n1.receive({payload:2, parts:{index:1, count:4, id:444} });
|
||||||
|
n1.receive({payload:4, parts:{index:3, count:4, id:444}, complete:true});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should join split strings back into a word', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"join", wires:[["n2"]]},
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(joinNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
msg.payload.should.be.an.Array;
|
||||||
|
msg.payload.should.equal("abcd");
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
catch(e) { console.log(e); }
|
||||||
|
});
|
||||||
|
n1.receive({payload:"a", parts:{index:0, count:4, ch:"", id:555}});
|
||||||
|
n1.receive({payload:"d", parts:{index:3, count:4, ch:"", id:555}});
|
||||||
|
n1.receive({payload:"c", parts:{index:2, count:4, ch:"", id:555}});
|
||||||
|
n1.receive({payload:"b", parts:{index:1, count:4, ch:"", id:555}});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should join split strings back overriding the join char', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"join", wires:[["n2"]], joiner:":"},
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(joinNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
msg.payload.should.be.an.Array;
|
||||||
|
msg.payload.should.equal("a:b:c:d");
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
catch(e) { console.log(e); }
|
||||||
|
});
|
||||||
|
n1.receive({payload:"a", parts:{index:0, count:4, ch:"", id:666}});
|
||||||
|
n1.receive({payload:"d", parts:{index:3, count:4, ch:"", id:666}});
|
||||||
|
n1.receive({payload:"c", parts:{index:2, count:4, ch:"", id:666}});
|
||||||
|
n1.receive({payload:"b", parts:{index:1, count:4, ch:"", id:666}});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user