mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
48 Commits
1.3.7
...
rerorder-i
Author | SHA1 | Date | |
---|---|---|---|
|
19d391fa05 | ||
|
d1aa1fd4d8 | ||
|
4133f9c56f | ||
|
53055064e1 | ||
|
06090d8de1 | ||
|
d6ccae38f8 | ||
|
f7210effec | ||
|
ea50ba16f9 | ||
|
b62e4f6662 | ||
|
46af2e37a7 | ||
|
62f2a552ea | ||
|
b053e02174 | ||
|
3798167908 | ||
|
56fe2014e1 | ||
|
be2e64433f | ||
|
8732e89e55 | ||
|
fdd0a93bad | ||
|
dd12572b1d | ||
|
5cc791690b | ||
|
93971537b4 | ||
|
87e816a7f5 | ||
|
0f45b1da48 | ||
|
a20049c82a | ||
|
250005ad16 | ||
|
719aea2a58 | ||
|
68fef169f3 | ||
|
c668201df4 | ||
|
1d68c8cc87 | ||
|
b9ac8b42ea | ||
|
b4a03a56b4 | ||
|
e0c7269b8e | ||
|
73063df11b | ||
|
f8855b83fa | ||
|
0d0459d83d | ||
|
d2432716ea | ||
|
52ef85cba3 | ||
|
8140057bea | ||
|
22df59e229 | ||
|
ed351eee54 | ||
|
c021b4c368 | ||
|
aac2a8f830 | ||
|
8269490dd1 | ||
|
82ced56bed | ||
|
982b8ea51d | ||
|
877c463494 | ||
|
9882582903 | ||
|
ba566657f1 | ||
|
cb1a178fbf |
@@ -13,9 +13,7 @@ matrix:
|
||||
- node_js: "12"
|
||||
script:
|
||||
- ./node_modules/.bin/grunt no-coverage
|
||||
- node_js: "10"
|
||||
allow_failures:
|
||||
- node_js: "16"
|
||||
script:
|
||||
- ./node_modules/.bin/grunt no-coverage
|
||||
#- node_js: "8"
|
||||
# script:
|
||||
# - ./node_modules/.bin/grunt no-coverage
|
||||
|
@@ -208,7 +208,9 @@ module.exports = function(grunt) {
|
||||
"node_modules/marked/marked.min.js",
|
||||
"node_modules/dompurify/dist/purify.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/d3/d3.v3.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/i18next/i18next.min.js",
|
||||
"node_modules/i18next/i18next.min.js",
|
||||
"node_modules/i18next-http-backend/i18nextHttpBackend.min.js",
|
||||
"node_modules/jquery-i18next/jquery-i18next.min.js",
|
||||
"node_modules/jsonata/jsonata-es5.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/formatter.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/ace/ace.js",
|
||||
|
33
package.json
33
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "1.3.1",
|
||||
"version": "2.0.0-beta.1",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "http://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -37,15 +37,15 @@
|
||||
"cookie": "0.4.1",
|
||||
"cookie-parser": "1.4.5",
|
||||
"cors": "2.8.5",
|
||||
"cron": "1.7.2",
|
||||
"cronosjs": "1.7.1",
|
||||
"denque": "1.5.0",
|
||||
"express": "4.17.1",
|
||||
"express-session": "1.17.1",
|
||||
"fs-extra": "8.1.0",
|
||||
"fs-extra": "9.1.0",
|
||||
"fs.notify": "0.0.4",
|
||||
"hash-sum": "2.0.0",
|
||||
"https-proxy-agent": "5.0.0",
|
||||
"i18next": "15.1.2",
|
||||
"i18next": "20.2.1",
|
||||
"iconv-lite": "0.6.2",
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "3.14.0",
|
||||
@@ -60,9 +60,6 @@
|
||||
"multer": "1.4.2",
|
||||
"mustache": "4.2.0",
|
||||
"node-red-admin": "^0.2.6",
|
||||
"node-red-node-rbe": "^0.5.0",
|
||||
"node-red-node-sentiment": "^0.1.6",
|
||||
"node-red-node-tail": "^0.3.0",
|
||||
"nopt": "5.0.0",
|
||||
"oauth2orize": "1.11.0",
|
||||
"on-headers": "1.0.2",
|
||||
@@ -71,14 +68,14 @@
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"raw-body": "2.4.1",
|
||||
"request": "2.88.0",
|
||||
"semver": "6.3.0",
|
||||
"semver": "7.3.5",
|
||||
"tar": "6.1.0",
|
||||
"uglify-js": "3.13.3",
|
||||
"ws": "6.2.1",
|
||||
"xml2js": "0.4.23"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bcrypt": "3.0.8"
|
||||
"bcrypt": "5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dompurify": "2.2.7",
|
||||
@@ -87,14 +84,14 @@
|
||||
"grunt-cli": "~1.4.2",
|
||||
"grunt-concurrent": "3.0.0",
|
||||
"grunt-contrib-clean": "~2.0.0",
|
||||
"grunt-contrib-compress": "1.6.0",
|
||||
"grunt-contrib-compress": "2.0.0",
|
||||
"grunt-contrib-concat": "~1.0.1",
|
||||
"grunt-contrib-copy": "~1.0.0",
|
||||
"grunt-contrib-jshint": "~2.1.0",
|
||||
"grunt-contrib-uglify": "~4.0.1",
|
||||
"grunt-contrib-jshint": "3.0.0",
|
||||
"grunt-contrib-uglify": "5.0.1",
|
||||
"grunt-contrib-watch": "~1.1.0",
|
||||
"grunt-jsdoc": "2.4.1",
|
||||
"grunt-jsdoc-to-markdown": "5.0.0",
|
||||
"grunt-jsdoc-to-markdown": "6.0.0",
|
||||
"grunt-jsonlint": "2.1.3",
|
||||
"grunt-mkdir": "~1.1.0",
|
||||
"grunt-npm-command": "~0.1.2",
|
||||
@@ -102,19 +99,21 @@
|
||||
"grunt-simple-mocha": "~0.4.1",
|
||||
"grunt-simple-nyc": "^3.0.1",
|
||||
"http-proxy": "1.18.1",
|
||||
"i18next-http-backend": "1.2.1",
|
||||
"jquery-i18next": "1.2.1",
|
||||
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
|
||||
"marked": "2.0.1",
|
||||
"minami": "1.2.3",
|
||||
"mocha": "^5.2.0",
|
||||
"mocha": "8.3.2",
|
||||
"node-red-node-test-helper": "^0.2.7",
|
||||
"node-sass": "^5.0.0",
|
||||
"nodemon": "2.0.7",
|
||||
"should": "13.2.3",
|
||||
"sinon": "1.17.7",
|
||||
"sinon": "10.0.1",
|
||||
"stoppable": "^1.1.0",
|
||||
"supertest": "5.0.0"
|
||||
"supertest": "6.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
"node": ">=12"
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-api",
|
||||
"version": "1.3.1",
|
||||
"version": "2.0.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,8 +16,8 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "1.3.1",
|
||||
"@node-red/editor-client": "1.3.1",
|
||||
"@node-red/util": "2.0.0-beta.1",
|
||||
"@node-red/editor-client": "2.0.0-beta.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.19.0",
|
||||
"clone": "2.1.2",
|
||||
@@ -35,6 +35,6 @@
|
||||
"ws": "6.2.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bcrypt": "3.0.6"
|
||||
"bcrypt": "5.0.1"
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-client",
|
||||
"version": "1.3.1",
|
||||
"version": "2.0.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@@ -18,53 +18,66 @@ RED.i18n = (function() {
|
||||
|
||||
var apiRootUrl;
|
||||
|
||||
function detectLanguage() {
|
||||
return navigator.language
|
||||
}
|
||||
|
||||
return {
|
||||
init: function(options, done) {
|
||||
apiRootUrl = options.apiRootUrl||"";
|
||||
var preferredLanguage = localStorage.getItem("editor-language");
|
||||
var opts = {
|
||||
resGetPath: apiRootUrl+'locales/__ns__?lng=__lng__',
|
||||
dynamicLoad: false,
|
||||
load:'current',
|
||||
ns: {
|
||||
namespaces: ["editor","node-red","jsonata","infotips"],
|
||||
defaultNs: "editor"
|
||||
backend: {
|
||||
loadPath: apiRootUrl+'locales/__ns__?lng=__lng__',
|
||||
},
|
||||
lng: 'en-US',
|
||||
// debug: true,
|
||||
preload:['en-US'],
|
||||
ns: ["editor","node-red","jsonata","infotips"],
|
||||
defaultNS: "editor",
|
||||
fallbackLng: ['en-US'],
|
||||
useCookie: false,
|
||||
returnObjectTrees: true
|
||||
returnObjects: true,
|
||||
interpolation: {
|
||||
unescapeSuffix: 'HTML',
|
||||
escapeValue: false,
|
||||
prefix: '__',
|
||||
suffix: '__'
|
||||
}
|
||||
};
|
||||
if (preferredLanguage) {
|
||||
opts.lng = preferredLanguage;
|
||||
}
|
||||
i18n.init(opts,function() {
|
||||
|
||||
i18next.use(i18nextHttpBackend).init(opts,function() {
|
||||
done();
|
||||
});
|
||||
jqueryI18next.init(i18next, $, { handleName: 'i18n' });
|
||||
|
||||
|
||||
RED["_"] = function() {
|
||||
var v = i18n.t.apply(null,arguments);
|
||||
var v = i18next.t.apply(i18next,arguments);
|
||||
if (typeof v === 'string') {
|
||||
return v;
|
||||
} else {
|
||||
return arguments[0];
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
lang: function() {
|
||||
// Gets the active message catalog language. This is based on what
|
||||
// locale the editor is using and what languages are available.
|
||||
//
|
||||
var preferredLangs = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
|
||||
var preferredLangs = [localStorage.getItem("editor-language")|| detectLanguage()].concat(i18next.languages);
|
||||
var knownLangs = RED.settings.theme("languages")||["en-US"];
|
||||
for (var i=0;i<preferredLangs.length;i++) {
|
||||
if (knownLangs.indexOf(preferredLangs[i]) > -1) {
|
||||
return preferredLangs[i]
|
||||
}
|
||||
}
|
||||
return 'end-US'
|
||||
return 'en-US'
|
||||
},
|
||||
loadNodeCatalog: function(namespace,done) {
|
||||
var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
|
||||
var languageList = [localStorage.getItem("editor-language")|| detectLanguage()].concat(i18next.languages);
|
||||
var toLoad = languageList.length;
|
||||
languageList.forEach(function(lang) {
|
||||
$.ajax({
|
||||
@@ -74,7 +87,7 @@ RED.i18n = (function() {
|
||||
cache: false,
|
||||
url: apiRootUrl+'nodes/'+namespace+'/messages?lng='+lang,
|
||||
success: function(data) {
|
||||
i18n.addResourceBundle(lang,namespace,data);
|
||||
i18next.addResourceBundle(lang,namespace,data);
|
||||
toLoad--;
|
||||
if (toLoad === 0) {
|
||||
done();
|
||||
@@ -86,7 +99,7 @@ RED.i18n = (function() {
|
||||
},
|
||||
|
||||
loadNodeCatalogs: function(done) {
|
||||
var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
|
||||
var languageList = [localStorage.getItem("editor-language")|| detectLanguage()].concat(i18next.languages);
|
||||
var toLoad = languageList.length;
|
||||
|
||||
languageList.forEach(function(lang) {
|
||||
@@ -99,7 +112,7 @@ RED.i18n = (function() {
|
||||
success: function(data) {
|
||||
var namespaces = Object.keys(data);
|
||||
namespaces.forEach(function(ns) {
|
||||
i18n.addResourceBundle(lang,ns,data[ns]);
|
||||
i18next.addResourceBundle(lang,ns,data[ns]);
|
||||
});
|
||||
toLoad--;
|
||||
if (toLoad === 0) {
|
||||
@@ -111,7 +124,7 @@ RED.i18n = (function() {
|
||||
},
|
||||
|
||||
loadPluginCatalogs: function(done) {
|
||||
var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
|
||||
var languageList = [localStorage.getItem("editor-language")|| detectLanguage()].concat(i18next.languages);
|
||||
var toLoad = languageList.length;
|
||||
|
||||
languageList.forEach(function(lang) {
|
||||
@@ -124,7 +137,7 @@ RED.i18n = (function() {
|
||||
success: function(data) {
|
||||
var namespaces = Object.keys(data);
|
||||
namespaces.forEach(function(ns) {
|
||||
i18n.addResourceBundle(lang,ns,data[ns]);
|
||||
i18next.addResourceBundle(lang,ns,data[ns]);
|
||||
});
|
||||
toLoad--;
|
||||
if (toLoad === 0) {
|
||||
@@ -133,6 +146,7 @@ RED.i18n = (function() {
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
detectLanguage: detectLanguage
|
||||
}
|
||||
})();
|
||||
|
@@ -36,7 +36,7 @@ var RED = (function() {
|
||||
}
|
||||
function loadPlugins(done) {
|
||||
loader.reportProgress(RED._("event.loadPlugins",{count:""}), 17)
|
||||
var lang = localStorage.getItem("editor-language")||i18n.detectLanguage();
|
||||
var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage();
|
||||
|
||||
$.ajax({
|
||||
headers: {
|
||||
@@ -176,7 +176,7 @@ var RED = (function() {
|
||||
|
||||
function loadNodes() {
|
||||
loader.reportProgress(RED._("event.loadNodes",{count:""}), 30)
|
||||
var lang = localStorage.getItem("editor-language")||i18n.detectLanguage();
|
||||
var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage();
|
||||
|
||||
$.ajax({
|
||||
headers: {
|
||||
|
@@ -233,7 +233,7 @@ RED.sidebar.help = (function() {
|
||||
var div = $('<div>',{class:"red-ui-info-outline-item"});
|
||||
RED.utils.createNodeIcon(n).appendTo(div);
|
||||
var contentDiv = $('<div>',{class:"red-ui-search-result-description"}).appendTo(div);
|
||||
$('<div>',{class:"red-ui-search-result-node-label red-ui-info-outline-item-label"}).text(n.name||n.type).appendTo(contentDiv);
|
||||
$('<div>',{class:"red-ui-search-result-node-label red-ui-info-outline-item-label"}).text(n.name||n._def.paletteLabel||n.type).appendTo(contentDiv);
|
||||
return div;
|
||||
}
|
||||
|
||||
@@ -248,7 +248,8 @@ RED.sidebar.help = (function() {
|
||||
title = subflowNode.name || nodeType;
|
||||
} else {
|
||||
helpText = RED.nodes.getNodeHelp(nodeType)||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
title = nodeType;
|
||||
var _def = RED.nodes.registry.getNodeType(nodeType);
|
||||
title = (_def && _def.paletteLabel)?_def.paletteLabel:nodeType;
|
||||
}
|
||||
setInfoText(title, helpText, helpSection);
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@@ -455,7 +455,7 @@
|
||||
var propertyValue = $('<input/>',{class:"node-input-prop-property-value",type:"text"})
|
||||
.css("width","calc(70% - 30px)")
|
||||
.appendTo(row)
|
||||
.typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','bin','date','jsonata','env']});
|
||||
.typedInput({default:'str',types:['flow','global','str','num','bool','json','bin','date','jsonata','env','msg']});
|
||||
|
||||
propertyName.typedInput('value',prop.p);
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var cron = require("cron");
|
||||
const {scheduleTask} = require("cronosjs");
|
||||
|
||||
function InjectNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
@@ -85,7 +85,7 @@ module.exports = function(RED) {
|
||||
if (RED.settings.verbose) {
|
||||
this.log(RED._("inject.crontab", this));
|
||||
}
|
||||
this.cronjob = new cron.CronJob(this.crontab, function() { node.emit("input", {}); }, null, true);
|
||||
this.cronjob = scheduleTask(this.crontab,() => { node.emit("input", {})});
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -78,8 +78,11 @@
|
||||
<option value="day" data-i18n="delay.label.units.day.singular"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row" id="rate-override">
|
||||
<label></label><input style="width:30px; vertical-align:baseline;" type="checkbox" id="node-input-allowrate"><label style="width: 250px;" for="node-input-allowrate" data-i18n="delay.allowrate"></label>
|
||||
</div>
|
||||
<div class="form-row" id="rate-details-drop">
|
||||
<label></label><input style="width: 30px;" type="checkbox" id="node-input-drop"><label style="width: 250px;" for="node-input-drop" data-i18n="delay.dropmsg"></label>
|
||||
<label></label><input style="width:30px;; vertical-align:baseline;" type="checkbox" id="node-input-drop"><label style="width: 250px;" for="node-input-drop" data-i18n="delay.dropmsg"></label>
|
||||
</div>
|
||||
<div class="form-row" id="rate-details-per-topic">
|
||||
<label></label>
|
||||
@@ -110,7 +113,8 @@
|
||||
randomFirst: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||
randomLast: {value:"5", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
|
||||
randomUnits: {value: "seconds"},
|
||||
drop: {value:false}
|
||||
drop: {value:false},
|
||||
allowrate: {value:false}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:1,
|
||||
|
@@ -20,6 +20,20 @@ module.exports = function(RED) {
|
||||
|
||||
var MILLIS_TO_NANOS = 1000000;
|
||||
var SECONDS_TO_NANOS = 1000000000;
|
||||
var _maxKeptMsgsCount;
|
||||
|
||||
function maxKeptMsgsCount(node) {
|
||||
if (_maxKeptMsgsCount === undefined) {
|
||||
var name = "nodeMessageBufferMaxLength";
|
||||
if (RED.settings.hasOwnProperty(name)) {
|
||||
_maxKeptMsgsCount = RED.settings[name];
|
||||
}
|
||||
else {
|
||||
_maxKeptMsgsCount = 0;
|
||||
}
|
||||
}
|
||||
return _maxKeptMsgsCount;
|
||||
}
|
||||
|
||||
function DelayNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
@@ -78,6 +92,9 @@ module.exports = function(RED) {
|
||||
this.randomID = -1;
|
||||
this.lastSent = null;
|
||||
this.drop = n.drop;
|
||||
this.droppedMsgs = 0;
|
||||
this.allowrate = n.allowrate|| false;
|
||||
this.fixedrate = this.rate;
|
||||
var node = this;
|
||||
|
||||
function ourTimeout(handler, delay, clearHandler) {
|
||||
@@ -88,6 +105,19 @@ module.exports = function(RED) {
|
||||
};
|
||||
}
|
||||
|
||||
var sendMsgFromBuffer = function() {
|
||||
if (node.buffer.length === 0) {
|
||||
clearInterval(node.intervalID);
|
||||
node.intervalID = -1;
|
||||
}
|
||||
if (node.buffer.length > 0) {
|
||||
const msgInfo = node.buffer.shift();
|
||||
msgInfo.send(msgInfo.msg);
|
||||
msgInfo.done();
|
||||
}
|
||||
node.reportDepth();
|
||||
}
|
||||
|
||||
var clearDelayList = function(s) {
|
||||
for (var i=0; i<node.idList.length; i++ ) { node.idList[i].clear(); }
|
||||
node.idList = [];
|
||||
@@ -112,21 +142,28 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
|
||||
var loggerId = setInterval(function () {
|
||||
if (node.droppedMsgs !== 0) {
|
||||
node.debug("node.droppedMsgs = " + node.droppedMsgs);
|
||||
node.droppedMsgs = 0;
|
||||
}
|
||||
}, 15 * 1000);
|
||||
node.on("close", function() { clearInterval(loggerId); });
|
||||
|
||||
if (node.pauseType === "delay") {
|
||||
node.on("input", function(msg, send, done) {
|
||||
var id = ourTimeout(function() {
|
||||
node.idList.splice(node.idList.indexOf(id),1);
|
||||
if (node.idList.length === 0) { node.status({}); }
|
||||
send(msg);
|
||||
done();
|
||||
}, node.timeout, () => done());
|
||||
if (Object.keys(msg).length === 2 && msg.hasOwnProperty("flush")) { id.clear(); }
|
||||
else { node.idList.push(id); }
|
||||
if (msg.hasOwnProperty("reset")) { clearDelayList(true); }
|
||||
if (msg.hasOwnProperty("flush")) { flushDelayList(); done(); }
|
||||
else {
|
||||
var id = ourTimeout(function() {
|
||||
node.idList.splice(node.idList.indexOf(id),1);
|
||||
if (node.idList.length === 0) { node.status({}); }
|
||||
send(msg);
|
||||
done();
|
||||
}, node.timeout, () => done());
|
||||
node.idList.push(id);
|
||||
if ((node.timeout > 1000) && (node.idList.length !== 0)) {
|
||||
node.status({fill:"blue",shape:"dot",text:" "});
|
||||
}
|
||||
if (msg.hasOwnProperty("reset")) { clearDelayList(true); }
|
||||
if ((node.timeout > 1000) && (node.idList.length !== 0)) {
|
||||
node.status({fill:"blue",shape:"dot",text:" "});
|
||||
}
|
||||
});
|
||||
node.on("close", function() { clearDelayList(); });
|
||||
@@ -145,11 +182,11 @@ module.exports = function(RED) {
|
||||
done();
|
||||
}, delayvar, () => done());
|
||||
node.idList.push(id);
|
||||
if (msg.hasOwnProperty("reset")) { clearDelayList(true); }
|
||||
if (msg.hasOwnProperty("flush")) { flushDelayList(); done(); }
|
||||
if ((delayvar >= 0) && (node.idList.length !== 0)) {
|
||||
node.status({fill:"blue",shape:"dot",text:delayvar/1000+"s"});
|
||||
}
|
||||
if (msg.hasOwnProperty("reset")) { clearDelayList(true); }
|
||||
if (msg.hasOwnProperty("flush")) { flushDelayList(); }
|
||||
});
|
||||
node.on("close", function() { clearDelayList(); });
|
||||
}
|
||||
@@ -162,32 +199,37 @@ module.exports = function(RED) {
|
||||
}
|
||||
delete node.lastSent;
|
||||
node.buffer = [];
|
||||
node.rate = node.fixedrate;
|
||||
node.status({text:"reset"});
|
||||
done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!node.drop) {
|
||||
var m = RED.util.cloneMessage(msg);
|
||||
delete m.flush;
|
||||
if (node.intervalID !== -1) {
|
||||
node.buffer.push({msg: m, send: send, done: done});
|
||||
node.reportDepth();
|
||||
if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate)) && node.rate !== msg.rate) {
|
||||
node.rate = msg.rate;
|
||||
clearInterval(node.intervalID);
|
||||
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
|
||||
}
|
||||
var max_msgs = maxKeptMsgsCount(node);
|
||||
if ((max_msgs > 0) && (node.buffer.length >= max_msgs)) {
|
||||
node.buffer = [];
|
||||
node.error(RED._("delay.errors.too-many"), msg);
|
||||
} else {
|
||||
node.buffer.push({msg: m, send: send, done: done});
|
||||
node.reportDepth();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate))) {
|
||||
node.rate = msg.rate;
|
||||
}
|
||||
send(m);
|
||||
node.reportDepth();
|
||||
node.intervalID = setInterval(function() {
|
||||
if (node.buffer.length === 0) {
|
||||
clearInterval(node.intervalID);
|
||||
node.intervalID = -1;
|
||||
}
|
||||
if (node.buffer.length > 0) {
|
||||
const msgInfo = node.buffer.shift();
|
||||
msgInfo.send(msgInfo.msg);
|
||||
msgInfo.done();
|
||||
}
|
||||
node.reportDepth();
|
||||
}, node.rate);
|
||||
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
|
||||
done();
|
||||
}
|
||||
if (msg.hasOwnProperty("flush")) {
|
||||
@@ -201,17 +243,40 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
var timeSinceLast;
|
||||
if (node.lastSent) {
|
||||
timeSinceLast = process.hrtime(node.lastSent);
|
||||
}
|
||||
if (!node.lastSent) { // ensuring that we always send the first message
|
||||
node.lastSent = process.hrtime();
|
||||
send(msg);
|
||||
}
|
||||
else if ( ( (timeSinceLast[0] * SECONDS_TO_NANOS) + timeSinceLast[1] ) > (node.rate * MILLIS_TO_NANOS) ) {
|
||||
node.lastSent = process.hrtime();
|
||||
send(msg);
|
||||
if (maxKeptMsgsCount(node) > 0) {
|
||||
if (node.intervalID === -1) {
|
||||
node.send(msg);
|
||||
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
|
||||
} else {
|
||||
if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate)) && node.rate !== msg.rate) {
|
||||
node.rate = msg.rate;
|
||||
clearInterval(node.intervalID);
|
||||
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
|
||||
}
|
||||
if (node.buffer.length < _maxKeptMsgsCount) {
|
||||
var m = RED.util.cloneMessage(msg);
|
||||
node.buffer.push({msg: m, send: send, done: done});
|
||||
} else {
|
||||
node.trace("dropped due to buffer overflow. msg._msgid = " + msg._msgid);
|
||||
node.droppedMsgs++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate))) {
|
||||
node.rate = msg.rate;
|
||||
}
|
||||
var timeSinceLast;
|
||||
if (node.lastSent) {
|
||||
timeSinceLast = process.hrtime(node.lastSent);
|
||||
}
|
||||
if (!node.lastSent) { // ensuring that we always send the first message
|
||||
node.lastSent = process.hrtime();
|
||||
send(msg);
|
||||
}
|
||||
else if ( ( (timeSinceLast[0] * SECONDS_TO_NANOS) + timeSinceLast[1] ) > (node.rate * MILLIS_TO_NANOS) ) {
|
||||
node.lastSent = process.hrtime();
|
||||
send(msg);
|
||||
}
|
||||
}
|
||||
done();
|
||||
}
|
||||
@@ -245,6 +310,11 @@ module.exports = function(RED) {
|
||||
|
||||
var hit;
|
||||
node.on("input", function(msg, send, done) {
|
||||
if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate)) && node.rate !== msg.rate) {
|
||||
node.rate = msg.rate;
|
||||
clearInterval(node.intervalID);
|
||||
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
|
||||
}
|
||||
if (!msg.hasOwnProperty("topic")) { msg.topic = "_none_"; }
|
||||
hit = false;
|
||||
for (var b in node.buffer) { // check if already in queue
|
||||
@@ -265,6 +335,7 @@ module.exports = function(RED) {
|
||||
msgInfo.done();
|
||||
}
|
||||
node.buffer = [];
|
||||
node.rate = node.fixedrate;
|
||||
node.status({text:"reset"});
|
||||
done();
|
||||
}
|
||||
@@ -297,12 +368,13 @@ module.exports = function(RED) {
|
||||
node.status({});
|
||||
done();
|
||||
}, wait, () => done());
|
||||
node.idList.push(id);
|
||||
if (Object.keys(msg).length === 2 && msg.hasOwnProperty("flush")) { id.clear(); }
|
||||
else { node.idList.push(id); }
|
||||
if (msg.hasOwnProperty("reset")) { clearDelayList(true); }
|
||||
if (msg.hasOwnProperty("flush")) { flushDelayList(); done(); }
|
||||
if ((node.timeout >= 1000) && (node.idList.length !== 0)) {
|
||||
node.status({fill:"blue",shape:"dot",text:parseInt(wait/10)/100+"s"});
|
||||
}
|
||||
if (msg.hasOwnProperty("reset")) { clearDelayList(true); }
|
||||
if (msg.hasOwnProperty("flush")) { flushDelayList(); }
|
||||
});
|
||||
node.on("close", function() { clearDelayList(); });
|
||||
}
|
||||
|
93
packages/node_modules/@node-red/nodes/core/function/rbe.html
vendored
Normal file
93
packages/node_modules/@node-red/nodes/core/function/rbe.html
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
|
||||
<script type="text/html" data-template-name="rbe">
|
||||
<div class="form-row">
|
||||
<label for="node-input-func"><i class="fa fa-wrench"></i> <span data-i18n="rbe.label.func"></span></label>
|
||||
<select type="text" id="node-input-func" style="width:70%;">
|
||||
<option value="rbe" data-i18n="rbe.opts.rbe"></option>
|
||||
<option value="rbei" data-i18n="rbe.opts.rbei"></option>
|
||||
<option value="deadbandEq" data-i18n="rbe.opts.deadbandEq"></option>
|
||||
<option value="deadband" data-i18n="rbe.opts.deadband"></option>
|
||||
<option value="narrowbandEq" data-i18n="rbe.opts.narrowbandEq"></option>
|
||||
<option value="narrowband" data-i18n="rbe.opts.narrowband"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row" id="node-bandgap">
|
||||
<label for="node-input-gap"> </label>
|
||||
<input type="text" id="node-input-gap" data-i18n="[placeholder]rbe.placeholder.bandgap" style="width:95px;">
|
||||
<select type="text" id="node-input-inout" style="width:54%;">
|
||||
<option value="out" data-i18n="rbe.opts.out"></option>
|
||||
<option value="in" data-i18n="rbe.opts.in"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row" id="node-startvalue">
|
||||
<label for="node-input-start"><i class="fa fa-thumb-tack"></i> <span data-i18n="rbe.label.start"></span></label>
|
||||
<input type="text" id="node-input-start" data-i18n="[placeholder]rbe.placeholder.start" style="width:70%;">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="node-red:common.label.property"></span></label>
|
||||
<input type="text" id="node-input-property" style="width:70%;"/>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-septopics" style="display:inline-block; width:20px; vertical-align:baseline;">
|
||||
<span data-i18n="rbe.label.septopics"></span> <input type="text" id="node-input-topi" style="width:27%;"/>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="rbe.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]rbe.label.name" style="width:70%;">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType("rbe", {
|
||||
color:"#E2D96E",
|
||||
category: 'function',
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
func: {value:"rbe"},
|
||||
gap: {value:"",validate:RED.validators.regex(/^(\d*[.]*\d*|)(%|)$/)},
|
||||
start: {value:""},
|
||||
inout: {value:"out"},
|
||||
septopics: {value:true},
|
||||
property: {value:"payload",required:true},
|
||||
topi: {value:"topic",required:true}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:1,
|
||||
icon: "rbe.png",
|
||||
paletteLabel: "filter",
|
||||
label: function() {
|
||||
var ll = (this.func||"").replace("Eq","").replace("rbei",this._("rbe.rbe")).replace("rbe",this._("rbe.rbe"))||this._("rbe.rbe");
|
||||
return this.name||ll||this._("rbe.rbe");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
if (this.property === undefined) {
|
||||
$("#node-input-property").val("payload");
|
||||
}
|
||||
if (this.septopics === undefined) {
|
||||
$("#node-input-septopics").prop('checked', true);
|
||||
}
|
||||
$("#node-input-property").typedInput({default:'msg',types:['msg']});
|
||||
$("#node-input-topi").typedInput({default:'msg',types:['msg']});
|
||||
//$( "#node-input-gap" ).spinner({min:0});
|
||||
if ($("#node-input-inout").val() === null) {
|
||||
$("#node-input-inout").val("out");
|
||||
}
|
||||
$("#node-input-func").on("change",function() {
|
||||
if (($("#node-input-func").val() === "rbe")||($("#node-input-func").val() === "rbei")) {
|
||||
$("#node-bandgap").hide();
|
||||
} else {
|
||||
$("#node-bandgap").show();
|
||||
}
|
||||
if (($("#node-input-func").val() === "narrowband")||($("#node-input-func").val() === "narrowbandEq")) {
|
||||
$("#node-startvalue").show();
|
||||
} else {
|
||||
$("#node-startvalue").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
97
packages/node_modules/@node-red/nodes/core/function/rbe.js
vendored
Normal file
97
packages/node_modules/@node-red/nodes/core/function/rbe.js
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
function RbeNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.func = n.func || "rbe";
|
||||
this.gap = n.gap || "0";
|
||||
this.start = n.start || '';
|
||||
this.inout = n.inout || "out";
|
||||
this.pc = false;
|
||||
if (this.gap.substr(-1) === "%") {
|
||||
this.pc = true;
|
||||
this.gap = parseFloat(this.gap);
|
||||
}
|
||||
this.g = this.gap;
|
||||
this.property = n.property || "payload";
|
||||
this.topi = n.topi || "topic";
|
||||
this.septopics = true;
|
||||
if (n.septopics !== undefined && n.septopics === false) {
|
||||
this.septopics = false;
|
||||
}
|
||||
|
||||
var node = this;
|
||||
|
||||
node.previous = {};
|
||||
this.on("input",function(msg) {
|
||||
var topic;
|
||||
try {
|
||||
topic = RED.util.getMessageProperty(msg,node.topi);
|
||||
}
|
||||
catch(e) { }
|
||||
if (msg.hasOwnProperty("reset")) {
|
||||
if (node.septopics && topic && (typeof topic === "string") && (topic !== "")) {
|
||||
delete node.previous[msg.topic];
|
||||
}
|
||||
else { node.previous = {}; }
|
||||
}
|
||||
var value = RED.util.getMessageProperty(msg,node.property);
|
||||
if (value !== undefined) {
|
||||
var t = "_no_topic";
|
||||
if (node.septopics) { t = topic || t; }
|
||||
if ((this.func === "rbe") || (this.func === "rbei")) {
|
||||
var doSend = (this.func !== "rbei") || (node.previous.hasOwnProperty(t)) || false;
|
||||
if (typeof(value) === "object") {
|
||||
if (typeof(node.previous[t]) !== "object") { node.previous[t] = {}; }
|
||||
if (!RED.util.compareObjects(value, node.previous[t])) {
|
||||
node.previous[t] = RED.util.cloneMessage(value);
|
||||
if (doSend) { node.send(msg); }
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (value !== node.previous[t]) {
|
||||
node.previous[t] = RED.util.cloneMessage(value);
|
||||
if (doSend) { node.send(msg); }
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var n = parseFloat(value);
|
||||
if (!isNaN(n)) {
|
||||
if ((typeof node.previous[t] === 'undefined') && (this.func === "narrowband")) {
|
||||
if (node.start === '') { node.previous[t] = n; }
|
||||
else { node.previous[t] = node.start; }
|
||||
}
|
||||
if (node.pc) { node.gap = Math.abs(node.previous[t] * node.g / 100) || 0; }
|
||||
else { node.gap = Number(node.gap); }
|
||||
if ((node.previous[t] === undefined) && (node.func === "narrowbandEq")) { node.previous[t] = n; }
|
||||
if (node.previous[t] === undefined) { node.previous[t] = n - node.gap - 1; }
|
||||
if (Math.abs(n - node.previous[t]) === node.gap) {
|
||||
if ((this.func === "deadbandEq")||(this.func === "narrowband")) {
|
||||
if (node.inout === "out") { node.previous[t] = n; }
|
||||
node.send(msg);
|
||||
}
|
||||
}
|
||||
else if (Math.abs(n - node.previous[t]) > node.gap) {
|
||||
if (this.func === "deadband" || this.func === "deadbandEq") {
|
||||
if (node.inout === "out") { node.previous[t] = n; }
|
||||
node.send(msg);
|
||||
}
|
||||
}
|
||||
else if (Math.abs(n - node.previous[t]) < node.gap) {
|
||||
if ((this.func === "narrowband")||(this.func === "narrowbandEq")) {
|
||||
if (node.inout === "out") { node.previous[t] = n; }
|
||||
node.send(msg);
|
||||
}
|
||||
}
|
||||
if (node.inout === "in") { node.previous[t] = n; }
|
||||
}
|
||||
else {
|
||||
node.warn(RED._("rbe.warn.nonumber"));
|
||||
}
|
||||
}
|
||||
} // ignore msg with no payload property.
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("rbe",RbeNode);
|
||||
}
|
@@ -201,7 +201,7 @@
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
mode: {value:"auto"},
|
||||
build: { value:"string"},
|
||||
build: { value:"object"},
|
||||
property: { value:"payload", validate:RED.validators.typedInput("propertyType")},
|
||||
propertyType: { value:"msg"},
|
||||
key: {value:"topic"},
|
||||
|
@@ -51,6 +51,10 @@ module.exports = function(RED) {
|
||||
|
||||
function processMsg(msg,nodeSend, done) {
|
||||
var filename = node.filename || msg.filename || "";
|
||||
var fullFilename = filename;
|
||||
if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) {
|
||||
fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename));
|
||||
}
|
||||
if ((!node.filename) && (!node.tout)) {
|
||||
node.tout = setTimeout(function() {
|
||||
node.status({fill:"grey",shape:"dot",text:filename});
|
||||
@@ -62,7 +66,7 @@ module.exports = function(RED) {
|
||||
node.warn(RED._("file.errors.nofilename"));
|
||||
done();
|
||||
} else if (node.overwriteFile === "delete") {
|
||||
fs.unlink(filename, function (err) {
|
||||
fs.unlink(fullFilename, function (err) {
|
||||
if (err) {
|
||||
node.error(RED._("file.errors.deletefail",{error:err.toString()}),msg);
|
||||
} else {
|
||||
@@ -74,7 +78,7 @@ module.exports = function(RED) {
|
||||
done();
|
||||
});
|
||||
} else if (msg.hasOwnProperty("payload") && (typeof msg.payload !== "undefined")) {
|
||||
var dir = path.dirname(filename);
|
||||
var dir = path.dirname(fullFilename);
|
||||
if (node.createDir) {
|
||||
try {
|
||||
fs.ensureDirSync(dir);
|
||||
@@ -94,7 +98,7 @@ module.exports = function(RED) {
|
||||
if ((node.appendNewline) && (!Buffer.isBuffer(data))) { data += os.EOL; }
|
||||
var buf = encode(data, node.encoding);
|
||||
if (node.overwriteFile === "true") {
|
||||
var wstream = fs.createWriteStream(filename, { encoding:'binary', flags:'w', autoClose:true });
|
||||
var wstream = fs.createWriteStream(fullFilename, { encoding:'binary', flags:'w', autoClose:true });
|
||||
node.wstream = wstream;
|
||||
wstream.on("error", function(err) {
|
||||
node.error(RED._("file.errors.writefail",{error:err.toString()}),msg);
|
||||
@@ -116,7 +120,7 @@ module.exports = function(RED) {
|
||||
// of the file. Check the file hasn't been deleted
|
||||
// or deleted and recreated.
|
||||
try {
|
||||
var stat = fs.statSync(filename);
|
||||
var stat = fs.statSync(fullFilename);
|
||||
// File exists - check the inode matches
|
||||
if (stat.ino !== node.wstreamIno) {
|
||||
// The file has been recreated. Close the current
|
||||
@@ -135,10 +139,10 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
if (recreateStream) {
|
||||
node.wstream = fs.createWriteStream(filename, { encoding:'binary', flags:'a', autoClose:true });
|
||||
node.wstream = fs.createWriteStream(fullFilename, { encoding:'binary', flags:'a', autoClose:true });
|
||||
node.wstream.on("open", function(fd) {
|
||||
try {
|
||||
var stat = fs.statSync(filename);
|
||||
var stat = fs.statSync(fullFilename);
|
||||
node.wstreamIno = stat.ino;
|
||||
} catch(err) {
|
||||
}
|
||||
@@ -258,6 +262,10 @@ module.exports = function(RED) {
|
||||
|
||||
this.on("input",function(msg, nodeSend, nodeDone) {
|
||||
var filename = (node.filename || msg.filename || "").replace(/\t|\r|\n/g,'');
|
||||
var fullFilename = filename;
|
||||
if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) {
|
||||
fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename));
|
||||
}
|
||||
if (!node.filename) {
|
||||
node.status({fill:"grey",shape:"dot",text:filename});
|
||||
}
|
||||
@@ -279,7 +287,7 @@ module.exports = function(RED) {
|
||||
var hwm;
|
||||
var getout = false;
|
||||
|
||||
var rs = fs.createReadStream(filename)
|
||||
var rs = fs.createReadStream(fullFilename)
|
||||
.on('readable', function () {
|
||||
var chunk;
|
||||
var hwm = rs._readableState.highWaterMark;
|
||||
|
BIN
packages/node_modules/@node-red/nodes/icons/rbe.png
vendored
Normal file
BIN
packages/node_modules/@node-red/nodes/icons/rbe.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 252 B |
40
packages/node_modules/@node-red/nodes/locales/de/function/rbe.html
vendored
Normal file
40
packages/node_modules/@node-red/nodes/locales/de/function/rbe.html
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<script type="text/html" data-help-name="rbe">
|
||||
<p>Report by Exception (RBE) - Daten-Weiterleitung nur bei Änderung der Nutzdaten (Payload).
|
||||
Der Node kann auch blockieren oder weiterleiten, wenn die Wertänderung eine Grenze überschreitet (Totband- und Nahband-Modus).</p>
|
||||
<h3>Eingangsdaten</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload
|
||||
<span class="property-type">number | string | (object)</span>
|
||||
</dt>
|
||||
<dd>Der RBE-Modus mit Prüfung auf Wertänderung akzeptiert Zahlen (numbers), Zeichenfolgen (string) und einfache Objekte (object).
|
||||
Bei den anderen wertvergleichenden Modies müssen analysierbare (parseable) Zahlenwerte übergeben werden.</dd>
|
||||
<dt class="optional">topic <span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd>Wenn vorgegeben erfolgt die Auswertung separat für jedes Topic</dd>
|
||||
<dt class="optional">reset<span class="property-type">any</span></dt>
|
||||
<dd>Wenn gesetzt wird/werden der/die gespeicherte(n) Wert(e) rückgesetzt</dd>
|
||||
</dl>
|
||||
<h3>Ausgangsdaten</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload
|
||||
<span class="property-type">wie Eingangsdaten</span>
|
||||
</dt>
|
||||
<dd>Wenn Bedingung erfüllt, sind die Ausgangsdaten gleich den Eingangsdaten</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>Im <i>RBE</i>-Modus mit Prüfung auf Wertänderung blockiert dieser Node die Datenweitergabe bis
|
||||
<code>msg.payload</code> (oder die eingestellte Eigenschaft) verändert ist gegenüber dessen vorherigen Wert.
|
||||
Wenn benötigt, wird der Anfangswert ignoriert, sodass beim Start nichts gesendet wird.</p>
|
||||
<p>In den <i>Totband</i>-Modies werden die Eingangswerte geblockt,
|
||||
<i>bis</i> die Wertänderung größer oder größer-gleich ist als ± des Bandes um den voherigen Wert.</p>
|
||||
<p>In den <i>Nahband</i>-Modies werden die Eingangswerte geblockt,
|
||||
<i>wenn</i> die Wertänderung größer oder größer-gleich ist als ± des Bandes um den voherigen Wert.
|
||||
Dies ist beispielsweise nützlich, um Ausreißer eines fehlerhaften Sensors zu ignorieren.</p>
|
||||
<p>In den Totband und Nahband-Modies müssen die Eingangswerte analysierbare (parseable) Zahlenwerte sein und
|
||||
beide unterstützen auch % (prozentuale Angabe), d.h. der Node sendet nur, wenn der Eingangswert mehr als x% vom vorherigen Wert abweicht.</p>
|
||||
<p>Die Totband- und Nahband-Modies erlauben den Vergleich entweder gegen den letzten gültigen Ausgangswert,
|
||||
dieses zum Ignorieren von Werten außerhalb des gültigen Bereichs, oder gegen den des vorherigen Eingangswertes,
|
||||
welches den Sollwert rücksetzt, was einen allmähligen Drift (Totband) oder einen eine schrittweise Veränderung (Nahband) ermöglicht.</p>
|
||||
<p><b>Hinweis</b>: Dieser Node arbeitet auf per-<code>msg.topic</code>-Basis.
|
||||
Dies bedeutet, dass ein einzelner rbe-Node mehrere verschiedene Topics parallel bearbeiten kann.</p>
|
||||
</script>
|
@@ -1000,5 +1000,32 @@
|
||||
"too-many": "Zu viele anstehende Nachrichten im <span style=\"background-color:Gainsboro\">batch</span>-Node",
|
||||
"unexpected": "Unerwarteter Modus",
|
||||
"no-parts": "Keine parts-Eigenschaft in Nachricht"
|
||||
},
|
||||
"rbe": {
|
||||
"rbe": "filter",
|
||||
"label": {
|
||||
"func": "Modus",
|
||||
"init": "Sende Anfangswert",
|
||||
"start": "Startwert",
|
||||
"name": "Name",
|
||||
"septopics": "Modus für jedes msg.topic separat anwenden"
|
||||
},
|
||||
"placeholder":{
|
||||
"bandgap": "z.B. 10 oder 5%",
|
||||
"start": "Leer lassen, um erste empfangenen Daten zu nutzen"
|
||||
},
|
||||
"opts": {
|
||||
"rbe": "Blockieren bis Wertänderung",
|
||||
"rbei": "Blockieren bis Wertänderung (Anfangswert ignorieren)",
|
||||
"deadband": "Blockieren bis Wertänderung ist größer als",
|
||||
"deadbandEq": "Blockieren bis Wertänderung ist größer-gleich",
|
||||
"narrowband": "Blockieren wenn Wertänderung ist größer als",
|
||||
"narrowbandEq": "Blockieren wenn Wertänderung ist größer-gleich",
|
||||
"in": "verglichen mit letzten Eingangswert",
|
||||
"out": "verglichen mit letzten gültigen Ausgangswert"
|
||||
},
|
||||
"warn": {
|
||||
"nonumber": "Keine Zahl gefunden in den Nutzdaten (Payload)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -22,6 +22,12 @@
|
||||
<dd>Sets the delay, in milliseconds, to be applied to the message. This
|
||||
option only applies if the node is configured to allow the message to
|
||||
override the configured default delay interval.</dd>
|
||||
<dt class="optional">rate <span class="property-type">number</span></dt>
|
||||
<dd>Sets the rate value in milliseconds between messages.
|
||||
This node overwrites the existing rate value defined in the node configuration
|
||||
when it receives the message which contains <code>msg.rate</code> value in milliSeconds.
|
||||
This option only applies if the node is configured to allow the message to
|
||||
override the configured default rate interval.</dd>
|
||||
<dt class="optional">reset</dt>
|
||||
<dd>If the received message has this property set to any value, all
|
||||
outstanding messages held by the node are cleared without being sent.</dd>
|
||||
@@ -32,15 +38,17 @@
|
||||
<h3>Details</h3>
|
||||
<p>When configured to delay messages, the delay interval can be a fixed value,
|
||||
a random value within a range or dynamically set for each message.
|
||||
Each message is delayed independently of any other message, based on
|
||||
Each message is delayed independently of any other message, based on
|
||||
the time of its arrival.
|
||||
</p>
|
||||
<p>When configured to rate limit messages, their delivery is spread across
|
||||
the configured time period. The status shows the number of messages currently in the queue.
|
||||
It can optionally discard intermediate messages as they arrive.</p>
|
||||
</p>
|
||||
<p> If set to allow override of the rate, the new rate will be applied immediately,
|
||||
and will remain in effect until changed again, the node is reset, or the flow is restarted.</p>
|
||||
<p>The rate limiting can be applied to all messages, or group them according to
|
||||
their <code>msg.topic</code> value. When grouping, intermerdiate messages are
|
||||
their <code>msg.topic</code> value. When grouping, intermediate messages are
|
||||
automatically dropped. At each time interval, the node can either release
|
||||
the most recent message for all topics, or release the most recent message
|
||||
for the next topic.
|
||||
|
41
packages/node_modules/@node-red/nodes/locales/en-US/function/rbe.html
vendored
Normal file
41
packages/node_modules/@node-red/nodes/locales/en-US/function/rbe.html
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<script type="text/html" data-help-name="rbe">
|
||||
<p>Report by Exception (RBE) node - only passes on data if the payload has changed.
|
||||
It can also block unless, or ignore if the value changes by a specified amount (Dead- and Narrowband mode).</p>
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload
|
||||
<span class="property-type">number | string | (object)</span>
|
||||
</dt>
|
||||
<dd>RBE mode will accept numbers, strings, and simple objects.
|
||||
Other modes must provide a parseable number.</dd>
|
||||
<dt class="optional">topic <span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd>if specified the function will work on a per topic basis. This property can be set by configuration.</dd>
|
||||
<dt class="optional">reset<span class="property-type">any</span></dt>
|
||||
<dd>if set clears the stored value for the specified msg.topic, or
|
||||
all topics if msg.topic is not specified.</dd>
|
||||
</dl>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload
|
||||
<span class="property-type">as per input</span>
|
||||
</dt>
|
||||
<dd>If triggered the output will be the same as the input.</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>In RBE mode this node will block until the <code>msg.payload</code>,
|
||||
(or selected property) value is different to the previous one.
|
||||
If required it can ignore the intial value, so as not to send anything at start.</p>
|
||||
<p>The <a href="https://en.wikipedia.org/wiki/Deadband" target="_blank">Deadband</a> modes will block the incoming value
|
||||
<i>unless</i> its change is greater or greater-equal than ± the band gap away from a previous value.</p>
|
||||
<p>The Narrowband modes will block the incoming value,
|
||||
<i>if</i> its change is greater or greater-equal than ± the band gap away from the previous value.
|
||||
It is useful for ignoring outliers from a faulty sensor for example.</p>
|
||||
<p>Both in Deadband and Narrowband modes the incoming value must contain a parseable number and
|
||||
both also supports % - only sends if/unless the input differs by more than x% of the original value.</p>
|
||||
<p>Both Deadband and Narrowband allow comparison against either the previous valid output value, thus
|
||||
ignoring any values out of range, or the previous input value, which resets the set point, thus allowing
|
||||
gradual drift (deadband), or a step change (narrowband).</p>
|
||||
<p><b>Note:</b> This works on a per <code>msg.topic</code> basis, though this can be changed to another property if desired.
|
||||
This means that a single rbe node can handle multiple different topics at the same time.</p>
|
||||
</script>
|
@@ -276,6 +276,7 @@
|
||||
"rate": "Rate",
|
||||
"msgper": "msg(s) per",
|
||||
"dropmsg": "drop intermediate messages",
|
||||
"allowrate": "allow msg.rate (in ms) to override rate",
|
||||
"label": {
|
||||
"delay": "delay",
|
||||
"variable": "variable",
|
||||
@@ -301,9 +302,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"buffer": "buffer exceeded 1000 messages",
|
||||
"buffer1": "buffer exceeded 10000 messages"
|
||||
"errors": {
|
||||
"too-many" : "too many pending messages in delay node"
|
||||
}
|
||||
},
|
||||
"trigger": {
|
||||
@@ -1001,5 +1001,32 @@
|
||||
"too-many" : "too many pending messages in batch node",
|
||||
"unexpected" : "unexpected mode",
|
||||
"no-parts" : "no parts property in message"
|
||||
},
|
||||
"rbe": {
|
||||
"rbe": "filter",
|
||||
"label": {
|
||||
"func": "Mode",
|
||||
"init": "Send initial value",
|
||||
"start": "Start value",
|
||||
"name": "Name",
|
||||
"septopics": "Apply mode separately for each "
|
||||
},
|
||||
"placeholder":{
|
||||
"bandgap": "e.g. 10 or 5%",
|
||||
"start": "leave blank to use first data received"
|
||||
},
|
||||
"opts": {
|
||||
"rbe": "block unless value changes",
|
||||
"rbei": "block unless value changes (ignore initial value)",
|
||||
"deadband": "block unless value change is greater than",
|
||||
"deadbandEq": "block unless value change is greater or equal to",
|
||||
"narrowband": "block if value change is greater than",
|
||||
"narrowbandEq": "block if value change is greater or equal to",
|
||||
"in": "compared to last input value",
|
||||
"out": "compared to last valid output value"
|
||||
},
|
||||
"warn": {
|
||||
"nonumber": "no number found in payload"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -20,6 +20,8 @@
|
||||
<dl class="message-properties">
|
||||
<dt class="optional">delay <span class="property-type">数値</span></dt>
|
||||
<dd>メッセージの遅延時間をミリ秒単位で設定します。これはノードの設定でデフォルトの遅延時間を上書きできるようノードを設定した場合にのみ適用します。</dd>
|
||||
<dt class="optional">rate <span class="property-type">数値</span></dt>
|
||||
<dd>メッセージ間の流量値をミリ秒単位で設定します。本ノードは、<code>msg.rate</code>値を含むメッセージを受け取ると、ノード設定で定義された既存の流量値を上書きします。このオプションは、デフォルトで設定された流量値を上書きできるように設定された場合のみ適用されます。</dd>
|
||||
<dt class="optional">reset</dt>
|
||||
<dd>受信メッセージでこのプロパティを任意の値に設定すると、ノードが保持する全ての未送信メッセージをクリアします。</dd>
|
||||
<dt class="optional">flush</dt>
|
||||
@@ -28,5 +30,6 @@
|
||||
<h3>詳細</h3>
|
||||
<p>メッセージを遅延させるように設定する場合、遅延時間は固定値、範囲内の乱数値、メッセージ毎の動的な指定値のいずれかを指定できます。</p>
|
||||
<p>流量制御する場合、メッセージは指定した時間間隔内に分散して送信します。キューに残っているメッセージ数はノードのステータスに表示されます。受け取った中間メッセージを破棄することも可能です。</p>
|
||||
<p>流量値を上書きできるように設定されている場合、新しい流量値はすぐに適用されます。この流量値は、再度変更されるまで、本ノードがリセットされるまで、またはフローが再実行されるまで有効です。</p>
|
||||
<p>流量制御は全てのメッセージに適用することも、<code>msg.topic</code>値でグループ化して適用することも可能です。グループ化すると、中間メッセージは自動的に破棄されます。時間間隔毎に全てのトピックの最新メッセージを送信するか、次のトピックの最新メッセージを送信するかを指定できます。</p>
|
||||
</script>
|
||||
|
31
packages/node_modules/@node-red/nodes/locales/ja/function/rbe.html
vendored
Normal file
31
packages/node_modules/@node-red/nodes/locales/ja/function/rbe.html
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<!-- Source revision: https://github.com/node-red/node-red-nodes/commit/467907776088422882076f46d85e25601449564d -->
|
||||
|
||||
<script type="text/html" data-help-name="rbe">
|
||||
<p>Report by Exception(例外データの報告)ノード - ペイロードの値が変化した場合だけデータを送信。</p>
|
||||
<p>値が指定した量変化するまでブロックすることもできます- 不感帯(deadband)モード。</p>
|
||||
<h3>入力</h3> <dl class="message-properties">
|
||||
<dt>payload
|
||||
<span class="property-type">数値 | 文字列 | (オブジェクト)</span>
|
||||
</dt>
|
||||
<dd>RBEモードでは数値、文字列、シンプルなオブジェクトを受け付けます。他のモードではパース可能な数値を指定します。</dd>
|
||||
<dt class="optional">topic <span class="property-type">文字列</span>
|
||||
</dt>
|
||||
<dd>指定すると、トピックごとに動作します。</dd>
|
||||
<dt class="optional">reset<span class="property-type">任意</span></dt>
|
||||
<dd>値を設定すると、保存した値をクリアします。msg.topicを指定した場合は対応する値、指定しなければ全てのトピックが対象となります。</dd>
|
||||
</dl>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload
|
||||
<span class="property-type">入力と同じ</span>
|
||||
</dt>
|
||||
<dd>トリガー条件を満たした場合、入力を出力として送信。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>RBEモードでは、<code>msg.payload</code>が前の値から変化するまでブロックします。</p>
|
||||
<p>不感帯モードでは、入力データはパース可能な数値でなければなりません。以前の入力値に対する差分が指定値より大きな場合にのみメッセージを出力します。</p>
|
||||
<p>不感帯モードでは%による指定もサポートしています。入力と前の値の差分がX%より大きな場合に出力を行います。</p>
|
||||
<p>狭帯域(narrowband)モードでは、前の値に対する差分が一定値より大きな場合に入力ペイロードをブロックします。このモードは、故障したセンサから発生する外れ値を無視する時などに有用です。</p>
|
||||
<p>不感帯モードと狭帯域モードでは、以前の有効出力値、もしくは、以前の入力値との比較ができます。有効出力値を用いると範囲外の値を無視することが、入力値を用いると設定点がリセットされるため漸次的変化(不感帯モード)もしくは段階的変化(狭帯域モード)が可能です。</p>
|
||||
<p><b>注:</b> このノードは<code>msg.topic</code>毎に動作します。そのため、ひとつのrbeノードで複数の異なるトピックを同時に扱うことができます。</p>
|
||||
</script>
|
@@ -276,6 +276,7 @@
|
||||
"rate": "流量",
|
||||
"msgper": "メッセージ/",
|
||||
"dropmsg": "中間メッセージを削除",
|
||||
"allowrate": "msg.rate(ミリ秒単位)で流量値を上書き",
|
||||
"label": {
|
||||
"delay": "delay",
|
||||
"variable": "variable",
|
||||
@@ -301,9 +302,8 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"buffer": "バッファ上限の1000メッセージを超えました",
|
||||
"buffer1": "バッファ上限の10000メッセージを超えました"
|
||||
"errors": {
|
||||
"too-many": "delayノード内で保持しているメッセージが多すぎます"
|
||||
}
|
||||
},
|
||||
"trigger": {
|
||||
@@ -999,5 +999,30 @@
|
||||
"too-many": "batchノード内で保持しているメッセージが多すぎます",
|
||||
"unexpected": "想定外のモード",
|
||||
"no-parts": "メッセージにpartsプロパティがありません"
|
||||
},
|
||||
"rbe": {
|
||||
"label": {
|
||||
"func": "動作",
|
||||
"init": "初期値を送付",
|
||||
"start": "初期値",
|
||||
"name": "名前"
|
||||
},
|
||||
"placeholder": {
|
||||
"bandgap": "例:10、5%",
|
||||
"start": "最初に受け取った値を用いる場合は空欄"
|
||||
},
|
||||
"opts": {
|
||||
"rbe": "値が変化した時のみメッセージを中継",
|
||||
"rbei": "値が変化した時のみメッセージを中継(初期値を無視)",
|
||||
"deadband": "値が指定した変化量を超える時のみメッセージを中継",
|
||||
"deadbandEq": "値が指定した変化量以上の時のみメッセージを中継",
|
||||
"narrowband": "値が指定した変化量を超えない時のみメッセージを中継",
|
||||
"narrowbandEq": "値が指定した変化量以上でない時のみメッセージを中継",
|
||||
"in": "最後の入力値と比較",
|
||||
"out": "最後の出力値と比較"
|
||||
},
|
||||
"warn": {
|
||||
"nonumber": "ペイロードに数値が含まれていません"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -272,10 +272,6 @@
|
||||
"singular": "일"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"buffer": "버퍼 상한의 1000메세지를 넘었습니다",
|
||||
"buffer1": "버퍼 상한의 10000메세지를 넘었습니다"
|
||||
}
|
||||
},
|
||||
"trigger": {
|
||||
|
@@ -290,10 +290,6 @@
|
||||
"singular": "天"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"buffer": "缓冲了超过 1000 条信息",
|
||||
"buffer1": "缓冲了超过 10000 条信息"
|
||||
}
|
||||
},
|
||||
"trigger": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/nodes",
|
||||
"version": "1.3.1",
|
||||
"version": "2.0.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -22,9 +22,9 @@
|
||||
"cookie-parser": "1.4.5",
|
||||
"cookie": "0.4.1",
|
||||
"cors": "2.8.5",
|
||||
"cron": "1.7.2",
|
||||
"cronosjs": "1.7.1",
|
||||
"denque": "1.5.0",
|
||||
"fs-extra": "8.1.0",
|
||||
"fs-extra": "9.1.0",
|
||||
"fs.notify": "0.0.4",
|
||||
"hash-sum": "2.0.0",
|
||||
"https-proxy-agent": "5.0.0",
|
||||
|
@@ -9,6 +9,7 @@ const path = require("path");
|
||||
const clone = require("clone");
|
||||
const exec = require("@node-red/util").exec;
|
||||
const log = require("@node-red/util").log;
|
||||
const hooks = require("@node-red/util").hooks;
|
||||
|
||||
const BUILTIN_MODULES = require('module').builtinModules;
|
||||
const EXTERNAL_MODULES_DIR = "externalModules";
|
||||
@@ -189,13 +190,29 @@ async function installModule(moduleDetails) {
|
||||
|
||||
await ensureModuleDir();
|
||||
|
||||
var args = ["install", installSpec, "--production"];
|
||||
return exec.run(NPM_COMMAND, args, {
|
||||
cwd: installDir
|
||||
},true).then(result => {
|
||||
let triggerPayload = {
|
||||
"module": moduleDetails.module,
|
||||
"version": moduleDetails.version,
|
||||
"dir": installDir,
|
||||
"args": ["--production"]
|
||||
}
|
||||
return hooks.trigger("preInstall", triggerPayload).then((result) => {
|
||||
// preInstall passed
|
||||
// - run install
|
||||
if (result !== false) {
|
||||
let extraArgs = triggerPayload.args || [];
|
||||
let args = ['install', ...extraArgs, installSpec]
|
||||
log.trace(NPM_COMMAND + JSON.stringify(args));
|
||||
return exec.run(NPM_COMMAND, args, { cwd: installDir },true)
|
||||
} else {
|
||||
log.trace("skipping npm install");
|
||||
}
|
||||
}).then(() => {
|
||||
return hooks.trigger("postInstall", triggerPayload)
|
||||
}).then(() => {
|
||||
log.info(log._("server.install.installed", { name: installSpec }));
|
||||
}).catch(result => {
|
||||
var output = result.stderr;
|
||||
var output = result.stderr || result.toString();
|
||||
var e;
|
||||
if (/E404/.test(output) || /ETARGET/.test(output)) {
|
||||
log.error(log._("server.install.install-failed-not-found",{name:installSpec}));
|
||||
|
@@ -23,7 +23,7 @@ const tar = require("tar");
|
||||
const registry = require("./registry");
|
||||
const registryUtil = require("./util");
|
||||
const library = require("./library");
|
||||
const {exec,log,events} = require("@node-red/util");
|
||||
const {exec,log,events,hooks} = require("@node-red/util");
|
||||
const child_process = require('child_process');
|
||||
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
||||
let installerEnabled = false;
|
||||
@@ -168,11 +168,30 @@ async function installModule(module,version,url) {
|
||||
}
|
||||
|
||||
var installDir = settings.userDir || process.env.NODE_RED_HOME || ".";
|
||||
var args = ['install','--no-audit','--no-update-notifier','--no-fund','--save','--save-prefix=~','--production',installName];
|
||||
log.trace(npmCommand + JSON.stringify(args));
|
||||
return exec.run(npmCommand,args,{
|
||||
cwd: installDir
|
||||
}, true).then(result => {
|
||||
let triggerPayload = {
|
||||
"module": module,
|
||||
"version": version,
|
||||
"url": url,
|
||||
"dir": installDir,
|
||||
"isExisting": isExisting,
|
||||
"isUpgrade": isUpgrade,
|
||||
"args": ['--no-audit','--no-update-notifier','--no-fund','--save','--save-prefix=~','--production']
|
||||
}
|
||||
|
||||
return hooks.trigger("preInstall", triggerPayload).then((result) => {
|
||||
// preInstall passed
|
||||
// - run install
|
||||
if (result !== false) {
|
||||
let extraArgs = triggerPayload.args || [];
|
||||
let args = ['install', ...extraArgs, installName]
|
||||
log.trace(npmCommand + JSON.stringify(args));
|
||||
return exec.run(npmCommand,args,{ cwd: installDir}, true)
|
||||
} else {
|
||||
log.trace("skipping npm install");
|
||||
}
|
||||
}).then(() => {
|
||||
return hooks.trigger("postInstall", triggerPayload)
|
||||
}).then(() => {
|
||||
if (isExisting) {
|
||||
// This is a module we already have installed as a non-user module.
|
||||
// That means it was discovered when loading, but was not listed
|
||||
@@ -191,29 +210,45 @@ async function installModule(module,version,url) {
|
||||
events.emit("runtime-event",{id:"restart-required",payload:{type:"warning",text:"notification.warnings.restartRequired"},retain:true});
|
||||
return require("./registry").setModulePendingUpdated(module,version);
|
||||
}
|
||||
}).catch(result => {
|
||||
var output = result.stderr;
|
||||
var e;
|
||||
var lookFor404 = new RegExp(" 404 .*"+module,"m");
|
||||
var lookForVersionNotFound = new RegExp("version not found: "+module+"@"+version,"m");
|
||||
if (lookFor404.test(output)) {
|
||||
log.warn(log._("server.install.install-failed-not-found",{name:module}));
|
||||
e = new Error("Module not found");
|
||||
e.code = 404;
|
||||
throw e;
|
||||
} else if (isUpgrade && lookForVersionNotFound.test(output)) {
|
||||
log.warn(log._("server.install.upgrade-failed-not-found",{name:module}));
|
||||
e = new Error("Module not found");
|
||||
e.code = 404;
|
||||
throw e;
|
||||
} else {
|
||||
}).catch(err => {
|
||||
let e;
|
||||
if (err.hook) {
|
||||
// preInstall failed
|
||||
log.warn(log._("server.install.install-failed-long",{name:module}));
|
||||
log.warn("------------------------------------------");
|
||||
log.warn(output);
|
||||
log.warn(err.toString());
|
||||
log.warn("------------------------------------------");
|
||||
throw new Error(log._("server.install.install-failed"));
|
||||
e = new Error(log._("server.install.install-failed")+": "+err.toString());
|
||||
if (err.hook === "postInstall") {
|
||||
return exec.run(npmCommand,["remove",module],{ cwd: installDir}, false).finally(() => {
|
||||
throw e;
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// npm install failed
|
||||
let output = err.stderr;
|
||||
let lookFor404 = new RegExp(" 404 .*"+module,"m");
|
||||
let lookForVersionNotFound = new RegExp("version not found: "+module+"@"+version,"m");
|
||||
if (lookFor404.test(output)) {
|
||||
log.warn(log._("server.install.install-failed-not-found",{name:module}));
|
||||
e = new Error("Module not found");
|
||||
e.code = 404;
|
||||
} else if (isUpgrade && lookForVersionNotFound.test(output)) {
|
||||
log.warn(log._("server.install.upgrade-failed-not-found",{name:module}));
|
||||
e = new Error("Module not found");
|
||||
e.code = 404;
|
||||
} else {
|
||||
log.warn(log._("server.install.install-failed-long",{name:module}));
|
||||
log.warn("------------------------------------------");
|
||||
log.warn(output);
|
||||
log.warn("------------------------------------------");
|
||||
e = new Error(log._("server.install.install-failed"));
|
||||
}
|
||||
}
|
||||
})
|
||||
if (e) {
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
}).catch(err => {
|
||||
// In case of error, reset activePromise to be resolvable
|
||||
activePromise = Promise.resolve();
|
||||
@@ -412,17 +447,29 @@ function uninstallModule(module) {
|
||||
log.info(log._("server.install.uninstalling",{name:module}));
|
||||
|
||||
var args = ['remove','--no-audit','--no-update-notifier','--no-fund','--save',module];
|
||||
log.trace(npmCommand + JSON.stringify(args));
|
||||
|
||||
exec.run(npmCommand,args,{
|
||||
cwd: installDir,
|
||||
},true).then(result => {
|
||||
let triggerPayload = {
|
||||
"module": module,
|
||||
"dir": installDir,
|
||||
}
|
||||
return hooks.trigger("preUninstall", triggerPayload).then(() => {
|
||||
// preUninstall passed
|
||||
// - run uninstall
|
||||
log.trace(npmCommand + JSON.stringify(args));
|
||||
return exec.run(npmCommand,args,{ cwd: installDir}, true)
|
||||
}).then(() => {
|
||||
log.info(log._("server.install.uninstalled",{name:module}));
|
||||
reportRemovedModules(list);
|
||||
library.removeExamplesDir(module);
|
||||
resolve(list);
|
||||
return hooks.trigger("postUninstall", triggerPayload).catch((err)=>{
|
||||
log.warn("------------------------------------------");
|
||||
log.warn(err.toString());
|
||||
log.warn("------------------------------------------");
|
||||
}).finally(() => {
|
||||
resolve(list);
|
||||
})
|
||||
}).catch(result => {
|
||||
var output = result.stderr;
|
||||
let output = result.stderr || result;
|
||||
log.warn(log._("server.install.uninstall-failed-long",{name:module}));
|
||||
log.warn("------------------------------------------");
|
||||
log.warn(output.toString());
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/registry",
|
||||
"version": "1.3.1",
|
||||
"version": "2.0.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,8 +16,8 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "1.3.1",
|
||||
"semver": "6.3.0",
|
||||
"@node-red/util": "2.0.0-beta.1",
|
||||
"semver": "7.3.5",
|
||||
"tar": "6.1.0",
|
||||
"uglify-js": "3.13.3"
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ var redUtil = require("@node-red/util").util;
|
||||
const events = require("@node-red/util").events;
|
||||
var flowUtil = require("./util");
|
||||
const context = require('../nodes/context');
|
||||
const hooks = require("../hooks");
|
||||
const hooks = require("@node-red/util").hooks;
|
||||
|
||||
var Subflow;
|
||||
var Log;
|
||||
|
@@ -20,7 +20,6 @@ var redNodes = require("./nodes");
|
||||
var flows = require("./flows");
|
||||
var storage = require("./storage");
|
||||
var library = require("./library");
|
||||
var hooks = require("./hooks");
|
||||
var plugins = require("./plugins");
|
||||
var settings = require("./settings");
|
||||
|
||||
@@ -29,7 +28,7 @@ var path = require('path');
|
||||
var fs = require("fs");
|
||||
var os = require("os");
|
||||
|
||||
const {log,i18n,events,exec,util} = require("@node-red/util");
|
||||
const {log,i18n,events,exec,util,hooks} = require("@node-red/util");
|
||||
|
||||
var runtimeMetricInterval = null;
|
||||
|
||||
@@ -181,6 +180,9 @@ function start() {
|
||||
if (settings.settingsFile) {
|
||||
log.info(log._("runtime.paths.settings",{path:settings.settingsFile}));
|
||||
}
|
||||
if (settings.httpRoot !== undefined) {
|
||||
log.warn(log._("server.deprecatedOption",{old:"httpRoot", new: "httpNodeRoot/httpAdminRoot"}));
|
||||
}
|
||||
if (settings.httpStatic) {
|
||||
log.info(log._("runtime.paths.httpStatic",{path:path.resolve(settings.httpStatic)}));
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@ var redUtil = require("@node-red/util").util;
|
||||
var Log = require("@node-red/util").log;
|
||||
var context = require("./context");
|
||||
var flows = require("../flows");
|
||||
const hooks = require("../hooks");
|
||||
const hooks = require("@node-red/util").hooks;
|
||||
|
||||
|
||||
const NOOP_SEND = function() {}
|
||||
|
@@ -38,6 +38,8 @@ var activeProject;
|
||||
|
||||
var globalGitUser = false;
|
||||
|
||||
var usingHostName = false;
|
||||
|
||||
function init(_settings, _runtime) {
|
||||
settings = _settings;
|
||||
runtime = _runtime;
|
||||
@@ -77,6 +79,7 @@ function init(_settings, _runtime) {
|
||||
} else {
|
||||
flowsFile = 'flows_'+require('os').hostname()+'.json';
|
||||
flowsFullPath = fspath.join(settings.userDir,flowsFile);
|
||||
usingHostName = true;
|
||||
}
|
||||
var ffExt = fspath.extname(flowsFullPath);
|
||||
var ffBase = fspath.basename(flowsFullPath,ffExt);
|
||||
@@ -526,7 +529,7 @@ async function getFlows() {
|
||||
if (projectsEnabled) {
|
||||
log.info(log._("storage.localfilesystem.projects.projects-directory", {projectsDirectory: projectsDir}));
|
||||
}
|
||||
|
||||
|
||||
if (activeProject) {
|
||||
// At this point activeProject will be a string, so go load it and
|
||||
// swap in an instance of Project
|
||||
@@ -541,6 +544,7 @@ async function getFlows() {
|
||||
} else {
|
||||
projectLogMessages.forEach(log.warn);
|
||||
}
|
||||
if (usingHostName) { log.warn(log._("storage.localfilesystem.warn_name")) };
|
||||
log.info(log._("storage.localfilesystem.flows-file",{path:flowsFullPath}));
|
||||
}
|
||||
}
|
||||
|
@@ -34,6 +34,7 @@
|
||||
"install-failed-not-found": "$t(server.install.install-failed-long) module not found",
|
||||
"install-failed-name": "$t(server.install.install-failed-long) invalid module name: __name__",
|
||||
"install-failed-url": "$t(server.install.install-failed-long) invalid url: __url__",
|
||||
"post-install-error": "Error running 'postInstall' hook:",
|
||||
"upgrading": "Upgrading module: __name__ to version: __version__",
|
||||
"upgraded": "Upgraded module: __name__. Restart Node-RED to use the new version",
|
||||
"upgrade-failed-not-found": "$t(server.install.install-failed-long) version not found",
|
||||
@@ -42,7 +43,7 @@
|
||||
"uninstall-failed-long": "Uninstall of module __name__ failed:",
|
||||
"uninstalled": "Uninstalled module: __name__"
|
||||
},
|
||||
"deprecatedOption": "Use of __old__ is deprecated. Use __new__ instead",
|
||||
"deprecatedOption": "Use of __old__ is DEPRECATED. Use __new__ instead",
|
||||
"unable-to-listen": "Unable to listen on __listenpath__",
|
||||
"port-in-use": "Error: port in use",
|
||||
"uncaught-exception": "Uncaught Exception:",
|
||||
@@ -50,7 +51,7 @@
|
||||
"now-running": "Server now running at __listenpath__",
|
||||
"failed-to-start": "Failed to start server:",
|
||||
"headless-mode": "Running in headless mode",
|
||||
"httpadminauth-deprecated": "use of httpAdminAuth is deprecated. Use adminAuth instead",
|
||||
"httpadminauth-deprecated": "Use of httpAdminAuth is DEPRECATED. Use adminAuth instead",
|
||||
"https": {
|
||||
"refresh-interval": "Refreshing https settings every __interval__ hours",
|
||||
"settings-refreshed": "Server https settings have been refreshed",
|
||||
@@ -159,6 +160,7 @@
|
||||
"restore": "Restoring __type__ file backup : __path__",
|
||||
"restore-fail": "Restoring __type__ file backup failed : __message__",
|
||||
"fsync-fail": "Flushing file __path__ to disk failed : __message__",
|
||||
"warn_name": "Flows file name not set. Generating name using hostname.",
|
||||
"projects": {
|
||||
"changing-project": "Setting active project : __project__",
|
||||
"active-project": "Active project : __project__",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/runtime",
|
||||
"version": "1.3.1",
|
||||
"version": "2.0.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,12 +16,12 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/registry": "1.3.1",
|
||||
"@node-red/util": "1.3.1",
|
||||
"@node-red/registry": "2.0.0-beta.1",
|
||||
"@node-red/util": "2.0.0-beta.1",
|
||||
"async-mutex": "0.3.1",
|
||||
"clone": "2.1.2",
|
||||
"express": "4.17.1",
|
||||
"fs-extra": "8.1.0",
|
||||
"fs-extra": "9.1.0",
|
||||
"json-stringify-safe": "5.0.1"
|
||||
}
|
||||
}
|
||||
|
10
packages/node_modules/@node-red/util/index.js
vendored
10
packages/node_modules/@node-red/util/index.js
vendored
@@ -19,6 +19,7 @@ const i18n = require("./lib/i18n");
|
||||
const util = require("./lib/util");
|
||||
const events = require("./lib/events");
|
||||
const exec = require("./lib/exec");
|
||||
const hooks = require("./lib/hooks");
|
||||
|
||||
/**
|
||||
* This module provides common utilities for the Node-RED runtime and editor
|
||||
@@ -69,5 +70,12 @@ module.exports = {
|
||||
* @mixes @node-red/util_exec
|
||||
* @memberof @node-red/util
|
||||
*/
|
||||
exec: exec
|
||||
exec: exec,
|
||||
|
||||
/**
|
||||
* Runtime hooks
|
||||
* @mixes @node-red/util_hooks
|
||||
* @memberof @node-red/util
|
||||
*/
|
||||
hooks: hooks
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
const Log = require("@node-red/util").log;
|
||||
const Log = require("./log.js");
|
||||
|
||||
const VALID_HOOKS = [
|
||||
// Message Routing Path
|
||||
@@ -8,14 +8,28 @@ const VALID_HOOKS = [
|
||||
"postDeliver",
|
||||
"onReceive",
|
||||
"postReceive",
|
||||
"onComplete"
|
||||
"onComplete",
|
||||
// Module install hooks
|
||||
"preInstall",
|
||||
"postInstall",
|
||||
"preUninstall",
|
||||
"postUninstall"
|
||||
]
|
||||
|
||||
|
||||
// Flags for what hooks have handlers registered
|
||||
let states = { }
|
||||
|
||||
// Hooks by id
|
||||
// Doubly-LinkedList of hooks by id.
|
||||
// - hooks[id] points to head of list
|
||||
// - each list item looks like:
|
||||
// {
|
||||
// cb: the callback function
|
||||
// location: filename/line of code that added the hook
|
||||
// previousHook: reference to previous hook in list
|
||||
// nextHook: reference to next hook in list
|
||||
// removed: a flag that is set if the item was removed
|
||||
// }
|
||||
let hooks = { }
|
||||
|
||||
// Hooks by label
|
||||
@@ -35,12 +49,12 @@ let labelledHooks = { }
|
||||
* - `postReceive` - passed a `ReceiveEvent` when the message has been given to the node's `input` handler(s)
|
||||
* - `onComplete` - passed a `CompleteEvent` when the node has completed with a message or logged an error
|
||||
*
|
||||
* @mixin @node-red/runtime_hooks
|
||||
* @mixin @node-red/util_hooks
|
||||
*/
|
||||
|
||||
/**
|
||||
* Register a handler to a named hook
|
||||
* @memberof @node-red/runtime_hooks
|
||||
* @memberof @node-red/util_hooks
|
||||
* @param {String} hookId - the name of the hook to attach to
|
||||
* @param {Function} callback - the callback function for the hook
|
||||
*/
|
||||
@@ -49,26 +63,39 @@ function add(hookId, callback) {
|
||||
if (VALID_HOOKS.indexOf(id) === -1) {
|
||||
throw new Error(`Invalid hook '${id}'`);
|
||||
}
|
||||
if (label) {
|
||||
if (labelledHooks[label] && labelledHooks[label][id]) {
|
||||
throw new Error("Hook "+hookId+" already registered")
|
||||
}
|
||||
labelledHooks[label] = labelledHooks[label]||{};
|
||||
labelledHooks[label][id] = callback;
|
||||
if (label && labelledHooks[label] && labelledHooks[label][id]) {
|
||||
throw new Error("Hook "+hookId+" already registered")
|
||||
}
|
||||
// Get location of calling code
|
||||
const stack = new Error().stack;
|
||||
const callModule = stack.split("\n")[2].split("(")[1].slice(0,-1);
|
||||
Log.debug(`Adding hook '${hookId}' from ${callModule}`);
|
||||
|
||||
hooks[id] = hooks[id] || [];
|
||||
hooks[id].push({cb:callback,location:callModule});
|
||||
const hookItem = {cb:callback, location: callModule, previousHook: null, nextHook: null }
|
||||
|
||||
let tailItem = hooks[id];
|
||||
if (tailItem === undefined) {
|
||||
hooks[id] = hookItem;
|
||||
} else {
|
||||
while(tailItem.nextHook !== null) {
|
||||
tailItem = tailItem.nextHook
|
||||
}
|
||||
tailItem.nextHook = hookItem;
|
||||
hookItem.previousHook = tailItem;
|
||||
}
|
||||
|
||||
if (label) {
|
||||
labelledHooks[label] = labelledHooks[label]||{};
|
||||
labelledHooks[label][id] = hookItem;
|
||||
}
|
||||
|
||||
// TODO: get rid of this;
|
||||
states[id] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a handled from a named hook
|
||||
* @memberof @node-red/runtime_hooks
|
||||
* @memberof @node-red/util_hooks
|
||||
* @param {String} hookId - the name of the hook event to remove - must be `name.label`
|
||||
*/
|
||||
function remove(hookId) {
|
||||
@@ -95,33 +122,66 @@ function remove(hookId) {
|
||||
}
|
||||
}
|
||||
|
||||
function removeHook(id,callback) {
|
||||
let i = hooks[id].findIndex(hook => hook.cb === callback);
|
||||
if (i !== -1) {
|
||||
hooks[id].splice(i,1);
|
||||
if (hooks[id].length === 0) {
|
||||
delete hooks[id];
|
||||
delete states[id];
|
||||
}
|
||||
function removeHook(id,hookItem) {
|
||||
let previousHook = hookItem.previousHook;
|
||||
let nextHook = hookItem.nextHook;
|
||||
|
||||
if (previousHook) {
|
||||
previousHook.nextHook = nextHook;
|
||||
} else {
|
||||
hooks[id] = nextHook;
|
||||
}
|
||||
if (nextHook) {
|
||||
nextHook.previousHook = previousHook;
|
||||
}
|
||||
hookItem.removed = true;
|
||||
if (!previousHook && !nextHook) {
|
||||
delete hooks[id];
|
||||
delete states[id];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function trigger(hookId, payload, done) {
|
||||
const hookStack = hooks[hookId];
|
||||
if (!hookStack || hookStack.length === 0) {
|
||||
done();
|
||||
return;
|
||||
let hookItem = hooks[hookId];
|
||||
if (!hookItem) {
|
||||
if (done) {
|
||||
done();
|
||||
return;
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
let i = 0;
|
||||
|
||||
if (!done) {
|
||||
return new Promise((resolve,reject) => {
|
||||
invokeStack(hookItem,payload,function(err) {
|
||||
if (err !== undefined && err !== false) {
|
||||
if (!(err instanceof Error)) {
|
||||
err = new Error(err);
|
||||
}
|
||||
err.hook = hookId
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(err);
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
invokeStack(hookItem,payload,done)
|
||||
}
|
||||
}
|
||||
function invokeStack(hookItem,payload,done) {
|
||||
function callNextHook(err) {
|
||||
if (i === hookStack.length || err) {
|
||||
if (!hookItem || err) {
|
||||
done(err);
|
||||
return;
|
||||
}
|
||||
const hook = hookStack[i++];
|
||||
const callback = hook.cb;
|
||||
if (hookItem.removed) {
|
||||
hookItem = hookItem.nextHook;
|
||||
callNextHook();
|
||||
return;
|
||||
}
|
||||
const callback = hookItem.cb;
|
||||
if (callback.length === 1) {
|
||||
try {
|
||||
let result = callback(payload);
|
||||
@@ -134,6 +194,7 @@ function trigger(hookId, payload, done) {
|
||||
result.then(handleResolve, callNextHook)
|
||||
return;
|
||||
}
|
||||
hookItem = hookItem.nextHook;
|
||||
callNextHook();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
@@ -148,15 +209,15 @@ function trigger(hookId, payload, done) {
|
||||
}
|
||||
}
|
||||
}
|
||||
callNextHook();
|
||||
|
||||
function handleResolve(result) {
|
||||
if (result === undefined) {
|
||||
hookItem = hookItem.nextHook;
|
||||
callNextHook();
|
||||
} else {
|
||||
done(result);
|
||||
}
|
||||
}
|
||||
callNextHook();
|
||||
}
|
||||
|
||||
function clear() {
|
||||
@@ -179,4 +240,4 @@ module.exports = {
|
||||
add,
|
||||
remove,
|
||||
trigger
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/util",
|
||||
"version": "1.3.1",
|
||||
"version": "2.0.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -16,7 +16,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"clone": "2.1.2",
|
||||
"i18next": "15.1.2",
|
||||
"i18next": "20.2.1",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"jsonata": "1.8.4",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
|
20
packages/node_modules/node-red/package.json
vendored
20
packages/node_modules/node-red/package.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "1.3.1",
|
||||
"version": "2.0.0-beta.1",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "http://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -31,24 +31,22 @@
|
||||
"flow"
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/editor-api": "1.3.1",
|
||||
"@node-red/runtime": "1.3.1",
|
||||
"@node-red/util": "1.3.1",
|
||||
"@node-red/nodes": "1.3.1",
|
||||
"@node-red/editor-api": "2.0.0-beta.1",
|
||||
"@node-red/runtime": "2.0.0-beta.1",
|
||||
"@node-red/util": "2.0.0-beta.1",
|
||||
"@node-red/nodes": "2.0.0-beta.1",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"express": "4.17.1",
|
||||
"fs-extra": "8.1.0",
|
||||
"fs-extra": "9.1.0",
|
||||
"node-red-admin": "^0.2.6",
|
||||
"node-red-node-rbe": "^0.5.0",
|
||||
"node-red-node-tail": "^0.3.0",
|
||||
"nopt": "5.0.0",
|
||||
"semver": "6.3.0"
|
||||
"semver": "7.3.5"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bcrypt": "3.0.6"
|
||||
"bcrypt": "5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
"node": ">=12"
|
||||
}
|
||||
}
|
||||
|
1
packages/node_modules/node-red/red.js
vendored
1
packages/node_modules/node-red/red.js
vendored
@@ -263,7 +263,6 @@ httpsPromise.then(function(startupHttps) {
|
||||
settings.httpAdminRoot = false;
|
||||
settings.httpNodeRoot = false;
|
||||
} else {
|
||||
settings.httpRoot = settings.httpRoot||"/";
|
||||
settings.disableEditor = settings.disableEditor||false;
|
||||
}
|
||||
|
||||
|
24
packages/node_modules/node-red/settings.js
vendored
24
packages/node_modules/node-red/settings.js
vendored
@@ -12,6 +12,13 @@
|
||||
**/
|
||||
|
||||
module.exports = {
|
||||
// The file containing the flows. If not set, it defaults to flows_<hostname>.json
|
||||
flowFile: 'flows.json',
|
||||
|
||||
// To enabled pretty-printing of the flow within the flow file, set the following
|
||||
// property to true:
|
||||
//flowFilePretty: true,
|
||||
|
||||
// the tcp port that the Node-RED web server is listening on
|
||||
uiPort: process.env.PORT || 1880,
|
||||
|
||||
@@ -46,6 +53,10 @@ module.exports = {
|
||||
// defaults to 10Mb
|
||||
//execMaxBufferSize: 10000000,
|
||||
|
||||
// The working directory to handle relative file paths from within the File nodes
|
||||
// defaults to the working directory of the Node-RED process.
|
||||
//fileWorkingDirectory: "",
|
||||
|
||||
// The maximum length, in characters, of any message sent to the debug sidebar tab
|
||||
debugMaxLength: 1000,
|
||||
|
||||
@@ -61,13 +72,6 @@ module.exports = {
|
||||
// Colourise the console output of the debug node
|
||||
//debugUseColors: true,
|
||||
|
||||
// The file containing the flows. If not set, it defaults to flows_<hostname>.json
|
||||
//flowFile: 'flows.json',
|
||||
|
||||
// To enabled pretty-printing of the flow within the flow file, set the following
|
||||
// property to true:
|
||||
//flowFilePretty: true,
|
||||
|
||||
// By default, credentials are encrypted in storage using a generated key. To
|
||||
// specify your own secret, set the following property.
|
||||
// If you want to disable encryption of credentials, set this property to false.
|
||||
@@ -96,10 +100,6 @@ module.exports = {
|
||||
// disabled.
|
||||
//httpNodeRoot: '/red-nodes',
|
||||
|
||||
// The following property can be used in place of 'httpAdminRoot' and 'httpNodeRoot',
|
||||
// to apply the same root to both parts.
|
||||
//httpRoot: '/red',
|
||||
|
||||
// When httpAdminRoot is used to move the UI to a different root path, the
|
||||
// following property can be used to identify a directory of static content
|
||||
// that should be served at http://localhost:1880/.
|
||||
@@ -110,7 +110,7 @@ module.exports = {
|
||||
//apiMaxLength: '5mb',
|
||||
|
||||
// If you installed the optional node-red-dashboard you can set it's path
|
||||
// relative to httpRoot
|
||||
// relative to httpNodeRoot
|
||||
// Other optional properties include
|
||||
// readOnly:{boolean},
|
||||
// middleware:{function or array}, (req,res,next) - http middleware
|
||||
|
@@ -18,6 +18,7 @@ var should = require("should");
|
||||
|
||||
var delayNode = require("nr-test-utils").require("@node-red/nodes/core/function/89-delay.js");
|
||||
var helper = require("node-red-node-test-helper");
|
||||
var RED = require("nr-test-utils").require("node-red/lib/red");
|
||||
|
||||
var GRACE_PERCENTAGE=10;
|
||||
|
||||
@@ -35,6 +36,7 @@ describe('delay Node', function() {
|
||||
});
|
||||
|
||||
afterEach(function(done) {
|
||||
RED.settings.nodeMessageBufferMaxLength = 0;
|
||||
helper.unload();
|
||||
helper.stopServer(done);
|
||||
});
|
||||
@@ -150,6 +152,7 @@ describe('delay Node', function() {
|
||||
* We send a message, take a timestamp then when the message is received by the helper node, we take another timestamp.
|
||||
* Then check if the message has been delayed by the expected amount.
|
||||
*/
|
||||
|
||||
it('delays the message in seconds', function(done) {
|
||||
genericDelayTest(0.5, "seconds", done);
|
||||
});
|
||||
@@ -176,14 +179,14 @@ describe('delay Node', function() {
|
||||
* @param nbUnit - the multiple of the unit, aLimit Message for nbUnit Seconds
|
||||
* @param runtimeInMillis - when to terminate run and count messages received
|
||||
*/
|
||||
function genericRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, done) {
|
||||
function genericRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, rateValue, done) {
|
||||
var flow = [{"id":"delayNode1","type":"delay","nbRateUnits":nbUnit,"name":"delayNode","pauseType":"rate","timeout":5,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper", wires:[]}];
|
||||
helper.load(delayNode, flow, function() {
|
||||
var delayNode1 = helper.getNode("delayNode1");
|
||||
var helperNode1 = helper.getNode("helperNode1");
|
||||
var receivedMessagesStack = [];
|
||||
var rate = 1000/aLimit;
|
||||
var rate = 1000 / aLimit * nbUnit;
|
||||
|
||||
var receiveTimestamp;
|
||||
|
||||
@@ -201,7 +204,7 @@ describe('delay Node', function() {
|
||||
|
||||
var i = 0;
|
||||
for (; i < possibleMaxMessageCount + 1; i++) {
|
||||
delayNode1.receive({payload:i});
|
||||
delayNode1.receive({ payload: i, rate: rateValue });
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
@@ -224,17 +227,22 @@ describe('delay Node', function() {
|
||||
}
|
||||
|
||||
it('limits the message rate to 1 per second', function(done) {
|
||||
genericRateLimitSECONDSTest(1, 1, 1500, done);
|
||||
genericRateLimitSECONDSTest(1, 1, 1500, null, done);
|
||||
});
|
||||
|
||||
it('limits the message rate to 1 per 2 seconds', function(done) {
|
||||
this.timeout(6000);
|
||||
genericRateLimitSECONDSTest(1, 2, 3000, done);
|
||||
genericRateLimitSECONDSTest(1, 2, 3000, null, done);
|
||||
});
|
||||
|
||||
it('limits the message rate to 2 per seconds, 2 seconds', function(done) {
|
||||
this.timeout(6000);
|
||||
genericRateLimitSECONDSTest(2, 1, 2100, done);
|
||||
genericRateLimitSECONDSTest(2, 1, 2100, null, done);
|
||||
});
|
||||
|
||||
it('limits the message rate using msg.rate', function (done) {
|
||||
RED.settings.nodeMessageBufferMaxLength = 3;
|
||||
genericRateLimitSECONDSTest(1, 1, 1500, 2000, done);
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -243,7 +251,7 @@ describe('delay Node', function() {
|
||||
* @param nbUnit - the multiple of the unit, aLimit Message for nbUnit Seconds
|
||||
* @param runtimeInMillis - when to terminate run and count messages received
|
||||
*/
|
||||
function dropRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, done) {
|
||||
function dropRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, rateValue, done) {
|
||||
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":5,"nbRateUnits":nbUnit,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"wires":[["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper", wires:[]}];
|
||||
helper.load(delayNode, flow, function() {
|
||||
@@ -269,7 +277,7 @@ describe('delay Node', function() {
|
||||
var possibleMaxMessageCount = Math.ceil(aLimit * (runtimeInMillis / 1000) + aLimit); // +aLimit as at the start of the 2nd period, we're allowing the 3rd burst
|
||||
|
||||
var i = 0;
|
||||
delayNode1.receive({payload:i});
|
||||
delayNode1.receive({ payload: i, rate: rateValue });
|
||||
i++;
|
||||
for (; i < possibleMaxMessageCount + 1; i++) {
|
||||
setTimeout(function() {
|
||||
@@ -306,17 +314,23 @@ describe('delay Node', function() {
|
||||
|
||||
it('limits the message rate to 1 per second, 4 seconds, with drop', function(done) {
|
||||
this.timeout(6000);
|
||||
dropRateLimitSECONDSTest(1, 1, 4000, done);
|
||||
dropRateLimitSECONDSTest(1, 1, 4000, null, done);
|
||||
});
|
||||
|
||||
it('limits the message rate to 1 per 2 seconds, 4 seconds, with drop', function(done) {
|
||||
this.timeout(6000);
|
||||
dropRateLimitSECONDSTest(1, 2, 4500, done);
|
||||
dropRateLimitSECONDSTest(1, 2, 4500, null, done);
|
||||
});
|
||||
|
||||
it('limits the message rate to 2 per second, 5 seconds, with drop', function(done) {
|
||||
this.timeout(6000);
|
||||
dropRateLimitSECONDSTest(2, 1, 5000, done);
|
||||
dropRateLimitSECONDSTest(2, 1, 5000, null, done);
|
||||
});
|
||||
|
||||
it('limits the message rate with drop using msg.rate', function (done) {
|
||||
this.timeout(6000);
|
||||
RED.settings.nodeMessageBufferMaxLength = 3;
|
||||
dropRateLimitSECONDSTest(2, 1, 5000, 1000, done);
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -719,7 +733,7 @@ describe('delay Node', function() {
|
||||
setImmediate( function() { delayNode1.receive({reset:true}); }); // reset the queue
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/* Messaging API support */
|
||||
function mapiDoneTestHelper(done, pauseType, drop, msgAndTimings) {
|
||||
const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
|
||||
@@ -747,7 +761,7 @@ describe('delay Node', function() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
it('calls done when queued message is emitted (type: delay)', function(done) {
|
||||
mapiDoneTestHelper(done, "delay", false, [{msg:{payload:1}, avr:1000, var:100}]);
|
||||
});
|
||||
|
@@ -483,7 +483,7 @@ describe('trigger node', function() {
|
||||
});
|
||||
|
||||
it('should be able to return things from flow and global context variables', function(done) {
|
||||
var spy = sinon.stub(RED.util, 'evaluateNodeProperty',
|
||||
var spy = sinon.stub(RED.util, 'evaluateNodeProperty').callsFake(
|
||||
function(arg1, arg2, arg3, arg4, arg5) { if (arg5) { arg5(null, arg1) } else { return arg1; } }
|
||||
);
|
||||
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1:"foo", op1type:"flow", op2:"bar", op2type:"global", duration:"20", wires:[["n2"]] },
|
||||
@@ -742,7 +742,7 @@ describe('trigger node', function() {
|
||||
|
||||
it('should be able to extend the delay', function(done) {
|
||||
this.timeout(5000); // add extra time for flake
|
||||
var spy = sinon.stub(RED.util, 'evaluateNodeProperty',
|
||||
var spy = sinon.stub(RED.util, 'evaluateNodeProperty').callsFake(
|
||||
function(arg1, arg2, arg3, arg4, arg5) { if (arg5) { arg5(null, arg1) } else { return arg1; } }
|
||||
);
|
||||
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", extend:"true", op1type:"flow", op1:"foo", op2:"bar", op2type:"global", duration:"100", wires:[["n2"]] },
|
||||
|
@@ -53,7 +53,7 @@ describe('exec node', function() {
|
||||
it('should exec a simple command', function(done) {
|
||||
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:false, append:"", oldrc:"false"},
|
||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||
var spy = sinon.stub(child_process, 'exec',
|
||||
var spy = sinon.stub(child_process, 'exec').callsFake(
|
||||
function(arg1, arg2, arg3, arg4) {
|
||||
// arg3(error,stdout,stderr);
|
||||
arg3(null,arg1,arg1.toUpperCase());
|
||||
@@ -137,7 +137,7 @@ describe('exec node', function() {
|
||||
it('should exec a simple command with extra parameters', function(done) {
|
||||
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:"payload", append:"more", oldrc:"false"},
|
||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||
var spy = sinon.stub(child_process, 'exec',
|
||||
var spy = sinon.stub(child_process, 'exec').callsFake(
|
||||
function(arg1, arg2, arg3, arg4) {
|
||||
//console.log(arg1);
|
||||
// arg3(error,stdout,stderr);
|
||||
@@ -193,7 +193,7 @@ describe('exec node', function() {
|
||||
it('should be able to return a binary buffer', function(done) {
|
||||
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:"more", oldrc:"false"},
|
||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||
var spy = sinon.stub(child_process, 'exec',
|
||||
var spy = sinon.stub(child_process, 'exec').callsFake(
|
||||
function(arg1, arg2, arg3, arg4) {
|
||||
//console.log(arg1);
|
||||
// arg3(error,stdout,stderr);
|
||||
@@ -325,7 +325,7 @@ describe('exec node', function() {
|
||||
it('should return the rc for a failing command', function(done) {
|
||||
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"error", addpay:false, append:"", oldrc:"false"},
|
||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||
var spy = sinon.stub(child_process, 'exec',
|
||||
var spy = sinon.stub(child_process, 'exec').callsFake(
|
||||
function(arg1, arg2, arg3, arg4) {
|
||||
//console.log(arg1);
|
||||
// arg3(error,stdout,stderr);
|
||||
@@ -388,7 +388,7 @@ describe('exec node', function() {
|
||||
it('should preserve existing properties on msg object', function(done) {
|
||||
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:false, append:"", oldrc:"false"},
|
||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||
var spy = sinon.stub(child_process, 'exec',
|
||||
var spy = sinon.stub(child_process, 'exec').callsFake(
|
||||
function(arg1, arg2, arg3, arg4) {
|
||||
// arg3(error,stdout,stderr);
|
||||
arg3(null,arg1,arg1.toUpperCase());
|
||||
@@ -455,7 +455,7 @@ describe('exec node', function() {
|
||||
it('should preserve existing properties on msg object for a failing command', function(done) {
|
||||
var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"error", addpay:false, append:"", oldrc:"false"},
|
||||
{id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
|
||||
var spy = sinon.stub(child_process, 'exec',
|
||||
var spy = sinon.stub(child_process, 'exec').callsFake(
|
||||
function(arg1, arg2, arg3, arg4) {
|
||||
// arg3(error,stdout,stderr);
|
||||
arg3({code: 1},arg1,arg1.toUpperCase());
|
||||
|
538
test/nodes/core/function/rbe_spec.js
Normal file
538
test/nodes/core/function/rbe_spec.js
Normal file
@@ -0,0 +1,538 @@
|
||||
|
||||
var should = require("should");
|
||||
var helper = require("node-red-node-test-helper");
|
||||
|
||||
var testNode = require("nr-test-utils").require("@node-red/nodes/core/function/rbe.js");
|
||||
|
||||
describe('rbe node', function() {
|
||||
"use strict";
|
||||
|
||||
beforeEach(function(done) {
|
||||
helper.startServer(done);
|
||||
});
|
||||
|
||||
afterEach(function(done) {
|
||||
helper.unload().then(function() {
|
||||
helper.stopServer(done);
|
||||
});
|
||||
});
|
||||
|
||||
it("should be loaded with correct defaults", function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", "name":"rbe1", "wires":[[]]}];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
n1.should.have.property("name", "rbe1");
|
||||
n1.should.have.property("func", "rbe");
|
||||
n1.should.have.property("gap", "0");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should only send output if payload changes - with multiple topics (rbe)', function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"rbe", gap:"0", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
if (c === 0) {
|
||||
msg.should.have.a.property("payload", "a");
|
||||
c+=1;
|
||||
}
|
||||
else if (c === 1) {
|
||||
msg.should.have.a.property("payload", 2);
|
||||
c+=1;
|
||||
}
|
||||
else if (c == 2) {
|
||||
msg.should.have.a.property("payload");
|
||||
msg.payload.should.have.a.property("b",1);
|
||||
msg.payload.should.have.a.property("c",2);
|
||||
c+=1;
|
||||
}
|
||||
else if (c == 3) {
|
||||
msg.should.have.a.property("payload",true);
|
||||
c+=1;
|
||||
}
|
||||
else if (c == 4) {
|
||||
msg.should.have.a.property("payload",false);
|
||||
c+=1;
|
||||
}
|
||||
else if (c == 5) {
|
||||
msg.should.have.a.property("payload",true);
|
||||
c+=1;
|
||||
}
|
||||
else if (c == 6) {
|
||||
msg.should.have.a.property("topic","a");
|
||||
msg.should.have.a.property("payload",1);
|
||||
c+=1;
|
||||
}
|
||||
else if (c == 7) {
|
||||
msg.should.have.a.property("topic","b");
|
||||
msg.should.have.a.property("payload",1);
|
||||
c+=1;
|
||||
}
|
||||
else {
|
||||
c += 1;
|
||||
msg.should.have.a.property("topic","c");
|
||||
msg.should.have.a.property("payload",1);
|
||||
done();
|
||||
}
|
||||
});
|
||||
n1.emit("input", {payload:"a"});
|
||||
n1.emit("input", {payload:"a"});
|
||||
n1.emit("input", {payload:"a"});
|
||||
n1.emit("input", {payload:2});
|
||||
n1.emit("input", {payload:2});
|
||||
n1.emit("input", {payload:{b:1,c:2}});
|
||||
n1.emit("input", {payload:{c:2,b:1}});
|
||||
n1.emit("input", {payload:{c:2,b:1}});
|
||||
n1.emit("input", {payload:true});
|
||||
n1.emit("input", {payload:false});
|
||||
n1.emit("input", {payload:false});
|
||||
n1.emit("input", {payload:true});
|
||||
|
||||
n1.emit("input", {topic:"a",payload:1});
|
||||
n1.emit("input", {topic:"b",payload:1});
|
||||
n1.emit("input", {topic:"b",payload:1});
|
||||
n1.emit("input", {topic:"a",payload:1});
|
||||
n1.emit("input", {topic:"c",payload:1});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
it('should ignore multiple topics if told to (rbe)', function(done) {
|
||||
var flow = [{id:"n1", type:"rbe", func:"rbe", gap:"0", septopics:false, wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
if (c === 0) {
|
||||
msg.should.have.a.property("payload", "a");
|
||||
c+=1;
|
||||
}
|
||||
else if (c === 1) {
|
||||
msg.should.have.a.property("payload", 2);
|
||||
c+=1;
|
||||
}
|
||||
else if (c == 2) {
|
||||
msg.should.have.a.property("payload");
|
||||
msg.payload.should.have.a.property("b",1);
|
||||
msg.payload.should.have.a.property("c",2);
|
||||
c+=1;
|
||||
}
|
||||
else if (c == 3) {
|
||||
msg.should.have.a.property("payload",true);
|
||||
c+=1;
|
||||
}
|
||||
else if (c == 4) {
|
||||
msg.should.have.a.property("payload",false);
|
||||
c+=1;
|
||||
}
|
||||
else if (c == 5) {
|
||||
msg.should.have.a.property("payload",true);
|
||||
c+=1;
|
||||
}
|
||||
else if (c == 6) {
|
||||
msg.should.have.a.property("topic","a");
|
||||
msg.should.have.a.property("payload",1);
|
||||
c+=1;
|
||||
}
|
||||
else {
|
||||
msg.should.have.a.property("topic","a");
|
||||
msg.should.have.a.property("payload",2);
|
||||
done();
|
||||
}
|
||||
});
|
||||
n1.emit("input", {topic:"a",payload:"a"});
|
||||
n1.emit("input", {topic:"b",payload:"a"});
|
||||
n1.emit("input", {topic:"c",payload:"a"});
|
||||
n1.emit("input", {topic:"a",payload:2});
|
||||
n1.emit("input", {topic:"b",payload:2});
|
||||
n1.emit("input", {payload:{b:1,c:2}});
|
||||
n1.emit("input", {payload:{c:2,b:1}});
|
||||
n1.emit("input", {payload:{c:2,b:1}});
|
||||
n1.emit("input", {topic:"a",payload:true});
|
||||
n1.emit("input", {topic:"b",payload:false});
|
||||
n1.emit("input", {topic:"c",payload:false});
|
||||
n1.emit("input", {topic:"d",payload:true});
|
||||
|
||||
n1.emit("input", {topic:"a",payload:1});
|
||||
n1.emit("input", {topic:"b",payload:1});
|
||||
n1.emit("input", {topic:"c",payload:1});
|
||||
n1.emit("input", {topic:"d",payload:1});
|
||||
n1.emit("input", {topic:"a",payload:2});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
it('should only send output if another chosen property changes - foo (rbe)', function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"rbe", gap:"0", property:"foo", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
if (c === 0) {
|
||||
msg.should.have.a.property("foo", "a");
|
||||
c+=1;
|
||||
}
|
||||
else if (c === 1) {
|
||||
msg.should.have.a.property("foo", "b");
|
||||
c+=1;
|
||||
}
|
||||
else {
|
||||
msg.should.have.a.property("foo");
|
||||
msg.foo.should.have.a.property("b",1);
|
||||
msg.foo.should.have.a.property("c",2);
|
||||
done();
|
||||
}
|
||||
});
|
||||
n1.emit("input", {foo:"a"});
|
||||
n1.emit("input", {payload:"a"});
|
||||
n1.emit("input", {foo:"a"});
|
||||
n1.emit("input", {payload:"a"});
|
||||
n1.emit("input", {foo:"a"});
|
||||
n1.emit("input", {foo:"b"});
|
||||
n1.emit("input", {foo:{b:1,c:2}});
|
||||
n1.emit("input", {foo:{c:2,b:1}});
|
||||
n1.emit("input", {payload:{c:2,b:1}});
|
||||
});
|
||||
});
|
||||
|
||||
it('should only send output if payload changes - ignoring first value (rbei)', function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"rbei", gap:"0", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
if (c === 0) {
|
||||
msg.should.have.a.property("payload", "b");
|
||||
msg.should.have.a.property("topic", "a");
|
||||
c+=1;
|
||||
}
|
||||
else if (c === 1) {
|
||||
msg.should.have.a.property("payload", "b");
|
||||
msg.should.have.a.property("topic", "b");
|
||||
c+=1;
|
||||
}
|
||||
else if (c === 2) {
|
||||
msg.should.have.a.property("payload", "c");
|
||||
msg.should.have.a.property("topic", "a");
|
||||
c+=1;
|
||||
}
|
||||
else {
|
||||
msg.should.have.a.property("payload", "c");
|
||||
msg.should.have.a.property("topic", "b");
|
||||
done();
|
||||
}
|
||||
|
||||
});
|
||||
n1.emit("input", {payload:"a", topic:"a"});
|
||||
n1.emit("input", {payload:"a", topic:"b"});
|
||||
n1.emit("input", {payload:"a", topic:"a"});
|
||||
n1.emit("input", {payload:"b", topic:"a"});
|
||||
n1.emit("input", {payload:"b", topic:"b"});
|
||||
n1.emit("input", {payload:"c", topic:"a"});
|
||||
n1.emit("input", {payload:"c", topic:"b"});
|
||||
});
|
||||
});
|
||||
|
||||
it('should send output if queue is reset (rbe)', function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"rbe", gap:"0", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
if (c === 0) {
|
||||
msg.should.have.a.property("payload", "a");
|
||||
c+=1;
|
||||
}
|
||||
else if (c === 1) {
|
||||
msg.should.have.a.property("payload", "b");
|
||||
c+=1;
|
||||
}
|
||||
else if (c === 2) {
|
||||
msg.should.have.a.property("payload", "a");
|
||||
c+=1;
|
||||
}
|
||||
else if (c === 3) {
|
||||
msg.should.have.a.property("payload", "b");
|
||||
c+=1;
|
||||
}
|
||||
else if (c === 4) {
|
||||
msg.should.have.a.property("payload", "b");
|
||||
c+=1;
|
||||
}
|
||||
else if (c === 5) {
|
||||
msg.should.have.a.property("payload", "b");
|
||||
c+=1;
|
||||
}
|
||||
else if (c === 6) {
|
||||
msg.should.have.a.property("payload", "a");
|
||||
c+=1;
|
||||
}
|
||||
else {
|
||||
msg.should.have.a.property("payload", "c");
|
||||
done();
|
||||
}
|
||||
});
|
||||
n1.emit("input", {topic:"a", payload:"a"});
|
||||
n1.emit("input", {topic:"a", payload:"a"});
|
||||
n1.emit("input", {topic:"b", payload:"b"});
|
||||
n1.emit("input", {reset:true}); // reset all
|
||||
n1.emit("input", {topic:"a", payload:"a"});
|
||||
n1.emit("input", {topic:"b", payload:"b"});
|
||||
n1.emit("input", {topic:"b", payload:"b"});
|
||||
n1.emit("input", {topic:"b", reset:""}); // reset b
|
||||
n1.emit("input", {topic:"b", payload:"b"});
|
||||
n1.emit("input", {topic:"a", payload:"a"});
|
||||
n1.emit("input", {reset:""}); // reset all
|
||||
n1.emit("input", {topic:"b", payload:"b"});
|
||||
n1.emit("input", {topic:"a", payload:"a"});
|
||||
n1.emit("input", {topic:"c"}); // don't reset a non topic
|
||||
n1.emit("input", {topic:"b", payload:"b"});
|
||||
n1.emit("input", {topic:"a", payload:"a"});
|
||||
n1.emit("input", {topic:"c", payload:"c"});
|
||||
});
|
||||
});
|
||||
|
||||
it('should only send output if x away from original value (deadbandEq)', function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"deadbandEq", gap:"10", inout:"out", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
c = c + 1;
|
||||
if (c === 1) {
|
||||
msg.should.have.a.property("payload", 0);
|
||||
}
|
||||
else if (c === 2) {
|
||||
msg.should.have.a.property("payload", 10);
|
||||
}
|
||||
else if (c == 3) {
|
||||
msg.should.have.a.property("payload", 20);
|
||||
done();
|
||||
}
|
||||
});
|
||||
n1.emit("input", {payload:0});
|
||||
n1.emit("input", {payload:2});
|
||||
n1.emit("input", {payload:4});
|
||||
n1.emit("input", {payload:6});
|
||||
n1.emit("input", {payload:8});
|
||||
n1.emit("input", {payload:10});
|
||||
n1.emit("input", {payload:15});
|
||||
n1.emit("input", {payload:20});
|
||||
});
|
||||
});
|
||||
|
||||
it('should only send output if more than x away from original value (deadband)', function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"deadband", gap:"10", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
c = c + 1;
|
||||
//console.log(c,msg);
|
||||
if (c === 1) {
|
||||
msg.should.have.a.property("payload", 0);
|
||||
}
|
||||
else if (c === 2) {
|
||||
msg.should.have.a.property("payload", 20);
|
||||
}
|
||||
else {
|
||||
msg.should.have.a.property("payload", "5 deg");
|
||||
done();
|
||||
}
|
||||
});
|
||||
n1.emit("input", {payload:0});
|
||||
n1.emit("input", {payload:2});
|
||||
n1.emit("input", {payload:4});
|
||||
n1.emit("input", {payload:"6 deg"});
|
||||
n1.emit("input", {payload:8});
|
||||
n1.emit("input", {payload:20});
|
||||
n1.emit("input", {payload:15});
|
||||
n1.emit("input", {payload:"5 deg"});
|
||||
});
|
||||
});
|
||||
|
||||
it('should only send output if more than x% away from original value (deadband)', function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"deadband", gap:"10%", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
c = c + 1;
|
||||
if (c === 1) {
|
||||
msg.should.have.a.property("payload", 100);
|
||||
}
|
||||
else if (c === 2) {
|
||||
msg.should.have.a.property("payload", 111);
|
||||
}
|
||||
else if (c === 3) {
|
||||
msg.should.have.a.property("payload", 135);
|
||||
done();
|
||||
}
|
||||
});
|
||||
n1.emit("input", {payload:100});
|
||||
n1.emit("input", {payload:95});
|
||||
n1.emit("input", {payload:105});
|
||||
n1.emit("input", {payload:111});
|
||||
n1.emit("input", {payload:120});
|
||||
n1.emit("input", {payload:135});
|
||||
});
|
||||
});
|
||||
|
||||
it('should warn if no number found in deadband mode', function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"deadband", gap:"10", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
c += 1;
|
||||
});
|
||||
setTimeout( function() {
|
||||
c.should.equal(0);
|
||||
helper.log().called.should.be.true;
|
||||
var logEvents = helper.log().args.filter(function (evt) {
|
||||
return evt[0].type == "rbe";
|
||||
});
|
||||
logEvents.should.have.length(1);
|
||||
var msg = logEvents[0][0];
|
||||
msg.should.have.property('level', helper.log().WARN);
|
||||
msg.should.have.property('id', 'n1');
|
||||
msg.should.have.property('type', 'rbe');
|
||||
msg.should.have.property('msg', 'rbe.warn.nonumber');
|
||||
done();
|
||||
},50);
|
||||
n1.emit("input", {payload:"banana"});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not send output if x away or greater from original value (narrowbandEq)', function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"narrowbandEq", gap:"10", inout:"out", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
c = c + 1;
|
||||
//console.log(c,msg);
|
||||
if (c === 1) {
|
||||
msg.should.have.a.property("payload", 0);
|
||||
}
|
||||
else if (c === 2) {
|
||||
msg.should.have.a.property("payload", 5);
|
||||
}
|
||||
else if (c === 3) {
|
||||
msg.should.have.a.property("payload", 10);
|
||||
done();
|
||||
}
|
||||
});
|
||||
n1.emit("input", {payload:0});
|
||||
n1.emit("input", {payload:10});
|
||||
n1.emit("input", {payload:5});
|
||||
n1.emit("input", {payload:15});
|
||||
n1.emit("input", {payload:10});
|
||||
n1.emit("input", {payload:20});
|
||||
n1.emit("input", {payload:25});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not send output if more than x away from original value (narrowband)', function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"narrowband", gap:"10", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
if (c === 0) {
|
||||
msg.should.have.a.property("payload", 0);
|
||||
}
|
||||
else if (c === 1) {
|
||||
msg.should.have.a.property("payload","6 deg");
|
||||
}
|
||||
else {
|
||||
msg.should.have.a.property("payload", "5 deg");
|
||||
done();
|
||||
}
|
||||
c += 1;
|
||||
});
|
||||
n1.emit("input", {payload:0});
|
||||
n1.emit("input", {payload:20});
|
||||
n1.emit("input", {payload:40});
|
||||
n1.emit("input", {payload:"6 deg"});
|
||||
n1.emit("input", {payload:18});
|
||||
n1.emit("input", {payload:20});
|
||||
n1.emit("input", {payload:50});
|
||||
n1.emit("input", {payload:"5 deg"});
|
||||
});
|
||||
});
|
||||
|
||||
it('should send output if gap is 0 and input doesnt change (narrowband)', function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"narrowband", gap:"0", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
if (c === 0) {
|
||||
msg.should.have.a.property("payload", 1);
|
||||
}
|
||||
else if (c === 4) {
|
||||
msg.should.have.a.property("payload",1);
|
||||
done();
|
||||
}
|
||||
c += 1;
|
||||
});
|
||||
n1.emit("input", {payload:1});
|
||||
n1.emit("input", {payload:1});
|
||||
n1.emit("input", {payload:1});
|
||||
n1.emit("input", {payload:1});
|
||||
n1.emit("input", {payload:0});
|
||||
n1.emit("input", {payload:1});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not send output if more than x away from original value (narrowband in step mode)', function(done) {
|
||||
var flow = [{"id":"n1", "type":"rbe", func:"narrowband", gap:"10", inout:"in", start:"500", wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"} ];
|
||||
helper.load(testNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
if (c === 0) {
|
||||
msg.should.have.a.property("payload", 55);
|
||||
}
|
||||
else if (c === 1) {
|
||||
msg.should.have.a.property("payload", 205);
|
||||
done();
|
||||
}
|
||||
c += 1;
|
||||
});
|
||||
n1.emit("input", {payload:50});
|
||||
n1.emit("input", {payload:55});
|
||||
n1.emit("input", {payload:200});
|
||||
n1.emit("input", {payload:205});
|
||||
});
|
||||
});
|
||||
});
|
@@ -22,6 +22,7 @@ var sinon = require("sinon");
|
||||
var iconv = require("iconv-lite");
|
||||
var fileNode = require("nr-test-utils").require("@node-red/nodes/core/storage/10-file.js");
|
||||
var helper = require("node-red-node-test-helper");
|
||||
var RED = require("nr-test-utils").require("node-red/lib/red");
|
||||
|
||||
describe('file Nodes', function() {
|
||||
|
||||
@@ -41,8 +42,9 @@ describe('file Nodes', function() {
|
||||
|
||||
describe('file out Node', function() {
|
||||
|
||||
var relativePathToFile = "50-file-test-file.txt";
|
||||
var resourcesDir = path.join(__dirname,"..","..","..","resources");
|
||||
var fileToTest = path.join(resourcesDir,"50-file-test-file.txt");
|
||||
var fileToTest = path.join(resourcesDir,relativePathToFile);
|
||||
var wait = 250;
|
||||
|
||||
beforeEach(function(done) {
|
||||
@@ -51,6 +53,7 @@ describe('file Nodes', function() {
|
||||
});
|
||||
|
||||
afterEach(function(done) {
|
||||
delete RED.settings.fileWorkingDirectory;
|
||||
fs.removeSync(path.join(resourcesDir,"file-out-node"));
|
||||
helper.unload().then(function() {
|
||||
//fs.unlinkSync(fileToTest);
|
||||
@@ -94,6 +97,30 @@ describe('file Nodes', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should write to a file using RED.settings.fileWorkingDirectory', function(done) {
|
||||
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":relativePathToFile, "appendNewline":false, "overwriteFile":true, wires: [["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper"}];
|
||||
helper.load(fileNode, flow, function() {
|
||||
RED.settings.fileWorkingDirectory = resourcesDir;
|
||||
var n1 = helper.getNode("fileNode1");
|
||||
var n2 = helper.getNode("helperNode1");
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
var f = fs.readFileSync(fileToTest);
|
||||
f.should.have.length(4);
|
||||
fs.unlinkSync(fileToTest);
|
||||
msg.should.have.property("payload", "test");
|
||||
done();
|
||||
}
|
||||
catch (e) {
|
||||
done(e);
|
||||
}
|
||||
});
|
||||
n1.receive({payload:"test"});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should write multi-byte string to a file', function(done) {
|
||||
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":true, wires: [["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper"}];
|
||||
@@ -391,7 +418,7 @@ describe('file Nodes', function() {
|
||||
|
||||
it('should fail to write to a ro file', function(done) {
|
||||
// Stub file write so we can make writes fail
|
||||
var spy = sinon.stub(fs, 'createWriteStream', function(arg1,arg2) {
|
||||
var spy = sinon.stub(fs, 'createWriteStream').callsFake(function(arg1,arg2) {
|
||||
var ws = {};
|
||||
ws.on = function(e,d) { throw("Stub error message"); }
|
||||
ws.write = function(e,d) { }
|
||||
@@ -421,7 +448,7 @@ describe('file Nodes', function() {
|
||||
|
||||
it('should fail to append to a ro file', function(done) {
|
||||
// Stub file write so we can make writes fail
|
||||
var spy = sinon.stub(fs, 'createWriteStream', function(arg1,arg2) {
|
||||
var spy = sinon.stub(fs, 'createWriteStream').callsFake(function(arg1,arg2) {
|
||||
var ws = {};
|
||||
ws.on = function(e,d) { throw("Stub error message"); }
|
||||
ws.write = function(e,d) { }
|
||||
@@ -451,7 +478,7 @@ describe('file Nodes', function() {
|
||||
|
||||
it('should cope with failing to delete a file', function(done) {
|
||||
// Stub file write so we can make writes fail
|
||||
var spy = sinon.stub(fs, 'unlink', function(arg,arg2) { arg2(new Error("Stub error message")); });
|
||||
var spy = sinon.stub(fs, 'unlink').callsFake(function(arg,arg2) { arg2(new Error("Stub error message")); });
|
||||
|
||||
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":true, "overwriteFile":"delete"}];
|
||||
helper.load(fileNode, flow, function() {
|
||||
@@ -477,7 +504,7 @@ describe('file Nodes', function() {
|
||||
it('should fail to create a new directory if not asked to do so (append)', function(done) {
|
||||
// Stub file write so we can make writes fail
|
||||
var fileToTest2 = path.join(resourcesDir,"file-out-node","50-file-test-file.txt");
|
||||
//var spy = sinon.stub(fs, 'appendFile', function(arg,arg2,arg3,arg4){ arg4(new Error("Stub error message")); });
|
||||
//var spy = sinon.stub(fs, 'appendFile').callsFake(function(arg,arg2,arg3,arg4){ arg4(new Error("Stub error message")); });
|
||||
|
||||
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest2, "appendNewline":true, "overwriteFile":false}];
|
||||
helper.load(fileNode, flow, function() {
|
||||
@@ -508,7 +535,7 @@ describe('file Nodes', function() {
|
||||
}
|
||||
// Stub file write so we can make writes fail
|
||||
var fileToTest2 = path.join(resourcesDir,"file-out-node","50-file-test-file.txt");
|
||||
var spy = sinon.stub(fs, "ensureDir", function(arg1,arg2,arg3,arg4) { arg2(null); });
|
||||
var spy = sinon.stub(fs, "ensureDir").callsFake(function(arg1,arg2,arg3,arg4) { arg2(null); });
|
||||
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest2, "appendNewline":true, "overwriteFile":false, "createDir":true}];
|
||||
helper.load(fileNode, flow, function() {
|
||||
var n1 = helper.getNode("fileNode1");
|
||||
@@ -531,7 +558,7 @@ describe('file Nodes', function() {
|
||||
it('should fail to create a new directory if not asked to do so (overwrite)', function(done) {
|
||||
// Stub file write so we can make writes fail
|
||||
var fileToTest2 = path.join(resourcesDir,"file-out-node","50-file-test-file.txt");
|
||||
//var spy = sinon.stub(fs, 'appendFile', function(arg,arg2,arg3,arg4){ arg4(new Error("Stub error message")); });
|
||||
//var spy = sinon.stub(fs, 'appendFile').callsFake(function(arg,arg2,arg3,arg4){ arg4(new Error("Stub error message")); });
|
||||
|
||||
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest2, "appendNewline":false, "overwriteFile":true}];
|
||||
helper.load(fileNode, flow, function() {
|
||||
@@ -557,7 +584,7 @@ describe('file Nodes', function() {
|
||||
it('should try to create a new directory if asked to do so (overwrite)', function(done) {
|
||||
// Stub file write so we can make writes fail
|
||||
var fileToTest2 = path.join(resourcesDir,"file-out-node","50-file-test-file.txt");
|
||||
var spy = sinon.stub(fs, "ensureDir", function(arg1,arg2,arg3,arg4) { arg2(null); });
|
||||
var spy = sinon.stub(fs, "ensureDir").callsFake(function(arg1,arg2,arg3,arg4) { arg2(null); });
|
||||
|
||||
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest2, "appendNewline":true, "overwriteFile":true, "createDir":true}];
|
||||
helper.load(fileNode, flow, function() {
|
||||
@@ -1036,9 +1063,10 @@ describe('file Nodes', function() {
|
||||
|
||||
describe('file in Node', function() {
|
||||
|
||||
var relativePathToFile = "50-file-test-file.txt";
|
||||
var resourcesDir = path.join(__dirname,"..","..","..","resources");
|
||||
var fileToTest = path.join(resourcesDir,"50-file-test-file.txt");
|
||||
var fileToTest2 = "\t"+path.join(resourcesDir,"50-file-test-file.txt")+"\r\n";
|
||||
var fileToTest = path.join(resourcesDir,relativePathToFile);
|
||||
var fileToTest2 = "\t"+path.join(resourcesDir,relativePathToFile)+"\r\n";
|
||||
var wait = 150;
|
||||
|
||||
beforeEach(function(done) {
|
||||
@@ -1047,6 +1075,7 @@ describe('file Nodes', function() {
|
||||
});
|
||||
|
||||
afterEach(function(done) {
|
||||
delete RED.settings.fileWorkingDirectory;
|
||||
helper.unload().then(function() {
|
||||
fs.unlinkSync(fileToTest);
|
||||
helper.stopServer(done);
|
||||
@@ -1100,6 +1129,30 @@ describe('file Nodes', function() {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should read in a file using fileWorkingDirectory to set cwd', function(done) {
|
||||
var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "filename":relativePathToFile, "format":"utf8", wires:[["n2"]]},
|
||||
{id:"n2", type:"helper"}];
|
||||
helper.load(fileNode, flow, function() {
|
||||
RED.settings.fileWorkingDirectory = resourcesDir;
|
||||
var n1 = helper.getNode("fileInNode1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.property('payload');
|
||||
msg.payload.should.be.a.String();
|
||||
msg.payload.should.have.length(40)
|
||||
msg.payload.should.equal("File message line 1\nFile message line 2\n");
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
n1.receive({payload:""});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should read in a file ending in cr and output a utf8 string', function(done) {
|
||||
var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "filename":fileToTest2, "format":"utf8", wires:[["n2"]]},
|
||||
{id:"n2", type:"helper"}];
|
||||
|
@@ -45,35 +45,35 @@ describe("api/admin/index", function() {
|
||||
};
|
||||
before(function() {
|
||||
mockList.forEach(function(m) {
|
||||
sinon.stub(m,"init",function(){});
|
||||
sinon.stub(m,"init").callsFake(function(){});
|
||||
});
|
||||
sinon.stub(auth,"needsPermission", function(permission) {
|
||||
sinon.stub(auth,"needsPermission").callsFake(function(permission) {
|
||||
return function(req,res,next) {
|
||||
permissionChecks[permission] = (permissionChecks[permission]||0)+1;
|
||||
next();
|
||||
};
|
||||
});
|
||||
|
||||
sinon.stub(flows,"get",stubApp);
|
||||
sinon.stub(flows,"post",stubApp);
|
||||
sinon.stub(flows,"get").callsFake(stubApp);
|
||||
sinon.stub(flows,"post").callsFake(stubApp);
|
||||
|
||||
sinon.stub(flow,"get",stubApp);
|
||||
sinon.stub(flow,"post",stubApp);
|
||||
sinon.stub(flow,"delete",stubApp);
|
||||
sinon.stub(flow,"put",stubApp);
|
||||
sinon.stub(flow,"get").callsFake(stubApp);
|
||||
sinon.stub(flow,"post").callsFake(stubApp);
|
||||
sinon.stub(flow,"delete").callsFake(stubApp);
|
||||
sinon.stub(flow,"put").callsFake(stubApp);
|
||||
|
||||
sinon.stub(nodes,"getAll",stubApp);
|
||||
sinon.stub(nodes,"post",stubApp);
|
||||
sinon.stub(nodes,"getModule",stubApp);
|
||||
sinon.stub(nodes,"putModule",stubApp);
|
||||
sinon.stub(nodes,"delete",stubApp);
|
||||
sinon.stub(nodes,"getSet",stubApp);
|
||||
sinon.stub(nodes,"putSet",stubApp);
|
||||
sinon.stub(nodes,"getModuleCatalog",stubApp);
|
||||
sinon.stub(nodes,"getModuleCatalogs",stubApp);
|
||||
sinon.stub(nodes,"getAll").callsFake(stubApp);
|
||||
sinon.stub(nodes,"post").callsFake(stubApp);
|
||||
sinon.stub(nodes,"getModule").callsFake(stubApp);
|
||||
sinon.stub(nodes,"putModule").callsFake(stubApp);
|
||||
sinon.stub(nodes,"delete").callsFake(stubApp);
|
||||
sinon.stub(nodes,"getSet").callsFake(stubApp);
|
||||
sinon.stub(nodes,"putSet").callsFake(stubApp);
|
||||
sinon.stub(nodes,"getModuleCatalog").callsFake(stubApp);
|
||||
sinon.stub(nodes,"getModuleCatalogs").callsFake(stubApp);
|
||||
|
||||
sinon.stub(context,"get",stubApp);
|
||||
sinon.stub(context,"delete",stubApp);
|
||||
sinon.stub(context,"get").callsFake(stubApp);
|
||||
sinon.stub(context,"delete").callsFake(stubApp);
|
||||
});
|
||||
after(function() {
|
||||
mockList.forEach(function(m) {
|
||||
|
@@ -41,7 +41,7 @@ describe("api/admin/nodes", function() {
|
||||
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
|
||||
app.get("/getIcons",nodes.getIcons);
|
||||
app.delete(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.delete);
|
||||
sinon.stub(apiUtil,"determineLangFromHeaders", function() {
|
||||
sinon.stub(apiUtil,"determineLangFromHeaders").callsFake(function() {
|
||||
return "en-US";
|
||||
});
|
||||
});
|
||||
|
@@ -29,7 +29,7 @@ var theme = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme");
|
||||
|
||||
describe("api/editor/settings", function() {
|
||||
before(function() {
|
||||
sinon.stub(theme,"settings",function() { return { existing: 123, test: 456 };});
|
||||
sinon.stub(theme,"settings").callsFake(function() { return { existing: 123, test: 456 };});
|
||||
app = express();
|
||||
app.use(bodyParser.json());
|
||||
app.get("/settings",info.runtimeSettings);
|
||||
|
@@ -58,7 +58,7 @@ describe("api/auth/index",function() {
|
||||
|
||||
describe("revoke", function() {
|
||||
it("revokes a token", function(done) {
|
||||
var revokeToken = sinon.stub(Tokens,"revoke",function() {
|
||||
var revokeToken = sinon.stub(Tokens,"revoke").callsFake(function() {
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
@@ -79,8 +79,8 @@ describe("api/auth/index",function() {
|
||||
|
||||
describe("login", function() {
|
||||
beforeEach(function() {
|
||||
sinon.stub(Tokens,"init",function(){});
|
||||
sinon.stub(Users,"init",function(){});
|
||||
sinon.stub(Tokens,"init").callsFake(function(){});
|
||||
sinon.stub(Users,"init").callsFake(function(){});
|
||||
});
|
||||
afterEach(function() {
|
||||
Tokens.init.restore();
|
||||
@@ -119,8 +119,8 @@ describe("api/auth/index",function() {
|
||||
});
|
||||
describe("needsPermission", function() {
|
||||
beforeEach(function() {
|
||||
sinon.stub(Tokens,"init",function(){});
|
||||
sinon.stub(Users,"init",function(){});
|
||||
sinon.stub(Tokens,"init").callsFake(function(){});
|
||||
sinon.stub(Users,"init").callsFake(function(){});
|
||||
});
|
||||
afterEach(function() {
|
||||
Tokens.init.restore();
|
||||
@@ -135,7 +135,7 @@ describe("api/auth/index",function() {
|
||||
|
||||
|
||||
it('no-ops if adminAuth not set', function(done) {
|
||||
sinon.stub(passport,"authenticate",function(scopes,opts) {
|
||||
sinon.stub(passport,"authenticate").callsFake(function(scopes,opts) {
|
||||
return function(req,res,next) {
|
||||
}
|
||||
});
|
||||
@@ -147,12 +147,12 @@ describe("api/auth/index",function() {
|
||||
})
|
||||
});
|
||||
it('skips auth if req.user undefined', function(done) {
|
||||
sinon.stub(passport,"authenticate",function(scopes,opts) {
|
||||
sinon.stub(passport,"authenticate").callsFake(function(scopes,opts) {
|
||||
return function(req,res,next) {
|
||||
next();
|
||||
}
|
||||
});
|
||||
sinon.stub(Permissions,"hasPermission",function(perm) { return true });
|
||||
sinon.stub(Permissions,"hasPermission").callsFake(function(perm) { return true });
|
||||
auth.init({adminAuth:{}});
|
||||
var func = auth.needsPermission("foo");
|
||||
func({user:null},{},function() {
|
||||
@@ -167,12 +167,12 @@ describe("api/auth/index",function() {
|
||||
});
|
||||
|
||||
it('passes for valid user permission', function(done) {
|
||||
sinon.stub(passport,"authenticate",function(scopes,opts) {
|
||||
sinon.stub(passport,"authenticate").callsFake(function(scopes,opts) {
|
||||
return function(req,res,next) {
|
||||
next();
|
||||
}
|
||||
});
|
||||
sinon.stub(Permissions,"hasPermission",function(perm) { return true });
|
||||
sinon.stub(Permissions,"hasPermission").callsFake(function(perm) { return true });
|
||||
auth.init({adminAuth:{}});
|
||||
var func = auth.needsPermission("foo");
|
||||
func({user:true,authInfo: { scope: "read"}},{},function() {
|
||||
@@ -189,12 +189,12 @@ describe("api/auth/index",function() {
|
||||
});
|
||||
|
||||
it('rejects for invalid user permission', function(done) {
|
||||
sinon.stub(passport,"authenticate",function(scopes,opts) {
|
||||
sinon.stub(passport,"authenticate").callsFake(function(scopes,opts) {
|
||||
return function(req,res,next) {
|
||||
next();
|
||||
}
|
||||
});
|
||||
sinon.stub(Permissions,"hasPermission",function(perm) { return false });
|
||||
sinon.stub(Permissions,"hasPermission").callsFake(function(perm) { return false });
|
||||
auth.init({adminAuth:{}});
|
||||
var func = auth.needsPermission("foo");
|
||||
func({user:true,authInfo: { scope: "read"}},{
|
||||
|
@@ -35,7 +35,7 @@ describe("api/auth/strategies", function() {
|
||||
});
|
||||
|
||||
it('Handles authentication failure',function(done) {
|
||||
userAuthentication = sinon.stub(Users,"authenticate",function(username,password) {
|
||||
userAuthentication = sinon.stub(Users,"authenticate").callsFake(function(username,password) {
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
|
||||
@@ -51,7 +51,7 @@ describe("api/auth/strategies", function() {
|
||||
});
|
||||
|
||||
it('Handles scope overreach',function(done) {
|
||||
userAuthentication = sinon.stub(Users,"authenticate",function(username,password) {
|
||||
userAuthentication = sinon.stub(Users,"authenticate").callsFake(function(username,password) {
|
||||
return Promise.resolve({username:"user",permissions:"read"});
|
||||
});
|
||||
|
||||
@@ -67,11 +67,11 @@ describe("api/auth/strategies", function() {
|
||||
});
|
||||
|
||||
it('Creates new token on authentication success',function(done) {
|
||||
userAuthentication = sinon.stub(Users,"authenticate",function(username,password) {
|
||||
userAuthentication = sinon.stub(Users,"authenticate").callsFake(function(username,password) {
|
||||
return Promise.resolve({username:"user",permissions:"*"});
|
||||
});
|
||||
var tokenDetails = {};
|
||||
var tokenCreate = sinon.stub(Tokens,"create",function(username,client,scope) {
|
||||
var tokenCreate = sinon.stub(Tokens,"create").callsFake(function(username,client,scope) {
|
||||
tokenDetails.username = username;
|
||||
tokenDetails.client = client;
|
||||
tokenDetails.scope = scope;
|
||||
@@ -98,7 +98,7 @@ describe("api/auth/strategies", function() {
|
||||
|
||||
describe("Anonymous Strategy", function() {
|
||||
it('Succeeds if anon user enabled',function(done) {
|
||||
var userDefault = sinon.stub(Users,"default",function() {
|
||||
var userDefault = sinon.stub(Users,"default").callsFake(function() {
|
||||
return Promise.resolve("anon");
|
||||
});
|
||||
strategies.anonymousStrategy._success = strategies.anonymousStrategy.success;
|
||||
@@ -111,7 +111,7 @@ describe("api/auth/strategies", function() {
|
||||
strategies.anonymousStrategy.authenticate({});
|
||||
});
|
||||
it('Fails if anon user not enabled',function(done) {
|
||||
var userDefault = sinon.stub(Users,"default",function() {
|
||||
var userDefault = sinon.stub(Users,"default").callsFake(function() {
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
strategies.anonymousStrategy._fail = strategies.anonymousStrategy.fail;
|
||||
@@ -130,10 +130,10 @@ describe("api/auth/strategies", function() {
|
||||
|
||||
describe("Tokens Strategy", function() {
|
||||
it('Succeeds if tokens user enabled custom header',function(done) {
|
||||
var userTokens = sinon.stub(Users,"tokens",function(token) {
|
||||
var userTokens = sinon.stub(Users,"tokens").callsFake(function(token) {
|
||||
return Promise.resolve("tokens-"+token);
|
||||
});
|
||||
var userTokenHeader = sinon.stub(Users,"tokenHeader",function(token) {
|
||||
var userTokenHeader = sinon.stub(Users,"tokenHeader").callsFake(function(token) {
|
||||
return "x-test-token";
|
||||
});
|
||||
strategies.tokensStrategy._success = strategies.tokensStrategy.success;
|
||||
@@ -146,10 +146,10 @@ describe("api/auth/strategies", function() {
|
||||
strategies.tokensStrategy.authenticate({headers:{"x-test-token":"1234"}});
|
||||
});
|
||||
it('Succeeds if tokens user enabled default header',function(done) {
|
||||
var userTokens = sinon.stub(Users,"tokens",function(token) {
|
||||
var userTokens = sinon.stub(Users,"tokens").callsFake(function(token) {
|
||||
return Promise.resolve("tokens-"+token);
|
||||
});
|
||||
var userTokenHeader = sinon.stub(Users,"tokenHeader",function(token) {
|
||||
var userTokenHeader = sinon.stub(Users,"tokenHeader").callsFake(function(token) {
|
||||
return "authorization";
|
||||
});
|
||||
strategies.tokensStrategy._success = strategies.tokensStrategy.success;
|
||||
@@ -162,10 +162,10 @@ describe("api/auth/strategies", function() {
|
||||
strategies.tokensStrategy.authenticate({headers:{"authorization":"Bearer 1234"}});
|
||||
});
|
||||
it('Fails if tokens user not enabled',function(done) {
|
||||
var userTokens = sinon.stub(Users,"tokens",function() {
|
||||
var userTokens = sinon.stub(Users,"tokens").callsFake(function() {
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
var userTokenHeader = sinon.stub(Users,"tokenHeader",function(token) {
|
||||
var userTokenHeader = sinon.stub(Users,"tokenHeader").callsFake(function(token) {
|
||||
return "authorization";
|
||||
});
|
||||
strategies.tokensStrategy._fail = strategies.tokensStrategy.fail;
|
||||
@@ -185,7 +185,7 @@ describe("api/auth/strategies", function() {
|
||||
|
||||
describe("Bearer Strategy", function() {
|
||||
it('Rejects invalid token',function(done) {
|
||||
var getToken = sinon.stub(Tokens,"get",function(token) {
|
||||
var getToken = sinon.stub(Tokens,"get").callsFake(function(token) {
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
|
||||
@@ -202,10 +202,10 @@ describe("api/auth/strategies", function() {
|
||||
});
|
||||
});
|
||||
it('Accepts valid token',function(done) {
|
||||
var getToken = sinon.stub(Tokens,"get",function(token) {
|
||||
var getToken = sinon.stub(Tokens,"get").callsFake(function(token) {
|
||||
return Promise.resolve({user:"user",scope:"scope"});
|
||||
});
|
||||
var getUser = sinon.stub(Users,"get",function(username) {
|
||||
var getUser = sinon.stub(Users,"get").callsFake(function(username) {
|
||||
return Promise.resolve("aUser");
|
||||
});
|
||||
|
||||
@@ -224,10 +224,10 @@ describe("api/auth/strategies", function() {
|
||||
});
|
||||
});
|
||||
it('Fail if no user for token',function(done) {
|
||||
var getToken = sinon.stub(Tokens,"get",function(token) {
|
||||
var getToken = sinon.stub(Tokens,"get").callsFake(function(token) {
|
||||
return Promise.resolve({user:"user",scope:"scope"});
|
||||
});
|
||||
var getUser = sinon.stub(Users,"get",function(username) {
|
||||
var getUser = sinon.stub(Users,"get").callsFake(function(username) {
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
|
||||
@@ -250,7 +250,7 @@ describe("api/auth/strategies", function() {
|
||||
describe("Client Password Strategy", function() {
|
||||
it('Accepts valid client',function(done) {
|
||||
var testClient = {id:"node-red-editor",secret:"not_available"};
|
||||
var getClient = sinon.stub(Clients,"get",function(client) {
|
||||
var getClient = sinon.stub(Clients,"get").callsFake(function(client) {
|
||||
return Promise.resolve(testClient);
|
||||
});
|
||||
|
||||
@@ -268,7 +268,7 @@ describe("api/auth/strategies", function() {
|
||||
});
|
||||
it('Rejects invalid client secret',function(done) {
|
||||
var testClient = {id:"node-red-editor",secret:"not_available"};
|
||||
var getClient = sinon.stub(Clients,"get",function(client) {
|
||||
var getClient = sinon.stub(Clients,"get").callsFake(function(client) {
|
||||
return Promise.resolve(testClient);
|
||||
});
|
||||
|
||||
@@ -285,7 +285,7 @@ describe("api/auth/strategies", function() {
|
||||
});
|
||||
});
|
||||
it('Rejects invalid client id',function(done) {
|
||||
var getClient = sinon.stub(Clients,"get",function(client) {
|
||||
var getClient = sinon.stub(Clients,"get").callsFake(function(client) {
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
strategies.clientPasswordStrategy("invalid_id","invalid_secret",function(err,client) {
|
||||
@@ -303,7 +303,7 @@ describe("api/auth/strategies", function() {
|
||||
|
||||
var userAuthentication;
|
||||
it('Blocks after 5 failures',function(done) {
|
||||
userAuthentication = sinon.stub(Users,"authenticate",function(username,password) {
|
||||
userAuthentication = sinon.stub(Users,"authenticate").callsFake(function(username,password) {
|
||||
return Promise.resolve(null);
|
||||
});
|
||||
for (var z=0; z<5; z++) {
|
||||
|
@@ -58,7 +58,7 @@ describe("api/editor/comms", function() {
|
||||
var url;
|
||||
var port;
|
||||
before(function(done) {
|
||||
sinon.stub(Users,"default",function() { return Promise.resolve(null);});
|
||||
sinon.stub(Users,"default").callsFake(function() { return Promise.resolve(null);});
|
||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||
comms.init(server, {}, {comms: mockComms});
|
||||
server.listen(listenPort, address);
|
||||
@@ -126,7 +126,7 @@ describe("api/editor/comms", function() {
|
||||
var url;
|
||||
var port;
|
||||
before(function(done) {
|
||||
sinon.stub(Users,"default",function() { return Promise.resolve(null);});
|
||||
sinon.stub(Users,"default").callsFake(function() { return Promise.resolve(null);});
|
||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||
comms.init(server, {disableEditor:true}, {comms: mockComms});
|
||||
server.listen(listenPort, address);
|
||||
@@ -164,7 +164,7 @@ describe("api/editor/comms", function() {
|
||||
var url;
|
||||
var port;
|
||||
before(function(done) {
|
||||
sinon.stub(Users,"default",function() { return Promise.resolve(null);});
|
||||
sinon.stub(Users,"default").callsFake(function() { return Promise.resolve(null);});
|
||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||
comms.init(server, {httpAdminRoot:"/adminPath"}, {comms: mockComms});
|
||||
server.listen(listenPort, address);
|
||||
@@ -202,7 +202,7 @@ describe("api/editor/comms", function() {
|
||||
var url;
|
||||
var port;
|
||||
before(function(done) {
|
||||
sinon.stub(Users,"default",function() { return Promise.resolve(null);});
|
||||
sinon.stub(Users,"default").callsFake(function() { return Promise.resolve(null);});
|
||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||
comms.init(server, {httpAdminRoot:"/adminPath/"}, {comms: mockComms});
|
||||
server.listen(listenPort, address);
|
||||
@@ -240,7 +240,7 @@ describe("api/editor/comms", function() {
|
||||
var url;
|
||||
var port;
|
||||
before(function(done) {
|
||||
sinon.stub(Users,"default",function() { return Promise.resolve(null);});
|
||||
sinon.stub(Users,"default").callsFake(function() { return Promise.resolve(null);});
|
||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||
comms.init(server, {httpAdminRoot:"adminPath"}, {comms: mockComms});
|
||||
server.listen(listenPort, address);
|
||||
@@ -278,7 +278,7 @@ describe("api/editor/comms", function() {
|
||||
var url;
|
||||
var port;
|
||||
before(function(done) {
|
||||
sinon.stub(Users,"default",function() { return Promise.resolve(null);});
|
||||
sinon.stub(Users,"default").callsFake(function() { return Promise.resolve(null);});
|
||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||
comms.init(server, {webSocketKeepAliveTime: 100}, {comms: mockComms});
|
||||
server.listen(listenPort, address);
|
||||
@@ -344,22 +344,22 @@ describe("api/editor/comms", function() {
|
||||
var getToken;
|
||||
var getUserToken;
|
||||
before(function(done) {
|
||||
getDefaultUser = sinon.stub(Users,"default",function() { return Promise.resolve(null);});
|
||||
getUser = sinon.stub(Users,"get", function(username) {
|
||||
getDefaultUser = sinon.stub(Users,"default").callsFake(function() { return Promise.resolve(null);});
|
||||
getUser = sinon.stub(Users,"get").callsFake(function(username) {
|
||||
if (username == "fred") {
|
||||
return Promise.resolve({permissions:"read"});
|
||||
} else {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
});
|
||||
getUserToken = sinon.stub(Users,"tokens", function(token) {
|
||||
getUserToken = sinon.stub(Users,"tokens").callsFake(function(token) {
|
||||
if (token == "abcde") {
|
||||
return Promise.resolve({user:"wilma", permissions:"*"})
|
||||
} else {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
});
|
||||
getToken = sinon.stub(Tokens,"get",function(token) {
|
||||
getToken = sinon.stub(Tokens,"get").callsFake(function(token) {
|
||||
if (token == "1234") {
|
||||
return Promise.resolve({user:"fred",scope:["*"]});
|
||||
} else if (token == "5678") {
|
||||
@@ -483,7 +483,7 @@ describe("api/editor/comms", function() {
|
||||
var port;
|
||||
var getDefaultUser;
|
||||
before(function(done) {
|
||||
getDefaultUser = sinon.stub(Users,"default",function() { return Promise.resolve({permissions:"read"});});
|
||||
getDefaultUser = sinon.stub(Users,"default").callsFake(function() { return Promise.resolve({permissions:"read"});});
|
||||
server = stoppable(http.createServer(function(req,res){app(req,res)}));
|
||||
comms.init(server, {adminAuth:{}}, {comms: mockComms});
|
||||
server.listen(listenPort, address);
|
||||
|
@@ -32,8 +32,8 @@ describe("api/editor/index", function() {
|
||||
var app;
|
||||
describe("disabled the editor", function() {
|
||||
beforeEach(function() {
|
||||
sinon.stub(comms,'init', function(){});
|
||||
sinon.stub(info,'init', function(){});
|
||||
sinon.stub(comms,'init').callsFake(function(){});
|
||||
sinon.stub(info,'init').callsFake(function(){});
|
||||
});
|
||||
afterEach(function() {
|
||||
comms.init.restore();
|
||||
@@ -54,13 +54,13 @@ describe("api/editor/index", function() {
|
||||
var errors = [];
|
||||
var session_data = {};
|
||||
before(function() {
|
||||
sinon.stub(auth,'needsPermission',function(permission) {
|
||||
sinon.stub(auth,'needsPermission').callsFake(function(permission) {
|
||||
return function(req,res,next) { next(); }
|
||||
});
|
||||
mockList.forEach(function(m) {
|
||||
sinon.stub(NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/"+m),"init",function(){});
|
||||
sinon.stub(NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/"+m),"init").callsFake(function(){});
|
||||
});
|
||||
sinon.stub(NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme"),"app",function(){ return express()});
|
||||
sinon.stub(NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme"),"app").callsFake(function(){ return express()});
|
||||
});
|
||||
after(function() {
|
||||
mockList.forEach(function(m) {
|
||||
@@ -72,7 +72,7 @@ describe("api/editor/index", function() {
|
||||
});
|
||||
|
||||
before(function() {
|
||||
sinon.stub(log,"error",function(err) { errors.push(err)})
|
||||
sinon.stub(log,"error").callsFake(function(err) { errors.push(err)})
|
||||
app = editorApi.init({},{httpNodeRoot:true, httpAdminRoot: true,disableEditor:false,exportNodeSettings:function(){}},{
|
||||
isStarted: () => Promise.resolve(isStarted)
|
||||
});
|
||||
|
@@ -50,9 +50,9 @@ describe("api/editor/locales", function() {
|
||||
locales.init({});
|
||||
|
||||
// bit of a mess of internal workings
|
||||
sinon.stub(i18n.i,'changeLanguage',function(lang,callback) { if (callback) {callback();}});
|
||||
sinon.stub(i18n.i,'changeLanguage').callsFake(function(lang,callback) { if (callback) {callback();}});
|
||||
if (i18n.i.getResourceBundle) {
|
||||
sinon.stub(i18n.i,'getResourceBundle',function(lang, namespace) {return {namespace:namespace, lang:lang};});
|
||||
sinon.stub(i18n.i,'getResourceBundle').callsFake(function(lang, namespace) {return {namespace:namespace, lang:lang};});
|
||||
} else {
|
||||
// If i18n.init has not been called, then getResourceBundle isn't
|
||||
// defined - so hardcode a stub
|
||||
@@ -121,7 +121,7 @@ describe("api/editor/locales", function() {
|
||||
// var app;
|
||||
// before(function() {
|
||||
// // bit of a mess of internal workings
|
||||
// sinon.stub(i18n,'catalog',function(namespace, lang) {
|
||||
// sinon.stub(i18n,'catalog').callsFake(function(namespace, lang) {
|
||||
// return {
|
||||
// "node-red": "should not return",
|
||||
// "test-module-a-id": "test-module-a-catalog",
|
||||
|
@@ -29,7 +29,7 @@ var theme = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme");
|
||||
|
||||
describe("api/editor/settings", function() {
|
||||
before(function() {
|
||||
sinon.stub(theme,"settings",function() { return { existing: 123, test: 456 };});
|
||||
sinon.stub(theme,"settings").callsFake(function() { return { existing: 123, test: 456 };});
|
||||
app = express();
|
||||
app.use(bodyParser.json());
|
||||
app.get("/settings/user",function(req,res,next) {req.user = "fred"; next()}, info.userSettings);
|
||||
|
@@ -27,7 +27,7 @@ var theme = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme");
|
||||
|
||||
describe("api/editor/theme", function () {
|
||||
beforeEach(function () {
|
||||
sinon.stub(fs, "statSync", function () { return true; });
|
||||
sinon.stub(fs, "statSync").callsFake(function () { return true; });
|
||||
});
|
||||
afterEach(function () {
|
||||
theme.init({settings: {}});
|
||||
|
@@ -31,18 +31,18 @@ var apiAdmin = NR_TEST_UTILS.require("@node-red/editor-api/lib/admin");
|
||||
|
||||
describe("api/index", function() {
|
||||
var beforeEach = function() {
|
||||
sinon.stub(apiAuth,"init",function(){});
|
||||
sinon.stub(apiEditor,"init",function(){
|
||||
sinon.stub(apiAuth,"init").callsFake(function(){});
|
||||
sinon.stub(apiEditor,"init").callsFake(function(){
|
||||
var app = express();
|
||||
app.get("/editor",function(req,res) { res.status(200).end(); });
|
||||
return app;
|
||||
});
|
||||
sinon.stub(apiAdmin,"init",function(){
|
||||
sinon.stub(apiAdmin,"init").callsFake(function(){
|
||||
var app = express();
|
||||
app.get("/admin",function(req,res) { res.status(200).end(); });
|
||||
return app;
|
||||
});
|
||||
sinon.stub(apiAuth,"login",function(req,res){
|
||||
sinon.stub(apiAuth,"login").callsFake(function(req,res){
|
||||
res.status(200).end();
|
||||
});
|
||||
};
|
||||
@@ -115,7 +115,7 @@ describe("api/index", 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', function(){});
|
||||
const stub = sinon.stub(apiAuth, 'genericStrategy').callsFake(function(){});
|
||||
const adminAuth = { type: 'strategy', strategy: {} }
|
||||
api.init({ httpAdminRoot: true, adminAuth },{},{},{});
|
||||
should(stub.called).be.ok();
|
||||
@@ -159,7 +159,7 @@ describe("api/index", function() {
|
||||
describe('editor start', function (done) {
|
||||
|
||||
it('cannot be started when editor is disabled', function (done) {
|
||||
const stub = sinon.stub(apiEditor, 'start', function () {
|
||||
const stub = sinon.stub(apiEditor, 'start').callsFake(function () {
|
||||
return Promise.resolve(true);
|
||||
});
|
||||
api.init({ httpAdminRoot: true, disableEditor: true }, {}, {}, {});
|
||||
|
@@ -33,8 +33,8 @@ describe("api/util", function() {
|
||||
var app;
|
||||
before(function() {
|
||||
app = express();
|
||||
sinon.stub(log,'error',function(msg) {loggedError = msg;});
|
||||
sinon.stub(log,'audit',function(event) {loggedEvent = event;});
|
||||
sinon.stub(log,'error').callsFake(function(msg) {loggedError = msg;});
|
||||
sinon.stub(log,'audit').callsFake(function(event) {loggedEvent = event;});
|
||||
app.get("/tooLarge", function(req,res) {
|
||||
var err = new Error();
|
||||
err.message = "request entity too large";
|
||||
|
@@ -14,6 +14,7 @@ const os = require("os");
|
||||
const NR_TEST_UTILS = require("nr-test-utils");
|
||||
const externalModules = NR_TEST_UTILS.require("@node-red/registry/lib/externalModules");
|
||||
const exec = NR_TEST_UTILS.require("@node-red/util/lib/exec");
|
||||
const hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
|
||||
|
||||
let homeDir;
|
||||
|
||||
@@ -40,19 +41,20 @@ describe("externalModules api", function() {
|
||||
await createUserDir()
|
||||
})
|
||||
afterEach(async function() {
|
||||
hooks.clear();
|
||||
await fs.remove(homeDir);
|
||||
})
|
||||
describe("checkFlowDependencies", function() {
|
||||
beforeEach(function() {
|
||||
sinon.stub(exec,"run", async function(cmd, args, options) {
|
||||
sinon.stub(exec,"run").callsFake(async function(cmd, args, options) {
|
||||
let error;
|
||||
if (args[1] === "moduleNotFound") {
|
||||
if (args[2] === "moduleNotFound") {
|
||||
error = new Error();
|
||||
error.stderr = "E404";
|
||||
} else if (args[1] === "moduleVersionNotFound") {
|
||||
} else if (args[2] === "moduleVersionNotFound") {
|
||||
error = new Error();
|
||||
error.stderr = "ETARGET";
|
||||
} else if (args[1] === "moduleFail") {
|
||||
} else if (args[2] === "moduleFail") {
|
||||
error = new Error();
|
||||
error.stderr = "Some unexpected install error";
|
||||
}
|
||||
@@ -102,6 +104,45 @@ describe("externalModules api", function() {
|
||||
fs.existsSync(path.join(homeDir,"externalModules")).should.be.true();
|
||||
})
|
||||
|
||||
|
||||
it("calls pre/postInstall hooks", async function() {
|
||||
externalModules.init({userDir: homeDir});
|
||||
externalModules.register("function", "libs");
|
||||
let receivedPreEvent,receivedPostEvent;
|
||||
hooks.add("preInstall", function(event) { event.args = ["a"]; receivedPreEvent = event; })
|
||||
hooks.add("postInstall", function(event) { receivedPostEvent = event; })
|
||||
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "foo"}]}
|
||||
])
|
||||
exec.run.called.should.be.true();
|
||||
// exec.run.lastCall.args[1].should.eql([ 'install', 'a', 'foo' ]);
|
||||
receivedPreEvent.should.have.property("module","foo")
|
||||
receivedPreEvent.should.have.property("version")
|
||||
receivedPreEvent.should.have.property("dir")
|
||||
receivedPreEvent.should.eql(receivedPostEvent)
|
||||
fs.existsSync(path.join(homeDir,"externalModules")).should.be.true();
|
||||
})
|
||||
|
||||
it("skips npm install if preInstall returns false", async function() {
|
||||
externalModules.init({userDir: homeDir});
|
||||
externalModules.register("function", "libs");
|
||||
let receivedPreEvent,receivedPostEvent;
|
||||
hooks.add("preInstall", function(event) { receivedPreEvent = event; return false })
|
||||
hooks.add("postInstall", function(event) { receivedPostEvent = event; })
|
||||
|
||||
await externalModules.checkFlowDependencies([
|
||||
{type: "function", libs:[{module: "foo"}]}
|
||||
])
|
||||
exec.run.called.should.be.false();
|
||||
receivedPreEvent.should.have.property("module","foo")
|
||||
receivedPreEvent.should.have.property("version")
|
||||
receivedPreEvent.should.have.property("dir")
|
||||
receivedPreEvent.should.eql(receivedPostEvent)
|
||||
fs.existsSync(path.join(homeDir,"externalModules")).should.be.true();
|
||||
})
|
||||
|
||||
|
||||
it("installs missing modules from inside subflow module", async function() {
|
||||
externalModules.init({userDir: homeDir});
|
||||
externalModules.register("function", "libs");
|
||||
@@ -299,4 +340,4 @@ describe("externalModules api", function() {
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
@@ -49,10 +49,10 @@ describe('red/registry/index', function() {
|
||||
|
||||
describe('#addModule', function() {
|
||||
it('loads the module and returns its info', function(done) {
|
||||
stubs.push(sinon.stub(loader,"addModule",function(module) {
|
||||
stubs.push(sinon.stub(loader,"addModule").callsFake(function(module) {
|
||||
return Promise.resolve();
|
||||
}));
|
||||
stubs.push(sinon.stub(typeRegistry,"getModuleInfo", function(module) {
|
||||
stubs.push(sinon.stub(typeRegistry,"getModuleInfo").callsFake(function(module) {
|
||||
return "info";
|
||||
}));
|
||||
registry.addModule("foo").then(function(info) {
|
||||
@@ -61,10 +61,10 @@ describe('red/registry/index', function() {
|
||||
}).catch(function(err) { done(err); });
|
||||
});
|
||||
it('rejects if loader rejects', function(done) {
|
||||
stubs.push(sinon.stub(loader,"addModule",function(module) {
|
||||
stubs.push(sinon.stub(loader,"addModule").callsFake(function(module) {
|
||||
return Promise.reject("error");
|
||||
}));
|
||||
stubs.push(sinon.stub(typeRegistry,"getModuleInfo", function(module) {
|
||||
stubs.push(sinon.stub(typeRegistry,"getModuleInfo").callsFake(function(module) {
|
||||
return "info";
|
||||
}));
|
||||
registry.addModule("foo").then(function(info) {
|
||||
@@ -78,10 +78,10 @@ describe('red/registry/index', function() {
|
||||
|
||||
describe('#enableNode',function() {
|
||||
it('enables a node set',function(done) {
|
||||
stubs.push(sinon.stub(typeRegistry,"enableNodeSet",function() {
|
||||
stubs.push(sinon.stub(typeRegistry,"enableNodeSet").callsFake(function() {
|
||||
return Promise.resolve();
|
||||
}));
|
||||
stubs.push(sinon.stub(typeRegistry,"getNodeInfo", function() {
|
||||
stubs.push(sinon.stub(typeRegistry,"getNodeInfo").callsFake(function() {
|
||||
return {id:"node-set",loaded:true};
|
||||
}));
|
||||
registry.enableNode("node-set").then(function(ns) {
|
||||
@@ -92,7 +92,7 @@ describe('red/registry/index', function() {
|
||||
});
|
||||
|
||||
it('rejects if node unknown',function() {
|
||||
stubs.push(sinon.stub(typeRegistry,"enableNodeSet",function() {
|
||||
stubs.push(sinon.stub(typeRegistry,"enableNodeSet").callsFake(function() {
|
||||
throw new Error('failure');
|
||||
}));
|
||||
/*jshint immed: false */
|
||||
@@ -102,15 +102,15 @@ describe('red/registry/index', function() {
|
||||
});
|
||||
|
||||
it('triggers a node load',function(done) {
|
||||
stubs.push(sinon.stub(typeRegistry,"enableNodeSet",function() {
|
||||
stubs.push(sinon.stub(typeRegistry,"enableNodeSet").callsFake(function() {
|
||||
return Promise.resolve();
|
||||
}));
|
||||
var calls = 0;
|
||||
stubs.push(sinon.stub(typeRegistry,"getNodeInfo", function() {
|
||||
stubs.push(sinon.stub(typeRegistry,"getNodeInfo").callsFake(function() {
|
||||
// loaded=false on first call, true on subsequent
|
||||
return {id:"node-set",loaded:(calls++>0)};
|
||||
}));
|
||||
stubs.push(sinon.stub(loader,"loadNodeSet",function(){return Promise.resolve();}));
|
||||
stubs.push(sinon.stub(loader,"loadNodeSet").callsFake(function(){return Promise.resolve();}));
|
||||
stubs.push(sinon.stub(typeRegistry,"getFullNodeInfo"));
|
||||
|
||||
registry.enableNode("node-set").then(function(ns) {
|
||||
|
@@ -25,7 +25,7 @@ var NR_TEST_UTILS = require("nr-test-utils");
|
||||
var installer = NR_TEST_UTILS.require("@node-red/registry/lib/installer");
|
||||
var registry = NR_TEST_UTILS.require("@node-red/registry/lib/index");
|
||||
var typeRegistry = NR_TEST_UTILS.require("@node-red/registry/lib/registry");
|
||||
const { events, exec, log } = NR_TEST_UTILS.require("@node-red/util");
|
||||
const { events, exec, log, hooks } = NR_TEST_UTILS.require("@node-red/util");
|
||||
|
||||
describe('nodes/registry/installer', function() {
|
||||
|
||||
@@ -42,7 +42,7 @@ describe('nodes/registry/installer', function() {
|
||||
var execResponse;
|
||||
|
||||
beforeEach(function() {
|
||||
sinon.stub(exec,"run", () => execResponse || Promise.resolve(""))
|
||||
sinon.stub(exec,"run").callsFake(() => execResponse || Promise.resolve(""))
|
||||
installer.init({})
|
||||
});
|
||||
|
||||
@@ -68,6 +68,7 @@ describe('nodes/registry/installer', function() {
|
||||
fs.statSync.restore();
|
||||
}
|
||||
exec.run.restore();
|
||||
hooks.clear();
|
||||
});
|
||||
|
||||
describe("installs module", function() {
|
||||
@@ -118,7 +119,7 @@ describe('nodes/registry/installer', function() {
|
||||
var p = Promise.reject(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
sinon.stub(typeRegistry,"getModuleInfo", function() {
|
||||
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||
return {
|
||||
version: "0.1.1"
|
||||
}
|
||||
@@ -129,7 +130,7 @@ describe('nodes/registry/installer', function() {
|
||||
}).catch(done);
|
||||
});
|
||||
it("rejects when update requested to existing version", function(done) {
|
||||
sinon.stub(typeRegistry,"getModuleInfo", function() {
|
||||
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||
return {
|
||||
user: true,
|
||||
version: "0.1.1"
|
||||
@@ -141,7 +142,7 @@ describe('nodes/registry/installer', function() {
|
||||
}).catch(done);
|
||||
});
|
||||
it("rejects when update requested to existing version and url", function(done) {
|
||||
sinon.stub(typeRegistry,"getModuleInfo", function() {
|
||||
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||
return {
|
||||
user: true,
|
||||
version: "0.1.1"
|
||||
@@ -180,7 +181,7 @@ describe('nodes/registry/installer', function() {
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
var addModule = sinon.stub(registry,"addModule",function(md) {
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
|
||||
@@ -211,7 +212,7 @@ describe('nodes/registry/installer', function() {
|
||||
});
|
||||
it("succeeds when path is valid node-red module", function(done) {
|
||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||
var addModule = sinon.stub(registry,"addModule",function(md) {
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
var resourcesDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule","node_modules","TestNodeModule"));
|
||||
@@ -241,7 +242,7 @@ describe('nodes/registry/installer', function() {
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
var addModule = sinon.stub(registry,"addModule",function(md) {
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
|
||||
@@ -251,6 +252,70 @@ describe('nodes/registry/installer', function() {
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it("triggers preInstall and postInstall hooks", function(done) {
|
||||
let receivedPreEvent,receivedPostEvent;
|
||||
hooks.add("preInstall", function(event) { event.args = ["a"]; receivedPreEvent = event; })
|
||||
hooks.add("postInstall", function(event) { receivedPostEvent = event; })
|
||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||
var res = {code: 0,stdout:"",stderr:""}
|
||||
var p = Promise.resolve(res);
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
|
||||
installer.installModule("this_wont_exist","1.2.3").then(function(info) {
|
||||
exec.run.called.should.be.true();
|
||||
exec.run.lastCall.args[1].should.eql([ 'install', 'a', 'this_wont_exist@1.2.3' ]);
|
||||
info.should.eql(nodeInfo);
|
||||
should.exist(receivedPreEvent)
|
||||
receivedPreEvent.should.have.property("module","this_wont_exist")
|
||||
receivedPreEvent.should.have.property("version","1.2.3")
|
||||
receivedPreEvent.should.have.property("dir")
|
||||
receivedPreEvent.should.have.property("url")
|
||||
receivedPreEvent.should.have.property("isExisting")
|
||||
receivedPreEvent.should.have.property("isUpgrade")
|
||||
receivedPreEvent.should.eql(receivedPostEvent)
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it("fails install if preInstall hook fails", function(done) {
|
||||
let receivedEvent;
|
||||
hooks.add("preInstall", function(event) { throw new Error("preInstall-error"); })
|
||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||
|
||||
installer.installModule("this_wont_exist","1.2.3").catch(function(err) {
|
||||
exec.run.called.should.be.false();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it("skips invoking npm if preInstall returns false", function(done) {
|
||||
let receivedEvent;
|
||||
hooks.add("preInstall", function(event) { return false })
|
||||
hooks.add("postInstall", function(event) { receivedEvent = event; })
|
||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||
|
||||
installer.installModule("this_wont_exist","1.2.3").catch(function(err) {
|
||||
exec.run.called.should.be.false();
|
||||
should.exist(receivedEvent);
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it("rollsback install if postInstall hook fails", function(done) {
|
||||
hooks.add("postInstall", function(event) { throw new Error("fail"); })
|
||||
installer.installModule("this_wont_exist","1.2.3").catch(function(err) {
|
||||
exec.run.calledTwice.should.be.true();
|
||||
exec.run.firstCall.args[1].includes("install").should.be.true();
|
||||
exec.run.secondCall.args[1].includes("remove").should.be.true();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
});
|
||||
describe("uninstalls module", function() {
|
||||
it("rejects invalid module names", function(done) {
|
||||
@@ -267,7 +332,7 @@ describe('nodes/registry/installer', function() {
|
||||
|
||||
it("rejects with generic error", function(done) {
|
||||
var nodeInfo = [{module:"foo",types:["a"]}];
|
||||
var removeModule = sinon.stub(registry,"removeModule",function(md) {
|
||||
var removeModule = sinon.stub(registry,"removeModule").callsFake(function(md) {
|
||||
return Promise.resolve(nodeInfo);
|
||||
});
|
||||
var res = {
|
||||
@@ -288,10 +353,10 @@ describe('nodes/registry/installer', function() {
|
||||
});
|
||||
it("succeeds when module is found", function(done) {
|
||||
var nodeInfo = [{module:"foo",types:["a"]}];
|
||||
var removeModule = sinon.stub(typeRegistry,"removeModule",function(md) {
|
||||
var removeModule = sinon.stub(typeRegistry,"removeModule").callsFake(function(md) {
|
||||
return nodeInfo;
|
||||
});
|
||||
var getModuleInfo = sinon.stub(registry,"getModuleInfo",function(md) {
|
||||
var getModuleInfo = sinon.stub(registry,"getModuleInfo").callsFake(function(md) {
|
||||
return {nodes:[]};
|
||||
});
|
||||
var res = {
|
||||
@@ -303,7 +368,7 @@ describe('nodes/registry/installer', function() {
|
||||
p.catch((err)=>{});
|
||||
execResponse = p;
|
||||
|
||||
sinon.stub(fs,"statSync", function(fn) { return {}; });
|
||||
sinon.stub(fs,"statSync").callsFake(function(fn) { return {}; });
|
||||
|
||||
installer.uninstallModule("this_wont_exist").then(function(info) {
|
||||
info.should.eql(nodeInfo);
|
||||
|
@@ -46,8 +46,8 @@ describe("red/nodes/registry/loader",function() {
|
||||
|
||||
describe("#load",function() {
|
||||
it("load empty set without settings available", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){ return {};}));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return {};}));
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){ return {};}));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return {};}));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return false;}}});
|
||||
loader.load(true).then(function() {
|
||||
localfilesystem.getNodeFiles.called.should.be.true();
|
||||
@@ -57,8 +57,8 @@ describe("red/nodes/registry/loader",function() {
|
||||
})
|
||||
});
|
||||
it("load empty set with settings available triggers registery save", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){ return {};}));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return {};}));
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){ return {};}));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return {};}));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
loader.load(true).then(function() {
|
||||
registry.saveNodeList.called.should.be.true();
|
||||
@@ -69,7 +69,7 @@ describe("red/nodes/registry/loader",function() {
|
||||
});
|
||||
|
||||
it("load core node files scanned by lfs - single node single file", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["node-red"] = {
|
||||
"name": "node-red",
|
||||
@@ -85,10 +85,10 @@ describe("red/nodes/registry/loader",function() {
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
@@ -126,7 +126,7 @@ describe("red/nodes/registry/loader",function() {
|
||||
});
|
||||
|
||||
it("load core node files scanned by lfs - ignore html if disableEditor true", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["node-red"] = {
|
||||
"name": "node-red",
|
||||
@@ -142,10 +142,10 @@ describe("red/nodes/registry/loader",function() {
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{disableEditor: true, available:function(){return true;}}});
|
||||
@@ -190,7 +190,7 @@ describe("red/nodes/registry/loader",function() {
|
||||
});
|
||||
|
||||
it("load core node files scanned by lfs - multiple nodes single file", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["node-red"] = {
|
||||
"name": "node-red",
|
||||
@@ -206,10 +206,10 @@ describe("red/nodes/registry/loader",function() {
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
loader.load().then(function(result) {
|
||||
@@ -250,7 +250,7 @@ describe("red/nodes/registry/loader",function() {
|
||||
|
||||
|
||||
it("load core node files scanned by lfs - node with promise", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["node-red"] = {
|
||||
"name": "node-red",
|
||||
@@ -266,10 +266,10 @@ describe("red/nodes/registry/loader",function() {
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
@@ -308,7 +308,7 @@ describe("red/nodes/registry/loader",function() {
|
||||
|
||||
|
||||
it("load core node files scanned by lfs - node with rejecting promise", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["node-red"] = {
|
||||
"name": "node-red",
|
||||
@@ -324,10 +324,10 @@ describe("red/nodes/registry/loader",function() {
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
@@ -362,7 +362,7 @@ describe("red/nodes/registry/loader",function() {
|
||||
});
|
||||
|
||||
it("load core node files scanned by lfs - missing file", function(done) {
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){
|
||||
stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["node-red"] = {
|
||||
"name": "node-red",
|
||||
@@ -378,10 +378,10 @@ describe("red/nodes/registry/loader",function() {
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
@@ -416,7 +416,7 @@ describe("red/nodes/registry/loader",function() {
|
||||
|
||||
// it("load core node files scanned by lfs - missing html file", function(done) {
|
||||
// // This is now an okay situation
|
||||
// stubs.push(sinon.stub(localfilesystem,"getNodeFiles", function(){
|
||||
// stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
|
||||
// var result = {};
|
||||
// result["node-red"] = {
|
||||
// "name": "node-red",
|
||||
@@ -432,10 +432,10 @@ describe("red/nodes/registry/loader",function() {
|
||||
// return result;
|
||||
// }));
|
||||
//
|
||||
// stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
|
||||
// stubs.push(sinon.stub(registry,"addModule", function(){ return }));
|
||||
// stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
|
||||
// stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
// // This module isn't already loaded
|
||||
// stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
|
||||
// stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
//
|
||||
// stubs.push(sinon.stub(nodes,"registerType"));
|
||||
// loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
@@ -481,7 +481,7 @@ describe("red/nodes/registry/loader",function() {
|
||||
});
|
||||
|
||||
it("returns rejected error if module already loaded", function(done) {
|
||||
stubs.push(sinon.stub(registry,"getModuleInfo",function(){return{}}));
|
||||
stubs.push(sinon.stub(registry,"getModuleInfo").callsFake(function(){return{}}));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
|
||||
loader.addModule("test-module").catch(function(err) {
|
||||
@@ -490,8 +490,8 @@ describe("red/nodes/registry/loader",function() {
|
||||
});
|
||||
});
|
||||
it("returns rejected error if module not found", function(done) {
|
||||
stubs.push(sinon.stub(registry,"getModuleInfo",function(){return null}));
|
||||
stubs.push(sinon.stub(localfilesystem,"getModuleFiles",function() {
|
||||
stubs.push(sinon.stub(registry,"getModuleInfo").callsFake(function(){return null}));
|
||||
stubs.push(sinon.stub(localfilesystem,"getModuleFiles").callsFake(function() {
|
||||
throw new Error("failure");
|
||||
}));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
@@ -504,9 +504,9 @@ describe("red/nodes/registry/loader",function() {
|
||||
|
||||
it("loads module by name", function(done) {
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
|
||||
stubs.push(sinon.stub(registry,"getModuleInfo",function(){ return null; }));
|
||||
stubs.push(sinon.stub(localfilesystem,"getModuleFiles", function(){
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
stubs.push(sinon.stub(registry,"getModuleInfo").callsFake(function(){ return null; }));
|
||||
stubs.push(sinon.stub(localfilesystem,"getModuleFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["TestNodeModule"] = {
|
||||
"name": "TestNodeModule",
|
||||
@@ -523,8 +523,8 @@ describe("red/nodes/registry/loader",function() {
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return "a node list" }));
|
||||
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return "a node list" }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
|
||||
loader.addModule("TestNodeModule").then(function(result) {
|
||||
@@ -560,9 +560,9 @@ describe("red/nodes/registry/loader",function() {
|
||||
|
||||
it("skips module that fails version check", function(done) {
|
||||
// This module isn't already loaded
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
|
||||
stubs.push(sinon.stub(registry,"getModuleInfo",function(){ return null; }));
|
||||
stubs.push(sinon.stub(localfilesystem,"getModuleFiles", function(){
|
||||
stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
|
||||
stubs.push(sinon.stub(registry,"getModuleInfo").callsFake(function(){ return null; }));
|
||||
stubs.push(sinon.stub(localfilesystem,"getModuleFiles").callsFake(function(){
|
||||
var result = {};
|
||||
result["TestNodeModule"] = {
|
||||
"name": "TestNodeModule",
|
||||
@@ -580,8 +580,8 @@ describe("red/nodes/registry/loader",function() {
|
||||
return result;
|
||||
}));
|
||||
|
||||
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return "a node list" }));
|
||||
stubs.push(sinon.stub(registry,"addModule", function(){ return }));
|
||||
stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return "a node list" }));
|
||||
stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
|
||||
stubs.push(sinon.stub(nodes,"registerType"));
|
||||
loader.init({log:{"_":function(){},warn:function(){}},nodes:nodes,version: function() { return "0.12.0"}, settings:{available:function(){return true;}}});
|
||||
loader.addModule("TestNodeModule").then(function(result) {
|
||||
@@ -643,7 +643,7 @@ describe("red/nodes/registry/loader",function() {
|
||||
},"en").should.eql("foo");
|
||||
});
|
||||
it("loads help, caching result", function() {
|
||||
stubs.push(sinon.stub(fs,"readFileSync", function(path) {
|
||||
stubs.push(sinon.stub(fs,"readFileSync").callsFake(function(path) {
|
||||
return 'bar';
|
||||
}))
|
||||
var node = {
|
||||
@@ -660,7 +660,7 @@ describe("red/nodes/registry/loader",function() {
|
||||
fs.readFileSync.calledOnce.should.be.true();
|
||||
});
|
||||
it("loads help, defaulting to en-US content", function() {
|
||||
stubs.push(sinon.stub(fs,"readFileSync", function(path) {
|
||||
stubs.push(sinon.stub(fs,"readFileSync").callsFake(function(path) {
|
||||
throw new Error("not found");
|
||||
}))
|
||||
var node = {
|
||||
@@ -677,7 +677,7 @@ describe("red/nodes/registry/loader",function() {
|
||||
fs.readFileSync.calledOnce.should.be.true();
|
||||
});
|
||||
it("loads help, defaulting to en-US content for extra nodes", function() {
|
||||
stubs.push(sinon.stub(fs,"readFileSync", function(path) {
|
||||
stubs.push(sinon.stub(fs,"readFileSync").callsFake(function(path) {
|
||||
if (path.indexOf("en-US") >= 0) {
|
||||
return 'bar';
|
||||
}
|
||||
@@ -698,7 +698,7 @@ describe("red/nodes/registry/loader",function() {
|
||||
fs.readFileSync.calledTwice.should.be.true();
|
||||
});
|
||||
it("fails to load en-US help content", function() {
|
||||
stubs.push(sinon.stub(fs,"readFileSync", function(path) {
|
||||
stubs.push(sinon.stub(fs,"readFileSync").callsFake(function(path) {
|
||||
throw new Error("not found");
|
||||
}));
|
||||
var node = {
|
||||
|
@@ -30,7 +30,7 @@ var i18n = NR_TEST_UTILS.require("@node-red/util").i18n;
|
||||
|
||||
describe("red/nodes/registry/localfilesystem",function() {
|
||||
beforeEach(function() {
|
||||
stubs.push(sinon.stub(i18n,"registerMessageCatalog", function() { return Promise.resolve(); }));
|
||||
stubs.push(sinon.stub(i18n,"registerMessageCatalog").callsFake(function() { return Promise.resolve(); }));
|
||||
})
|
||||
|
||||
var stubs = [];
|
||||
@@ -131,7 +131,7 @@ describe("red/nodes/registry/localfilesystem",function() {
|
||||
});
|
||||
it("Finds nodes module path",function(done) {
|
||||
var _join = path.join;
|
||||
stubs.push(sinon.stub(path,"join",function() {
|
||||
stubs.push(sinon.stub(path,"join").callsFake(function() {
|
||||
if (arguments[0] == resourcesDir) {
|
||||
// This stops the module tree scan from going any higher
|
||||
// up the tree than resourcesDir.
|
||||
@@ -206,7 +206,7 @@ describe("red/nodes/registry/localfilesystem",function() {
|
||||
describe("#getModuleFiles",function() {
|
||||
it("gets a nodes module files",function(done) {
|
||||
var _join = path.join;
|
||||
stubs.push(sinon.stub(path,"join",function() {
|
||||
stubs.push(sinon.stub(path,"join").callsFake(function() {
|
||||
if (arguments[0] == resourcesDir) {
|
||||
// This stops the module tree scan from going any higher
|
||||
// up the tree than resourcesDir.
|
||||
@@ -232,7 +232,7 @@ describe("red/nodes/registry/localfilesystem",function() {
|
||||
});
|
||||
it("throws an error if a node isn't found",function(done) {
|
||||
var _join = path.join;
|
||||
stubs.push(sinon.stub(path,"join",function() {
|
||||
stubs.push(sinon.stub(path,"join").callsFake(function() {
|
||||
if (arguments[0] == resourcesDir) {
|
||||
// This stops the module tree scan from going any higher
|
||||
// up the tree than resourcesDir.
|
||||
@@ -251,7 +251,7 @@ describe("red/nodes/registry/localfilesystem",function() {
|
||||
it.skip("finds icon path directory");
|
||||
it("scans icon files with a module file",function(done) {
|
||||
var _join = path.join;
|
||||
stubs.push(sinon.stub(path,"join",function() {
|
||||
stubs.push(sinon.stub(path,"join").callsFake(function() {
|
||||
if (arguments[0] == resourcesDir) {
|
||||
// This stops the module tree scan from going any higher
|
||||
// up the tree than resourcesDir.
|
||||
|
@@ -37,8 +37,8 @@ describe("red/nodes/registry/plugins",function() {
|
||||
}
|
||||
}
|
||||
events.on("registry:plugin-added",handleEvent);
|
||||
sinon.stub(registry,"getModule", moduleId => modules[moduleId]);
|
||||
sinon.stub(registry,"getModuleList", () => modules)
|
||||
sinon.stub(registry,"getModule").callsFake(moduleId => modules[moduleId]);
|
||||
sinon.stub(registry,"getModuleList").callsFake(() => modules)
|
||||
});
|
||||
afterEach(function() {
|
||||
events.removeListener("registry:plugin-added",handleEvent);
|
||||
|
@@ -31,8 +31,8 @@ describe("runtime-api/comms", function() {
|
||||
}
|
||||
var eventHandlers = {};
|
||||
before(function(done) {
|
||||
sinon.stub(events,"removeListener", function() {})
|
||||
sinon.stub(events,"on", function(evt,handler) { eventHandlers[evt] = handler })
|
||||
sinon.stub(events,"removeListener").callsFake(function() {})
|
||||
sinon.stub(events,"on").callsFake(function(evt,handler) { eventHandlers[evt] = handler })
|
||||
comms.init({
|
||||
log: {
|
||||
trace: function(){}
|
||||
@@ -97,8 +97,8 @@ describe("runtime-api/comms", function() {
|
||||
}
|
||||
}
|
||||
before(function() {
|
||||
sinon.stub(events,"removeListener", function() {})
|
||||
sinon.stub(events,"on", function(evt,handler) { eventHandlers[evt] = handler })
|
||||
sinon.stub(events,"removeListener").callsFake(function() {})
|
||||
sinon.stub(events,"on").callsFake(function(evt,handler) { eventHandlers[evt] = handler })
|
||||
comms.init({
|
||||
log: {
|
||||
trace: function(){}
|
||||
@@ -177,8 +177,8 @@ describe("runtime-api/comms", function() {
|
||||
}
|
||||
var eventHandlers = {};
|
||||
before(function() {
|
||||
sinon.stub(events,"removeListener", function() {})
|
||||
sinon.stub(events,"on", function(evt,handler) { eventHandlers[evt] = handler })
|
||||
sinon.stub(events,"removeListener").callsFake(function() {})
|
||||
sinon.stub(events,"on").callsFake(function(evt,handler) { eventHandlers[evt] = handler })
|
||||
comms.init({
|
||||
log: {
|
||||
trace: function(){}
|
||||
|
@@ -24,7 +24,7 @@ var index = NR_TEST_UTILS.require("@node-red/runtime/lib/api/index");
|
||||
describe("runtime-api/index", function() {
|
||||
before(function() {
|
||||
["comms","flows","nodes","settings","library","projects"].forEach(n => {
|
||||
sinon.stub(NR_TEST_UTILS.require(`@node-red/runtime/lib/api/${n}`),"init",()=>{});
|
||||
sinon.stub(NR_TEST_UTILS.require(`@node-red/runtime/lib/api/${n}`),"init").callsFake(()=>{});
|
||||
})
|
||||
});
|
||||
after(function() {
|
||||
|
@@ -217,7 +217,7 @@ describe("api/admin/nodes", function() {
|
||||
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
|
||||
app.get("/getIcons",nodes.getIcons);
|
||||
app.delete("/nodes/:id",nodes.delete);
|
||||
sinon.stub(apiUtil,"determineLangFromHeaders", function() {
|
||||
sinon.stub(apiUtil,"determineLangFromHeaders").callsFake(function() {
|
||||
return "en-US";
|
||||
});
|
||||
});
|
||||
|
@@ -26,7 +26,7 @@ var flowUtils = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/util");
|
||||
var Flow = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/Flow");
|
||||
var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
|
||||
var Node = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
|
||||
var hooks = NR_TEST_UTILS.require("@node-red/runtime/lib/hooks");
|
||||
var hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
|
||||
var typeRegistry = NR_TEST_UTILS.require("@node-red/registry");
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ describe('Flow', function() {
|
||||
util.inherits(TestDoneNode,Node);
|
||||
|
||||
before(function() {
|
||||
getType = sinon.stub(typeRegistry,"get",function(type) {
|
||||
getType = sinon.stub(typeRegistry,"get").callsFake(function(type) {
|
||||
if (type=="test") {
|
||||
return TestNode;
|
||||
} else if (type=="testError"){
|
||||
|
@@ -202,7 +202,7 @@ describe('Subflow', function() {
|
||||
util.inherits(TestEnvNode,Node);
|
||||
|
||||
before(function() {
|
||||
getType = sinon.stub(typeRegistry,"get",function(type) {
|
||||
getType = sinon.stub(typeRegistry,"get").callsFake(function(type) {
|
||||
if (type=="test") {
|
||||
return TestNode;
|
||||
} else if (type=="testError"){
|
||||
|
@@ -51,10 +51,10 @@ describe('flows/index', function() {
|
||||
|
||||
|
||||
before(function() {
|
||||
getType = sinon.stub(typeRegistry,"get",function(type) {
|
||||
getType = sinon.stub(typeRegistry,"get").callsFake(function(type) {
|
||||
return type.indexOf('missing') === -1;
|
||||
});
|
||||
checkFlowDependencies = sinon.stub(typeRegistry, "checkFlowDependencies", async function(flow) {
|
||||
checkFlowDependencies = sinon.stub(typeRegistry, "checkFlowDependencies").callsFake(async function(flow) {
|
||||
if (flow[0].id === "node-with-missing-modules") {
|
||||
throw new Error("Missing module");
|
||||
}
|
||||
@@ -69,20 +69,20 @@ describe('flows/index', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
eventsOn = sinon.spy(events,"on");
|
||||
credentialsClean = sinon.stub(credentials,"clean",function(conf) {
|
||||
credentialsClean = sinon.stub(credentials,"clean").callsFake(function(conf) {
|
||||
conf.forEach(function(n) {
|
||||
delete n.credentials;
|
||||
});
|
||||
return Promise.resolve();
|
||||
});
|
||||
credentialsLoad = sinon.stub(credentials,"load",function(creds) {
|
||||
credentialsLoad = sinon.stub(credentials,"load").callsFake(function(creds) {
|
||||
if (creds && creds.hasOwnProperty("$") && creds['$'] === "fail") {
|
||||
return Promise.reject("creds error");
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
credentialsAdd = sinon.stub(credentials,"add", async function(id, conf){})
|
||||
flowCreate = sinon.stub(Flow,"create",function(parent, global, flow) {
|
||||
credentialsAdd = sinon.stub(credentials,"add").callsFake(async function(id, conf){})
|
||||
flowCreate = sinon.stub(Flow,"create").callsFake(function(parent, global, flow) {
|
||||
var id;
|
||||
if (typeof flow === 'undefined') {
|
||||
flow = global;
|
||||
@@ -551,7 +551,7 @@ describe('flows/index', function() {
|
||||
describe('#checkTypeInUse', function() {
|
||||
|
||||
before(function() {
|
||||
sinon.stub(typeRegistry,"getNodeInfo",function(id) {
|
||||
sinon.stub(typeRegistry,"getNodeInfo").callsFake(function(id) {
|
||||
if (id === 'unused-module') {
|
||||
return {types:['one','two','three']}
|
||||
} else {
|
||||
|
@@ -26,7 +26,7 @@ describe('flows/util', function() {
|
||||
var getType;
|
||||
|
||||
before(function() {
|
||||
getType = sinon.stub(typeRegistry,"get",function(type) {
|
||||
getType = sinon.stub(typeRegistry,"get").callsFake(function(type) {
|
||||
return type!=='missing';
|
||||
});
|
||||
});
|
||||
|
@@ -44,13 +44,13 @@ describe("runtime", function() {
|
||||
delete process.env.NODE_RED_HOME;
|
||||
});
|
||||
function mockUtil(metrics) {
|
||||
sinon.stub(log,"log",function(){})
|
||||
sinon.stub(log,"warn",function(){})
|
||||
sinon.stub(log,"info",function(){})
|
||||
sinon.stub(log,"trace",function(){})
|
||||
sinon.stub(log,"metric",function(){ return !!metrics })
|
||||
sinon.stub(log,"_",function(){ return "abc"})
|
||||
sinon.stub(i18n,"registerMessageCatalog",function(){ return Promise.resolve()})
|
||||
sinon.stub(log,"log").callsFake(function(){})
|
||||
sinon.stub(log,"warn").callsFake(function(){})
|
||||
sinon.stub(log,"info").callsFake(function(){})
|
||||
sinon.stub(log,"trace").callsFake(function(){})
|
||||
sinon.stub(log,"metric").callsFake(function(){ return !!metrics })
|
||||
sinon.stub(log,"_").callsFake(function(){ return "abc"})
|
||||
sinon.stub(i18n,"registerMessageCatalog").callsFake(function(){ return Promise.resolve()})
|
||||
}
|
||||
function unmockUtil() {
|
||||
log.log.restore && log.log.restore();
|
||||
@@ -63,9 +63,9 @@ describe("runtime", function() {
|
||||
}
|
||||
describe("init", function() {
|
||||
beforeEach(function() {
|
||||
sinon.stub(log,"init",function() {});
|
||||
sinon.stub(settings,"init",function() {});
|
||||
sinon.stub(redNodes,"init",function() {})
|
||||
sinon.stub(log,"init").callsFake(function() {});
|
||||
sinon.stub(settings,"init").callsFake(function() {});
|
||||
sinon.stub(redNodes,"init").callsFake(function() {})
|
||||
mockUtil();
|
||||
});
|
||||
afterEach(function() {
|
||||
@@ -103,13 +103,13 @@ describe("runtime", function() {
|
||||
var redNodesLoadContextsPlugin;
|
||||
|
||||
beforeEach(function() {
|
||||
storageInit = sinon.stub(storage,"init",function(settings) {return Promise.resolve();});
|
||||
redNodesInit = sinon.stub(redNodes,"init", function() {});
|
||||
redNodesLoad = sinon.stub(redNodes,"load", function() {return Promise.resolve()});
|
||||
redNodesCleanModuleList = sinon.stub(redNodes,"cleanModuleList",function(){});
|
||||
redNodesLoadFlows = sinon.stub(redNodes,"loadFlows",function() {return Promise.resolve()});
|
||||
redNodesStartFlows = sinon.stub(redNodes,"startFlows",function() {});
|
||||
redNodesLoadContextsPlugin = sinon.stub(redNodes,"loadContextsPlugin",function() {return Promise.resolve()});
|
||||
storageInit = sinon.stub(storage,"init").callsFake(function(settings) {return Promise.resolve();});
|
||||
redNodesInit = sinon.stub(redNodes,"init").callsFake(function() {});
|
||||
redNodesLoad = sinon.stub(redNodes,"load").callsFake(function() {return Promise.resolve()});
|
||||
redNodesCleanModuleList = sinon.stub(redNodes,"cleanModuleList").callsFake(function(){});
|
||||
redNodesLoadFlows = sinon.stub(redNodes,"loadFlows").callsFake(function() {return Promise.resolve()});
|
||||
redNodesStartFlows = sinon.stub(redNodes,"startFlows").callsFake(function() {});
|
||||
redNodesLoadContextsPlugin = sinon.stub(redNodes,"loadContextsPlugin").callsFake(function() {return Promise.resolve()});
|
||||
mockUtil();
|
||||
});
|
||||
afterEach(function() {
|
||||
@@ -124,7 +124,7 @@ describe("runtime", function() {
|
||||
unmockUtil();
|
||||
});
|
||||
it("reports errored/missing modules",function(done) {
|
||||
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function(cb) {
|
||||
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList").callsFake(function(cb) {
|
||||
return [
|
||||
{ err:"errored",name:"errName" }, // error
|
||||
{ module:"module",enabled:true,loaded:false,types:["typeA","typeB"]} // missing
|
||||
@@ -151,7 +151,7 @@ describe("runtime", function() {
|
||||
}).catch(err=>{done(err)});
|
||||
});
|
||||
it("initiates load of missing modules",function(done) {
|
||||
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function(cb) {
|
||||
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList").callsFake(function(cb) {
|
||||
return [
|
||||
{ err:"errored",name:"errName" }, // error
|
||||
{ err:"errored",name:"errName" }, // error
|
||||
@@ -159,7 +159,7 @@ describe("runtime", function() {
|
||||
{ module:"node-red",enabled:true,loaded:false,types:["typeC","typeD"]} // missing
|
||||
].filter(cb);
|
||||
});
|
||||
var serverInstallModule = sinon.stub(redNodes,"installModule",function(name) { return Promise.resolve({nodes:[]});});
|
||||
var serverInstallModule = sinon.stub(redNodes,"installModule").callsFake(function(name) { return Promise.resolve({nodes:[]});});
|
||||
runtime.init({testSettings: true, autoInstallModules:true, httpAdminRoot:"/", load:function() { return Promise.resolve();}});
|
||||
sinon.stub(console,"log");
|
||||
runtime.start().then(function() {
|
||||
@@ -181,7 +181,7 @@ describe("runtime", function() {
|
||||
}).catch(err=>{done(err)});
|
||||
});
|
||||
it("reports errored modules when verbose is enabled",function(done) {
|
||||
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function(cb) {
|
||||
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList").callsFake(function(cb) {
|
||||
return [
|
||||
{ err:"errored",name:"errName" } // error
|
||||
].filter(cb);
|
||||
@@ -201,8 +201,8 @@ describe("runtime", function() {
|
||||
});
|
||||
|
||||
it("reports runtime metrics",function(done) {
|
||||
var stopFlows = sinon.stub(redNodes,"stopFlows",function() { return Promise.resolve();} );
|
||||
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function() {return []});
|
||||
var stopFlows = sinon.stub(redNodes,"stopFlows").callsFake(function() { return Promise.resolve();} );
|
||||
redNodesGetNodeList = sinon.stub(redNodes,"getNodeList").callsFake(function() {return []});
|
||||
unmockUtil();
|
||||
mockUtil(true);
|
||||
runtime.init(
|
||||
@@ -233,8 +233,8 @@ describe("runtime", function() {
|
||||
});
|
||||
|
||||
it("stops components", function(done) {
|
||||
var stopFlows = sinon.stub(redNodes,"stopFlows",function() { return Promise.resolve();} );
|
||||
var closeContextsPlugin = sinon.stub(redNodes,"closeContextsPlugin",function() { return Promise.resolve();} );
|
||||
var stopFlows = sinon.stub(redNodes,"stopFlows").callsFake(function() { return Promise.resolve();} );
|
||||
var closeContextsPlugin = sinon.stub(redNodes,"closeContextsPlugin").callsFake(function() { return Promise.resolve();} );
|
||||
runtime.stop().then(function(){
|
||||
stopFlows.called.should.be.true();
|
||||
closeContextsPlugin.called.should.be.true();
|
||||
|
@@ -65,7 +65,7 @@ describe("runtime/library/examples", function() {
|
||||
}
|
||||
}
|
||||
});
|
||||
sinon.stub(fs,"readFile", function(path,opts,callback) {
|
||||
sinon.stub(fs,"readFile").callsFake(function(path,opts,callback) {
|
||||
if (path === "/tmp/test-module/abc") {
|
||||
callback(null,"Example flow result");
|
||||
} else if (path === "/tmp/@scope/test-module/abc") {
|
||||
|
@@ -37,14 +37,14 @@ var mockLog = {
|
||||
|
||||
describe("runtime/library", function() {
|
||||
before(function() {
|
||||
sinon.stub(localLibrary,"getEntry",function(type,path) {
|
||||
sinon.stub(localLibrary,"getEntry").callsFake(function(type,path) {
|
||||
return Promise.resolve({
|
||||
library: "local",
|
||||
type:type,
|
||||
path:path
|
||||
})
|
||||
});
|
||||
sinon.stub(localLibrary,"saveEntry",function(type, path, meta, body) {
|
||||
sinon.stub(localLibrary,"saveEntry").callsFake(function(type, path, meta, body) {
|
||||
return Promise.resolve({
|
||||
library: "local",
|
||||
type:type,
|
||||
@@ -53,7 +53,7 @@ describe("runtime/library", function() {
|
||||
body:body
|
||||
})
|
||||
});
|
||||
sinon.stub(examplesLibrary,"getEntry",function(type,path) {
|
||||
sinon.stub(examplesLibrary,"getEntry").callsFake(function(type,path) {
|
||||
return Promise.resolve({
|
||||
library: "_examples_",
|
||||
type:type,
|
||||
|
@@ -19,7 +19,7 @@ var sinon = require('sinon');
|
||||
var NR_TEST_UTILS = require("nr-test-utils");
|
||||
var RedNode = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
|
||||
var Log = NR_TEST_UTILS.require("@node-red/util").log;
|
||||
var hooks = NR_TEST_UTILS.require("@node-red/runtime/lib/hooks");
|
||||
var hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
|
||||
var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
|
||||
|
||||
describe('Node', function() {
|
||||
@@ -151,7 +151,7 @@ describe('Node', function() {
|
||||
|
||||
it('handles thrown errors', function(done) {
|
||||
var n = new RedNode({id:'123',type:'abc'});
|
||||
sinon.stub(n,"error",function(err,msg) {});
|
||||
sinon.stub(n,"error").callsFake(function(err,msg) {});
|
||||
var message = {payload:"hello world"};
|
||||
n.on('input',function(msg) {
|
||||
throw new Error("test error");
|
||||
@@ -271,7 +271,7 @@ describe('Node', function() {
|
||||
});
|
||||
it('logs error if callback provides error', function(done) {
|
||||
var n = new RedNode({id:'123',type:'abc'});
|
||||
sinon.stub(n,"error",function(err,msg) {});
|
||||
sinon.stub(n,"error").callsFake(function(err,msg) {});
|
||||
|
||||
var message = {payload:"hello world"};
|
||||
n.on('input',function(msg, nodeSend, nodeDone) {
|
||||
@@ -723,7 +723,7 @@ describe('Node', function() {
|
||||
it('produces a metric message', function(done) {
|
||||
var n = new RedNode({id:'123',type:'abc'});
|
||||
var loginfo = {};
|
||||
sinon.stub(Log, 'log', function(msg) {
|
||||
sinon.stub(Log, 'log').callsFake(function(msg) {
|
||||
loginfo = msg;
|
||||
});
|
||||
var msg = {payload:"foo", _msgid:"987654321"};
|
||||
@@ -739,7 +739,7 @@ describe('Node', function() {
|
||||
it('returns metric value if eventname undefined', function(done) {
|
||||
var n = new RedNode({id:'123',type:'abc'});
|
||||
var loginfo = {};
|
||||
sinon.stub(Log, 'log', function(msg) {
|
||||
sinon.stub(Log, 'log').callsFake(function(msg) {
|
||||
loginfo = msg;
|
||||
});
|
||||
var msg = {payload:"foo", _msgid:"987654321"};
|
||||
@@ -751,7 +751,7 @@ describe('Node', function() {
|
||||
it('returns not defined if eventname defined', function(done) {
|
||||
var n = new RedNode({id:'123',type:'abc'});
|
||||
var loginfo = {};
|
||||
sinon.stub(Log, 'log', function(msg) {
|
||||
sinon.stub(Log, 'log').callsFake(function(msg) {
|
||||
loginfo = msg;
|
||||
});
|
||||
var msg = {payload:"foo", _msgid:"987654321"};
|
||||
|
@@ -320,7 +320,7 @@ describe('context', function() {
|
||||
|
||||
describe('external context storage',function() {
|
||||
var resourcesDir = path.resolve(path.join(__dirname,"..","resources","context"));
|
||||
var sandbox = sinon.sandbox.create();
|
||||
var sandbox = sinon.createSandbox();
|
||||
var stubGet = sandbox.stub();
|
||||
var stubSet = sandbox.stub();
|
||||
var stubKeys = sandbox.stub();
|
||||
|
@@ -177,15 +177,15 @@ describe("red/nodes/index", function() {
|
||||
|
||||
var userDir = path.join(__dirname,".testUserHome");
|
||||
before(function(done) {
|
||||
sinon.stub(log,"log",function(){});
|
||||
sinon.stub(log,"log").callsFake(function(){});
|
||||
fs.remove(userDir,function(err) {
|
||||
fs.mkdir(userDir,function() {
|
||||
sinon.stub(index, 'load', function() {
|
||||
sinon.stub(index, 'load').callsFake(function() {
|
||||
return new Promise(function(resolve,reject){
|
||||
resolve([]);
|
||||
});
|
||||
});
|
||||
sinon.stub(localfilesystem, 'getCredentials', function() {
|
||||
sinon.stub(localfilesystem, 'getCredentials').callsFake(function() {
|
||||
return new Promise(function(resolve,reject) {
|
||||
resolve({"tab1":{"b":1,"c":2}});
|
||||
});
|
||||
@@ -271,7 +271,7 @@ describe("red/nodes/index", function() {
|
||||
var randomNodeInfo = {id:"5678",types:["random"]};
|
||||
|
||||
beforeEach(function() {
|
||||
sinon.stub(registry,"getNodeInfo",function(id) {
|
||||
sinon.stub(registry,"getNodeInfo").callsFake(function(id) {
|
||||
if (id == "test") {
|
||||
return {id:"1234",types:["test"]};
|
||||
} else if (id == "doesnotexist") {
|
||||
@@ -280,7 +280,7 @@ describe("red/nodes/index", function() {
|
||||
return randomNodeInfo;
|
||||
}
|
||||
});
|
||||
sinon.stub(registry,"disableNode",function(id) {
|
||||
sinon.stub(registry,"disableNode").callsFake(function(id) {
|
||||
return Promise.resolve(randomNodeInfo);
|
||||
});
|
||||
});
|
||||
@@ -343,7 +343,7 @@ describe("red/nodes/index", function() {
|
||||
};
|
||||
|
||||
before(function() {
|
||||
sinon.stub(registry,"getNodeInfo",function(id) {
|
||||
sinon.stub(registry,"getNodeInfo").callsFake(function(id) {
|
||||
if (id == "node-red/foo") {
|
||||
return {id:"1234",types:["test"]};
|
||||
} else if (id == "doesnotexist") {
|
||||
@@ -352,7 +352,7 @@ describe("red/nodes/index", function() {
|
||||
return randomNodeInfo;
|
||||
}
|
||||
});
|
||||
sinon.stub(registry,"getModuleInfo",function(module) {
|
||||
sinon.stub(registry,"getModuleInfo").callsFake(function(module) {
|
||||
if (module == "node-red") {
|
||||
return {nodes:[{name:"foo"}]};
|
||||
} else if (module == "doesnotexist") {
|
||||
@@ -361,7 +361,7 @@ describe("red/nodes/index", function() {
|
||||
return randomModuleInfo;
|
||||
}
|
||||
});
|
||||
sinon.stub(registry,"removeModule",function(id) {
|
||||
sinon.stub(registry,"removeModule").callsFake(function(id) {
|
||||
return randomModuleInfo;
|
||||
});
|
||||
});
|
||||
|
@@ -313,7 +313,7 @@ describe('storage/localfilesystem', function() {
|
||||
var flowFile = 'test.json';
|
||||
var flowFilePath = path.join(userDir,flowFile);
|
||||
localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||
sinon.stub(fs,"fsync", function(fd, cb) {
|
||||
sinon.stub(fs,"fsync").callsFake(function(fd, cb) {
|
||||
cb(new Error());
|
||||
});
|
||||
sinon.spy(log,"warn");
|
||||
|
@@ -34,7 +34,7 @@ describe("localfilesystem/projects/ssh/keygen", function() {
|
||||
var command;
|
||||
var args;
|
||||
var opts;
|
||||
sinon.stub(child_process,"spawn", function(_command,_args,_opts) {
|
||||
sinon.stub(child_process,"spawn").callsFake(function(_command,_args,_opts) {
|
||||
_command = command;
|
||||
_args = args;
|
||||
_opts = opts;
|
||||
|
@@ -41,7 +41,7 @@ describe("runtime/exec", function() {
|
||||
mockProcess = new EventEmitter();
|
||||
mockProcess.stdout = new EventEmitter();
|
||||
mockProcess.stderr = new EventEmitter();
|
||||
sinon.stub(child_process,'spawn',function(command,args,options) {
|
||||
sinon.stub(child_process,'spawn').callsFake(function(command,args,options) {
|
||||
mockProcess._args = {command,args,options};
|
||||
return mockProcess;
|
||||
});
|
||||
|
@@ -1,9 +1,9 @@
|
||||
const should = require("should");
|
||||
const NR_TEST_UTILS = require("nr-test-utils");
|
||||
|
||||
const hooks = NR_TEST_UTILS.require("@node-red/runtime/lib/hooks");
|
||||
const hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
|
||||
|
||||
describe("runtime/hooks", function() {
|
||||
describe("util/hooks", function() {
|
||||
afterEach(function() {
|
||||
hooks.clear();
|
||||
})
|
||||
@@ -81,7 +81,7 @@ describe("runtime/hooks", function() {
|
||||
hooks.has("onSend.A").should.be.false();
|
||||
hooks.has("onSend.B").should.be.false();
|
||||
hooks.has("onSend").should.be.false();
|
||||
|
||||
|
||||
done(err);
|
||||
} catch(err2) {
|
||||
done(err2);
|
||||
@@ -121,7 +121,46 @@ describe("runtime/hooks", function() {
|
||||
})
|
||||
})
|
||||
})
|
||||
it("allows a hook to remove itself whilst being called", function(done) {
|
||||
let data = { order: [] }
|
||||
hooks.add("onSend.A", function(payload) { payload.order.push("A") } )
|
||||
hooks.add("onSend.B", function(payload) {
|
||||
hooks.remove("*.B");
|
||||
})
|
||||
hooks.add("onSend.C", function(payload) { payload.order.push("C") } )
|
||||
hooks.add("onSend.D", function(payload) { payload.order.push("D") } )
|
||||
|
||||
hooks.trigger("onSend", data, err => {
|
||||
try {
|
||||
should.not.exist(err);
|
||||
data.order.should.eql(["A","C","D"])
|
||||
done();
|
||||
} catch(e) {
|
||||
done(e);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
it("allows a hook to remove itself and others whilst being called", function(done) {
|
||||
let data = { order: [] }
|
||||
hooks.add("onSend.A", function(payload) { payload.order.push("A") } )
|
||||
hooks.add("onSend.B", function(payload) {
|
||||
hooks.remove("*.B");
|
||||
hooks.remove("*.C");
|
||||
})
|
||||
hooks.add("onSend.C", function(payload) { payload.order.push("C") } )
|
||||
hooks.add("onSend.D", function(payload) { payload.order.push("D") } )
|
||||
|
||||
hooks.trigger("onSend", data, err => {
|
||||
try {
|
||||
should.not.exist(err);
|
||||
data.order.should.eql(["A","D"])
|
||||
done();
|
||||
} catch(e) {
|
||||
done(e);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
it("halts execution on return false", function(done) {
|
||||
hooks.add("onSend.A", function(payload) { payload.order.push("A"); return false } )
|
||||
@@ -249,4 +288,51 @@ describe("runtime/hooks", function() {
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
it("handler can use callback function - promise API", function(done) {
|
||||
hooks.add("onSend.A", function(payload, done) {
|
||||
setTimeout(function() {
|
||||
payload.order.push("A")
|
||||
done()
|
||||
},30)
|
||||
})
|
||||
hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
|
||||
|
||||
let data = { order:[] };
|
||||
hooks.trigger("onSend",data).then(() => {
|
||||
data.order.should.eql(["A","B"])
|
||||
done()
|
||||
}).catch(done)
|
||||
})
|
||||
|
||||
it("handler can halt execution - promise API", function(done) {
|
||||
hooks.add("onSend.A", function(payload, done) {
|
||||
setTimeout(function() {
|
||||
payload.order.push("A")
|
||||
done(false)
|
||||
},30)
|
||||
})
|
||||
hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
|
||||
|
||||
let data = { order:[] };
|
||||
hooks.trigger("onSend",data).then(() => {
|
||||
data.order.should.eql(["A"])
|
||||
done()
|
||||
}).catch(done)
|
||||
})
|
||||
|
||||
it("handler can halt execution on error - promise API", function(done) {
|
||||
hooks.add("onSend.A", function(payload, done) {
|
||||
throw new Error("error");
|
||||
})
|
||||
hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
|
||||
|
||||
let data = { order:[] };
|
||||
hooks.trigger("onSend",data).then(() => {
|
||||
done("hooks.trigger resolved unexpectedly")
|
||||
}).catch(err => {
|
||||
done();
|
||||
})
|
||||
})
|
||||
});
|
@@ -24,7 +24,7 @@ var log = NR_TEST_UTILS.require("@node-red/util").log;
|
||||
|
||||
describe("@node-red/util/log", function() {
|
||||
beforeEach(function () {
|
||||
var spy = sinon.stub(util, 'log', function(arg){});
|
||||
var spy = sinon.stub(util, 'log').callsFake(function(arg){});
|
||||
var settings = {logging: { console: { level: 'metric', metrics: true } } };
|
||||
log.init(settings);
|
||||
});
|
||||
|
@@ -33,9 +33,9 @@ describe("red/red", function() {
|
||||
|
||||
// describe("check build", function() {
|
||||
// beforeEach(function() {
|
||||
// sinon.stub(runtime,"init",function() {});
|
||||
// sinon.stub(api,"init",function() {});
|
||||
// // sinon.stub(RED,"version",function() { return "version";});
|
||||
// sinon.stub(runtime,"init").callsFake(function() {});
|
||||
// sinon.stub(api,"init").callsFake(function() {});
|
||||
// // sinon.stub(RED,"version").callsFake(function() { return "version";});
|
||||
// });
|
||||
// afterEach(function() {
|
||||
// runtime.init.restore();
|
||||
@@ -44,7 +44,7 @@ describe("red/red", function() {
|
||||
// // RED.version.restore();
|
||||
// });
|
||||
// it.skip('warns if build has not been run',function() {
|
||||
// sinon.stub(fs,"statSync",function() { throw new Error();});
|
||||
// sinon.stub(fs,"statSync").callsFake(function() { throw new Error();});
|
||||
//
|
||||
// /*jshint immed: false */
|
||||
// (function() {
|
||||
@@ -52,7 +52,7 @@ describe("red/red", function() {
|
||||
// }).should.throw("Node-RED not built");
|
||||
// });
|
||||
// it('passed if build has been run',function() {
|
||||
// sinon.stub(fs,"statSync",function() { });
|
||||
// sinon.stub(fs,"statSync").callsFake(function() { });
|
||||
// RED.init({},{});
|
||||
// });
|
||||
// });
|
||||
|
Reference in New Issue
Block a user