Merge branch 'master' into dev

This commit is contained in:
Nick O'Leary 2020-01-22 11:54:24 +00:00
commit 6b52206186
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
54 changed files with 442 additions and 352 deletions

View File

@ -28,7 +28,7 @@ module.exports = function(grunt) {
var nonHeadless = grunt.option('non-headless');
if (nonHeadless) {
process.env.NODE_RED_NON_HEADLESS = 'true';
process.env.NODE_RED_NON_HEADLESS = true;
}
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
@ -80,20 +80,20 @@ module.exports = function(grunt) {
//"loopfunc": true, // allow functions to be defined in loops
//"sub": true // don't warn that foo['bar'] should be written as foo.bar
},
all: [
'Gruntfile.js',
'red.js',
'packages/**/*.js'
],
core: {
files: {
src: [
'Gruntfile.js',
'red.js',
'packages/**/*.js',
]
}
},
// all: [
// 'Gruntfile.js',
// 'red.js',
// 'packages/**/*.js'
// ],
// core: {
// files: {
// src: [
// 'Gruntfile.js',
// 'red.js',
// 'packages/**/*.js',
// ]
// }
// },
nodes: {
files: {
src: [ 'nodes/core/*/*.js' ]
@ -101,7 +101,7 @@ module.exports = function(grunt) {
},
editor: {
files: {
src: [ 'editor/js/**/*.js' ]
src: [ 'packages/node_modules/@node-red/editor-client/src/js/**/*.js' ]
}
},
tests: {

View File

@ -54,9 +54,9 @@
"mqtt": "2.18.8",
"multer": "1.4.2",
"mustache": "3.0.2",
"node-red-node-rbe": "^0.2.5",
"node-red-node-sentiment": "^0.1.4",
"node-red-node-tail": "^0.0.3",
"node-red-node-rbe": "^0.2.6",
"node-red-node-sentiment": "^0.1.6",
"node-red-node-tail": "^0.1.0",
"nopt": "4.0.1",
"oauth2orize": "1.11.0",
"on-headers": "1.0.2",

View File

@ -88,13 +88,13 @@ module.exports = {
// Locales
var locales = require("./locales");
locales.init(runtimeAPI);
editorApp.get(/locales\/(.+)\/?$/,locales.get,apiUtil.errorHandler);
editorApp.get(/^\/locales\/(.+)\/?$/,locales.get,apiUtil.errorHandler);
// Library
var library = require("./library");
library.init(runtimeAPI);
editorApp.get(/library\/([^\/]+)\/([^\/]+)(?:$|\/(.*))/,needsPermission("library.read"),library.getEntry);
editorApp.post(/library\/([^\/]+)\/([^\/]+)\/(.*)/,needsPermission("library.write"),library.saveEntry);
editorApp.get(/^\/library\/([^\/]+)\/([^\/]+)(?:$|\/(.*))/,needsPermission("library.read"),library.getEntry);
editorApp.post(/^\/library\/([^\/]+)\/([^\/]+)\/(.*)/,needsPermission("library.write"),library.saveEntry);
// Credentials

View File

@ -418,8 +418,6 @@ var RED = (function() {
RED.notify(RED._("palette.event.nodeUpgraded", {module:msg.module,version:msg.version}),"success");
RED.nodes.registry.setModulePendingUpdated(msg.module,msg.version);
}
// Refresh flow library to ensure any examples are updated
RED.library.loadFlowLibrary();
});
RED.comms.subscribe("event-log/#", function(topic,payload) {
var id = topic.substring(9);

View File

@ -56,8 +56,9 @@ RED.settings = (function () {
if (key === "auth-tokens") {
return JSON.parse(localStorage.getItem(key));
} else {
var v;
try {
var v = RED.utils.getMessageProperty(userSettings,key);
v = RED.utils.getMessageProperty(userSettings,key);
if (v === undefined) {
v = defaultIfUndefined;
}

View File

@ -410,7 +410,7 @@
return;
}
if (container.hasClass("expanded")) {
done && done();
if (done) { done() }
return;
}
if (!container.hasClass("built") && (item.deferBuild || typeof item.children === 'function')) {
@ -435,7 +435,7 @@
spinner.remove();
}
}
done && done();
if (done) { done() }
that._trigger("childrenloaded",null,item)
}
if (typeof item.children === 'function') {
@ -457,7 +457,7 @@
} else {
item.treeList.childList.slideDown('fast');
}
done && done();
if (done) { done() }
}
container.addClass("expanded");
}

View File

@ -1029,9 +1029,9 @@ RED.diff = (function() {
}
var localSelectDiv = $('<label>',{class:"red-ui-diff-selectbox",for:safeNodeId+"-local"}).on("click", function(e) { e.stopPropagation();}).appendTo(localDiv);
var localRadio = $('<input>',{class:"red-ui-diff-selectbox-input",id:safeNodeId+"-local",type:'radio',value:"local",name:safeNodeId,class:className+"-local"}).data('node-id',node.id).on("change", changeHandler).appendTo(localSelectDiv);
var localRadio = $('<input>',{class:"red-ui-diff-selectbox-input "+className+"-local",id:safeNodeId+"-local",type:'radio',value:"local",name:safeNodeId}).data('node-id',node.id).on("change", changeHandler).appendTo(localSelectDiv);
var remoteSelectDiv = $('<label>',{class:"red-ui-diff-selectbox",for:safeNodeId+"-remote"}).on("click", function(e) { e.stopPropagation();}).appendTo(remoteDiv);
var remoteRadio = $('<input>',{class:"red-ui-diff-selectbox-input",id:safeNodeId+"-remote",type:'radio',value:"remote",name:safeNodeId,class:className+"-remote"}).data('node-id',node.id).on("change", changeHandler).appendTo(remoteSelectDiv);
var remoteRadio = $('<input>',{class:"red-ui-diff-selectbox-input "+className+"-remote",id:safeNodeId+"-remote",type:'radio',value:"remote",name:safeNodeId}).data('node-id',node.id).on("change", changeHandler).appendTo(remoteSelectDiv);
if (state === 'local') {
localRadio.prop('checked',true);
} else if (state === 'remote') {

View File

@ -1320,11 +1320,13 @@ RED.editor = (function() {
newValue = parseInt(newValue);
}
}
if (editing_node._def.defaults[d].type) {
if (newValue == "_ADD_") {
newValue = "";
}
}
if (editing_node[d] != newValue) {
if (editing_node._def.defaults[d].type) {
if (newValue == "_ADD_") {
newValue = "";
}
// Change to a related config node
var configNode = RED.nodes.node(editing_node[d]);
if (configNode) {

View File

@ -301,9 +301,9 @@
var val = $('<input type="text" class="red-ui-editor-type-json-editor-value">').css({width:w+"px"}).val(""+valValue).insertAfter(valueLabel).typedInput({
types:[
'str','num','bool',
{value:"null",label:"null",hasValue:false},
{value:"array",label:RED._("common.type.array"),hasValue:false},
{value:"object",label:RED._("common.type.object"),hasValue:false}
{value:"null",label:RED._("common.type.null"),hasValue:false},
{value:"array",label:RED._("common.type.array"),hasValue:false,icon:"red/images/typedInput/json.png"},
{value:"object",label:RED._("common.type.object"),hasValue:false,icon:"red/images/typedInput/json.png"}
],
default: valType
});
@ -327,10 +327,10 @@
item.value = valValue;
var valClass;
switch(valType) {
case 'str': item.children && (orphanedChildren = item.children); item.treeList.makeLeaf(true); item.type = "string"; valClass = "red-ui-debug-msg-type-string"; valValue = '"'+valValue+'"'; break;
case 'num': item.children && (orphanedChildren = item.children); item.treeList.makeLeaf(true); item.type = "number"; valClass = "red-ui-debug-msg-type-number"; break;
case 'bool': item.children && (orphanedChildren = item.children); item.treeList.makeLeaf(true); item.type = "boolean"; valClass = "red-ui-debug-msg-type-other"; item.value = (valValue === "true"); break;
case 'null': item.children && (orphanedChildren = item.children); item.treeList.makeLeaf(true); item.type = "null"; valClass = "red-ui-debug-msg-type-null"; item.value = valValue = "null"; break;
case 'str': if (item.children) { orphanedChildren = item.children } item.treeList.makeLeaf(true); item.type = "string"; valClass = "red-ui-debug-msg-type-string"; valValue = '"'+valValue+'"'; break;
case 'num': if (item.children) { orphanedChildren = item.children } item.treeList.makeLeaf(true); item.type = "number"; valClass = "red-ui-debug-msg-type-number"; break;
case 'bool': if (item.children) { orphanedChildren = item.children } item.treeList.makeLeaf(true); item.type = "boolean"; valClass = "red-ui-debug-msg-type-other"; item.value = (valValue === "true"); break;
case 'null': if (item.children) { orphanedChildren = item.children } item.treeList.makeLeaf(true); item.type = "null"; valClass = "red-ui-debug-msg-type-null"; item.value = valValue = "null"; break;
case 'object':
item.treeList.makeParent(orphanedChildren);
item.type = "object";
@ -485,7 +485,7 @@
} else if (activeTab === "json-raw") {
result = expressionEditor.getValue();
}
onComplete && onComplete(result);
if (onComplete) { onComplete(result) }
RED.tray.close();
}
}

View File

@ -32,7 +32,7 @@
'<button type="button" class="red-ui-button" data-style="bq"><i class="fa fa-quote-left"></i></button>'+
'<button type="button" class="red-ui-button" data-style="hr"><i class="fa fa-minus"></i></button>'+
'<button type="button" class="red-ui-button" data-style="link"><i class="fa fa-link"></i></button>'+
'</span>'
'</span>'+
'</div>';
var template = '<script type="text/x-red" data-template-name="_markdown">'+

View File

@ -212,16 +212,14 @@ RED.palette = (function() {
}
$('<div/>', {
class: "red-ui-palette-label"
+ (((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-label-right" : "")
class: "red-ui-palette-label"+(((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-label-right" : "")
}).appendTo(d);
if (def.icon) {
var icon_url = RED.utils.getNodeIcon(def);
var iconContainer = $('<div/>', {
class: "red-ui-palette-icon-container"
+ (((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-icon-container-right" : "")
class: "red-ui-palette-icon-container"+(((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-icon-container-right" : "")
}).appendTo(d);
RED.utils.createIconElement(icon_url, iconContainer, true);
}
@ -419,14 +417,10 @@ RED.palette = (function() {
var portOutput = paletteNode.find(".red-ui-palette-port-output");
var paletteLabel = paletteNode.find(".red-ui-palette-label");
paletteLabel.attr("class","red-ui-palette-label"
+ (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-label-right" : "")
);
paletteLabel.attr("class","red-ui-palette-label" + (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-label-right" : ""));
var paletteIconContainer = paletteNode.find(".red-ui-palette-icon-container");
paletteIconContainer.attr("class","red-ui-palette-icon-container"
+ (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-icon-container-right" : "")
);
paletteIconContainer.attr("class","red-ui-palette-icon-container" + (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-icon-container-right" : ""));
if (portInput.length === 0 && sf.in.length > 0) {
var portIn = document.createElement("div");

View File

@ -1938,8 +1938,9 @@ RED.projects = (function() {
resultCallbackArgs = data;
}
}).fail(function(xhr,textStatus,err) {
var responses;
if (options.responses && options.responses[xhr.status]) {
var responses = options.responses[xhr.status];
responses = options.responses[xhr.status];
if (typeof responses === 'function') {
resultCallback = responses;
resultCallbackArgs = {error:responses.statusText};

View File

@ -753,7 +753,7 @@ RED.view = (function() {
// .attr("d","M 0 "+(node_height/2)+" H "+(gridSize * -2))
// .attr("opacity",0);
var filter = undefined;
var filter;
if (drag_lines.length > 0) {
if (drag_lines[0].virtualLink) {
filter = {type:drag_lines[0].node.type === 'link in'?'link out':'link in'}
@ -1495,6 +1495,7 @@ RED.view = (function() {
var lastSelection = null;
function updateSelection() {
var selection = {};
var activeWorkspace = RED.workspaces.active();
var workspaceSelection = RED.workspaces.selection();
if (workspaceSelection.length === 0) {
@ -1504,7 +1505,6 @@ RED.view = (function() {
if (selected_link != null) {
selection.link = selected_link;
}
var activeWorkspace = RED.workspaces.active();
activeLinks = RED.nodes.filterLinks({
source:{z:activeWorkspace},
target:{z:activeWorkspace}
@ -1622,7 +1622,7 @@ RED.view = (function() {
var workspaceSelection = RED.workspaces.selection();
if (workspaceSelection.length > 0) {
var workspaceCount = 0;
workspaceSelection.forEach(function(ws) { if (ws.type === 'tab') workspaceCount++ });
workspaceSelection.forEach(function(ws) { if (ws.type === 'tab') { workspaceCount++ } });
if (workspaceCount === RED.workspaces.count()) {
// Cannot delete all workspaces
return;
@ -1663,7 +1663,7 @@ RED.view = (function() {
var removedLinks = [];
var removedSubflowOutputs = [];
var removedSubflowInputs = [];
var removedSubflowStatus = undefined;
var removedSubflowStatus;
var subflowInstances = [];
var startDirty = RED.nodes.dirty();

View File

@ -52,6 +52,10 @@
@include component-shadow;
border-color: $popover-background;
}
textarea.ace_text-input {
overflow: hidden;
padding: 0px 1px !important;
}
#red-ui-event-log-editor {
.ace_scroller {

View File

@ -145,8 +145,8 @@ g.red-ui-flow-node-selected {
border-color: $node-selected-color !important;
border-style: dashed !important;
stroke: $node-selected-color;
stroke-width: 2;
stroke-dasharray: 8, 3;
stroke-width: 3;
stroke-dasharray: 8, 4;
}
.red-ui-flow-subflow .red-ui-flow-node {

View File

@ -131,8 +131,32 @@
RED.view.redraw();
}
},
messageSourceClick: function(sourceId) {
RED.view.reveal(sourceId);
messageSourceClick: function(sourceId, aliasId, path) {
// Get all of the nodes that could have logged this message
var candidateNodes = [RED.nodes.node(sourceId)]
if (path) {
for (var i=2;i<path.length;i++) {
candidateNodes.push(RED.nodes.node(path[i]))
}
}
if (aliasId) {
candidateNodes.push(RED.nodes.node(aliasId));
}
if (candidateNodes.length > 1) {
// The node is in a subflow. Check to see if the active
// workspace is a subflow in the node's parentage. If
// so, reveal the relevant subflow instance node.
var ws = RED.workspaces.active();
for (var i=0;i<candidateNodes.length;i++) {
if (candidateNodes[i].z === ws) {
RED.view.reveal(candidateNodes[i].id);
return
}
}
// The active workspace is unrelated to the node. So
// fall back to revealing the top most node
}
RED.view.reveal(candidateNodes[0].id);
},
clear: function() {
RED.nodes.eachNode(function(node) {
@ -179,9 +203,44 @@
RED.events.on("workspace:change", this.refreshMessageList);
this.handleDebugMessage = function(t,o) {
var sourceNode = RED.nodes.node(o.id) || RED.nodes.node(o.z);
// console.log("->",o.id,o.z,o._alias);
//
// sourceNode should be the top-level node - one that is on a flow.
var sourceNode;
var pathParts;
if (o.path) {
// Path is a `/`-separated list of ids that identifies the
// complete parentage of the node that generated this message.
// flow-id/subflow-A-instance/subflow-A-type/subflow-B-instance/subflow-B-type/node-id
// If it has one id, that is a top level flow
// each subsequent id is the instance id of a subflow node
//
pathParts = o.path.split("/");
if (pathParts.length === 1) {
// The source node is on a flow - so can use its id to find
sourceNode = RED.nodes.node(o.id);
} else if (pathParts.length > 1) {
// Highlight the subflow instance node.
sourceNode = RED.nodes.node(pathParts[1]);
}
} else {
// This is probably redundant...
sourceNode = RED.nodes.node(o.id) || RED.nodes.node(o.z);
}
if (sourceNode) {
o._source = {id:sourceNode.id,z:sourceNode.z,name:sourceNode.name,type:sourceNode.type,_alias:o._alias};
o._source = {
id:sourceNode.id,
z:sourceNode.z,
name:sourceNode.name,
type:sourceNode.type,
// _alias identifies the actual logging node. This is
// not necessarily the same as sourceNode, which will be
// the top-level subflow instance node.
// This means the node's name is displayed in the sidebar.
_alias:o._alias,
path: pathParts
};
}
RED.debug.handleDebugMessage(o);
if (subWindow) {
@ -235,7 +294,7 @@
} else if (msg.event === "mouseLeave") {
options.messageMouseLeave(msg.id);
} else if (msg.event === "mouseClick") {
options.messageSourceClick(msg.id);
options.messageSourceClick(msg.id,msg._alias,msg.path);
} else if (msg.event === "clear") {
options.clear();
}

View File

@ -62,7 +62,7 @@ module.exports = function(RED) {
if (err) {
done(RED._("debug.invalid-exp", {error: editExpression}));
} else {
done(null,{id:node.id, z:node.z, name:node.name, topic:msg.topic, msg:value, _path:msg._path});
done(null,{id:node.id, z:node.z, _alias: node._alias, path:node._flow.path, name:node.name, topic:msg.topic, msg:value});
}
});
} else {
@ -77,7 +77,7 @@ module.exports = function(RED) {
output = undefined;
}
}
done(null,{id:node.id, z:node.z, name:node.name, topic:msg.topic, property:property, msg:output, _path:msg._path});
done(null,{id:node.id, z:node.z, _alias: node._alias, path:node._flow.path, name:node.name, topic:msg.topic, property:property, msg:output});
}
}
@ -88,7 +88,7 @@ module.exports = function(RED) {
node.log("\n"+util.inspect(msg, {colors:useColors, depth:10}));
}
if (this.active && this.tosidebar) {
sendDebug({id:node.id, z:node.z, name:node.name, topic:msg.topic, msg:msg, _path:msg._path});
sendDebug({id:node.id, z:node.z, _alias: node._alias, path:node._flow.path, name:node.name, topic:msg.topic, msg:msg});
}
done();
} else {

View File

@ -406,10 +406,16 @@ RED.debug = (function() {
msg.on("mouseenter", function() {
msg.addClass('red-ui-debug-msg-hover');
if (o._source) {
// highlight the top-level node (could be subflow instance)
config.messageMouseEnter(o._source.id);
if (o._source._alias) {
// this is inside a subflow - highlight the node itself
config.messageMouseEnter(o._source._alias);
}
// if path.length > 2, we are nested - highlight subflow instances
for (var i=2;i<o._source.path.length;i++) {
config.messageMouseEnter(o._source.path[i]);
}
}
});
msg.on("mouseleave", function() {
@ -419,6 +425,9 @@ RED.debug = (function() {
if (o._source._alias) {
config.messageMouseLeave(o._source._alias);
}
for (var i=2;i<o._source.path.length;i++) {
config.messageMouseLeave(o._source.path[i]);
}
}
});
var name = sanitize(((o.name?o.name:o.id)||"").toString());
@ -452,7 +461,7 @@ RED.debug = (function() {
.appendTo(metaRow)
.on("click", function(evt) {
evt.preventDefault();
config.messageSourceClick(sourceNode.id);
config.messageSourceClick(sourceNode.id, sourceNode._alias, sourceNode.path);
});
} else if (name) {
$('<span class="red-ui-debug-msg-name">'+name+'</span>').appendTo(metaRow);

View File

@ -7,8 +7,8 @@ $(function() {
messageMouseLeave: function(sourceId) {
window.opener.postMessage({event:"mouseLeave",id:sourceId},'*');
},
messageSourceClick: function(sourceId) {
window.opener.postMessage({event:"mouseClick",id:sourceId},'*');
messageSourceClick: function(sourceId, aliasId, path) {
window.opener.postMessage({event:"mouseClick",id:sourceId, _alias: aliasId, path: path},'*');
},
clear: function() {
window.opener.postMessage({event:"clear"},'*');

View File

@ -173,7 +173,7 @@
}
}
$("#node-input-rule-container").css('min-height','250px').css('min-width','450px').editableList({
$("#node-input-rule-container").css('min-height','150px').css('min-width','450px').editableList({
addItem: function(container,i,opt) {
if (!opt.hasOwnProperty('r')) {
opt.r = {};
@ -453,6 +453,7 @@
}
var editorRow = $("#dialog-form>div.node-input-rule-container-row");
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
height += 16;
$("#node-input-rule-container").editableList('height',height);
}
});

View File

@ -81,7 +81,7 @@
rule.find('.red-ui-typedInput').typedInput("width",newWidth-130);
}
$('#node-input-rule-container').css('min-height','300px').css('min-width','450px').editableList({
$('#node-input-rule-container').css('min-height','150px').css('min-width','450px').editableList({
addItem: function(container,i,opt) {
var rule = opt;
if (!rule.hasOwnProperty('t')) {
@ -259,7 +259,7 @@
}
var editorRow = $("#dialog-form>div.node-input-rule-container-row");
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
height += 16;
$("#node-input-rule-container").editableList('height',height);
}
});

View File

@ -137,7 +137,7 @@
<div class="form-row">
<ul style="min-width: 600px; margin-bottom: 20px;" id="node-config-mqtt-broker-tabs"></ul>
</div>
<div id="node-config-mqtt-broker-tabs-content" style="min-height: 170px;">
<div id="node-config-mqtt-broker-tabs-content" style="min-height:150px;">
<div id="mqtt-broker-tab-connection" style="display:none">
<div class="form-row node-input-broker">
<label for="node-config-input-broker"><i class="fa fa-globe"></i> <span data-i18n="mqtt.label.broker"></span></label>

View File

@ -99,7 +99,7 @@
}
$("#node-input-topics-container")
.css('min-height','200px').css('min-width','430px')
.css('min-height','150px').css('min-width','430px')
.editableList({
addItem: function(container, i, opt) {
if (!opt.hasOwnProperty('topic')) {

View File

@ -38,13 +38,13 @@
<h3>入力</h3>
<dl class="message-properties">
<dt>payload <span class="property-type">文字列 | バッファ</span></dt>
<dd>多くの場合単純なテキスト形式のペイロードが使われますが、バイナリバッファを発行することも可能です。</dd>
<dd>発行するペイロード。プロパティが設定されていない場合には、メッセージは送信されません。空のメッセージを送信するには、プロパティに空文字列を設定します。</dd>
<dt class="optional">topic <span class="property-type">文字列</span></dt>
<dd>発行対象のMQTTトピック</dd>
<dt class="optional">qos <span class="property-type">数値</span></dt>
<dd>0: 最大1度到着, 1: 一度以上到着, 2: 1度のみ到着。デフォルトは0です。</dd>
<dd>0: 最大一度到着, 1: 一度以上到着, 2: 一度のみ到着。デフォルトは0です。</dd>
<dt class="optional">retain <span class="property-type">真偽値</span></dt>
<dd>真の場合、メッセージをブローカに保持します。デフォルトは偽です。</dd>

View File

@ -52,7 +52,7 @@ function Node(n) {
// the object (such as dashboard) will not like circular refs
// The value must still be writable in the case that a node does:
// Object.assign(this,config)
// as part of its constructure - config._flow will overwrite this._flow
// as part of its constructor - config._flow will overwrite this._flow
// which we can tolerate as they are the same object.
Object.defineProperty(this,'_flow', {value: n._flow, enumerable: false, writable: true })
this._asyncDelivery = n._flow.asyncMessageDelivery;
@ -462,6 +462,9 @@ function log_helper(self, level, msg) {
if (self._alias) {
o._alias = self._alias;
}
if (self._flow) {
o.path = self._flow.path;
}
if (self.z) {
o.z = self.z;
}

View File

@ -53,6 +53,7 @@ class Flow {
this.subflowInstanceNodes = {};
this.catchNodes = [];
this.statusNodes = [];
this.path = this.id;
}
/**
@ -120,7 +121,7 @@ class Flow {
* @return {[type]} [description]
*/
start(diff) {
this.trace("start "+this.TYPE);
this.trace("start "+this.TYPE+" ["+this.path+"]");
var node;
var newNode;
var id;
@ -234,7 +235,7 @@ class Flow {
for (id in this.activeNodes) {
if (this.activeNodes.hasOwnProperty(id)) {
node = this.activeNodes[id];
this.trace(" "+id.padEnd(16)+" | "+node.type.padEnd(12)+" | "+(node._alias||""));
this.trace(" "+id.padEnd(16)+" | "+node.type.padEnd(12)+" | "+(node._alias||"")+(node._zAlias?" [zAlias:"+node._zAlias+"]":""));
if (node.type === "catch") {
this.catchNodes.push(node);
} else if (node.type === "status") {

View File

@ -88,7 +88,7 @@ class Subflow extends Flow {
* @param {[type]} subflowInstance [description]
*/
constructor(parent,globalFlow,subflowDef,subflowInstance) {
// console.log("CREATE SUBFLOW",subflowDef.id,subflowInstance.id);
// console.log("CREATE SUBFLOW",subflowDef.id,subflowInstance.id,"alias?",subflowInstance._alias);
// console.log("SubflowInstance\n"+JSON.stringify(subflowInstance," ",2));
// console.log("SubflowDef\n"+JSON.stringify(subflowDef," ",2));
var subflows = parent.flow.subflows;
@ -140,6 +140,7 @@ class Subflow extends Flow {
this.subflowDef = subflowDef;
this.subflowInstance = subflowInstance;
this.node_map = node_map;
this.path = parent.path+"/"+(subflowInstance._alias||subflowInstance.id);
var env = [];
if (this.subflowDef.env) {
@ -451,7 +452,7 @@ class Subflow extends Flow {
function createNodeInSubflow(subflowInstanceId, def) {
let node = clone(def);
let nid = redUtil.generateId();
// console.log("Create Node In subflow",node.id, "--->",nid, "(",node.type,")")
// console.log("Create Node In subflow",node._alias, "--->",nid, "(",node.type,")")
// node_map[node.id] = node;
node._alias = node.id;
node.id = nid;

View File

@ -39,8 +39,8 @@
"bcryptjs": "2.4.3",
"express": "4.17.1",
"fs-extra": "8.1.0",
"node-red-node-rbe": "^0.2.5",
"node-red-node-tail": "^0.0.3",
"node-red-node-rbe": "^0.2.6",
"node-red-node-tail": "^0.1.0",
"nopt": "4.0.1",
"semver": "6.3.0"
},

View File

@ -52,8 +52,14 @@ function getFlowFilename() {
}
function cleanup(flowFile) {
deleteFile(homeDir+"/"+flowFile);
deleteFile(homeDir+"/."+flowFile+".backup");
var credentialFile = flowFile.replace(/\.json$/, '') + '_cred.json';
deleteFile(homeDir + "/" + flowFile);
deleteFile(homeDir + "/." + flowFile + ".backup");
deleteFile(homeDir + "/" + credentialFile);
deleteFile(homeDir + "/." + credentialFile + ".backup");
deleteFile(homeDir + "/package.json");
deleteFile(homeDir + "/lib/flows");
deleteFile(homeDir + "/lib");
}
function deleteFile(flowFile) {
@ -63,7 +69,7 @@ function deleteFile(flowFile) {
fs.unlinkSync(flowFile);
}
} catch (e) {}
};
}
module.exports = {
startServer: function() {
@ -101,7 +107,7 @@ module.exports = {
});
});
browser.url(url);
browser.waitForExist(".red-ui-palette-node[data-palette-type='inject']")
browser.waitForExist(".red-ui-palette-node[data-palette-type='inject']");
} catch (err) {
console.log(err);
throw err;

View File

@ -17,7 +17,7 @@
var idMap = {
// input
"inject": ".red-ui-palette-node[data-palette-type='inject']",
"httpin": ".red-ui-palette-node[data-palette-type='http in']",
"httpIn": ".red-ui-palette-node[data-palette-type='http in']",
"mqttIn": ".red-ui-palette-node[data-palette-type='mqtt in']",
// output
"debug": ".red-ui-palette-node[data-palette-type='debug']",
@ -32,7 +32,7 @@ var idMap = {
"html": ".red-ui-palette-node[data-palette-type='html']",
"json": ".red-ui-palette-node[data-palette-type='json']",
// storage
"filein": ".red-ui-palette-node[data-palette-type='file in']",
"fileIn": ".red-ui-palette-node[data-palette-type='file in']",
};
function getId(type) {

View File

@ -14,19 +14,16 @@
* limitations under the License.
**/
var when = require("when");
var when = require("when");
var events = require("nr-test-utils").require("@node-red/runtime/lib/events.js");
var palette = require("./palette_page");
var nodeFactory = require("../nodes/nodefactory_page");
var keyPage = require("../util/key_page");
var flowLayout = {
flowRightEnd : 600,
widthInterval : 300,
heightInterval : 80
};
var previousX = -flowLayout.widthInterval;
var previousY = 0;
@ -44,6 +41,10 @@ function addNode(type, x, y) {
previousY = previousY + flowLayout.heightInterval;
}
}
browser.waitForVisible('#red-ui-palette-search');
browser.setValue('//*[@id="red-ui-palette-search"]/div/input', type.replace(/([A-Z])/g,' $1').toLowerCase());
browser.pause(300);
browser.waitForVisible(palette.getId(type));
browser.moveToObject(palette.getId(type));
browser.buttonDown();
browser.moveToObject("#red-ui-palette-search", previousX + 300, previousY + 100); // adjust to the top-left corner of workspace.
@ -56,8 +57,10 @@ function addNode(type, x, y) {
}
function deleteAllNodes() {
browser.click('.red-ui-workspace-chart-event-layer');
browser.keys(['Control', 'a', 'a', 'Control']); // call twice to release the keys.
browser.waitForVisible('//*[contains(@class, "active")]/a[@class="red-ui-tab-label"]');
browser.click('//*[contains(@class, "active")]/a[@class="red-ui-tab-label"]');
browser.pause(1000);
browser.keys(keyPage.selectAll());
browser.keys(['Delete']);
}
@ -66,13 +69,14 @@ function deploy() {
return when.promise(function(resolve, reject) {
events.on("runtime-event", function(event) {
if (event.id === 'runtime-deploy') {
events.removeListener("runtime-event", arguments.callee);
resolve();
}
});
browser.clickWithWait('#red-ui-header-button-deploy');
});
});
browser.waitForText('#red-ui-header-button-deploy', 2000);
browser.waitForText('#red-ui-header-button-deploy', 10000);
// Need additional wait until buttons becomes clickable.
browser.pause(50);
}

View File

@ -47,11 +47,11 @@ injectNode.prototype.setPayload = function(payloadType, payload) {
// Open a payload type list.
browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-container")]');
// Select a payload type.
var payloadTypeXPath = '//*[@class="red-ui-typedInput-options"]/a[' + payloadTypeList[payloadType] + ']';
var payloadTypeXPath = '//*[contains(@class, "red-ui-typedInput-options")]/a[' + payloadTypeList[payloadType] + ']';
browser.clickWithWait(payloadTypeXPath);
if (payload) {
// Input a value.
browser.setValue('//*[@class="red-ui-typedInput-input"]/input', payload);
browser.setValue('//*[contains(@class, "red-ui-typedInput-input")]/input', payload);
}
}

View File

@ -26,16 +26,13 @@ function debugNode(id) {
util.inherits(debugNode, nodePage);
debugNode.prototype.setOutput = function(complete) {
debugNode.prototype.setOutput = function (complete) {
// Open a payload type list.
browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-container")]/button');
if (complete !== 'true') {
// Select the "msg" type.
browser.clickWithWait('//div[@class="red-ui-typedInput-options"][1]/a[1]');
browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options")][1]/a[1]');
// Input the path in msg.
browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-input")]/input');
browser.keys(keyPage.selectAll());
browser.keys(['Delete']);
browser.setValue('//*[contains(@class, "red-ui-typedInput-input")]/input', complete);
} else {
// Select the "complete msg object" type.

View File

@ -26,12 +26,11 @@ function functionNode(id) {
util.inherits(functionNode, nodePage);
functionNode.prototype.setFunction = function(func) {
functionNode.prototype.setFunction = function (func) {
browser.clickWithWait('#node-input-func-editor');
browser.keys(keyPage.selectAll());
for (var i = 0; i < func.length; i++) {
browser.keys([func.charAt(i)]);
}
browser.keys(['Delete']);
browser.keys(func);
// Delete the unnecessary code that ace editor does the autocompletion.
browser.keys(keyPage.selectToEnd());
browser.keys(['Delete']);

View File

@ -49,13 +49,13 @@ function setT(t, index) {
}
// It is better to create a function whose input value is the object type in the future,
changeNode.prototype.ruleSet = function(p, pt, to, tot, index) {
index = index ? index : 1;
changeNode.prototype.ruleSet = function (p, pt, to, tot, index) {
index = index || 1;
setT("set", index);
if (pt) {
browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/button[1]');
var num = 5 * (index - 1) + 1;
var ptXPath = '//div[@class="red-ui-typedInput-options"][' + num + ']/a[' + ptType[pt] + ']';
var ptXPath = '//div[contains(@class, "red-ui-typedInput-options")][' + num + ']/a[' + ptType[pt] + ']';
browser.clickWithWait(ptXPath);
}
if (p) {
@ -64,27 +64,27 @@ changeNode.prototype.ruleSet = function(p, pt, to, tot, index) {
if (tot) {
browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[2]/div[2]/button[1]');
var num = 5 * (index - 1) + 2;
var totXPath = '//div[@class="red-ui-typedInput-options"][' + num + ']/a[' + totType[tot] + ']';
var totXPath = '//div[contains(@class, "red-ui-typedInput-options")][' + num + ']/a[' + totType[tot] + ']';
browser.clickWithWait(totXPath);
}
if (to) {
browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[2]/div[2]/div/input' , to);
browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[2]/div[2]/div/input', to);
}
}
changeNode.prototype.ruleDelete = function(index) {
index = index ? index : 1;
changeNode.prototype.ruleDelete = function (index) {
index = index || 1;
setT("delete", index);
}
changeNode.prototype.ruleMove = function(p, to, index) {
index = index ? index : 1;
changeNode.prototype.ruleMove = function (p, to, index) {
index = index || 1;
setT("move", index);
browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/div/input', p);
browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[4]/div[2]/div/input', to);
}
changeNode.prototype.addRule = function() {
changeNode.prototype.addRule = function () {
browser.clickWithWait('//*[@id="dialog-form"]/div[3]/div/a');
}

View File

@ -26,21 +26,19 @@ function templateNode(id) {
util.inherits(templateNode, nodePage);
templateNode.prototype.setSyntax = function(syntax) {
templateNode.prototype.setSyntax = function (syntax) {
browser.selectWithWait('#node-input-syntax', syntax);
}
templateNode.prototype.setFormat = function(format) {
templateNode.prototype.setFormat = function (format) {
browser.selectWithWait('#node-input-format', format);
}
templateNode.prototype.setTemplate = function(template) {
templateNode.prototype.setTemplate = function (template) {
browser.clickWithWait('#node-input-template-editor');
browser.keys(keyPage.selectAll());
// Need to add a character one by one since some words such as 'Control' are treated as a special word.
for (var i = 0; i < template.length; i++) {
browser.keys([template.charAt(i)]);
}
browser.keys(['Delete']);
browser.keys(template);
browser.keys(keyPage.selectToEnd());
browser.keys(['Delete']);
// Need to wait until ace editor correctly checks the syntax.

View File

@ -23,13 +23,14 @@ function setServer(broker, port) {
function clickOk() {
browser.clickWithWait('#node-config-dialog-ok');
// Wait until an config dialog closes.
browser.waitForVisible('#node-config-dialog-ok', 2000, true);
browser.waitForVisible('#node-config-dialog-ok', 10000, true);
}
function edit() {
browser.clickWithWait('#node-input-lookup-broker');
browser.waitForVisible('#node-input-lookup-broker');
browser.click('#node-input-lookup-broker');
// Wait until a config dialog opens.
browser.waitForVisible('#node-config-dialog-ok', 2000);
browser.waitForVisible('#node-config-dialog-ok', 10000);
}
module.exports = {

View File

@ -18,18 +18,18 @@ var util = require("util");
var nodePage = require("../../node_page");
function httpinNode(id) {
function httpInNode(id) {
nodePage.call(this, id);
}
util.inherits(httpinNode, nodePage);
util.inherits(httpInNode, nodePage);
httpinNode.prototype.setMethod = function(method) {
httpInNode.prototype.setMethod = function(method) {
browser.selectWithWait('#node-input-method', method);
}
httpinNode.prototype.setUrl = function(url) {
httpInNode.prototype.setUrl = function(url) {
browser.setValue('#node-input-url', url);
}
module.exports = httpinNode;
module.exports = httpInNode;

View File

@ -18,11 +18,11 @@ var util = require("util");
var nodePage = require("../../node_page");
function fileinNode(id) {
function fileInNode(id) {
nodePage.call(this, id);
}
util.inherits(fileinNode, nodePage);
util.inherits(fileInNode, nodePage);
var formatType = {
"utf8": 1,
@ -31,14 +31,14 @@ var formatType = {
"stream": 4
};
fileinNode.prototype.setFilename = function(filename) {
fileInNode.prototype.setFilename = function(filename) {
browser.setValue('#node-input-filename', filename);
}
fileinNode.prototype.setOutput = function(format) {
fileInNode.prototype.setOutput = function(format) {
browser.clickWithWait('#node-input-format');
var formatTypeXPath = '//*[@id="node-input-format"]/option[' + formatType[format] + ']';
browser.clickWithWait(formatTypeXPath);
}
module.exports = fileinNode;
module.exports = fileInNode;

View File

@ -18,28 +18,33 @@ function Node(id) {
this.id = '//*[@id="' + id + '"]';
}
Node.prototype.edit = function() {
browser.clickWithWait(this.id);
browser.clickWithWait(this.id);
Node.prototype.edit = function () {
browser.waitForVisible(this.id);
browser.moveToObject(this.id);
browser.buttonDown();
browser.buttonUp();
browser.keys(['Enter']);
// Wait until an edit dialog opens.
browser.waitForVisible('#node-dialog-ok', 2000);
browser.waitForVisible('#node-dialog-ok', 10000);
}
Node.prototype.clickOk = function() {
Node.prototype.clickOk = function () {
browser.clickWithWait('#node-dialog-ok');
// Wait untile an edit dialog closes.
browser.waitForVisible('#node-dialog-ok', 2000, true);
browser.waitForVisible('#node-dialog-ok', 10000, true);
browser.pause(50);
}
Node.prototype.connect = function(targetNode) {
Node.prototype.connect = function (targetNode) {
var outputPort = this.id + '/*[@class="red-ui-flow-port-output"]';
var inputPort = targetNode.id + '/*[@class="red-ui-flow-port-input"]';
browser.dragAndDrop(outputPort, inputPort)
}
Node.prototype.clickLeftButton = function() {
browser.clickWithWait(this.id + '/*[@class="red-ui-flow-node-button"]');
Node.prototype.clickLeftButton = function () {
browser.moveToObject(this.id + '/*[@class="red-ui-flow-node-button"]');
browser.buttonDown();
browser.buttonUp();
}
module.exports = Node;

View File

@ -14,46 +14,46 @@
* limitations under the License.
**/
var injectNode = require('./core/core/20-inject_page');
var debugNode = require('./core/core/58-debug_page');
var templateNode = require('./core/core/80-template_page');
var functionNode = require('./core/core/80-function_page');
var mqttInNode = require('./core/io/10-mqttin_page');
var mqttOutNode = require('./core/io/10-mqttout_page');
var httpinNode = require('./core/io/21-httpin_page');
var httpResponseNode = require('./core/io/21-httpresponse_page');
var changeNode = require('./core/logic/15-change_page');
var rangeNode = require('./core/logic/16-range_page');
var httpRequestNode = require('./core/io/21-httprequest_page');
var injectNode = require('./core/common/20-inject_page');
var debugNode = require('./core/common/21-debug_page');
var functionNode = require('./core/function/10-function_page');
var changeNode = require('./core/function/15-change_page');
var rangeNode = require('./core/function/16-range_page');
var templateNode = require('./core/function/80-template_page');
var mqttInNode = require('./core/network/10-mqttin_page');
var mqttOutNode = require('./core/network/10-mqttout_page');
var httpInNode = require('./core/network/21-httpin_page');
var httpResponseNode = require('./core/network/21-httpresponse_page');
var httpRequestNode = require('./core/network/21-httprequest_page');
var htmlNode = require('./core/parsers/70-HTML_page');
var jsonNode = require('./core/parsers/70-JSON_page');
var fileinNode = require('./core/storage/50-filein_page');
var fileInNode = require('./core/storage/10-filein_page');
var nodeCatalog = {
// input
// common
"inject": injectNode,
"httpin": httpinNode,
"mqttIn":mqttInNode,
// output
"debug": debugNode,
"httpResponse": httpResponseNode,
"mqttOut": mqttOutNode,
// function
"function": functionNode,
"template": templateNode,
"change": changeNode,
"range": rangeNode,
"template": templateNode,
// network
"mqttIn": mqttInNode,
"mqttOut": mqttOutNode,
"httpIn": httpInNode,
"httpResponse": httpResponseNode,
"httpRequest": httpRequestNode,
// parser
"html": htmlNode,
"json":jsonNode,
"json": jsonNode,
// storage
"filein": fileinNode,
}
"fileIn": fileInNode
};
function create(type, id) {
var node = nodeCatalog[type];
return new node(id);
var Node = nodeCatalog[type];
return new Node(id);
}
module.exports = {

View File

@ -17,21 +17,20 @@
var os = require("os");
var shortCutKeyMap = {
"selectAll": ['Control', 'a', 'Control'],
"selectAll": ['Control', 'a', 'a', 'Control'],
"selectToEnd": ['Control', 'Shift', 'End', 'Shift', 'Control'],
};
var shortCutKeyMapForMac = {
"selectAll": ['Command', 'a', 'Command'],
"selectAll": ['Command', 'a', 'a', 'Command'],
"selectToEnd": ['Command', 'Shift', 'ArrowDown', 'Shift', 'Command'],
};
function getShortCutKey(type) {
if (os.type() === "Darwin") {
if (os.type() === 'Darwin') {
return shortCutKeyMapForMac[type];
} else {
return shortCutKeyMap[type];
}
return shortCutKeyMap[type];
}
function selectAll() {

View File

@ -37,7 +37,7 @@ describe('Workspace', function() {
});
it('should have a right title', function () {
browser.getTitle().should.equal('Node-RED');
browser.getTitle().should.startWith('Node-RED');
});
it('should output a timestamp', function() {

View File

@ -38,14 +38,14 @@ describe('cookbook', function() {
describe('HTTP endpoints', function () {
it('create an HTTP endpoint', function () {
var httpinNode = workspace.addNode("httpin");
var httpInNode = workspace.addNode("httpIn");
var templateNode = workspace.addNode("template");
var httpResponseNode = workspace.addNode("httpResponse");
httpinNode.edit();
httpinNode.setMethod("get");
httpinNode.setUrl("/hello");
httpinNode.clickOk();
httpInNode.edit();
httpInNode.setMethod("get");
httpInNode.setUrl("/hello");
httpInNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
@ -53,7 +53,7 @@ describe('cookbook', function() {
templateNode.setTemplate("<html>\n<head></head>\n<body>\n<h1>Hello World!</h1>\n</body>\n</html>");
templateNode.clickOk();
httpinNode.connect(templateNode);
httpInNode.connect(templateNode);
templateNode.connect(httpResponseNode);
// The code for confirmation starts from here.
@ -77,14 +77,14 @@ describe('cookbook', function() {
});
it('handle query parameters passed to an HTTP endpoint', function () {
var httpinNode = workspace.addNode("httpin");
var httpInNode = workspace.addNode("httpIn");
var templateNode = workspace.addNode("template");
var httpResponseNode = workspace.addNode("httpResponse");
httpinNode.edit();
httpinNode.setMethod("get");
httpinNode.setUrl("/hello-query");
httpinNode.clickOk();
httpInNode.edit();
httpInNode.setMethod("get");
httpInNode.setUrl("/hello-query");
httpInNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
@ -92,7 +92,7 @@ describe('cookbook', function() {
templateNode.setTemplate("<html>\n<head></head>\n<body>\n<h1>Hello {{req.query.name}}!</h1>\n</body>\n</html>");
templateNode.clickOk();
httpinNode.connect(templateNode);
httpInNode.connect(templateNode);
templateNode.connect(httpResponseNode);
// The code for confirmation starts from here.
@ -116,14 +116,14 @@ describe('cookbook', function() {
});
it('handle url parameters in an HTTP endpoint', function () {
var httpinNode = workspace.addNode("httpin");
var httpInNode = workspace.addNode("httpIn");
var templateNode = workspace.addNode("template");
var httpResponseNode = workspace.addNode("httpResponse");
httpinNode.edit();
httpinNode.setMethod("get");
httpinNode.setUrl("/hello-param/:name");
httpinNode.clickOk();
httpInNode.edit();
httpInNode.setMethod("get");
httpInNode.setUrl("/hello-param/:name");
httpInNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
@ -131,7 +131,7 @@ describe('cookbook', function() {
templateNode.setTemplate("<html>\n<head></head>\n<body>\n<h1>Hello {{req.params.name}}!</h1>\n</body>\n</html>");
templateNode.clickOk();
httpinNode.connect(templateNode);
httpInNode.connect(templateNode);
templateNode.connect(httpResponseNode);
// The code for confirmation starts from here.
@ -155,14 +155,14 @@ describe('cookbook', function() {
});
it('access HTTP request headers', function () {
var httpinNode = workspace.addNode("httpin");
var httpInNode = workspace.addNode("httpIn");
var templateNode = workspace.addNode("template");
var httpResponseNode = workspace.addNode("httpResponse");
httpinNode.edit();
httpinNode.setMethod("get");
httpinNode.setUrl("/hello-headers");
httpinNode.clickOk();
httpInNode.edit();
httpInNode.setMethod("get");
httpInNode.setUrl("/hello-headers");
httpInNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
@ -170,7 +170,7 @@ describe('cookbook', function() {
templateNode.setTemplate("<html>\n<head></head>\n<body>\n<h1>User agent: {{req.headers.user-agent}}</h1>\n</body>\n</html>");
templateNode.clickOk();
httpinNode.connect(templateNode);
httpInNode.connect(templateNode);
templateNode.connect(httpResponseNode);
// The code for confirmation starts from here.
@ -203,7 +203,7 @@ describe('cookbook', function() {
var injectNodeTimestamp = workspace.addNode("inject");
var changeNodeStore = workspace.addNode("change");
var httpinNode = workspace.addNode("httpin", 0, 100);
var httpInNode = workspace.addNode("httpIn", 0, 100);
var changeNodeCopy = workspace.addNode("change");
var templateNode = workspace.addNode("template");
var httpResponseNode = workspace.addNode("httpResponse");
@ -218,10 +218,10 @@ describe('cookbook', function() {
injectNodeTimestamp.connect(changeNodeStore);
httpinNode.edit();
httpinNode.setMethod("get");
httpinNode.setUrl("/hello-data");
httpinNode.clickOk();
httpInNode.edit();
httpInNode.setMethod("get");
httpInNode.setUrl("/hello-data");
httpInNode.clickOk();
changeNodeCopy.edit();
changeNodeCopy.ruleSet("timestamp", "msg", "timestamp", "flow");
@ -233,7 +233,7 @@ describe('cookbook', function() {
templateNode.setTemplate("<html>\n<head></head>\n<body>\n<h1>Time: {{ timestamp }}</h1>\n</body>\n</html>");
templateNode.clickOk();
httpinNode.connect(changeNodeCopy);
httpInNode.connect(changeNodeCopy);
changeNodeCopy.connect(templateNode);
templateNode.connect(httpResponseNode);
@ -260,15 +260,15 @@ describe('cookbook', function() {
});
it('serve JSON content', function () {
var httpinNode = workspace.addNode("httpin");
var httpInNode = workspace.addNode("httpIn");
var templateNode = workspace.addNode("template");
var changeNode = workspace.addNode("change");
var httpResponseNode = workspace.addNode("httpResponse");
httpinNode.edit();
httpinNode.setMethod("get");
httpinNode.setUrl("/hello-json");
httpinNode.clickOk();
httpInNode.edit();
httpInNode.setMethod("get");
httpInNode.setUrl("/hello-json");
httpInNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
@ -282,7 +282,7 @@ describe('cookbook', function() {
changeNode.ruleSet("headers.content-type", "msg", "application/json", "str", "2");
changeNode.clickOk();
httpinNode.connect(templateNode);
httpInNode.connect(templateNode);
templateNode.connect(changeNode);
changeNode.connect(httpResponseNode);
@ -314,20 +314,20 @@ describe('cookbook', function() {
});
it('serve a local file', function () {
var httpinNode = workspace.addNode("httpin");
var fileinNode = workspace.addNode("filein");
var httpInNode = workspace.addNode("httpIn");
var fileInNode = workspace.addNode("fileIn");
var changeNode = workspace.addNode("change", 200, 100);
var httpResponseNode = workspace.addNode("httpResponse");
httpinNode.edit();
httpinNode.setMethod("get");
httpinNode.setUrl("/hello-file");
httpinNode.clickOk();
httpInNode.edit();
httpInNode.setMethod("get");
httpInNode.setUrl("/hello-file");
httpInNode.clickOk();
fileinNode.edit();
fileinNode.setFilename("test/resources/file-in-node/test.txt");
fileinNode.setOutput("");
fileinNode.clickOk();
fileInNode.edit();
fileInNode.setFilename("test/resources/file-in-node/test.txt");
fileInNode.setOutput("");
fileInNode.clickOk();
changeNode.edit();
changeNode.ruleSet("headers", "msg", "{}", "json");
@ -335,8 +335,8 @@ describe('cookbook', function() {
changeNode.ruleSet("headers.content-type", "msg", "text/plain", "str", "2");
changeNode.clickOk();
httpinNode.connect(fileinNode);
fileinNode.connect(changeNode);
httpInNode.connect(fileInNode);
fileInNode.connect(changeNode);
changeNode.connect(httpResponseNode);
// The code for confirmation starts from here.
@ -360,14 +360,14 @@ describe('cookbook', function() {
});
it('post raw data to a flow', function() {
var httpinNode = workspace.addNode("httpin");
var httpInNode = workspace.addNode("httpIn");
var templateNode = workspace.addNode("template");
var httpResponseNode = workspace.addNode("httpResponse");
httpinNode.edit();
httpinNode.setMethod("post");
httpinNode.setUrl("/hello-raw");
httpinNode.clickOk();
httpInNode.edit();
httpInNode.setMethod("post");
httpInNode.setUrl("/hello-raw");
httpInNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
@ -375,7 +375,7 @@ describe('cookbook', function() {
templateNode.setTemplate("<html>\n<head></head>\n<body>\n<h1>Hello {{ payload }}!</h1>\n</body>\n</html>");
templateNode.clickOk();
httpinNode.connect(templateNode);
httpInNode.connect(templateNode);
templateNode.connect(httpResponseNode);
// The code for confirmation starts from here.
@ -403,14 +403,14 @@ describe('cookbook', function() {
});
it('post form data to a flow', function () {
var httpinNode = workspace.addNode("httpin");
var httpInNode = workspace.addNode("httpIn");
var templateNode = workspace.addNode("template");
var httpResponseNode = workspace.addNode("httpResponse");
httpinNode.edit();
httpinNode.setMethod("post");
httpinNode.setUrl("/hello-form");
httpinNode.clickOk();
httpInNode.edit();
httpInNode.setMethod("post");
httpInNode.setUrl("/hello-form");
httpInNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
@ -418,7 +418,7 @@ describe('cookbook', function() {
templateNode.setTemplate("<html>\n<head></head>\n<body>\n<h1>Hello {{ payload.name }}!</h1>\n</body>\n</html>");
templateNode.clickOk();
httpinNode.connect(templateNode);
httpInNode.connect(templateNode);
templateNode.connect(httpResponseNode);
// The code for confirmation starts from here.
@ -452,14 +452,14 @@ describe('cookbook', function() {
});
it('post JSON data to a flow', function() {
var httpinNode = workspace.addNode("httpin");
var httpInNode = workspace.addNode("httpIn");
var templateNode = workspace.addNode("template");
var httpResponseNode = workspace.addNode("httpResponse");
httpinNode.edit();
httpinNode.setMethod("post");
httpinNode.setUrl("/hello-json");
httpinNode.clickOk();
httpInNode.edit();
httpInNode.setMethod("post");
httpInNode.setUrl("/hello-json");
httpInNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
@ -467,7 +467,7 @@ describe('cookbook', function() {
templateNode.setTemplate("<html>\n<head></head>\n<body>\n<h1>Hello {{ payload.name }}!</h1>\n</body>\n</html>");
templateNode.clickOk();
httpinNode.connect(templateNode);
httpInNode.connect(templateNode);
templateNode.connect(httpResponseNode);
// The code for confirmation starts from here.
@ -501,24 +501,22 @@ describe('cookbook', function() {
});
it('work with cookies', function () {
this.timeout(60000);
var httpinNodeFormat = workspace.addNode("httpin");
var httpInNodeFormat = workspace.addNode("httpIn");
var functionNodeFormat = workspace.addNode("function", 240);
var templateNode = workspace.addNode("template", 400);
var httpResponseNode = workspace.addNode("httpResponse", 600);
var httpinNodeAdd = workspace.addNode("httpin", 0, 100);
var httpInNodeAdd = workspace.addNode("httpIn", 0, 100);
var functionNodeAdd = workspace.addNode("function", 240);
var changeNode = workspace.addNode("change", 400);
var httpinNodeClear = workspace.addNode("httpin", 0, 200);
var httpInNodeClear = workspace.addNode("httpIn", 0, 200);
var functionNodeClear = workspace.addNode("function", 250);
httpinNodeFormat.edit();
httpinNodeFormat.setMethod("get");
httpinNodeFormat.setUrl("/hello-cookie");
httpinNodeFormat.clickOk();
httpInNodeFormat.edit();
httpInNodeFormat.setMethod("get");
httpInNodeFormat.setUrl("/hello-cookie");
httpInNodeFormat.clickOk();
functionNodeFormat.edit();
functionNodeFormat.setFunction("msg.payload = JSON.stringify(msg.req.cookies,null,4);\nreturn msg;");
@ -530,14 +528,14 @@ describe('cookbook', function() {
templateNode.setTemplate('<html>\n<head></head>\n<body>\n<h1>Cookies</h1>\n<p></p><a href="hello-cookie/add">Add a cookie</a> &bull; <a href="hello-cookie/clear">Clear cookies</a></p>\n<pre>{{ payload }}</pre>\n</body>\n</html>');
templateNode.clickOk();
httpinNodeFormat.connect(functionNodeFormat);
httpInNodeFormat.connect(functionNodeFormat);
functionNodeFormat.connect(templateNode);
templateNode.connect(httpResponseNode);
httpinNodeAdd.edit();
httpinNodeAdd.setMethod("get");
httpinNodeAdd.setUrl("/hello-cookie/add");
httpinNodeAdd.clickOk();
httpInNodeAdd.edit();
httpInNodeAdd.setMethod("get");
httpInNodeAdd.setUrl("/hello-cookie/add");
httpInNodeAdd.clickOk();
functionNodeAdd.edit();
functionNodeAdd.setFunction('msg.cookies = { };\n msg.cookies["demo-"+(Math.floor(Math.random()*1000))] = Date.now();\nreturn msg;');
@ -551,20 +549,20 @@ describe('cookbook', function() {
changeNode.ruleSet("headers.location", "msg", httpNodeRoot + "/hello-cookie", "str", "3");
changeNode.clickOk();
httpinNodeAdd.connect(functionNodeAdd);
httpInNodeAdd.connect(functionNodeAdd);
functionNodeAdd.connect(changeNode);
changeNode.connect(httpResponseNode);
httpinNodeClear.edit();
httpinNodeClear.setMethod("get");
httpinNodeClear.setUrl("/hello-cookie/clear");
httpinNodeClear.clickOk();
httpInNodeClear.edit();
httpInNodeClear.setMethod("get");
httpInNodeClear.setUrl("/hello-cookie/clear");
httpInNodeClear.clickOk();
functionNodeClear.edit();
functionNodeClear.setFunction("var cookieNames = Object.keys(msg.req.cookies).filter(function(cookieName) { return /^demo-/.test(cookieName);});\nmsg.cookies = {};\n\ncookieNames.forEach(function(cookieName) {\n msg.cookies[cookieName] = null;\n});\nreturn msg;\n");
functionNodeClear.clickOk();
httpinNodeClear.connect(functionNodeClear);
httpInNodeClear.connect(functionNodeClear);
functionNodeClear.connect(changeNode);
workspace.deploy();

View File

@ -22,42 +22,45 @@ var helper = require("../../editor_helper");
var debugTab = require('../../pageobjects/editor/debugTab_page');
var workspace = require('../../pageobjects/editor/workspace_page');
var specUtil = require('../../pageobjects/util/spec_util_page');
var mqttConfig = require('../../pageobjects/nodes/core/io/10-mqttconfig_page.js');
var mqttConfig = require('../../pageobjects/nodes/core/network/10-mqttconfig_page.js');
var httpNodeRoot = "/api";
var mqttServer;
var mosca = require('mosca');
var moscaSettings = {
port: 1883,
port: parseInt(Math.random() * 16383 + 49152),
persistence: {
// Needs for retaining messages.
factory: mosca.persistence.Memory
}
};
// https://cookbook.nodered.org/
describe('cookbook', function() {
beforeEach(function() {
describe('cookbook', function () {
beforeEach(function () {
workspace.init();
});
before(function() {
browser.call(function() {
return new Promise(function(resolve, reject) {
mqttServer = new mosca.Server(moscaSettings, function() {
resolve();
before(function () {
browser.call(function () {
return new Promise(function (resolve, reject) {
mqttServer = new mosca.Server(moscaSettings, function (err) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
});
helper.startServer();
});
after(function() {
browser.call(function() {
return new Promise(function(resolve, reject) {
mqttServer.close(function() {
after(function () {
browser.call(function () {
return new Promise(function (resolve, reject) {
mqttServer.close(function () {
resolve();
});
});
@ -65,20 +68,20 @@ describe('cookbook', function() {
helper.stopServer();
});
describe('MQTT', function() {
it('Add an MQTT broker to prepare for UI test', function() {
describe('MQTT', function () {
it('Add an MQTT broker to prepare for UI test', function () {
var mqttOutNode = workspace.addNode("mqttOut");
mqttOutNode.edit();
mqttConfig.edit();
mqttConfig.setServer("localhost");
mqttConfig.setServer("localhost", moscaSettings.port);
mqttConfig.clickOk();
mqttOutNode.clickOk();
workspace.deploy();
});
it('Connect to an MQTT broker', function() {
it('Connect to an MQTT broker', function () {
var injectNode = workspace.addNode("inject");
var mqttOutNode = workspace.addNode("mqttOut");
@ -112,7 +115,7 @@ describe('cookbook', function() {
// skip this case since it is same as other cases.
it.skip('Publish messages to a topic');
it('Set the topic of a published message', function() {
it('Set the topic of a published message', function () {
var injectNode = workspace.addNode("inject");
var mqttOutNode = workspace.addNode("mqttOut");
@ -144,7 +147,7 @@ describe('cookbook', function() {
debugTab.getMessage().should.eql('"22"');
});
it('Publish a retained message to a topic', function() {
it('Publish a retained message to a topic', function () {
var injectNode = workspace.addNode("inject");
var mqttOutNode = workspace.addNode("mqttOut");
@ -182,7 +185,7 @@ describe('cookbook', function() {
// skip this case since it is same as other cases.
it.skip('Subscribe to a topic');
it('Receive a parsed JSON message', function() {
it('Receive a parsed JSON message', function () {
var injectNode = workspace.addNode("inject");
var mqttOutNode = workspace.addNode("mqttOut");

View File

@ -284,14 +284,14 @@ describe('cookbook', function() {
httpRequetNode.connect(debugNode);
// The code for confirmation starts from here.
var httpinNode = workspace.addNode("httpin", 0, 200);
var httpInNode = workspace.addNode("httpIn", 0, 200);
var templateNode = workspace.addNode("template");
var httpResponseNode = workspace.addNode("httpResponse");
httpinNode.edit();
httpinNode.setMethod("get");
httpinNode.setUrl("/set-query");
httpinNode.clickOk();
httpInNode.edit();
httpInNode.setMethod("get");
httpInNode.setUrl("/set-query");
httpInNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
@ -299,7 +299,7 @@ describe('cookbook', function() {
templateNode.setTemplate("Hello {{req.query.q}}");
templateNode.clickOk();
httpinNode.connect(templateNode);
httpInNode.connect(templateNode);
templateNode.connect(httpResponseNode);
// The code for confirmation ends here.
@ -331,7 +331,7 @@ describe('cookbook', function() {
httpRequetNode.clickOk();
debugNode.edit();
debugNode.setOutput("payload.title");
debugNode.setOutput(".title");
debugNode.clickOk();
injectNode.connect(changeNodeSetPost);
@ -339,15 +339,15 @@ describe('cookbook', function() {
httpRequetNode.connect(debugNode);
// The code for confirmation starts from here.
var httpinNode = workspace.addNode("httpin", 0, 200);
var httpInNode = workspace.addNode("httpIn", 0, 200);
var templateNode = workspace.addNode("template");
var changeNodeSetHeader = workspace.addNode("change");
var httpResponseNode = workspace.addNode("httpResponse");
httpinNode.edit();
httpinNode.setMethod("get");
httpinNode.setUrl("/json-response");
httpinNode.clickOk();
httpInNode.edit();
httpInNode.setMethod("get");
httpInNode.setUrl("/json-response");
httpInNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
@ -359,7 +359,7 @@ describe('cookbook', function() {
changeNodeSetHeader.ruleSet("headers", "msg", '{"content-type":"application/json"}', "json");
changeNodeSetHeader.clickOk();
httpinNode.connect(templateNode);
httpInNode.connect(templateNode);
templateNode.connect(changeNodeSetHeader);
changeNodeSetHeader.connect(httpResponseNode);
// The code for confirmation ends here.
@ -413,14 +413,14 @@ describe('cookbook', function() {
httpRequetNode.connect(debugNode);
// The code for confirmation starts from here.
var httpinNode = workspace.addNode("httpin", 0, 200);
var httpInNode = workspace.addNode("httpIn", 0, 200);
var templateNode = workspace.addNode("template");
var httpResponseNode = workspace.addNode("httpResponse");
httpinNode.edit();
httpinNode.setMethod("post");
httpinNode.setUrl("/set-header");
httpinNode.clickOk();
httpInNode.edit();
httpInNode.setMethod("post");
httpInNode.setUrl("/set-header");
httpInNode.clickOk();
templateNode.edit();
templateNode.setSyntax("mustache");
@ -428,7 +428,7 @@ describe('cookbook', function() {
templateNode.setTemplate("{{ payload }}");
templateNode.clickOk();
httpinNode.connect(templateNode);
httpInNode.connect(templateNode);
templateNode.connect(httpResponseNode);
// The code for confirmation ends here.

View File

@ -15,7 +15,7 @@
**/
exports.config = {
//
// ==================
// Specify Test Files
@ -64,9 +64,9 @@ exports.config = {
'goog:chromeOptions': {
args: process.env.NODE_RED_NON_HEADLESS
// Runs tests with opening a browser.
? ['--disable-gpu']
? ['--disable-gpu', '--no-sandbox']
// Runs tests without opening a browser.
: ['--headless', '--disable-gpu', 'window-size=1920,1080']
: ['--headless', '--disable-gpu', 'window-size=1920,1080', '--no-sandbox']
},
}],
//
@ -150,12 +150,12 @@ exports.config = {
// The only one supported by default is 'dot'
// see also: http://webdriver.io/guide/reporters/dot.html
reporters: ['spec'],
//
// Options to be passed to Mocha.
// See the full list at http://mochajs.org/
mochaOpts: {
timeout: 60000,
timeout: 100000,
ui: 'bdd'
},
//
@ -197,7 +197,7 @@ exports.config = {
*/
// beforeCommand: function (commandName, args) {
// },
/**
* Hook that gets executed before the suite starts
* @param {Object} suite suite details
@ -217,13 +217,13 @@ exports.config = {
// beforeHook: function () {
// },
/**
* Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling
* Hook that gets executed _after_ a hook within the suite ends (e.g. runs after calling
* afterEach in Mocha)
*/
// afterHook: function () {
// },
/**
* Function to be executed after a test (in Mocha/Jasmine) or a step (in Cucumber) starts.
* Function to be executed after a test (in Mocha/Jasmine) or a step (in Cucumber) ends.
* @param {Object} test test details
*/
// afterTest: function (test) {
@ -234,7 +234,7 @@ exports.config = {
*/
// afterSuite: function (suite) {
// },
/**
* Runs after a WebdriverIO command gets executed
* @param {String} commandName hook command name

View File

@ -58,7 +58,7 @@ describe('debug node', function() {
n1.emit("input", {payload:"test"});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",name:"Debug",msg:"test",
topic:"debug",data:{id:"n1",name:"Debug",msg:"test",path:"global",
format:"string[4]",property:"payload"}
}]);
}, done);
@ -74,7 +74,7 @@ describe('debug node', function() {
n1.emit("input", {payload:"test"});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"test",property:"payload",format:"string[4]"}
topic:"debug",data:{id:"n1",msg:"test",property:"payload",format:"string[4]",path:"global"}
}]);
count++;
}, function() {
@ -85,7 +85,7 @@ describe('debug node', function() {
});
logEvents.should.have.length(1);
var tstmp = logEvents[0][0].timestamp;
logEvents[0][0].should.eql({level:helper.log().INFO, id:'n1',type:'debug',msg:'test', timestamp:tstmp});
logEvents[0][0].should.eql({level:helper.log().INFO, id:'n1',type:'debug',msg:'test', timestamp:tstmp,path:"global"});
done();
} catch(err) {
@ -104,7 +104,7 @@ describe('debug node', function() {
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",
data:{id:"n1",msg:'{\n "payload": "test"\n}',format:"Object"}
data:{id:"n1",msg:'{\n "payload": "test"\n}',format:"Object",path:"global"}
}]);
}, done);
});
@ -119,7 +119,7 @@ describe('debug node', function() {
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",
data:{id:"n1",msg:'{\n "payload": "test"\n}',format:"Object"}
data:{id:"n1",msg:'{\n "payload": "test"\n}',format:"Object",path:"global"}
}]);
}, function() {
try {
@ -129,7 +129,7 @@ describe('debug node', function() {
});
logEvents.should.have.length(1);
var tstmp = logEvents[0][0].timestamp;
logEvents[0][0].should.eql({level:helper.log().INFO, id:"n1",type:"debug",msg:'\n{ payload: \'test\' }',timestamp:tstmp});
logEvents[0][0].should.eql({level:helper.log().INFO, id:"n1",type:"debug",msg:'\n{ payload: \'test\' }',timestamp:tstmp,path:"global"});
done();
} catch(err) {
done(err);
@ -146,7 +146,7 @@ describe('debug node', function() {
n1.emit("input", {payload:"test", foo:"bar"});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"bar",property:"foo",format:"string[3]"}
topic:"debug",data:{id:"n1",msg:"bar",property:"foo",format:"string[3]",path:"global"}
}]);
}, done);
});
@ -160,7 +160,7 @@ describe('debug node', function() {
n1.emit("input", {payload:"test", foo: {bar:"bar"}});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"bar",property:"foo.bar",format:"string[3]"}
topic:"debug",data:{id:"n1",msg:"bar",property:"foo.bar",format:"string[3]",path:"global"}
}]);
}, done);
});
@ -174,7 +174,7 @@ describe('debug node', function() {
n1.emit("input", {payload: new Error("oops")});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:'{"name":"Error","message":"oops"}',property:"payload",format:"error"}
topic:"debug",data:{id:"n1",msg:'{"name":"Error","message":"oops"}',property:"payload",format:"error",path:"global"}
}]);
}, done);
});
@ -188,7 +188,7 @@ describe('debug node', function() {
n1.emit("input", {payload: true});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg: 'true',property:"payload",format:"boolean"}
topic:"debug",data:{id:"n1",msg: 'true',property:"payload",format:"boolean",path:"global"}
}]);
}, done);
});
@ -202,7 +202,7 @@ describe('debug node', function() {
n1.emit("input", {payload: 7});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"7",property:"payload",format:"number"}
topic:"debug",data:{id:"n1",msg:"7",property:"payload",format:"number",path:"global"}
}]);
}, done);
});
@ -216,7 +216,7 @@ describe('debug node', function() {
n1.emit("input", {payload: Number.NaN});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"NaN",property:"payload",format:"number"}
topic:"debug",data:{id:"n1",msg:"NaN",property:"payload",format:"number",path:"global"}
}]);
}, done);
});
@ -230,7 +230,7 @@ describe('debug node', function() {
n1.emit("input", {});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:'(undefined)',property:"payload",format:"undefined"}
topic:"debug",data:{id:"n1",msg:'(undefined)',property:"payload",format:"undefined",path:"global"}
}]);
}, done);
});
@ -244,7 +244,7 @@ describe('debug node', function() {
n1.emit("input", {payload:null});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:'(undefined)',property:"payload",format:"null"}
topic:"debug",data:{id:"n1",msg:'(undefined)',property:"payload",format:"null",path:"global"}
}]);
}, done);
});
@ -259,7 +259,7 @@ describe('debug node', function() {
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",
data:{id:"n1",msg:'{\n "type": "foo"\n}',property:"payload",format:"Object"}
data:{id:"n1",msg:'{\n "type": "foo"\n}',property:"payload",format:"Object",path:"global"}
}]);
}, done);
});
@ -275,7 +275,7 @@ describe('debug node', function() {
JSON.parse(msg).should.eql([{
topic:"debug",
data:{id:"n1",msg: '[\n 0,\n 1,\n 2,\n 3\n]',format:"array[4]",
property:"payload"}
property:"payload",path:"global"}
}]);
}, done);
});
@ -295,7 +295,7 @@ describe('debug node', function() {
data:{
id:"n1",
msg:'{\n "name": "bar",\n "o": "[Circular ~]"\n}',
property:"payload",format:"Object"
property:"payload",format:"Object",path:"global"
}
}]);
}, done);
@ -310,7 +310,7 @@ describe('debug node', function() {
n1.emit("input", {payload: {type:'foo'}});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:'{\n "type": "foo"\n}',property:"payload",format:"Object"}
topic:"debug",data:{id:"n1",msg:'{\n "type": "foo"\n}',property:"payload",format:"Object",path:"global"}
}]);
}, function() {
try {
@ -320,7 +320,7 @@ describe('debug node', function() {
});
logEvents.should.have.length(1);
var tstmp = logEvents[0][0].timestamp;
logEvents[0][0].should.eql({level:helper.log().INFO,id:"n1",type:"debug",msg:'\n{ type: \'foo\' }',timestamp:tstmp});
logEvents[0][0].should.eql({level:helper.log().INFO,id:"n1",type:"debug",msg:'\n{ type: \'foo\' }',timestamp:tstmp,path:"global"});
done();
} catch(err) {
done(err);
@ -337,7 +337,7 @@ describe('debug node', function() {
n1.emit("input", {payload:"test\ntest"});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"test\ntest",property:"payload",format:"string[9]"}
topic:"debug",data:{id:"n1",msg:"test\ntest",property:"payload",format:"string[9]",path:"global"}
}]);
}, function() {
try {
@ -347,7 +347,7 @@ describe('debug node', function() {
});
logEvents.should.have.length(1);
var tstmp = logEvents[0][0].timestamp;
logEvents[0][0].should.eql({level:helper.log().INFO,id:"n1",type:"debug",msg:"\ntest\ntest",timestamp:tstmp});
logEvents[0][0].should.eql({level:helper.log().INFO,id:"n1",type:"debug",msg:"\ntest\ntest",timestamp:tstmp,path:"global"});
done();
} catch(err) {
done(err);
@ -366,7 +366,7 @@ describe('debug node', function() {
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",name:"Debug",msg:"<test>",
format:"string[6]"}
format:"string[6]",path:"global"}
}]);
}, done);
});
@ -386,7 +386,8 @@ describe('debug node', function() {
id:"n1",
msg: Array(1001).join("X")+'...',
property:"payload",
format:"string[1001]"
format:"string[1001]",
path:"global"
}
}]);
}, done);
@ -407,7 +408,8 @@ describe('debug node', function() {
id:"n1",
msg:'{\n "foo": "'+Array(1001).join("X")+'..."\n}',
property:"payload",
format:"Object"
format:"Object",
path:"global"
}
}]);
}, done);
@ -433,7 +435,8 @@ describe('debug node', function() {
length: 1001
},null," "),
property:"payload",
format:"array[1001]"
format:"array[1001]",
path:"global"
}
}]);
}, done);
@ -461,7 +464,8 @@ describe('debug node', function() {
}
},null," "),
property:"payload",
format:"Object"
format:"Object",
path:"global"
}
}]);
}, done);
@ -473,7 +477,7 @@ describe('debug node', function() {
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload: Buffer(501).fill("\"")});
n1.emit("input", {payload: Buffer.alloc(501,"\"")});
}, function(msg) {
var a = JSON.parse(msg);
a[0].should.eql({
@ -482,7 +486,8 @@ describe('debug node', function() {
id:"n1",
msg: Array(1001).join("2"),
property:"payload",
format:"buffer[501]"
format:"buffer[501]",
path:"global"
}
});
}, done);
@ -494,7 +499,7 @@ describe('debug node', function() {
helper.load(debugNode, flow, function() {
var n1 = helper.getNode("n1");
websocket_test(function() {
n1.emit("input", {payload: {foo: Buffer(1001).fill("X")}});
n1.emit("input", {payload: {foo: Buffer.alloc(1001,"X")}});
}, function(msg) {
var a = JSON.parse(msg);
a[0].should.eql({
@ -510,7 +515,8 @@ describe('debug node', function() {
}
},null," "),
property:"payload",
format:"Object"
format:"Object",
path:"global"
}
});
}, done);
@ -530,7 +536,8 @@ describe('debug node', function() {
id:"n1",
msg:'48454c4c4f',
property:"payload",
format:"buffer[5]"
format:"buffer[5]",
path:"global"
}
}]);
}, done);
@ -551,7 +558,7 @@ describe('debug node', function() {
});
}, function(msg) {
JSON.parse(msg).should.eql([{
topic:"debug",data:{id:"n1",msg:"message 2",property:"payload",format:"string[9]"}
topic:"debug",data:{id:"n1",msg:"message 2",property:"payload",format:"string[9]",path:"global"}
}]);
}, done);
});

View File

@ -898,7 +898,7 @@ describe('HTTP Request Node', function() {
});
logEvents.should.have.length(1);
var tstmp = logEvents[0][0].timestamp;
logEvents[0][0].should.eql({level:helper.log().ERROR, id:'n1',type:'http request',msg:'common.notification.errors.no-response', timestamp:tstmp});
logEvents[0][0].should.eql({level:helper.log().ERROR, id:'n1',type:'http request',msg:'common.notification.errors.no-response', timestamp:tstmp, path:"global"});
done();
} catch(err) {
done(err);
@ -924,7 +924,7 @@ describe('HTTP Request Node', function() {
});
logEvents.should.have.length(1);
var tstmp = logEvents[0][0].timestamp;
logEvents[0][0].should.eql({level:helper.log().ERROR, id:'n1',type:'http request',msg:'common.notification.errors.no-response', timestamp:tstmp});
logEvents[0][0].should.eql({level:helper.log().ERROR, id:'n1',type:'http request',msg:'common.notification.errors.no-response', timestamp:tstmp, path:"global"});
done();
} catch(err) {
done(err);
@ -947,7 +947,7 @@ describe('HTTP Request Node', function() {
});
logEvents.should.have.length(2);
var tstmp = logEvents[0][0].timestamp;
logEvents[0][0].should.eql({level:helper.log().WARN, id:'n1',type:'http request',msg:'httpin.errors.timeout-isnan', timestamp:tstmp});
logEvents[0][0].should.eql({level:helper.log().WARN, id:'n1',type:'http request',msg:'httpin.errors.timeout-isnan', timestamp:tstmp, path:"global"});
done();
} catch(err) {
done(err);
@ -970,7 +970,7 @@ describe('HTTP Request Node', function() {
});
logEvents.should.have.length(2);
var tstmp = logEvents[0][0].timestamp;
logEvents[0][0].should.eql({level:helper.log().WARN, id:'n1',type:'http request',msg:'httpin.errors.timeout-isnegative', timestamp:tstmp});
logEvents[0][0].should.eql({level:helper.log().WARN, id:'n1',type:'http request',msg:'httpin.errors.timeout-isnegative', timestamp:tstmp, path:"global"});
done();
} catch(err) {
done(err);
@ -993,7 +993,7 @@ describe('HTTP Request Node', function() {
});
logEvents.should.have.length(2);
var tstmp = logEvents[0][0].timestamp;
logEvents[0][0].should.eql({level:helper.log().WARN, id:'n1',type:'http request',msg:'httpin.errors.timeout-isnegative', timestamp:tstmp});
logEvents[0][0].should.eql({level:helper.log().WARN, id:'n1',type:'http request',msg:'httpin.errors.timeout-isnegative', timestamp:tstmp, path:"global"});
done();
} catch(err) {
done(err);
@ -1291,7 +1291,6 @@ describe('HTTP Request Node', function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
console.log(msg.payload);
try {
msg.payload.headers.should.have.property('content-type').which.startWith('application/json');
msg.payload.headers.should.not.have.property('x-node-red-request-node');