mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
4 Commits
Fix-for-cs
...
mqtt-follo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0abba15a6 | ||
|
|
81b4874a7c | ||
|
|
f11b9c1e18 | ||
|
|
e15ecc00ce |
@@ -936,9 +936,6 @@
|
||||
"invalid-expr": "Invalid JSONata expression:\n __message__",
|
||||
"invalid-msg": "Invalid example JSON message:\n __message__",
|
||||
"context-unsupported": "Cannot test context functions\n $flowContext or $globalContext",
|
||||
"env-unsupported": "Cannot test $env function",
|
||||
"moment-unsupported": "Cannot test $moment function",
|
||||
"clone-unsupported": "Cannot test $clone function",
|
||||
"eval": "Error evaluating expression:\n __message__"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -935,11 +935,8 @@
|
||||
"errors": {
|
||||
"invalid-expr": "不正なJSONata式:\n __message__",
|
||||
"invalid-msg": "不正なJSONメッセージ例:\n __message__",
|
||||
"context-unsupported": "$flowContext や $globalContextの\nコンテキスト関数をテストできません",
|
||||
"env-unsupported": "$env関数はテストできません",
|
||||
"moment-unsupported": "$moment関数はテストできません",
|
||||
"clone-unsupported": "$clone関数はテストできません",
|
||||
"eval": "式評価エラー:\n __message__"
|
||||
"context-unsupported": "$flowContext や $globalContextの\nコンテキスト機能をテストできません",
|
||||
"eval": "表現評価エラー:\n __message__"
|
||||
}
|
||||
},
|
||||
"monaco": {
|
||||
@@ -1171,7 +1168,8 @@
|
||||
"takeATour": "ツアーを開始",
|
||||
"start": "開始",
|
||||
"next": "次へ",
|
||||
"welcomeTours": "ウェルカムツアー"
|
||||
"welcomeTours": "ウェルカムツアー",
|
||||
"tours": "ツアー"
|
||||
},
|
||||
"diagnostics": {
|
||||
"title": "システム情報"
|
||||
|
||||
@@ -100,7 +100,7 @@ RED.editor.codeEditor.monaco = (function() {
|
||||
"node-red-util": {package: "node-red", module: "util", path: "node-red/util.d.ts" },
|
||||
"node-red-func": {package: "node-red", module: "func", path: "node-red/func.d.ts" },
|
||||
}
|
||||
const defaultServerSideTypes = [ knownModules["node-red-util"], knownModules["node-red-func"], knownModules["globals"], knownModules["console"], knownModules["buffer"] , knownModules["util"] ];
|
||||
const defaultServerSideTypes = [ knownModules["node-red-util"], knownModules["node-red-func"], knownModules["globals"], knownModules["console"], knownModules["buffer"] ];
|
||||
|
||||
const modulesCache = {};
|
||||
|
||||
|
||||
@@ -255,9 +255,6 @@
|
||||
var currentExpression = expressionEditor.getValue();
|
||||
var expr;
|
||||
var usesContext = false;
|
||||
var usesEnv = false;
|
||||
var usesMoment = false;
|
||||
var usesClone = false;
|
||||
var legacyMode = /(^|[^a-zA-Z0-9_'".])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
|
||||
$(".red-ui-editor-type-expression-legacy").toggle(legacyMode);
|
||||
try {
|
||||
@@ -270,18 +267,6 @@
|
||||
usesContext = true;
|
||||
return null;
|
||||
});
|
||||
expr.assign("env", function(name) {
|
||||
usesEnv = true;
|
||||
return null;
|
||||
});
|
||||
expr.assign("moment", function(name) {
|
||||
usesMoment = true;
|
||||
return null;
|
||||
});
|
||||
expr.assign("clone", function(name) {
|
||||
usesClone = true;
|
||||
return null;
|
||||
});
|
||||
} catch(err) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.invalid-expr",{message:err.message}),-1);
|
||||
return;
|
||||
@@ -299,18 +284,6 @@
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.context-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
if (usesEnv) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.env-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
if (usesMoment) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.moment-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
if (usesClone) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.clone-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
|
||||
var formattedResult;
|
||||
if (result !== undefined) {
|
||||
|
||||
@@ -175,19 +175,9 @@ RED.palette = (function() {
|
||||
$('<button type="button" onclick="RED.workspaces.show(\''+type.substring(8).replace(/'/g,"\\'")+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-pencil"></i></button>').appendTo(popOverContent)
|
||||
}
|
||||
|
||||
const safeType = type.replace(/'/g,"\\'");
|
||||
const wrapStr = function (str) {
|
||||
if(str.indexOf(' ') >= 0) {
|
||||
return '"' + str + '"'
|
||||
}
|
||||
return str
|
||||
}
|
||||
var safeType = type.replace(/'/g,"\\'");
|
||||
|
||||
$('<button type="button"; return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-search"></i></button>')
|
||||
.appendTo(popOverContent)
|
||||
.on('click', function() {
|
||||
RED.search.show('type:' + wrapStr(safeType))
|
||||
})
|
||||
$('<button type="button" onclick="RED.search.show(\'type:'+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-search"></i></button>').appendTo(popOverContent)
|
||||
$('<button type="button" onclick="RED.sidebar.help.show(\''+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-book"></i></button>').appendTo(popOverContent)
|
||||
|
||||
$('<p>',{style:"font-size: 0.8em"}).text(metaData).appendTo(popOverContent);
|
||||
|
||||
@@ -545,7 +545,7 @@ RED.projects = (function() {
|
||||
var sshwarningRow = $('<div class="red-ui-projects-dialog-screen-create-row-auth-error-no-keys"></div>').hide().appendTo(subrow);
|
||||
$('<div class="form-row"><i class="fa fa-warning"></i> '+RED._("projects.clone-project.ssh-key-desc")+'</div>').appendTo(sshwarningRow);
|
||||
subrow = $('<div style="text-align: center">').appendTo(sshwarningRow);
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.clone-project.ssh-key-add")+'</button>').appendTo(subrow).on("click", function(e) {
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.clone-project.ssh-key-add")+'</button>').appendTo(subrow).on("click", function(e) {
|
||||
e.preventDefault();
|
||||
dialog.dialog( "close" );
|
||||
RED.userSettings.show('gitconfig');
|
||||
@@ -1171,11 +1171,11 @@ RED.projects = (function() {
|
||||
|
||||
row = $('<div class="form-row button-group"></div>').appendTo(container);
|
||||
|
||||
var openProject = $('<button type="button" data-type="open" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-folder-open"></i><br/>'+RED._("projects.create.open")+'</button>').appendTo(row);
|
||||
var createAsEmpty = $('<button type="button" data-type="empty" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-asterisk"></i><br/>'+RED._("projects.create.create")+'</button>').appendTo(row);
|
||||
// var createAsCopy = $('<button type="button" data-type="copy" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i class="fa fa-long-arrow-right fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Copy existing</button>').appendTo(row);
|
||||
var createAsClone = $('<button type="button" data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-git"></i><br/>'+RED._("projects.create.clone")+'</button>').appendTo(row);
|
||||
// var createAsClone = $('<button type="button" data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-git fa-2x"></i><i class="fa fa-arrows-h fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Clone Repository</button>').appendTo(row);
|
||||
var openProject = $('<button data-type="open" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-folder-open"></i><br/>'+RED._("projects.create.open")+'</button>').appendTo(row);
|
||||
var createAsEmpty = $('<button data-type="empty" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-asterisk"></i><br/>'+RED._("projects.create.create")+'</button>').appendTo(row);
|
||||
// var createAsCopy = $('<button data-type="copy" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i class="fa fa-long-arrow-right fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Copy existing</button>').appendTo(row);
|
||||
var createAsClone = $('<button data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-git"></i><br/>'+RED._("projects.create.clone")+'</button>').appendTo(row);
|
||||
// var createAsClone = $('<button data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-git fa-2x"></i><i class="fa fa-arrows-h fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Clone Repository</button>').appendTo(row);
|
||||
row.find(".red-ui-projects-dialog-screen-create-type").on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
container.find(".red-ui-projects-dialog-screen-create-type").removeClass('selected');
|
||||
@@ -1271,7 +1271,7 @@ RED.projects = (function() {
|
||||
var credentialsLeftBox = $('<div class="red-ui-projects-dialog-credentials-box-left">').appendTo(credentialsBox);
|
||||
|
||||
var credentialsEnabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-enabled"></div>').appendTo(credentialsLeftBox);
|
||||
$('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="enabled" checked> <i class="fa fa-lock"></i> <span>'+RED._("projects.encryption-config.enable")+'</span></label>').appendTo(credentialsEnabledBox);
|
||||
$('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="enabled"> <i class="fa fa-lock"></i> <span>'+RED._("projects.encryption-config.enable")+'</span></label>').appendTo(credentialsEnabledBox);
|
||||
var credentialsDisabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-disabled disabled"></div>').appendTo(credentialsLeftBox);
|
||||
$('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="disabled"> <i class="fa fa-unlock"></i> <span>'+RED._("projects.encryption-config.disable")+'</span></label>').appendTo(credentialsDisabledBox);
|
||||
|
||||
@@ -1397,7 +1397,7 @@ RED.projects = (function() {
|
||||
var sshwarningRow = $('<div class="red-ui-projects-dialog-screen-create-row-auth-error-no-keys"></div>').hide().appendTo(subrow);
|
||||
$('<div class="form-row"><i class="fa fa-warning"></i> '+RED._("projects.create.desc2")+'</div>').appendTo(sshwarningRow);
|
||||
subrow = $('<div style="text-align: center">').appendTo(sshwarningRow);
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.create.add-ssh-key")+'</button>').appendTo(subrow).on("click", function(e) {
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.create.add-ssh-key")+'</button>').appendTo(subrow).on("click", function(e) {
|
||||
e.preventDefault();
|
||||
$('#red-ui-projects-dialog-cancel').trigger("click");
|
||||
RED.userSettings.show('gitconfig');
|
||||
@@ -1631,14 +1631,14 @@ RED.projects = (function() {
|
||||
function deleteProject(row,name,done) {
|
||||
var cover = $('<div class="red-ui-projects-dialog-project-list-entry-delete-confirm"></div>').on("click", function(evt) { evt.stopPropagation(); }).appendTo(row);
|
||||
$('<span>').text(RED._("projects.delete.confirm")).appendTo(cover);
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button">'+RED._("common.label.cancel")+'</button>')
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("common.label.cancel")+'</button>')
|
||||
.appendTo(cover)
|
||||
.on("click", function(e) {
|
||||
e.stopPropagation();
|
||||
cover.remove();
|
||||
done(true);
|
||||
});
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button primary">'+RED._("common.label.delete")+'</button>')
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button primary">'+RED._("common.label.delete")+'</button>')
|
||||
.appendTo(cover)
|
||||
.on("click", function(e) {
|
||||
e.stopPropagation();
|
||||
@@ -1822,7 +1822,7 @@ RED.projects = (function() {
|
||||
header.addClass("selectable");
|
||||
|
||||
var tools = $('<div class="red-ui-projects-dialog-project-list-entry-tools"></div>').appendTo(header);
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button red-ui-button-small" style="float: right;"><i class="fa fa-trash"></i></button>')
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button red-ui-button-small" style="float: right;"><i class="fa fa-trash"></i></button>')
|
||||
.appendTo(tools)
|
||||
.on("click", function(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -106,51 +106,38 @@ RED.search = (function() {
|
||||
return val;
|
||||
}
|
||||
|
||||
function extractType(val, flags) {
|
||||
// extracts: type:XYZ & type:"X Y Z"
|
||||
const regEx = /(?:type):\s*(?:"([^"]+)"|([^" ]+))/;
|
||||
let m
|
||||
while ((m = regEx.exec(val)) !== null) {
|
||||
// avoid infinite loops with zero-width matches
|
||||
if (m.index === regEx.lastIndex) {
|
||||
regEx.lastIndex++;
|
||||
}
|
||||
val = val.replace(m[0]," ").trim()
|
||||
const flag = m[2] || m[1] // quoted entries in capture group 1, unquoted in capture group 2
|
||||
flags.type = flags.type || [];
|
||||
flags.type.push(flag);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
function search(val) {
|
||||
const results = [];
|
||||
const flags = {};
|
||||
var results = [];
|
||||
var typeFilter;
|
||||
var m = /(?:^| )type:([^ ]+)/.exec(val);
|
||||
if (m) {
|
||||
val = val.replace(/(?:^| )type:[^ ]+/,"");
|
||||
typeFilter = m[1];
|
||||
}
|
||||
var flags = {};
|
||||
val = extractFlag(val,"invalid",flags);
|
||||
val = extractFlag(val,"unused",flags);
|
||||
val = extractFlag(val,"config",flags);
|
||||
val = extractFlag(val,"subflow",flags);
|
||||
val = extractFlag(val,"hidden",flags);
|
||||
val = extractFlag(val,"modified",flags);
|
||||
val = extractValue(val,"flow",flags);// flow:current or flow:<flow-id>
|
||||
val = extractValue(val,"flow",flags);// flow:active or flow:<flow-id>
|
||||
val = extractValue(val,"uses",flags);// uses:<node-id>
|
||||
val = extractType(val,flags);// type:<node-type>
|
||||
val = val.trim();
|
||||
const hasFlags = Object.keys(flags).length > 0;
|
||||
const hasTypeFilter = flags.type && flags.type.length > 0
|
||||
var hasFlags = Object.keys(flags).length > 0;
|
||||
if (flags.flow && flags.flow.indexOf("current") >= 0) {
|
||||
let idx = flags.flow.indexOf("current");
|
||||
flags.flow[idx] = RED.workspaces.active();//convert 'current' to active flow ID
|
||||
flags.flow[idx] = RED.workspaces.active();//convert active to flow ID
|
||||
}
|
||||
if (flags.flow && flags.flow.length) {
|
||||
flags.flow = [ ...new Set(flags.flow) ]; //deduplicate
|
||||
}
|
||||
if (val.length > 0 || hasFlags) {
|
||||
if (val.length > 0 || typeFilter || hasFlags) {
|
||||
val = val.toLowerCase();
|
||||
let i;
|
||||
let j;
|
||||
let list = [];
|
||||
const nodes = {};
|
||||
var i;
|
||||
var j;
|
||||
var list = [];
|
||||
var nodes = {};
|
||||
let keys = [];
|
||||
if (flags.uses) {
|
||||
keys = flags.uses;
|
||||
@@ -158,10 +145,10 @@ RED.search = (function() {
|
||||
keys = Object.keys(index);
|
||||
}
|
||||
for (i=0;i<keys.length;i++) {
|
||||
const key = keys[i];
|
||||
const kpos = val ? keys[i].indexOf(val) : -1;
|
||||
if (kpos > -1 || (val === "" && hasFlags)) {
|
||||
const ids = Object.keys(index[key]||{});
|
||||
var key = keys[i];
|
||||
var kpos = keys[i].indexOf(val);
|
||||
if (kpos > -1) {
|
||||
var ids = Object.keys(index[key]||{});
|
||||
for (j=0;j<ids.length;j++) {
|
||||
var node = index[key][ids[j]];
|
||||
var isConfigNode = node.node._def.category === "config" && node.node.type !== 'group';
|
||||
@@ -169,7 +156,7 @@ RED.search = (function() {
|
||||
continue;
|
||||
}
|
||||
if (flags.hasOwnProperty("invalid")) {
|
||||
const nodeIsValid = !node.node.hasOwnProperty("valid") || node.node.valid;
|
||||
var nodeIsValid = !node.node.hasOwnProperty("valid") || node.node.valid;
|
||||
if (flags.invalid === nodeIsValid) {
|
||||
continue;
|
||||
}
|
||||
@@ -199,7 +186,7 @@ RED.search = (function() {
|
||||
}
|
||||
}
|
||||
if (flags.hasOwnProperty("unused")) {
|
||||
const isUnused = (node.node.type === 'subflow' && node.node.instances.length === 0) ||
|
||||
var isUnused = (node.node.type === 'subflow' && node.node.instances.length === 0) ||
|
||||
(isConfigNode && node.node.users.length === 0 && node.node._def.hasUsers !== false)
|
||||
if (flags.unused !== isUnused) {
|
||||
continue;
|
||||
@@ -210,16 +197,12 @@ RED.search = (function() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let typeIndex = -1
|
||||
if(hasTypeFilter) {
|
||||
typeIndex = flags.type.indexOf(node.node.type)
|
||||
}
|
||||
if (!hasTypeFilter || typeIndex > -1) {
|
||||
nodes[node.node.id] = nodes[node.node.id] || {
|
||||
if (!typeFilter || node.node.type === typeFilter) {
|
||||
nodes[node.node.id] = nodes[node.node.id] = {
|
||||
node: node.node,
|
||||
label: node.label
|
||||
};
|
||||
nodes[node.node.id].index = Math.min(nodes[node.node.id].index || Infinity, typeIndex > -1 ? typeIndex : kpos);
|
||||
nodes[node.node.id].index = Math.min(nodes[node.node.id].index||Infinity,kpos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,6 @@ declare var msg: NodeMessage;
|
||||
/** @type {string} the id of the incoming `msg` (alias of msg._msgid) */
|
||||
declare const __msgid__:string;
|
||||
|
||||
declare const util:typeof import('util')
|
||||
declare const promisify:typeof import('util').promisify
|
||||
|
||||
/**
|
||||
* @typedef NodeStatus
|
||||
* @type {object}
|
||||
|
||||
@@ -160,7 +160,6 @@
|
||||
'$base64encode':{ args:[ ]},
|
||||
'$boolean':{ args:[ 'arg' ]},
|
||||
'$ceil':{ args:[ 'number' ]},
|
||||
'$clone': { args:[ 'arg' ]},
|
||||
'$contains':{ args:[ 'str', 'pattern' ]},
|
||||
'$count':{ args:[ 'array' ]},
|
||||
'$decodeUrl':{ args:[ 'str' ]},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script type="text/html" data-template-name="complete">
|
||||
<div class="form-row node-input-target-row">
|
||||
<button type="button" id="node-input-complete-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
<button id="node-input-complete-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
|
||||
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-complete-target-filter"></div>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<label for="node-input-uncaught" style="width: auto" data-i18n="catch.label.uncaught"></label>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row">
|
||||
<button type="button" id="node-input-catch-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
<button id="node-input-catch-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
|
||||
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-catch-target-filter"></div>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row">
|
||||
<button type="button" id="node-input-status-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
<button id="node-input-status-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
|
||||
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-status-target-filter"></div>
|
||||
|
||||
@@ -91,21 +91,21 @@
|
||||
<div id="func-tab-init" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-init-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="func-tab-body" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 220px; min-height:150px;" class="node-text-editor" id="node-input-func-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="func-tab-finalize" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-finalize-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -294,7 +294,7 @@
|
||||
if (val === "_custom_") {
|
||||
val = $(this).val();
|
||||
}
|
||||
var varName = val.trim().replace(/^@/,"").replace(/@.*$/,"").replace(/[-_/\.].?/g, function(v) { return v[1]?v[1].toUpperCase():"" });
|
||||
var varName = val.trim().replace(/^@/,"").replace(/@.*$/,"").replace(/[-_/].?/g, function(v) { return v[1]?v[1].toUpperCase():"" });
|
||||
fvar.val(varName);
|
||||
fvar.trigger("change");
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<option value="yaml">YAML</option>
|
||||
<option value="text" data-i18n="template.label.none"></option>
|
||||
</select>
|
||||
<button type="button" id="node-template-expand-editor" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button>
|
||||
<button id="node-template-expand-editor" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<label class="red-ui-button" for="node-config-input-certfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
|
||||
<input class="hide" type="file" id="node-config-input-certfile">
|
||||
<span id="tls-config-certname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span>
|
||||
<button type="button" class="red-ui-button red-ui-button-small" id="tls-config-button-cert-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
<button class="red-ui-button red-ui-button-small" id="tls-config-button-cert-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
</span>
|
||||
<input type="hidden" id="node-config-input-certname">
|
||||
<input type="hidden" id="node-config-input-certdata">
|
||||
@@ -37,7 +37,7 @@
|
||||
<label class="red-ui-button" for="node-config-input-keyfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
|
||||
<input class="hide" type="file" id="node-config-input-keyfile">
|
||||
<span id="tls-config-keyname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span>
|
||||
<button type="button" class="red-ui-button red-ui-button-small" id="tls-config-button-key-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
<button class="red-ui-button red-ui-button-small" id="tls-config-button-key-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
</span>
|
||||
<input type="hidden" id="node-config-input-keyname">
|
||||
<input type="hidden" id="node-config-input-keydata">
|
||||
@@ -53,7 +53,7 @@
|
||||
<label class="red-ui-button" for="node-config-input-cafile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
|
||||
<input class="hide" type="file" title=" " id="node-config-input-cafile">
|
||||
<span id="tls-config-caname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span>
|
||||
<button type="button" class="red-ui-button red-ui-button-small" id="tls-config-button-ca-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
<button class="red-ui-button red-ui-button-small" id="tls-config-button-ca-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
</span>
|
||||
<input type="hidden" id="node-config-input-caname">
|
||||
<input type="hidden" id="node-config-input-cadata">
|
||||
|
||||
@@ -101,7 +101,6 @@
|
||||
hostField.val(data.host);
|
||||
}
|
||||
},
|
||||
sortable: true,
|
||||
removable: true
|
||||
});
|
||||
if (this.noproxy) {
|
||||
|
||||
@@ -459,7 +459,6 @@ module.exports = function(RED) {
|
||||
if(!opts || typeof opts !== "object") {
|
||||
return; //nothing to change, simply return
|
||||
}
|
||||
const originalBrokerURL = node.brokerurl;
|
||||
|
||||
//apply property changes (only if the property exists in the opts object)
|
||||
setIfHasProperty(opts, node, "url", init);
|
||||
@@ -468,12 +467,12 @@ module.exports = function(RED) {
|
||||
setIfHasProperty(opts, node, "clientid", init);
|
||||
setIfHasProperty(opts, node, "autoConnect", init);
|
||||
setIfHasProperty(opts, node, "usetls", init);
|
||||
setIfHasProperty(opts, node, "usews", init);
|
||||
setIfHasProperty(opts, node, "verifyservercert", init);
|
||||
setIfHasProperty(opts, node, "compatmode", init);
|
||||
setIfHasProperty(opts, node, "protocolVersion", init);
|
||||
setIfHasProperty(opts, node, "keepalive", init);
|
||||
setIfHasProperty(opts, node, "cleansession", init);
|
||||
setIfHasProperty(opts, node, "sessionExpiry", init);
|
||||
setIfHasProperty(opts, node, "topicAliasMaximum", init);
|
||||
setIfHasProperty(opts, node, "maximumPacketSize", init);
|
||||
setIfHasProperty(opts, node, "receiveMaximum", init);
|
||||
@@ -483,11 +482,6 @@ module.exports = function(RED) {
|
||||
} else if (hasProperty(opts, "userProps")) {
|
||||
node.userProperties = opts.userProps;
|
||||
}
|
||||
if (hasProperty(opts, "sessionExpiry")) {
|
||||
node.sessionExpiryInterval = opts.sessionExpiry;
|
||||
} else if (hasProperty(opts, "sessionExpiryInterval")) {
|
||||
node.sessionExpiryInterval = opts.sessionExpiryInterval
|
||||
}
|
||||
|
||||
function createLWT(topic, payload, qos, retain, v5opts, v5SubPropName) {
|
||||
let message = undefined;
|
||||
@@ -571,9 +565,6 @@ module.exports = function(RED) {
|
||||
if (typeof node.usetls === 'undefined') {
|
||||
node.usetls = false;
|
||||
}
|
||||
if (typeof node.usews === 'undefined') {
|
||||
node.usews = false;
|
||||
}
|
||||
if (typeof node.verifyservercert === 'undefined') {
|
||||
node.verifyservercert = false;
|
||||
}
|
||||
@@ -786,9 +777,7 @@ module.exports = function(RED) {
|
||||
|
||||
// Send any birth message
|
||||
if (node.birthMessage) {
|
||||
setTimeout(() => {
|
||||
node.publish(node.birthMessage);
|
||||
}, 1);
|
||||
node.publish(node.birthMessage);
|
||||
}
|
||||
});
|
||||
node._clientOn("reconnect", function() {
|
||||
@@ -1000,7 +989,7 @@ module.exports = function(RED) {
|
||||
node.client.publish(msg.topic, msg.payload, options, function (err) {
|
||||
if (done) {
|
||||
done(err)
|
||||
} else {
|
||||
} else if(err) {
|
||||
node.error(err, msg)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -227,7 +227,6 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
sortable: true,
|
||||
removable: true
|
||||
});
|
||||
|
||||
|
||||
@@ -417,7 +417,6 @@
|
||||
});
|
||||
|
||||
},
|
||||
sortable: true,
|
||||
removable: true
|
||||
});
|
||||
if (node.headers) {
|
||||
|
||||
@@ -86,7 +86,6 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
||||
if (n.paytoqs === true || n.paytoqs === "query") { paytoqs = true; }
|
||||
else if (n.paytoqs === "body") { paytobody = true; }
|
||||
|
||||
node.insecureHTTPParser = n.insecureHTTPParser
|
||||
|
||||
var prox, noprox;
|
||||
if (process.env.http_proxy) { prox = process.env.http_proxy; }
|
||||
|
||||
@@ -110,12 +110,7 @@ module.exports = function(RED) {
|
||||
if (msg.payload[s].hasOwnProperty(p)) {
|
||||
/* istanbul ignore else */
|
||||
if (typeof msg.payload[s][p] !== "object") {
|
||||
// Fix to honour include null values flag
|
||||
//if (typeof msg.payload[s][p] !== "object" || (node.include_null_values === true && msg.payload[s][p] === null)) {
|
||||
var q = "";
|
||||
if (msg.payload[s][p] !== undefined) {
|
||||
q += msg.payload[s][p];
|
||||
}
|
||||
var q = "" + msg.payload[s][p];
|
||||
if (q.indexOf(node.quo) !== -1) { // add double quotes if any quotes
|
||||
q = q.replace(/"/g, '""');
|
||||
ou += node.quo + q + node.quo + node.sep;
|
||||
@@ -135,12 +130,9 @@ module.exports = function(RED) {
|
||||
ou += node.sep;
|
||||
}
|
||||
else {
|
||||
var p = RED.util.getMessageProperty(msg,"payload["+s+"]['"+template[t]+"']");
|
||||
var p = RED.util.ensureString(RED.util.getMessageProperty(msg,"payload["+s+"]['"+template[t]+"']"));
|
||||
/* istanbul ignore else */
|
||||
if (p === undefined) { p = ""; }
|
||||
// fix to honour include null values flag
|
||||
//if (p === null && node.include_null_values !== true) { p = "";}
|
||||
p = RED.util.ensureString(p);
|
||||
if (p === "undefined") { p = ""; }
|
||||
if (p.indexOf(node.quo) !== -1) { // add double quotes if any quotes
|
||||
p = p.replace(/"/g, '""');
|
||||
ou += node.quo + p + node.quo + node.sep;
|
||||
|
||||
@@ -52,7 +52,4 @@
|
||||
used to mark the templated sections. For example, to use <code>[[ ]]</code>
|
||||
instead, add the following line to the top of the template:</p>
|
||||
<pre>{{=[[ ]]=}}</pre>
|
||||
<h4>Using environment variables</h4>
|
||||
<p>The template node can access environment variables using the syntax:</p>
|
||||
<pre>My favourite colour is {{env.COLOUR}}.</pre>
|
||||
</script>
|
||||
|
||||
@@ -48,7 +48,4 @@
|
||||
<p><b>注: </b>デフォルトでは、<i>mustache</i>形式は置換対象のHTML要素をエスケープします。これを抑止するには<code>{{{三重}}}</code>括弧形式を使います。</p>
|
||||
<p>もし、コンテンツの中で<code>{{ }}</code>を出力する必要がある場合は、テンプレートで使われる記号文字を変えることもできます。例えば、<code>[[ ]]</code>を代わりに用いるには、テンプレートの先頭に以下の行を追加します。</p>
|
||||
<pre>{{=[[ ]]=}}</pre>
|
||||
<h4>環境変数の利用</h4>
|
||||
<p>templateノードでは、次の構文を用いると環境変数にアクセスできます:</p>
|
||||
<pre>私の好きな色は{{env.COLOUR}}です。</pre>
|
||||
</script>
|
||||
|
||||
@@ -554,8 +554,7 @@
|
||||
},
|
||||
"status": {
|
||||
"requesting": "要求中"
|
||||
},
|
||||
"insecureHTTPParser": "厳密なHTTPパース処理を無効化"
|
||||
}
|
||||
},
|
||||
"websocket": {
|
||||
"label": {
|
||||
|
||||
@@ -31,8 +31,6 @@ var multer = require("multer");
|
||||
var RED = require("nr-test-utils").require("node-red/lib/red");
|
||||
var fs = require('fs-extra');
|
||||
var auth = require('basic-auth');
|
||||
const { version } = require("os");
|
||||
const net = require('net')
|
||||
|
||||
describe('HTTP Request Node', function() {
|
||||
var testApp;
|
||||
@@ -2267,71 +2265,4 @@ describe('HTTP Request Node', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('should parse broken headers', function() {
|
||||
|
||||
const versions = process.versions.node.split('.')
|
||||
|
||||
if (( versions[0] == 14 && versions[1] >= 20 ) ||
|
||||
( versions[0] == 16 && versions[1] >= 16 ) ||
|
||||
( versions[0] == 18 && versions[1] >= 5 ) ||
|
||||
( versions[0] > 18)) {
|
||||
// only test if on new enough NodeJS version
|
||||
|
||||
let port = testPort++
|
||||
|
||||
let server;
|
||||
|
||||
before(function() {
|
||||
server = net.createServer(function (socket) {
|
||||
socket.write("HTTP/1.0 200\nContent-Type: text/plain\n\nHelloWorld")
|
||||
socket.end()
|
||||
})
|
||||
|
||||
server.listen(port,'127.0.0.1', function(err) {
|
||||
})
|
||||
});
|
||||
|
||||
after(function() {
|
||||
server.close()
|
||||
});
|
||||
|
||||
it('should accept broken headers', function (done) {
|
||||
var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:`http://localhost:${port}/`, insecureHTTPParser: true},
|
||||
{id:"n2", type:"helper"}];
|
||||
helper.load(httpRequestNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on('input', function(msg) {
|
||||
try {
|
||||
msg.payload.should.equal('HelloWorld')
|
||||
done()
|
||||
} catch (err) {
|
||||
done(err)
|
||||
}
|
||||
})
|
||||
n1.receive({payload: 'foo'})
|
||||
});
|
||||
});
|
||||
|
||||
it('should reject broken headers', function (done) {
|
||||
var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:`http://localhost:${port}/`},
|
||||
{id:"n2", type:"helper"}];
|
||||
helper.load(httpRequestNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on('input', function(msg) {
|
||||
try{
|
||||
msg.payload.should.equal(`RequestError: Parse Error: Missing expected CR after header value : http://localhost:${port}/`)
|
||||
done()
|
||||
} catch (err) {
|
||||
done(err)
|
||||
}
|
||||
})
|
||||
n1.receive({payload: 'foo'})
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('MQTT Nodes', function () {
|
||||
} catch (error) { }
|
||||
});
|
||||
|
||||
it('should be loaded and have default values (MQTT V4)', function (done) {
|
||||
it('should be loaded and have default values', function (done) {
|
||||
this.timeout = 2000;
|
||||
const { flow, nodes } = buildBasicMQTTSendRecvFlow({ id: "mqtt.broker", name: "mqtt_broker", autoConnect: false }, { id: "mqtt.in", topic: "in_topic" }, { id: "mqtt.out", topic: "out_topic" });
|
||||
helper.load(mqttNodes, flow, function () {
|
||||
@@ -61,52 +61,6 @@ describe('MQTT Nodes', function () {
|
||||
mqttBroker.options.clientId.should.containEql('nodered_');
|
||||
mqttBroker.options.should.have.property('keepalive').type("number");
|
||||
mqttBroker.options.should.have.property('reconnectPeriod').type("number");
|
||||
//as this is not a v5 connection, ensure v5 properties are not present
|
||||
mqttBroker.options.should.not.have.property('protocolVersion', 5);
|
||||
mqttBroker.options.should.not.have.property('properties');
|
||||
done();
|
||||
} catch (error) {
|
||||
done(error)
|
||||
}
|
||||
});
|
||||
});
|
||||
it('should be loaded and have default values (MQTT V5)', function (done) {
|
||||
this.timeout = 2000;
|
||||
const { flow, nodes } = buildBasicMQTTSendRecvFlow({ id: "mqtt.broker", name: "mqtt_broker", autoConnect: false, cleansession: false, clientid: 'clientid', keepalive: 35, sessionExpiry: '6000', protocolVersion: '5', userProps: {"prop": "val"}}, { id: "mqtt.in", topic: "in_topic" }, { id: "mqtt.out", topic: "out_topic" });
|
||||
helper.load(mqttNodes, flow, function () {
|
||||
try {
|
||||
const mqttIn = helper.getNode("mqtt.in");
|
||||
const mqttOut = helper.getNode("mqtt.out");
|
||||
const mqttBroker = helper.getNode("mqtt.broker");
|
||||
|
||||
should(mqttIn).be.type("object", "mqtt in node should be an object")
|
||||
mqttIn.should.have.property('broker', nodes.mqtt_broker.id); //should be the id of the broker node
|
||||
mqttIn.should.have.property('datatype', 'utf8'); //default: 'utf8'
|
||||
mqttIn.should.have.property('isDynamic', false); //default: false
|
||||
mqttIn.should.have.property('inputs', 0); //default: 0
|
||||
mqttIn.should.have.property('qos', 2); //default: 2
|
||||
mqttIn.should.have.property('topic', "in_topic");
|
||||
mqttIn.should.have.property('wires', [["helper.node"]]);
|
||||
|
||||
should(mqttOut).be.type("object", "mqtt out node should be an object")
|
||||
mqttOut.should.have.property('broker', nodes.mqtt_broker.id); //should be the id of the broker node
|
||||
mqttOut.should.have.property('topic', "out_topic");
|
||||
|
||||
should(mqttBroker).be.type("object", "mqtt broker node should be an object")
|
||||
mqttBroker.should.have.property('broker', BROKER_HOST);
|
||||
mqttBroker.should.have.property('port', BROKER_PORT);
|
||||
mqttBroker.should.have.property('brokerurl');
|
||||
// mqttBroker.should.have.property('autoUnsubscribe', true);//default: true
|
||||
mqttBroker.should.have.property('autoConnect', false);//Set "autoConnect:false" in brokerOptions
|
||||
mqttBroker.should.have.property('options');
|
||||
mqttBroker.options.should.have.property('clean', false);
|
||||
mqttBroker.options.should.have.property('clientId', 'clientid');
|
||||
mqttBroker.options.should.have.property('keepalive').type("number", 35);
|
||||
mqttBroker.options.should.have.property('reconnectPeriod').type("number");
|
||||
//as this IS a v5 connection, ensure v5 properties are not present
|
||||
mqttBroker.options.should.have.property('protocolVersion', 5);
|
||||
mqttBroker.options.should.have.property('properties');
|
||||
mqttBroker.options.properties.should.have.property('sessionExpiryInterval');
|
||||
done();
|
||||
} catch (error) {
|
||||
done(error)
|
||||
@@ -219,7 +173,7 @@ describe('MQTT Nodes', function () {
|
||||
topic: nextTopic(),
|
||||
payload: '{prop:"value3", "num":3}', // send invalid JSON ...
|
||||
}
|
||||
const hooks = { done: null, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
hooks.afterLoad = (helperNode, mqttBroker, mqttIn, mqttOut) => {
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
@@ -345,7 +299,7 @@ describe('MQTT Nodes', function () {
|
||||
topic: nextTopic(),
|
||||
payload: '{prop:"value3", "num":3}', contentType: "application/json", // send invalid JSON ...
|
||||
}
|
||||
const hooks = { done: null, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
hooks.afterLoad = (helperNode, mqttBroker, mqttIn, mqttOut) => {
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
@@ -431,7 +385,7 @@ describe('MQTT Nodes', function () {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
const hooks = { beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
hooks.beforeLoad = (flow) => { //add a status node pointed at MQTT Out node (to watch for connection status change)
|
||||
flow.push({ "id": "status.node", "type": "status", "name": "status_node", "scope": ["mqtt.out"], "wires": [["helper.node"]] });//add status node to watch mqtt_out
|
||||
}
|
||||
@@ -462,32 +416,52 @@ describe('MQTT Nodes', function () {
|
||||
this.timeout = 2000;
|
||||
const baseTopic = nextTopic();
|
||||
const brokerOptions = {
|
||||
autoConnect: false,
|
||||
protocolVersion: 4,
|
||||
birthTopic: baseTopic + "/birth",
|
||||
birthPayload: "broker birth",
|
||||
birthPayload: "broker connected",
|
||||
birthQos: 2,
|
||||
}
|
||||
const expectMsg = {
|
||||
const options = {};
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null };
|
||||
options.expectMsg = {
|
||||
topic: brokerOptions.birthTopic,
|
||||
payload: brokerOptions.birthPayload,
|
||||
qos: brokerOptions.birthQos
|
||||
};
|
||||
const options = { };
|
||||
const hooks = { };
|
||||
testSendRecv(brokerOptions, { topic: brokerOptions.birthTopic }, {}, options, hooks);
|
||||
});
|
||||
itConditional('should safely discard bad birth topic', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const baseTopic = nextTopic();
|
||||
const brokerOptions = {
|
||||
protocolVersion: 4,
|
||||
birthTopic: baseTopic + "#", // a publish topic should never have a wildcard
|
||||
birthPayload: "broker connected",
|
||||
birthQos: 2,
|
||||
}
|
||||
const options = {};
|
||||
const hooks = { done: null, beforeLoad: null, afterLoad: null, afterConnect: null };
|
||||
hooks.afterLoad = (helperNode, mqttBroker, mqttIn, mqttOut) => {
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
compareMsgToExpected(msg, expectMsg);
|
||||
msg.should.have.a.property("error").type("object");
|
||||
msg.error.should.have.a.property("source").type("object");
|
||||
msg.error.source.should.have.a.property("id", mqttIn.id);
|
||||
done();
|
||||
} catch (error) {
|
||||
done(error)
|
||||
} catch (err) {
|
||||
done(err)
|
||||
}
|
||||
})
|
||||
mqttIn.receive({ "action": "connect" }); //now request connect action
|
||||
});
|
||||
return true; //handled
|
||||
}
|
||||
testSendRecv(brokerOptions, { topic: brokerOptions.birthTopic }, {}, options, hooks);
|
||||
}
|
||||
options.expectMsg = null;
|
||||
try {
|
||||
testSendRecv(brokerOptions, { topic: brokerOptions.birthTopic }, {}, options, hooks);
|
||||
done()
|
||||
} catch(err) {
|
||||
done(e)
|
||||
}
|
||||
});
|
||||
itConditional('should publish close message', function (done) {
|
||||
if (skipTests) { return this.skip() }
|
||||
@@ -646,12 +620,13 @@ function testSendRecv(brokerOptions, inNodeOptions, outNodeOptions, options, hoo
|
||||
const mqttBroker = helper.getNode(brokerOptions.id);
|
||||
const mqttIn = helper.getNode(nodes.mqtt_in.id);
|
||||
const mqttOut = helper.getNode(nodes.mqtt_out.id);
|
||||
let afterLoadHandled = false;
|
||||
let afterLoadHandled = false, finished = false;
|
||||
if (hooks.afterLoad) {
|
||||
afterLoadHandled = hooks.afterLoad(helperNode, mqttBroker, mqttIn, mqttOut)
|
||||
}
|
||||
if (!afterLoadHandled) {
|
||||
helperNode.on("input", function (msg) {
|
||||
finished = true
|
||||
try {
|
||||
compareMsgToExpected(msg, expectMsg);
|
||||
if (hooks.done) { hooks.done(); }
|
||||
@@ -676,10 +651,12 @@ function testSendRecv(brokerOptions, inNodeOptions, outNodeOptions, options, hoo
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
if(finished) { return }
|
||||
if (hooks.done) { hooks.done(e); }
|
||||
else { throw e; }
|
||||
});
|
||||
} catch (err) {
|
||||
if(finished) { return }
|
||||
if (hooks.done) { hooks.done(err); }
|
||||
else { throw err; }
|
||||
}
|
||||
@@ -725,7 +702,6 @@ function buildMQTTBrokerNode(id, name, brokerHost, brokerPort, options) {
|
||||
node.cleansession = String(options.cleansession) == "false" ? false : true;
|
||||
node.autoUnsubscribe = String(options.autoUnsubscribe) == "false" ? false : true;
|
||||
node.autoConnect = String(options.autoConnect) == "false" ? false : true;
|
||||
node.sessionExpiry = options.sessionExpiry ? options.sessionExpiry : undefined;
|
||||
|
||||
if (options.birthTopic) {
|
||||
node.birthTopic = options.birthTopic;
|
||||
@@ -820,8 +796,8 @@ function waitBrokerConnect(broker, timeLimit) {
|
||||
let waitConnected = (broker, timeLimit) => {
|
||||
const brokers = Array.isArray(broker) ? broker : [broker];
|
||||
timeLimit = timeLimit || 1000;
|
||||
let timer, resolved = false;
|
||||
return new Promise( (resolve, reject) => {
|
||||
let timer, resolved = false;
|
||||
timer = wait();
|
||||
function wait() {
|
||||
if (brokers.every(e => e.connected == true)) {
|
||||
|
||||
@@ -693,20 +693,19 @@ describe('CSV node', function() {
|
||||
describe('json object to csv', function() {
|
||||
|
||||
it('should convert a simple object back to a csv', function(done) {
|
||||
var flow = [ { id:"n1", type:"csv", temp:"a,b,c,,e,f,g,h,i,j,k", wires:[["n2"]] },
|
||||
var flow = [ { id:"n1", type:"csv", temp:"a,b,c,,e,f", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(csvNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
// console.log("GOT",msg)
|
||||
try {
|
||||
msg.should.have.property('payload', '4,foo,true,,0,"Hello\nWorld",,,undefined,null,null\n');
|
||||
msg.should.have.property('payload', '4,foo,true,,0,"Hello\nWorld"\n');
|
||||
done();
|
||||
}
|
||||
catch(e) { done(e); }
|
||||
});
|
||||
var testJson = { e:0, d:1, b:"foo", c:true, a:4, f:"Hello\nWorld", h:undefined, i:"undefined",j:null,k:"null" };
|
||||
var testJson = { e:0, d:1, b:"foo", c:true, a:4, f:"Hello\nWorld" };
|
||||
n1.emit("input", {payload:testJson});
|
||||
});
|
||||
});
|
||||
@@ -718,14 +717,13 @@ describe('CSV node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
// console.log("GOT",msg)
|
||||
try {
|
||||
msg.should.have.property('payload', '1,foo,"ba""r","di,ng",,undefined,null\n');
|
||||
msg.should.have.property('payload', '1,foo,"ba""r","di,ng"\n');
|
||||
done();
|
||||
}
|
||||
catch(e) { done(e); }
|
||||
});
|
||||
var testJson = { d:1, b:"foo", c:"ba\"r", a:"di,ng", e:undefined, f:"undefined", g:null,h:"null" };
|
||||
var testJson = { d:1, b:"foo", c:"ba\"r", a:"di,ng" };
|
||||
n1.emit("input", {payload:testJson});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -61,7 +61,7 @@ describe("api/index", function() {
|
||||
should.not.exist(api.httpAdmin);
|
||||
done();
|
||||
});
|
||||
describe('initalises admin api without adminAuth', function() {
|
||||
describe('initalises admin api without adminAuth', function(done) {
|
||||
before(function() {
|
||||
beforeEach();
|
||||
api.init({},{},{},{});
|
||||
@@ -78,7 +78,7 @@ describe("api/index", function() {
|
||||
})
|
||||
});
|
||||
|
||||
describe('initalises admin api without editor', function() {
|
||||
describe('initalises admin api without editor', function(done) {
|
||||
before(function() {
|
||||
beforeEach();
|
||||
api.init({ disableEditor: true },{},{},{});
|
||||
@@ -95,7 +95,7 @@ describe("api/index", function() {
|
||||
})
|
||||
});
|
||||
|
||||
describe('initialises api with admin middleware', function() {
|
||||
describe('initialises api with admin middleware', function(done) {
|
||||
it('ignores non-function values',function(done) {
|
||||
api.init({ httpAdminRoot: true, httpAdminMiddleware: undefined },{},{},{});
|
||||
const middlewareFound = api.httpAdmin._router.stack.filter((layer) => layer.name === 'testMiddleware')
|
||||
@@ -112,7 +112,7 @@ describe("api/index", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('initialises api with authentication enabled', function() {
|
||||
describe('initialises api with authentication enabled', function(done) {
|
||||
|
||||
it('enables an oauth/openID based authentication mechanism',function(done) {
|
||||
const stub = sinon.stub(apiAuth, 'genericStrategy').callsFake(function(){});
|
||||
@@ -135,7 +135,7 @@ describe("api/index", function() {
|
||||
|
||||
});
|
||||
|
||||
describe('initialises api with custom cors config', function () {
|
||||
describe('initialises api with custom cors config', function (done) {
|
||||
const httpAdminCors = {
|
||||
origin: "*",
|
||||
methods: "GET,PUT,POST,DELETE"
|
||||
@@ -156,7 +156,7 @@ describe("api/index", function() {
|
||||
})
|
||||
});
|
||||
|
||||
describe('editor start', function () {
|
||||
describe('editor start', function (done) {
|
||||
|
||||
it('cannot be started when editor is disabled', function (done) {
|
||||
const stub = sinon.stub(apiEditor, 'start').callsFake(function () {
|
||||
|
||||
Reference in New Issue
Block a user