1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

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

View File

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

View File

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

View File

@ -418,8 +418,6 @@ var RED = (function() {
RED.notify(RED._("palette.event.nodeUpgraded", {module:msg.module,version:msg.version}),"success"); RED.notify(RED._("palette.event.nodeUpgraded", {module:msg.module,version:msg.version}),"success");
RED.nodes.registry.setModulePendingUpdated(msg.module,msg.version); 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) { RED.comms.subscribe("event-log/#", function(topic,payload) {
var id = topic.substring(9); var id = topic.substring(9);

View File

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

View File

@ -410,7 +410,7 @@
return; return;
} }
if (container.hasClass("expanded")) { if (container.hasClass("expanded")) {
done && done(); if (done) { done() }
return; return;
} }
if (!container.hasClass("built") && (item.deferBuild || typeof item.children === 'function')) { if (!container.hasClass("built") && (item.deferBuild || typeof item.children === 'function')) {
@ -435,7 +435,7 @@
spinner.remove(); spinner.remove();
} }
} }
done && done(); if (done) { done() }
that._trigger("childrenloaded",null,item) that._trigger("childrenloaded",null,item)
} }
if (typeof item.children === 'function') { if (typeof item.children === 'function') {
@ -457,7 +457,7 @@
} else { } else {
item.treeList.childList.slideDown('fast'); item.treeList.childList.slideDown('fast');
} }
done && done(); if (done) { done() }
} }
container.addClass("expanded"); 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 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 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') { if (state === 'local') {
localRadio.prop('checked',true); localRadio.prop('checked',true);
} else if (state === 'remote') { } else if (state === 'remote') {

View File

@ -1320,11 +1320,13 @@ RED.editor = (function() {
newValue = parseInt(newValue); newValue = parseInt(newValue);
} }
} }
if (editing_node._def.defaults[d].type) {
if (newValue == "_ADD_") {
newValue = "";
}
}
if (editing_node[d] != newValue) { if (editing_node[d] != newValue) {
if (editing_node._def.defaults[d].type) { if (editing_node._def.defaults[d].type) {
if (newValue == "_ADD_") {
newValue = "";
}
// Change to a related config node // Change to a related config node
var configNode = RED.nodes.node(editing_node[d]); var configNode = RED.nodes.node(editing_node[d]);
if (configNode) { 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({ var val = $('<input type="text" class="red-ui-editor-type-json-editor-value">').css({width:w+"px"}).val(""+valValue).insertAfter(valueLabel).typedInput({
types:[ types:[
'str','num','bool', 'str','num','bool',
{value:"null",label:"null",hasValue:false}, {value:"null",label:RED._("common.type.null"),hasValue:false},
{value:"array",label:RED._("common.type.array"),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} {value:"object",label:RED._("common.type.object"),hasValue:false,icon:"red/images/typedInput/json.png"}
], ],
default: valType default: valType
}); });
@ -327,10 +327,10 @@
item.value = valValue; item.value = valValue;
var valClass; var valClass;
switch(valType) { 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 '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': item.children && (orphanedChildren = item.children); item.treeList.makeLeaf(true); item.type = "number"; valClass = "red-ui-debug-msg-type-number"; 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': 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 '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': 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 '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': case 'object':
item.treeList.makeParent(orphanedChildren); item.treeList.makeParent(orphanedChildren);
item.type = "object"; item.type = "object";
@ -485,7 +485,7 @@
} else if (activeTab === "json-raw") { } else if (activeTab === "json-raw") {
result = expressionEditor.getValue(); result = expressionEditor.getValue();
} }
onComplete && onComplete(result); if (onComplete) { onComplete(result) }
RED.tray.close(); 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="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="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>'+ '<button type="button" class="red-ui-button" data-style="link"><i class="fa fa-link"></i></button>'+
'</span>' '</span>'+
'</div>'; '</div>';
var template = '<script type="text/x-red" data-template-name="_markdown">'+ var template = '<script type="text/x-red" data-template-name="_markdown">'+

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -131,8 +131,32 @@
RED.view.redraw(); RED.view.redraw();
} }
}, },
messageSourceClick: function(sourceId) { messageSourceClick: function(sourceId, aliasId, path) {
RED.view.reveal(sourceId); // 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() { clear: function() {
RED.nodes.eachNode(function(node) { RED.nodes.eachNode(function(node) {
@ -179,9 +203,44 @@
RED.events.on("workspace:change", this.refreshMessageList); RED.events.on("workspace:change", this.refreshMessageList);
this.handleDebugMessage = function(t,o) { 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) { 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); RED.debug.handleDebugMessage(o);
if (subWindow) { if (subWindow) {
@ -235,7 +294,7 @@
} else if (msg.event === "mouseLeave") { } else if (msg.event === "mouseLeave") {
options.messageMouseLeave(msg.id); options.messageMouseLeave(msg.id);
} else if (msg.event === "mouseClick") { } else if (msg.event === "mouseClick") {
options.messageSourceClick(msg.id); options.messageSourceClick(msg.id,msg._alias,msg.path);
} else if (msg.event === "clear") { } else if (msg.event === "clear") {
options.clear(); options.clear();
} }

View File

@ -62,7 +62,7 @@ module.exports = function(RED) {
if (err) { if (err) {
done(RED._("debug.invalid-exp", {error: editExpression})); done(RED._("debug.invalid-exp", {error: editExpression}));
} else { } 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 { } else {
@ -77,7 +77,7 @@ module.exports = function(RED) {
output = undefined; 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})); node.log("\n"+util.inspect(msg, {colors:useColors, depth:10}));
} }
if (this.active && this.tosidebar) { 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(); done();
} else { } else {

View File

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

View File

@ -7,8 +7,8 @@ $(function() {
messageMouseLeave: function(sourceId) { messageMouseLeave: function(sourceId) {
window.opener.postMessage({event:"mouseLeave",id:sourceId},'*'); window.opener.postMessage({event:"mouseLeave",id:sourceId},'*');
}, },
messageSourceClick: function(sourceId) { messageSourceClick: function(sourceId, aliasId, path) {
window.opener.postMessage({event:"mouseClick",id:sourceId},'*'); window.opener.postMessage({event:"mouseClick",id:sourceId, _alias: aliasId, path: path},'*');
}, },
clear: function() { clear: function() {
window.opener.postMessage({event:"clear"},'*'); 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) { addItem: function(container,i,opt) {
if (!opt.hasOwnProperty('r')) { if (!opt.hasOwnProperty('r')) {
opt.r = {}; opt.r = {};
@ -453,6 +453,7 @@
} }
var editorRow = $("#dialog-form>div.node-input-rule-container-row"); var editorRow = $("#dialog-form>div.node-input-rule-container-row");
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom"))); height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
height += 16;
$("#node-input-rule-container").editableList('height',height); $("#node-input-rule-container").editableList('height',height);
} }
}); });

View File

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

View File

@ -137,7 +137,7 @@
<div class="form-row"> <div class="form-row">
<ul style="min-width: 600px; margin-bottom: 20px;" id="node-config-mqtt-broker-tabs"></ul> <ul style="min-width: 600px; margin-bottom: 20px;" id="node-config-mqtt-broker-tabs"></ul>
</div> </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 id="mqtt-broker-tab-connection" style="display:none">
<div class="form-row node-input-broker"> <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> <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") $("#node-input-topics-container")
.css('min-height','200px').css('min-width','430px') .css('min-height','150px').css('min-width','430px')
.editableList({ .editableList({
addItem: function(container, i, opt) { addItem: function(container, i, opt) {
if (!opt.hasOwnProperty('topic')) { if (!opt.hasOwnProperty('topic')) {

View File

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

View File

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

View File

@ -53,6 +53,7 @@ class Flow {
this.subflowInstanceNodes = {}; this.subflowInstanceNodes = {};
this.catchNodes = []; this.catchNodes = [];
this.statusNodes = []; this.statusNodes = [];
this.path = this.id;
} }
/** /**
@ -120,7 +121,7 @@ class Flow {
* @return {[type]} [description] * @return {[type]} [description]
*/ */
start(diff) { start(diff) {
this.trace("start "+this.TYPE); this.trace("start "+this.TYPE+" ["+this.path+"]");
var node; var node;
var newNode; var newNode;
var id; var id;
@ -234,7 +235,7 @@ class Flow {
for (id in this.activeNodes) { for (id in this.activeNodes) {
if (this.activeNodes.hasOwnProperty(id)) { if (this.activeNodes.hasOwnProperty(id)) {
node = this.activeNodes[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") { if (node.type === "catch") {
this.catchNodes.push(node); this.catchNodes.push(node);
} else if (node.type === "status") { } else if (node.type === "status") {

View File

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

View File

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

View File

@ -52,8 +52,14 @@ function getFlowFilename() {
} }
function cleanup(flowFile) { function cleanup(flowFile) {
deleteFile(homeDir+"/"+flowFile); var credentialFile = flowFile.replace(/\.json$/, '') + '_cred.json';
deleteFile(homeDir+"/."+flowFile+".backup"); 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) { function deleteFile(flowFile) {
@ -63,7 +69,7 @@ function deleteFile(flowFile) {
fs.unlinkSync(flowFile); fs.unlinkSync(flowFile);
} }
} catch (e) {} } catch (e) {}
}; }
module.exports = { module.exports = {
startServer: function() { startServer: function() {
@ -101,7 +107,7 @@ module.exports = {
}); });
}); });
browser.url(url); 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) { } catch (err) {
console.log(err); console.log(err);
throw err; throw err;

View File

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

View File

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

View File

@ -47,11 +47,11 @@ injectNode.prototype.setPayload = function(payloadType, payload) {
// Open a payload type list. // Open a payload type list.
browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-container")]'); browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-container")]');
// Select a payload type. // 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); browser.clickWithWait(payloadTypeXPath);
if (payload) { if (payload) {
// Input a value. // 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); util.inherits(debugNode, nodePage);
debugNode.prototype.setOutput = function(complete) { debugNode.prototype.setOutput = function (complete) {
// Open a payload type list. // Open a payload type list.
browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-container")]/button'); browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-container")]/button');
if (complete !== 'true') { if (complete !== 'true') {
// Select the "msg" type. // 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. // 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); browser.setValue('//*[contains(@class, "red-ui-typedInput-input")]/input', complete);
} else { } else {
// Select the "complete msg object" type. // Select the "complete msg object" type.

View File

@ -26,12 +26,11 @@ function functionNode(id) {
util.inherits(functionNode, nodePage); util.inherits(functionNode, nodePage);
functionNode.prototype.setFunction = function(func) { functionNode.prototype.setFunction = function (func) {
browser.clickWithWait('#node-input-func-editor'); browser.clickWithWait('#node-input-func-editor');
browser.keys(keyPage.selectAll()); browser.keys(keyPage.selectAll());
for (var i = 0; i < func.length; i++) { browser.keys(['Delete']);
browser.keys([func.charAt(i)]); browser.keys(func);
}
// Delete the unnecessary code that ace editor does the autocompletion. // Delete the unnecessary code that ace editor does the autocompletion.
browser.keys(keyPage.selectToEnd()); browser.keys(keyPage.selectToEnd());
browser.keys(['Delete']); 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, // 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) { changeNode.prototype.ruleSet = function (p, pt, to, tot, index) {
index = index ? index : 1; index = index || 1;
setT("set", index); setT("set", index);
if (pt) { if (pt) {
browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/button[1]'); browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/button[1]');
var num = 5 * (index - 1) + 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); browser.clickWithWait(ptXPath);
} }
if (p) { if (p) {
@ -64,27 +64,27 @@ changeNode.prototype.ruleSet = function(p, pt, to, tot, index) {
if (tot) { if (tot) {
browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[2]/div[2]/button[1]'); browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[2]/div[2]/button[1]');
var num = 5 * (index - 1) + 2; 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); browser.clickWithWait(totXPath);
} }
if (to) { 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) { changeNode.prototype.ruleDelete = function (index) {
index = index ? index : 1; index = index || 1;
setT("delete", index); setT("delete", index);
} }
changeNode.prototype.ruleMove = function(p, to, index) { changeNode.prototype.ruleMove = function (p, to, index) {
index = index ? index : 1; index = index || 1;
setT("move", index); 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[1]/div/div/input', p);
browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[4]/div[2]/div/input', to); 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'); browser.clickWithWait('//*[@id="dialog-form"]/div[3]/div/a');
} }

View File

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

View File

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

View File

@ -18,18 +18,18 @@ var util = require("util");
var nodePage = require("../../node_page"); var nodePage = require("../../node_page");
function httpinNode(id) { function httpInNode(id) {
nodePage.call(this, 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); browser.selectWithWait('#node-input-method', method);
} }
httpinNode.prototype.setUrl = function(url) { httpInNode.prototype.setUrl = function(url) {
browser.setValue('#node-input-url', 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"); var nodePage = require("../../node_page");
function fileinNode(id) { function fileInNode(id) {
nodePage.call(this, id); nodePage.call(this, id);
} }
util.inherits(fileinNode, nodePage); util.inherits(fileInNode, nodePage);
var formatType = { var formatType = {
"utf8": 1, "utf8": 1,
@ -31,14 +31,14 @@ var formatType = {
"stream": 4 "stream": 4
}; };
fileinNode.prototype.setFilename = function(filename) { fileInNode.prototype.setFilename = function(filename) {
browser.setValue('#node-input-filename', filename); browser.setValue('#node-input-filename', filename);
} }
fileinNode.prototype.setOutput = function(format) { fileInNode.prototype.setOutput = function(format) {
browser.clickWithWait('#node-input-format'); browser.clickWithWait('#node-input-format');
var formatTypeXPath = '//*[@id="node-input-format"]/option[' + formatType[format] + ']'; var formatTypeXPath = '//*[@id="node-input-format"]/option[' + formatType[format] + ']';
browser.clickWithWait(formatTypeXPath); browser.clickWithWait(formatTypeXPath);
} }
module.exports = fileinNode; module.exports = fileInNode;

View File

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

View File

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

View File

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

View File

@ -37,7 +37,7 @@ describe('Workspace', function() {
}); });
it('should have a right title', 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() { it('should output a timestamp', function() {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -898,7 +898,7 @@ describe('HTTP Request Node', function() {
}); });
logEvents.should.have.length(1); logEvents.should.have.length(1);
var tstmp = logEvents[0][0].timestamp; 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(); done();
} catch(err) { } catch(err) {
done(err); done(err);
@ -924,7 +924,7 @@ describe('HTTP Request Node', function() {
}); });
logEvents.should.have.length(1); logEvents.should.have.length(1);
var tstmp = logEvents[0][0].timestamp; 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(); done();
} catch(err) { } catch(err) {
done(err); done(err);
@ -947,7 +947,7 @@ describe('HTTP Request Node', function() {
}); });
logEvents.should.have.length(2); logEvents.should.have.length(2);
var tstmp = logEvents[0][0].timestamp; 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(); done();
} catch(err) { } catch(err) {
done(err); done(err);
@ -970,7 +970,7 @@ describe('HTTP Request Node', function() {
}); });
logEvents.should.have.length(2); logEvents.should.have.length(2);
var tstmp = logEvents[0][0].timestamp; 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(); done();
} catch(err) { } catch(err) {
done(err); done(err);
@ -993,7 +993,7 @@ describe('HTTP Request Node', function() {
}); });
logEvents.should.have.length(2); logEvents.should.have.length(2);
var tstmp = logEvents[0][0].timestamp; 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(); done();
} catch(err) { } catch(err) {
done(err); done(err);
@ -1291,7 +1291,6 @@ describe('HTTP Request Node', function() {
var n1 = helper.getNode("n1"); var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2"); var n2 = helper.getNode("n2");
n2.on("input", function(msg) { n2.on("input", function(msg) {
console.log(msg.payload);
try { try {
msg.payload.headers.should.have.property('content-type').which.startWith('application/json'); msg.payload.headers.should.have.property('content-type').which.startWith('application/json');
msg.payload.headers.should.not.have.property('x-node-red-request-node'); msg.payload.headers.should.not.have.property('x-node-red-request-node');