mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
31 Commits
fix-auto-c
...
Fix-file-w
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95a7980ada | ||
|
|
281e9d1357 | ||
|
|
946def022f | ||
|
|
c62a101635 | ||
|
|
32999ffa84 | ||
|
|
f06c53f1f1 | ||
|
|
a9eec28360 | ||
|
|
5cda972872 | ||
|
|
087946876b | ||
|
|
318f0f1b7e | ||
|
|
93c1600980 | ||
|
|
c3d1e6181f | ||
|
|
87e7f3a61c | ||
|
|
e724f216bf | ||
|
|
b0abba15a6 | ||
|
|
81b4874a7c | ||
|
|
f11b9c1e18 | ||
|
|
e15ecc00ce | ||
|
|
3e4c45ac6a | ||
|
|
4115c13a65 | ||
|
|
f872e2ab80 | ||
|
|
a81b1aa0cb | ||
|
|
efc0f1ab91 | ||
|
|
ce31edc803 | ||
|
|
199caccbc3 | ||
|
|
f060309002 | ||
|
|
fc3d86e6ff | ||
|
|
7507a7b459 | ||
|
|
d657817211 | ||
|
|
954649007c | ||
|
|
7bd7c99dd4 |
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@@ -5,6 +5,9 @@ on:
|
|||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
generate:
|
generate:
|
||||||
name: 'Update node-red-docker image'
|
name: 'Update node-red-docker image'
|
||||||
|
|||||||
10
.github/workflows/tests.yml
vendored
10
.github/workflows/tests.yml
vendored
@@ -6,16 +6,22 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master, dev ]
|
branches: [ master, dev ]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
permissions:
|
||||||
|
checks: write # for coverallsapp/github-action to create new checks
|
||||||
|
contents: read # for actions/checkout to fetch code
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [14, 16]
|
node-version: [14, 16]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
|
|||||||
@@ -935,11 +935,11 @@
|
|||||||
"errors": {
|
"errors": {
|
||||||
"invalid-expr": "不正なJSONata式:\n __message__",
|
"invalid-expr": "不正なJSONata式:\n __message__",
|
||||||
"invalid-msg": "不正なJSONメッセージ例:\n __message__",
|
"invalid-msg": "不正なJSONメッセージ例:\n __message__",
|
||||||
"context-unsupported": "$flowContext や $globalContextの\nコンテキスト機能をテストできません",
|
"context-unsupported": "$flowContext や $globalContextの\nコンテキスト関数をテストできません",
|
||||||
"env-unsupported": "$env関数はテストできません",
|
"env-unsupported": "$env関数はテストできません",
|
||||||
"moment-unsupported": "$moment関数はテストできません",
|
"moment-unsupported": "$moment関数はテストできません",
|
||||||
"clone-unsupported": "$clone関数はテストできません",
|
"clone-unsupported": "$clone関数はテストできません",
|
||||||
"eval": "表現評価エラー:\n __message__"
|
"eval": "式評価エラー:\n __message__"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"monaco": {
|
"monaco": {
|
||||||
|
|||||||
@@ -452,10 +452,12 @@
|
|||||||
|
|
||||||
$( "#node-input-outputs" ).spinner({
|
$( "#node-input-outputs" ).spinner({
|
||||||
min: 0,
|
min: 0,
|
||||||
|
max: 500,
|
||||||
change: function(event, ui) {
|
change: function(event, ui) {
|
||||||
var value = this.value;
|
var value = parseInt(this.value);
|
||||||
if (!value.match(/^\d+$/)) { value = 1; }
|
value = isNaN(value) ? 1 : value;
|
||||||
else if (value < this.min) { value = this.min; }
|
value = Math.max(value, parseInt($(this).attr("aria-valuemin")));
|
||||||
|
value = Math.min(value, parseInt($(this).attr("aria-valuemax")));
|
||||||
if (value !== this.value) { $(this).spinner("value", value); }
|
if (value !== this.value) { $(this).spinner("value", value); }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
var r = node.rules[currentRule];
|
var r = node.rules[currentRule];
|
||||||
if (r.t === "move") {
|
if (r.t === "move") {
|
||||||
if ((r.tot !== r.pt) || (r.p.indexOf(r.to) !== -1)) {
|
if ((r.tot !== r.pt) || (r.p.indexOf(r.to) !== -1) && (r.p !== r.to)) {
|
||||||
applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:r.p, tot:r.pt},(err,msg) => {
|
applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:r.p, tot:r.pt},(err,msg) => {
|
||||||
applyRule(msg,{t:"delete", p:r.p, pt:r.pt}, (err,msg) => {
|
applyRule(msg,{t:"delete", p:r.p, pt:r.pt}, (err,msg) => {
|
||||||
completeApplyingRules(msg,currentRule,done);
|
completeApplyingRules(msg,currentRule,done);
|
||||||
|
|||||||
@@ -421,7 +421,11 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
var typedInputNoneOpt = { value: 'none', label: '', hasValue: false };
|
var typedInputNoneOpt = {
|
||||||
|
value: 'none',
|
||||||
|
label: RED._("node-red:mqtt.label.none"),
|
||||||
|
hasValue: false
|
||||||
|
};
|
||||||
var makeTypedInputOpt = function(value){
|
var makeTypedInputOpt = function(value){
|
||||||
return {
|
return {
|
||||||
value: value,
|
value: value,
|
||||||
@@ -436,7 +440,11 @@
|
|||||||
makeTypedInputOpt("text/csv"),
|
makeTypedInputOpt("text/csv"),
|
||||||
makeTypedInputOpt("text/html"),
|
makeTypedInputOpt("text/html"),
|
||||||
makeTypedInputOpt("text/plain"),
|
makeTypedInputOpt("text/plain"),
|
||||||
{value:"other", label:""}
|
{
|
||||||
|
value: "other",
|
||||||
|
label: RED._("node-red:mqtt.label.other"),
|
||||||
|
icon: "red/images/typedInput/az.svg"
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
function getDefaultContentType(value) {
|
function getDefaultContentType(value) {
|
||||||
@@ -499,17 +507,17 @@
|
|||||||
cleansession: {value: true},
|
cleansession: {value: true},
|
||||||
birthTopic: {value:"", validate:validateMQTTPublishTopic},
|
birthTopic: {value:"", validate:validateMQTTPublishTopic},
|
||||||
birthQos: {value:"0"},
|
birthQos: {value:"0"},
|
||||||
birthRetain: {value:false},
|
birthRetain: {value:"false"},
|
||||||
birthPayload: {value:""},
|
birthPayload: {value:""},
|
||||||
birthMsg: { value: {}},
|
birthMsg: { value: {}},
|
||||||
closeTopic: {value:"", validate:validateMQTTPublishTopic},
|
closeTopic: {value:"", validate:validateMQTTPublishTopic},
|
||||||
closeQos: {value:"0"},
|
closeQos: {value:"0"},
|
||||||
closeRetain: {value:false},
|
closeRetain: {value:"false"},
|
||||||
closePayload: {value:""},
|
closePayload: {value:""},
|
||||||
closeMsg: { value: {}},
|
closeMsg: { value: {}},
|
||||||
willTopic: {value:"", validate:validateMQTTPublishTopic},
|
willTopic: {value:"", validate:validateMQTTPublishTopic},
|
||||||
willQos: {value:"0"},
|
willQos: {value:"0"},
|
||||||
willRetain: {value:false},
|
willRetain: {value:"false"},
|
||||||
willPayload: {value:""},
|
willPayload: {value:""},
|
||||||
willMsg: { value: {}},
|
willMsg: { value: {}},
|
||||||
userProps: { value: ""},
|
userProps: { value: ""},
|
||||||
|
|||||||
@@ -459,7 +459,6 @@ module.exports = function(RED) {
|
|||||||
if(!opts || typeof opts !== "object") {
|
if(!opts || typeof opts !== "object") {
|
||||||
return; //nothing to change, simply return
|
return; //nothing to change, simply return
|
||||||
}
|
}
|
||||||
const originalBrokerURL = node.brokerurl;
|
|
||||||
|
|
||||||
//apply property changes (only if the property exists in the opts object)
|
//apply property changes (only if the property exists in the opts object)
|
||||||
setIfHasProperty(opts, node, "url", init);
|
setIfHasProperty(opts, node, "url", init);
|
||||||
@@ -468,7 +467,6 @@ module.exports = function(RED) {
|
|||||||
setIfHasProperty(opts, node, "clientid", init);
|
setIfHasProperty(opts, node, "clientid", init);
|
||||||
setIfHasProperty(opts, node, "autoConnect", init);
|
setIfHasProperty(opts, node, "autoConnect", init);
|
||||||
setIfHasProperty(opts, node, "usetls", init);
|
setIfHasProperty(opts, node, "usetls", init);
|
||||||
setIfHasProperty(opts, node, "usews", init);
|
|
||||||
setIfHasProperty(opts, node, "verifyservercert", init);
|
setIfHasProperty(opts, node, "verifyservercert", init);
|
||||||
setIfHasProperty(opts, node, "compatmode", init);
|
setIfHasProperty(opts, node, "compatmode", init);
|
||||||
setIfHasProperty(opts, node, "protocolVersion", init);
|
setIfHasProperty(opts, node, "protocolVersion", init);
|
||||||
@@ -571,9 +569,6 @@ module.exports = function(RED) {
|
|||||||
if (typeof node.usetls === 'undefined') {
|
if (typeof node.usetls === 'undefined') {
|
||||||
node.usetls = false;
|
node.usetls = false;
|
||||||
}
|
}
|
||||||
if (typeof node.usews === 'undefined') {
|
|
||||||
node.usews = false;
|
|
||||||
}
|
|
||||||
if (typeof node.verifyservercert === 'undefined') {
|
if (typeof node.verifyservercert === 'undefined') {
|
||||||
node.verifyservercert = false;
|
node.verifyservercert = false;
|
||||||
}
|
}
|
||||||
@@ -1000,7 +995,7 @@ module.exports = function(RED) {
|
|||||||
node.client.publish(msg.topic, msg.payload, options, function (err) {
|
node.client.publish(msg.topic, msg.payload, options, function (err) {
|
||||||
if (done) {
|
if (done) {
|
||||||
done(err)
|
done(err)
|
||||||
} else {
|
} else if(err) {
|
||||||
node.error(err, msg)
|
node.error(err, msg)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ module.exports = function(RED) {
|
|||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
var node = this;
|
var node = this;
|
||||||
this.headers = n.headers||{};
|
this.headers = n.headers||{};
|
||||||
this.statusCode = n.statusCode;
|
this.statusCode = parseInt(n.statusCode);
|
||||||
this.on("input",function(msg,_send,done) {
|
this.on("input",function(msg,_send,done) {
|
||||||
if (msg.res) {
|
if (msg.res) {
|
||||||
var headers = RED.util.cloneMessage(node.headers);
|
var headers = RED.util.cloneMessage(node.headers);
|
||||||
@@ -323,7 +323,7 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var statusCode = node.statusCode || msg.statusCode || 200;
|
var statusCode = node.statusCode || parseInt(msg.statusCode) || 200;
|
||||||
if (typeof msg.payload == "object" && !Buffer.isBuffer(msg.payload)) {
|
if (typeof msg.payload == "object" && !Buffer.isBuffer(msg.payload)) {
|
||||||
msg.res._res.status(statusCode).jsonp(msg.payload);
|
msg.res._res.status(statusCode).jsonp(msg.payload);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -110,7 +110,12 @@ module.exports = function(RED) {
|
|||||||
if (msg.payload[s].hasOwnProperty(p)) {
|
if (msg.payload[s].hasOwnProperty(p)) {
|
||||||
/* istanbul ignore else */
|
/* istanbul ignore else */
|
||||||
if (typeof msg.payload[s][p] !== "object") {
|
if (typeof msg.payload[s][p] !== "object") {
|
||||||
var q = "" + msg.payload[s][p];
|
// Fix to honour include null values flag
|
||||||
|
//if (typeof msg.payload[s][p] !== "object" || (node.include_null_values === true && msg.payload[s][p] === null)) {
|
||||||
|
var q = "";
|
||||||
|
if (msg.payload[s][p] !== undefined) {
|
||||||
|
q += msg.payload[s][p];
|
||||||
|
}
|
||||||
if (q.indexOf(node.quo) !== -1) { // add double quotes if any quotes
|
if (q.indexOf(node.quo) !== -1) { // add double quotes if any quotes
|
||||||
q = q.replace(/"/g, '""');
|
q = q.replace(/"/g, '""');
|
||||||
ou += node.quo + q + node.quo + node.sep;
|
ou += node.quo + q + node.quo + node.sep;
|
||||||
@@ -130,9 +135,12 @@ module.exports = function(RED) {
|
|||||||
ou += node.sep;
|
ou += node.sep;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var p = RED.util.ensureString(RED.util.getMessageProperty(msg,"payload["+s+"]['"+template[t]+"']"));
|
var p = RED.util.getMessageProperty(msg,"payload["+s+"]['"+template[t]+"']");
|
||||||
/* istanbul ignore else */
|
/* istanbul ignore else */
|
||||||
if (p === "undefined") { p = ""; }
|
if (p === undefined) { p = ""; }
|
||||||
|
// fix to honour include null values flag
|
||||||
|
//if (p === null && node.include_null_values !== true) { p = "";}
|
||||||
|
p = RED.util.ensureString(p);
|
||||||
if (p.indexOf(node.quo) !== -1) { // add double quotes if any quotes
|
if (p.indexOf(node.quo) !== -1) { // add double quotes if any quotes
|
||||||
p = p.replace(/"/g, '""');
|
p = p.replace(/"/g, '""');
|
||||||
ou += node.quo + p + node.quo + node.sep;
|
ou += node.quo + p + node.quo + node.sep;
|
||||||
|
|||||||
@@ -117,7 +117,9 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
if (typeof data === "boolean") { data = data.toString(); }
|
if (typeof data === "boolean") { data = data.toString(); }
|
||||||
if (typeof data === "number") { data = data.toString(); }
|
if (typeof data === "number") { data = data.toString(); }
|
||||||
if ((node.appendNewline) && (!Buffer.isBuffer(data))) { data += os.EOL; }
|
var aflg = true;
|
||||||
|
if (msg.hasOwnProperty("parts") && msg.parts.type === "string" && (msg.parts.count === msg.parts.index + 1)) { aflg = false; }
|
||||||
|
if ((node.appendNewline) && (!Buffer.isBuffer(data)) && aflg) { data += os.EOL; }
|
||||||
var buf;
|
var buf;
|
||||||
if (node.encoding === "setbymsg") {
|
if (node.encoding === "setbymsg") {
|
||||||
buf = encode(data, msg.encoding || "none");
|
buf = encode(data, msg.encoding || "none");
|
||||||
@@ -314,7 +316,6 @@ module.exports = function(RED) {
|
|||||||
});
|
});
|
||||||
filename = filename || "";
|
filename = filename || "";
|
||||||
var fullFilename = filename;
|
var fullFilename = filename;
|
||||||
var filePath = "";
|
|
||||||
if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) {
|
if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) {
|
||||||
fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename));
|
fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,4 +52,7 @@
|
|||||||
used to mark the templated sections. For example, to use <code>[[ ]]</code>
|
used to mark the templated sections. For example, to use <code>[[ ]]</code>
|
||||||
instead, add the following line to the top of the template:</p>
|
instead, add the following line to the top of the template:</p>
|
||||||
<pre>{{=[[ ]]=}}</pre>
|
<pre>{{=[[ ]]=}}</pre>
|
||||||
|
<h4>Using environment variables</h4>
|
||||||
|
<p>The template node can access environment variables using the syntax:</p>
|
||||||
|
<pre>My favourite colour is {{env.COLOUR}}.</pre>
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -446,7 +446,9 @@
|
|||||||
"staticTopic": "Subscribe to single topic",
|
"staticTopic": "Subscribe to single topic",
|
||||||
"dynamicTopic": "Dynamic subscription",
|
"dynamicTopic": "Dynamic subscription",
|
||||||
"auto-connect": "Connect automatically",
|
"auto-connect": "Connect automatically",
|
||||||
"auto-mode-depreciated": "This option is depreciated. Please use the new auto-detect mode."
|
"auto-mode-depreciated": "This option is depreciated. Please use the new auto-detect mode.",
|
||||||
|
"none": "none",
|
||||||
|
"other": "other"
|
||||||
},
|
},
|
||||||
"sections-label": {
|
"sections-label": {
|
||||||
"birth-message": "Message sent on connection (birth message)",
|
"birth-message": "Message sent on connection (birth message)",
|
||||||
|
|||||||
@@ -48,4 +48,7 @@
|
|||||||
<p><b>注: </b>デフォルトでは、<i>mustache</i>形式は置換対象のHTML要素をエスケープします。これを抑止するには<code>{{{三重}}}</code>括弧形式を使います。</p>
|
<p><b>注: </b>デフォルトでは、<i>mustache</i>形式は置換対象のHTML要素をエスケープします。これを抑止するには<code>{{{三重}}}</code>括弧形式を使います。</p>
|
||||||
<p>もし、コンテンツの中で<code>{{ }}</code>を出力する必要がある場合は、テンプレートで使われる記号文字を変えることもできます。例えば、<code>[[ ]]</code>を代わりに用いるには、テンプレートの先頭に以下の行を追加します。</p>
|
<p>もし、コンテンツの中で<code>{{ }}</code>を出力する必要がある場合は、テンプレートで使われる記号文字を変えることもできます。例えば、<code>[[ ]]</code>を代わりに用いるには、テンプレートの先頭に以下の行を追加します。</p>
|
||||||
<pre>{{=[[ ]]=}}</pre>
|
<pre>{{=[[ ]]=}}</pre>
|
||||||
|
<h4>環境変数の利用</h4>
|
||||||
|
<p>templateノードでは、次の構文を用いると環境変数にアクセスできます:</p>
|
||||||
|
<pre>私の好きな色は{{env.COLOUR}}です。</pre>
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -446,7 +446,9 @@
|
|||||||
"staticTopic": "1つのトピックを購読",
|
"staticTopic": "1つのトピックを購読",
|
||||||
"dynamicTopic": "動的な購読",
|
"dynamicTopic": "動的な購読",
|
||||||
"auto-connect": "自動接続",
|
"auto-connect": "自動接続",
|
||||||
"auto-mode-depreciated": "本オプションは非推奨になりました。新しい自動判定モードを使用してください。"
|
"auto-mode-depreciated": "本オプションは非推奨になりました。新しい自動判定モードを使用してください。",
|
||||||
|
"none": "なし",
|
||||||
|
"other": "その他"
|
||||||
},
|
},
|
||||||
"sections-label": {
|
"sections-label": {
|
||||||
"birth-message": "接続時の送信メッセージ(Birthメッセージ)",
|
"birth-message": "接続時の送信メッセージ(Birthメッセージ)",
|
||||||
|
|||||||
@@ -1717,6 +1717,24 @@ describe('change Node', function() {
|
|||||||
changeNode1.receive({topic:{foo:{bar:1}}, payload:"String"});
|
changeNode1.receive({topic:{foo:{bar:1}}, payload:"String"});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('moves the value of a message property object to itself', function(done) {
|
||||||
|
var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"move","p":"payload","pt":"msg","to":"payload","tot":"msg"}],"name":"changeNode","wires":[["helperNode1"]]},
|
||||||
|
{id:"helperNode1", type:"helper", wires:[]}];
|
||||||
|
helper.load(changeNode, flow, function() {
|
||||||
|
var changeNode1 = helper.getNode("changeNode1");
|
||||||
|
var helperNode1 = helper.getNode("helperNode1");
|
||||||
|
helperNode1.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property('payload');
|
||||||
|
msg.payload.should.equal("bar");
|
||||||
|
done();
|
||||||
|
} catch(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
changeNode1.receive({payload:"bar"});
|
||||||
|
});
|
||||||
|
});
|
||||||
it('moves the value of a message property object to a sub-property', function(done) {
|
it('moves the value of a message property object to a sub-property', function(done) {
|
||||||
var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"move","p":"payload","pt":"msg","to":"payload.foo","tot":"msg"}],"name":"changeNode","wires":[["helperNode1"]]},
|
var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"move","p":"payload","pt":"msg","to":"payload.foo","tot":"msg"}],"name":"changeNode","wires":[["helperNode1"]]},
|
||||||
{id:"helperNode1", type:"helper", wires:[]}];
|
{id:"helperNode1", type:"helper", wires:[]}];
|
||||||
|
|||||||
@@ -2322,7 +2322,7 @@ describe('HTTP Request Node', function() {
|
|||||||
var n2 = helper.getNode("n2");
|
var n2 = helper.getNode("n2");
|
||||||
n2.on('input', function(msg) {
|
n2.on('input', function(msg) {
|
||||||
try{
|
try{
|
||||||
msg.payload.should.equal(`RequestError: Parse Error: Missing expected CR after header value : http://localhost:${port}/`)
|
msg.payload.should.match(/RequestError: Parse Error/)
|
||||||
done()
|
done()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
done(err)
|
done(err)
|
||||||
|
|||||||
@@ -489,6 +489,39 @@ describe('MQTT Nodes', function () {
|
|||||||
}
|
}
|
||||||
testSendRecv(brokerOptions, { topic: brokerOptions.birthTopic }, {}, options, hooks);
|
testSendRecv(brokerOptions, { topic: brokerOptions.birthTopic }, {}, options, hooks);
|
||||||
});
|
});
|
||||||
|
itConditional('should safely discard bad birth topic', function (done) {
|
||||||
|
if (skipTests) { return this.skip() }
|
||||||
|
this.timeout = 2000;
|
||||||
|
const baseTopic = nextTopic();
|
||||||
|
const brokerOptions = {
|
||||||
|
protocolVersion: 4,
|
||||||
|
birthTopic: baseTopic + "#", // a publish topic should never have a wildcard
|
||||||
|
birthPayload: "broker connected",
|
||||||
|
birthQos: 2,
|
||||||
|
}
|
||||||
|
const options = {};
|
||||||
|
const hooks = { done: null, beforeLoad: null, afterLoad: null, afterConnect: null };
|
||||||
|
hooks.afterLoad = (helperNode, mqttBroker, mqttIn, mqttOut) => {
|
||||||
|
helperNode.on("input", function (msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.a.property("error").type("object");
|
||||||
|
msg.error.should.have.a.property("source").type("object");
|
||||||
|
msg.error.source.should.have.a.property("id", mqttIn.id);
|
||||||
|
done();
|
||||||
|
} catch (err) {
|
||||||
|
done(err)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true; //handled
|
||||||
|
}
|
||||||
|
options.expectMsg = null;
|
||||||
|
try {
|
||||||
|
testSendRecv(brokerOptions, { topic: brokerOptions.birthTopic }, {}, options, hooks);
|
||||||
|
done()
|
||||||
|
} catch(err) {
|
||||||
|
done(e)
|
||||||
|
}
|
||||||
|
});
|
||||||
itConditional('should publish close message', function (done) {
|
itConditional('should publish close message', function (done) {
|
||||||
if (skipTests) { return this.skip() }
|
if (skipTests) { return this.skip() }
|
||||||
this.timeout = 2000;
|
this.timeout = 2000;
|
||||||
@@ -646,12 +679,13 @@ function testSendRecv(brokerOptions, inNodeOptions, outNodeOptions, options, hoo
|
|||||||
const mqttBroker = helper.getNode(brokerOptions.id);
|
const mqttBroker = helper.getNode(brokerOptions.id);
|
||||||
const mqttIn = helper.getNode(nodes.mqtt_in.id);
|
const mqttIn = helper.getNode(nodes.mqtt_in.id);
|
||||||
const mqttOut = helper.getNode(nodes.mqtt_out.id);
|
const mqttOut = helper.getNode(nodes.mqtt_out.id);
|
||||||
let afterLoadHandled = false;
|
let afterLoadHandled = false, finished = false;
|
||||||
if (hooks.afterLoad) {
|
if (hooks.afterLoad) {
|
||||||
afterLoadHandled = hooks.afterLoad(helperNode, mqttBroker, mqttIn, mqttOut)
|
afterLoadHandled = hooks.afterLoad(helperNode, mqttBroker, mqttIn, mqttOut)
|
||||||
}
|
}
|
||||||
if (!afterLoadHandled) {
|
if (!afterLoadHandled) {
|
||||||
helperNode.on("input", function (msg) {
|
helperNode.on("input", function (msg) {
|
||||||
|
finished = true
|
||||||
try {
|
try {
|
||||||
compareMsgToExpected(msg, expectMsg);
|
compareMsgToExpected(msg, expectMsg);
|
||||||
if (hooks.done) { hooks.done(); }
|
if (hooks.done) { hooks.done(); }
|
||||||
@@ -676,10 +710,12 @@ function testSendRecv(brokerOptions, inNodeOptions, outNodeOptions, options, hoo
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
|
if(finished) { return }
|
||||||
if (hooks.done) { hooks.done(e); }
|
if (hooks.done) { hooks.done(e); }
|
||||||
else { throw e; }
|
else { throw e; }
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
if(finished) { return }
|
||||||
if (hooks.done) { hooks.done(err); }
|
if (hooks.done) { hooks.done(err); }
|
||||||
else { throw err; }
|
else { throw err; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -693,19 +693,20 @@ describe('CSV node', function() {
|
|||||||
describe('json object to csv', function() {
|
describe('json object to csv', function() {
|
||||||
|
|
||||||
it('should convert a simple object back to a csv', function(done) {
|
it('should convert a simple object back to a csv', function(done) {
|
||||||
var flow = [ { id:"n1", type:"csv", temp:"a,b,c,,e,f", wires:[["n2"]] },
|
var flow = [ { id:"n1", type:"csv", temp:"a,b,c,,e,f,g,h,i,j,k", wires:[["n2"]] },
|
||||||
{id:"n2", type:"helper"} ];
|
{id:"n2", type:"helper"} ];
|
||||||
helper.load(csvNode, flow, function() {
|
helper.load(csvNode, flow, function() {
|
||||||
var n1 = helper.getNode("n1");
|
var n1 = helper.getNode("n1");
|
||||||
var n2 = helper.getNode("n2");
|
var n2 = helper.getNode("n2");
|
||||||
n2.on("input", function(msg) {
|
n2.on("input", function(msg) {
|
||||||
|
// console.log("GOT",msg)
|
||||||
try {
|
try {
|
||||||
msg.should.have.property('payload', '4,foo,true,,0,"Hello\nWorld"\n');
|
msg.should.have.property('payload', '4,foo,true,,0,"Hello\nWorld",,,undefined,null,null\n');
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
catch(e) { done(e); }
|
catch(e) { done(e); }
|
||||||
});
|
});
|
||||||
var testJson = { e:0, d:1, b:"foo", c:true, a:4, f:"Hello\nWorld" };
|
var testJson = { e:0, d:1, b:"foo", c:true, a:4, f:"Hello\nWorld", h:undefined, i:"undefined",j:null,k:"null" };
|
||||||
n1.emit("input", {payload:testJson});
|
n1.emit("input", {payload:testJson});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -717,13 +718,14 @@ describe('CSV node', function() {
|
|||||||
var n1 = helper.getNode("n1");
|
var n1 = helper.getNode("n1");
|
||||||
var n2 = helper.getNode("n2");
|
var n2 = helper.getNode("n2");
|
||||||
n2.on("input", function(msg) {
|
n2.on("input", function(msg) {
|
||||||
|
// console.log("GOT",msg)
|
||||||
try {
|
try {
|
||||||
msg.should.have.property('payload', '1,foo,"ba""r","di,ng"\n');
|
msg.should.have.property('payload', '1,foo,"ba""r","di,ng",,undefined,null\n');
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
catch(e) { done(e); }
|
catch(e) { done(e); }
|
||||||
});
|
});
|
||||||
var testJson = { d:1, b:"foo", c:"ba\"r", a:"di,ng" };
|
var testJson = { d:1, b:"foo", c:"ba\"r", a:"di,ng", e:undefined, f:"undefined", g:null,h:"null" };
|
||||||
n1.emit("input", {payload:testJson});
|
n1.emit("input", {payload:testJson});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -194,6 +194,55 @@ describe('file Nodes', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should append to a file and add newline, except last line of multipart input', function(done) {
|
||||||
|
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":true, "overwriteFile":false, wires: [["helperNode1"]]},
|
||||||
|
{id:"helperNode1", type:"helper"}];
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(fileToTest);
|
||||||
|
} catch(err) {
|
||||||
|
}
|
||||||
|
helper.load(fileNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("fileNode1");
|
||||||
|
var n2 = helper.getNode("helperNode1");
|
||||||
|
var count = 0;
|
||||||
|
//var data = ["Line1", "Line2"];
|
||||||
|
|
||||||
|
n2.on("input", function (msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property("payload");
|
||||||
|
//data.should.containDeep([msg.payload]);
|
||||||
|
if (count === 3) {
|
||||||
|
var f = fs.readFileSync(fileToTest).toString();
|
||||||
|
if (os.type() !== "Windows_NT") {
|
||||||
|
f.should.have.length(23);
|
||||||
|
f.should.equal("Line1\nLine2\nLine3\nLine4");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
f.should.have.length(23);
|
||||||
|
f.should.equal("Line1\r\nLine2\r\nLine3\r\nLine4");
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
done(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
n1.receive({payload:"Line1",parts:{index:0,type:"string"}}); // string
|
||||||
|
setTimeout(function() {
|
||||||
|
n1.receive({payload:"Line2",parts:{index:1,type:"string"}}); // string
|
||||||
|
},30);
|
||||||
|
setTimeout(function() {
|
||||||
|
n1.receive({payload:"Line3",parts:{index:2,type:"string"}}); // string
|
||||||
|
},60);
|
||||||
|
setTimeout(function() {
|
||||||
|
n1.receive({payload:"Line4",parts:{index:3,type:"string",count:4}}); // string
|
||||||
|
},90);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should append to a file after it has been deleted ', function(done) {
|
it('should append to a file after it has been deleted ', function(done) {
|
||||||
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":false, wires: [["helperNode1"]]},
|
var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":false, wires: [["helperNode1"]]},
|
||||||
{id:"helperNode1", type:"helper"}];
|
{id:"helperNode1", type:"helper"}];
|
||||||
|
|||||||
Reference in New Issue
Block a user