').appendTo(metaRow);
- var resetButton = $('use default ').appendTo(metaRow).click(function(e) {
+ var resetButton = $(''+RED._("editor.useDefault")+' ').appendTo(metaRow).click(function(e) {
e.preventDefault();
hide();
done(null);
diff --git a/nodes/core/core/89-trigger.html b/nodes/core/core/89-trigger.html
index 57b8e4ba8..3bbdfe603 100644
--- a/nodes/core/core/89-trigger.html
+++ b/nodes/core/core/89-trigger.html
@@ -162,7 +162,7 @@
$("#node-input-op1").typedInput({
default: 'str',
typeField: $("#node-input-op1type"),
- types:['flow','global','str','num','bool','json',
+ types:['flow','global','str','num','bool','json','bin','date','env',
optionPayload,
optionNothing
]
@@ -170,7 +170,7 @@
$("#node-input-op2").typedInput({
default: 'str',
typeField: $("#node-input-op2type"),
- types:['flow','global','str','num','bool','json',
+ types:['flow','global','str','num','bool','json','bin','date','env',
optionOriginalPayload,
optionLatestPayload,
optionNothing
diff --git a/nodes/core/locales/ja/core/75-exec.html b/nodes/core/locales/ja/core/75-exec.html
index bc7d9b5de..7eb75b10a 100644
--- a/nodes/core/locales/ja/core/75-exec.html
+++ b/nodes/core/locales/ja/core/75-exec.html
@@ -26,7 +26,7 @@
kill 文字列
execノードのプロセスに対して送るシグナルの種別を指定します
pid 数値|文字列
- シグナル送信対象のexecノードのプロセスID
+ シグナル送信対象のexecノードのプロセスIDを指定します
出力
@@ -60,13 +60,12 @@
詳細
デフォルトでは、exec
システムコールを用いてコマンドを呼び出してその完了を待ち、出力を返します。例えば、コマンドの実行が成功した場合には、{ code: 0 }
と言う返却値を返します。
- spawn
を使ってコマンドを実行し、
-標準出力および標準エラー出力へ出力を返すようにすることもできます。この場合、通常1行毎に値を返します。コマンドの実行が完了すると、3番目の端子にオブジェクトを出力します。例えば、コマンドの実行が成功した場合には、{ code: 0 }
と言う返却値を返します。
+ spawn
を使ってコマンドを実行し、標準出力および標準エラー出力へ出力を返すようにすることもできます。この場合、通常1行毎に値を返します。コマンドの実行が完了すると、3番目の端子にオブジェクトを出力します。例えば、コマンドの実行が成功した場合には、{ code: 0 }
という返却値を返します。
エラー発生時には、3番目の端子のmsg.payload
にmessage
、signal
など付加情報を返します。
実行対象のコマンドはノード設定で定義します。msg.payload
や追加引数をコマンドに追加することもできます。
- コマンドもしくはパラメータが空白を含む場合には、引用符で囲みます。- "This is a single parameter"
+ コマンドもしくはパラメータが空白を含む場合には、引用符で囲みます。- "これは一つのパラメータです"
返却するpayload
は通常文字列 ですが、UTF8文字以外が存在するとバッファ となります。
- ノードが実行中の場合、ステータスアイコンとPIDを表示します。この状態変化はstatus
ノードで検知できます。
+ ノードが実行中の場合、ステータスアイコンとPIDを表示します。この状態変化はStatus
ノードで検知できます。
プロセスの停止
msg.kill
を受信すると、実行中のプロセスを停止することができます。msg.kill
には送出するシグナルの種別を指定します。例えば、SIGINT
、SIGQUIT
、SIGHUP
などです。空の文字列を指定した場合には、SIGTERM
を指定したものとみなします。
ノードが1つ以上のプロセスを実行している場合、msg.pid
に停止対象のPIDを指定しなければなりません。
diff --git a/nodes/core/locales/ja/io/21-httprequest.html b/nodes/core/locales/ja/io/21-httprequest.html
index 7740632c1..662367343 100644
--- a/nodes/core/locales/ja/io/21-httprequest.html
+++ b/nodes/core/locales/ja/io/21-httprequest.html
@@ -30,7 +30,9 @@
payload
リクエストボディとして送るデータ
rejectUnauthorized
- true
をセットすると、自己署名証明書を使用するhttpsサイトへのリクエストを許可します。
+ false
をセットすると、自己署名証明書を使用するhttpsサイトへのリクエストを許可します。
+ followRedirects
+ false
をセットすると、リダイレクトを行いません。デフォルトはtrue
です。
出力
diff --git a/nodes/core/locales/ja/logic/10-switch.html b/nodes/core/locales/ja/logic/10-switch.html
index bb0e20ac8..2417ad164 100644
--- a/nodes/core/locales/ja/logic/10-switch.html
+++ b/nodes/core/locales/ja/logic/10-switch.html
@@ -29,7 +29,11 @@
その他 - これより前のルールにマッチするものがなかった場合に適用
+ 注釈
+ is true/false
とis null
のルールは、型に対して厳密な比較を行います。型変換した上での比較はしません。
+ is empty
のルールは、長さ0の文字列・配列・バッファ、またはプロパティを持たないオブジェクトを出力します。null
やundefined
は出力しません。
+
メッセージ列の扱い
switchノードは入力メッセージの列に関する情報を保持するmsg.parts
をデフォルトでは変更しません。
- 「メッセージ列の補正 」オプションを指定すると、マッチした各ルールに対して新しいメッセージ列を生成します。このモードでは、switchノードは新たなメッセージ列を送信する前に、入力メッセージ列全体を内部に蓄積します。nodeMessageBufferMaxLength
を設定すると、蓄積するメッセージ数を制限できます。
+ 「メッセージ列の補正 」オプションを指定すると、マッチした各ルールに対して新しいメッセージ列を生成します。このモードでは、switchノードは新たなメッセージ列を送信する前に、入力メッセージ列全体を内部に蓄積します。settings.js のnodeMessageBufferMaxLength
を設定すると、蓄積するメッセージ数を制限できます。
diff --git a/nodes/core/locales/ja/logic/19-batch.html b/nodes/core/locales/ja/logic/19-batch.html
index 6109866ff..41cef364c 100644
--- a/nodes/core/locales/ja/logic/19-batch.html
+++ b/nodes/core/locales/ja/logic/19-batch.html
@@ -30,5 +30,5 @@
メッセージの蓄積
- このノードの処理ではメッセージ列の処理のためメッセージを内部に蓄積します。nodeMessageBufferMaxLength
を指定することで蓄積するメッセージの最大値を制限することができます。
+ このノードの処理ではメッセージ列の処理のためメッセージを内部に蓄積します。settings.js のnodeMessageBufferMaxLength
を指定することで蓄積するメッセージの最大値を制限することができます。
diff --git a/nodes/core/locales/ja/parsers/70-JSON.html b/nodes/core/locales/ja/parsers/70-JSON.html
index 2199d7f89..80595789f 100644
--- a/nodes/core/locales/ja/parsers/70-JSON.html
+++ b/nodes/core/locales/ja/parsers/70-JSON.html
@@ -20,6 +20,8 @@
payloadオブジェクト | 文字列
JavaScriptオブジェクトもしくはJSON文字列
+ schemaオブジェクト
+ JSONの検証に利用するJSONスキーマ。設定されていない場合は検証を行いません。
出力
@@ -30,9 +32,12 @@
入力がJavaScriptオブジェクトの場合、JSON文字列に変換します。JSON文字列は整形することも可能です。
+ schemaError配列
+ JSONの検証でエラーが発生した場合、Catchノードを利用し、エラーを配列としてschemaError
プロパティから取得することができます。
詳細
デフォルトの変換対象はmsg.payload
ですが、他のメッセージプロパティを変換対象とすることも可能です。
双方向の変換を自動選択するのではなく、特定の変換のみ行うように設定できます。この機能は、例えば、HTTP In
ノードに対するリクエストがcontent-typeを正しく設定していない場合であっても、JSONノードによる変換結果がJavaScriptオブジェクトであることを保証するために利用します。
JSON文字列への変換が指定されている場合、受信した文字列に対してさらなるチェックは行いません。すなわち、文字列がJSONとして正しいかどうかの検査や、整形オプションを指定していたとしても整形処理を実施しません。
+ JSONスキーマの詳細については、こちら を参照してください。
diff --git a/nodes/core/locales/ja/storage/50-file.html b/nodes/core/locales/ja/storage/50-file.html
index 2e9bb839b..8bd5cdbaf 100644
--- a/nodes/core/locales/ja/storage/50-file.html
+++ b/nodes/core/locales/ja/storage/50-file.html
@@ -21,6 +21,8 @@
filename 文字列
対象ファイル名をノードに設定していない場合、このプロパティでファイルを指定できます
+ 出力
+ 書き込みの完了時、入力メッセージを出力端子に送出します。
詳細
入力メッセージのペイロードをファイルの最後に追記します。改行(\n)を各データの最後に追加することもできます。
msg.filename
を使う場合、書き込みを行う毎にファイルをクローズします。より良い性能を得るためにはファイル名をノードに設定してください。
diff --git a/nodes/core/logic/10-switch.html b/nodes/core/logic/10-switch.html
index de1acbae3..4b8c8405b 100644
--- a/nodes/core/logic/10-switch.html
+++ b/nodes/core/logic/10-switch.html
@@ -147,7 +147,7 @@
}
if ((rule.t === 'btwn') || (rule.t === 'index')) {
label += " "+getValueLabel(rule.vt,rule.v)+" & "+getValueLabel(rule.v2t,rule.v2);
- } else if (rule.t !== 'true' && rule.t !== 'false' && rule.t !== 'null' && rule.t !== 'nnull' && rule.t !== 'else' ) {
+ } else if (rule.t !== 'true' && rule.t !== 'false' && rule.t !== 'null' && rule.t !== 'nnull' && rule.t !== 'empty' && rule.t !== 'nempty' && rule.t !== 'else' ) {
label += " "+getValueLabel(rule.vt,rule.v);
}
return label;
@@ -199,7 +199,7 @@
} else if (type === "istype") {
typeField.typedInput("width",(newWidth-selectWidth-70));
} else {
- if (type === "true" || type === "false" || type === "null" || type === "nnull" || type === "else") {
+ if (type === "true" || type === "false" || type === "null" || type === "nnull" || type === "empty" || type === "nempty" || type === "else") {
// valueField.hide();
} else {
valueField.typedInput("width",(newWidth-selectWidth-70));
@@ -295,7 +295,7 @@
numValueField.typedInput('hide');
typeValueField.typedInput('hide');
valueField.typedInput('hide');
- if (type === "true" || type === "false" || type === "null" || type === "nnull" || type === "else") {
+ if (type === "true" || type === "false" || type === "null" || type === "nnull" || type === "empty" || type === "nempty" || type === "else") {
valueField.typedInput('hide');
typeValueField.typedInput('hide');
}
@@ -396,7 +396,7 @@
var rule = $(this);
var type = rule.find("select").val();
var r = {t:type};
- if (!(type === "true" || type === "false" || type === "null" || type === "nnull" || type === "else")) {
+ if (!(type === "true" || type === "false" || type === "null" || type === "nnull" || type === "empty" || type === "nempty" || type === "else")) {
if ((type === "btwn") || (type === "index")) {
r.v = rule.find(".node-input-rule-btwn-value").typedInput('value');
r.vt = rule.find(".node-input-rule-btwn-value").typedInput('type');
diff --git a/nodes/core/logic/10-switch.js b/nodes/core/logic/10-switch.js
index e7f5cc841..89593047e 100644
--- a/nodes/core/logic/10-switch.js
+++ b/nodes/core/logic/10-switch.js
@@ -34,7 +34,7 @@ module.exports = function(RED) {
'empty': function(a) {
if (typeof a === 'string' || Array.isArray(a) || Buffer.isBuffer(a)) {
return a.length === 0;
- } else if (typeof a === 'object') {
+ } else if (typeof a === 'object' && a !== null) {
return Object.keys(a).length === 0;
}
return false;
@@ -42,7 +42,7 @@ module.exports = function(RED) {
'nempty': function(a) {
if (typeof a === 'string' || Array.isArray(a) || Buffer.isBuffer(a)) {
return a.length !== 0;
- } else if (typeof a === 'object') {
+ } else if (typeof a === 'object' && a !== null) {
return Object.keys(a).length !== 0;
}
return false;
diff --git a/nodes/core/logic/15-change.js b/nodes/core/logic/15-change.js
index 4a1ce33ec..2c1443846 100644
--- a/nodes/core/logic/15-change.js
+++ b/nodes/core/logic/15-change.js
@@ -143,7 +143,7 @@ module.exports = function(RED) {
if (rule.fromt === "msg") {
resolve(RED.util.getMessageProperty(msg,rule.from));
} else if (rule.fromt === 'flow' || rule.fromt === 'global') {
- var contextKey = RED.util.parseContextStore(rule.from);
+ var contextKey = RED.util.parseContextStore(rule.from);
node.context()[rule.fromt].get(contextKey.key, contextKey.store, (err,fromValue) => {
if (err) {
reject(err);
@@ -166,12 +166,10 @@ module.exports = function(RED) {
try {
fromRE = new RegExp(fromRE, "g");
} catch (e) {
- reject(new Error(RED._("change.errors.invalid-from",{error:e.message})));
- return;
+ return Promise.reject(new Error(RED._("change.errors.invalid-from",{error:e.message})));
}
} else {
- reject(new Error(RED._("change.errors.invalid-from",{error:"unsupported type: "+(typeof fromValue)})));
- return;
+ return Promise.reject(new Error(RED._("change.errors.invalid-from",{error:"unsupported type: "+(typeof fromValue)})));
}
return {
fromType,
diff --git a/nodes/core/storage/50-file.html b/nodes/core/storage/50-file.html
index eabf56a76..00a698cee 100644
--- a/nodes/core/storage/50-file.html
+++ b/nodes/core/storage/50-file.html
@@ -37,6 +37,8 @@
filename string
If not configured in the node, this optional property sets the name of the file to be updated.
+ Output
+ On completion of write, input message is sent to output port.
Details
Each message payload will be added to the end of the file, optionally appending
a newline (\n) character between each one.
diff --git a/red/api/editor/locales/en-US/editor.json b/red/api/editor/locales/en-US/editor.json
index d0bc7bf1e..cfd88fd2e 100644
--- a/red/api/editor/locales/en-US/editor.json
+++ b/red/api/editor/locales/en-US/editor.json
@@ -265,6 +265,8 @@
"settingIcon": "Icon",
"noDefaultLabel": "none",
"defaultLabel": "use default label",
+ "searchIcons": "Search icons",
+ "useDefault": "use default",
"errors": {
"scopeChange": "Changing the scope will make it unavailable to nodes in other flows that use it"
}
diff --git a/red/api/editor/locales/ja/editor.json b/red/api/editor/locales/ja/editor.json
index 892d3e04c..d5161b19c 100644
--- a/red/api/editor/locales/ja/editor.json
+++ b/red/api/editor/locales/ja/editor.json
@@ -264,6 +264,8 @@
"settingIcon": "アイコン",
"noDefaultLabel": "なし",
"defaultLabel": "既定の名前を使用",
+ "searchIcons": "アイコンを検索",
+ "useDefault": "デフォルトを使用",
"errors": {
"scopeChange": "スコープの変更は、他のフローで使われているノードを無効にします"
}
@@ -455,8 +457,14 @@
"filtered": "__count__ 個が無効"
},
"context": {
- "name": "コンテキスト",
- "label": "コンテキスト"
+ "name": "コンテキストデータ",
+ "label": "コンテキストデータ",
+ "none": "選択されていません",
+ "refresh": "読み込みのため更新してください",
+ "empty": "データが存在しません",
+ "node": "Node",
+ "flow": "Flow",
+ "global": "Global"
},
"palette": {
"name": "パレットの管理",
@@ -637,6 +645,9 @@
"eval": "表現評価エラー:\n __message__"
}
},
+ "jsEditor": {
+ "title": "JavaScriptエディタ"
+ },
"jsonEditor": {
"title": "JSONエディタ",
"format": "JSONフォーマット"
diff --git a/red/runtime/nodes/context/localfilesystem.js b/red/runtime/nodes/context/localfilesystem.js
index 551289a95..74e1f30c0 100644
--- a/red/runtime/nodes/context/localfilesystem.js
+++ b/red/runtime/nodes/context/localfilesystem.js
@@ -203,6 +203,8 @@ LocalFileSystem.prototype.set = function(scope, key, value, callback) {
var storagePath = getStoragePath(this.storageBaseDir ,scope);
fs.outputFile(storagePath + ".json", JSON.stringify(newContext, undefined, 4), "utf8").catch(function(err) {
});
+ } else if (callback && typeof callback !== 'function') {
+ throw new Error("Callback must be a function");
} else {
this._set(scope,key,value,callback);
}
diff --git a/test/editor/pageobjects/nodes/core/core/20-inject_page.js b/test/editor/pageobjects/nodes/core/core/20-inject_page.js
index 09248f268..3ba0b26d3 100644
--- a/test/editor/pageobjects/nodes/core/core/20-inject_page.js
+++ b/test/editor/pageobjects/nodes/core/core/20-inject_page.js
@@ -27,7 +27,7 @@ util.inherits(injectNode, nodePage);
var payloadType = {
"flow": 1,
"global": 2,
- "string": 3,
+ "str": 3,
"num": 4,
"bool": 5,
"json": 6,
@@ -43,6 +43,13 @@ var timeType = {
"atASpecificTime": 4,
};
+var timeType = {
+ "none": 1,
+ "interval": 2,
+ "intervalBetweenTimes": 3,
+ "atASpecificTime": 4,
+};
+
injectNode.prototype.setPayload = function(type, value) {
// Open a payload type list.
browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-container")]');
diff --git a/test/editor/pageobjects/nodes/core/core/58-debug_page.js b/test/editor/pageobjects/nodes/core/core/58-debug_page.js
index f87f29646..b04e4a228 100644
--- a/test/editor/pageobjects/nodes/core/core/58-debug_page.js
+++ b/test/editor/pageobjects/nodes/core/core/58-debug_page.js
@@ -24,4 +24,23 @@ function debugNode(id) {
util.inherits(debugNode, nodePage);
+var target = {
+ "msg": 1,
+ "full": 2
+};
+
+debugNode.prototype.setTarget = function(type, value) {
+ // Open a payload type list.
+ browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-container")]/button');
+ // Select a payload type.
+ var xPath = '/html/body/div[11]/a[' + target[type] + ']';
+ browser.clickWithWait(xPath);
+ if (value) {
+ browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-input")]/input');
+ browser.keys(['Control', 'a', 'Control']);
+ browser.keys(['Delete']);
+ browser.setValue('//*[contains(@class, "red-ui-typedInput-input")]/input', value);
+ }
+}
+
module.exports = debugNode;
diff --git a/test/editor/pageobjects/nodes/core/core/80-function_page.js b/test/editor/pageobjects/nodes/core/core/80-function_page.js
new file mode 100644
index 000000000..1cd47f8b9
--- /dev/null
+++ b/test/editor/pageobjects/nodes/core/core/80-function_page.js
@@ -0,0 +1,35 @@
+/**
+ * Copyright JS Foundation and other contributors, http://js.foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+var util = require("util");
+
+var nodePage = require("../../node_page");
+
+function functionNode(id) {
+ nodePage.call(this, id);
+}
+
+util.inherits(functionNode, nodePage);
+
+functionNode.prototype.setCode = function(value) {
+ browser.click('#node-input-func-editor');
+ browser.keys(['Control', 'Home', 'Control']);
+ for (var i=0; iNode-RED');
+ });
+
+ it('set the URL of a request using a template', function() {
+ var injectNode = workspace.addNode("inject");
+ var changeNode = workspace.addNode("change", nodeWidth * 1.5);
+ var httpRequetNode = workspace.addNode("httpRequest", nodeWidth * 2.5);
+ var debugNode = workspace.addNode("debug", nodeWidth * 3.5);
+
+ injectNode.edit();
+ injectNode.setPayload("str", 'settings');
+ injectNode.clickOk();
+
+ changeNode.edit();
+ changeNode.ruleSet("query", "msg", "payload", "msg");
+ changeNode.clickOk();
+
+ httpRequetNode.edit();
+ httpRequetNode.setUrl(helper.url() + "/{{{query}}}");
+ httpRequetNode.clickOk();
+
+ injectNode.connect(changeNode);
+ changeNode.connect(httpRequetNode);
+ httpRequetNode.connect(debugNode);
+
+ workspace.deploy();
+
+ debugTab.open();
+ debugTab.clearMessage();
+ injectNode.clickLeftButton();
+ debugTab.getMessage().should.containEql('httpNodeRoot');
+ });
+
+ it('set the query string parameters', function() {
+ var injectNode = workspace.addNode("inject");
+ var changeNode = workspace.addNode("change", nodeWidth);
+ var httpRequetNode = workspace.addNode("httpRequest", nodeWidth * 2);
+ var debugNode = workspace.addNode("debug", nodeWidth * 3);
+
+ injectNode.edit();
+ injectNode.setPayload("str", 'Nick');
+ injectNode.clickOk();
+
+ changeNode.edit();
+ changeNode.ruleSet("query", "msg", "payload", "msg");
+ changeNode.clickOk();
+
+ httpRequetNode.edit();
+ httpRequetNode.setUrl(helper.url() + httpNodeRoot + '/set-query?q={{{query}}}');
+ httpRequetNode.clickOk();
+
+ injectNode.connect(changeNode);
+ changeNode.connect(httpRequetNode);
+ httpRequetNode.connect(debugNode);
+
+ // The code for confirmation starts from here.
+ var httpinNode = workspace.addNode("httpin", 0, nodeHeight);
+ var templateNode = workspace.addNode("template", nodeWidth, nodeHeight);
+ var httpResponseNode = workspace.addNode("httpResponse", nodeWidth * 2, nodeHeight);
+
+ httpinNode.edit();
+ httpinNode.setMethod("get");
+ httpinNode.setUrl("/set-query");
+ httpinNode.clickOk();
+
+ templateNode.edit();
+ templateNode.setSyntax("mustache");
+ templateNode.setFormat("handlebars");
+ templateNode.setTemplate("Hello {{req.query.q}}");
+ templateNode.clickOk();
+
+ httpinNode.connect(templateNode);
+ templateNode.connect(httpResponseNode);
+ // The code for confirmation ends here.
+
+ workspace.deploy();
+ debugTab.open();
+ debugTab.clearMessage();
+ injectNode.clickLeftButton();
+ debugTab.getMessage().should.eql('"Hello Nick"');
+ });
+
+ it('get a parsed JSON response', function() {
+ var injectNode = workspace.addNode("inject");
+ var changeNode_setPost = workspace.addNode("change", nodeWidth);
+ var httpRequetNode = workspace.addNode("httpRequest", nodeWidth * 2);
+ var debugNode = workspace.addNode("debug", nodeWidth * 3);
+
+ injectNode.edit();
+ injectNode.setPayload("str", "json-response");
+ injectNode.clickOk();
+
+ changeNode_setPost.edit();
+ changeNode_setPost.ruleSet("post", "msg", "payload", "msg");
+ changeNode_setPost.clickOk();
+
+ httpRequetNode.edit();
+ httpRequetNode.setMethod("get");
+ var url = helper.url() + httpNodeRoot + "/{{post}}";
+ httpRequetNode.setUrl(url);
+ httpRequetNode.setRet("obj");
+ httpRequetNode.clickOk();
+
+ debugNode.edit();
+ debugNode.setTarget("msg", "payload.title");
+ debugNode.clickOk();
+
+ injectNode.connect(changeNode_setPost);
+ changeNode_setPost.connect(httpRequetNode);
+ httpRequetNode.connect(debugNode);
+
+ // The code for confirmation starts from here.
+ var httpinNode = workspace.addNode("httpin", 0, nodeHeight);
+ var templateNode = workspace.addNode("template", nodeWidth * 1.5, nodeHeight);
+ var changeNode_setHeader = workspace.addNode("change", nodeWidth * 2.5, nodeHeight);
+ var httpResponseNode = workspace.addNode("httpResponse", nodeWidth * 3.5, nodeHeight);
+
+ httpinNode.edit();
+ httpinNode.setMethod("get");
+ httpinNode.setUrl("/json-response");
+ httpinNode.clickOk();
+
+ templateNode.edit();
+ templateNode.setSyntax("mustache");
+ templateNode.setFormat("handlebars");
+ templateNode.setTemplate("{\"title\": \"Hello\"}");
+ templateNode.clickOk();
+
+ changeNode_setHeader.edit();
+ changeNode_setHeader.ruleSet("headers", "msg", "{\"content-type\":\"application/json\"}", "json");
+ changeNode_setHeader.clickOk();
+
+ httpinNode.connect(templateNode);
+ templateNode.connect(changeNode_setHeader);
+ changeNode_setHeader.connect(httpResponseNode);
+ // The code for confirmation ends here.
+
+ workspace.deploy();
+ debugTab.open();
+ debugTab.clearMessage();
+ injectNode.clickLeftButton();
+ debugTab.getMessage().should.eql('"Hello"');
+ });
+
+ it('get a binary response', function() {
+ var injectNode = workspace.addNode("inject");
+ var httpRequetNode = workspace.addNode("httpRequest", nodeWidth);
+ var debugNode = workspace.addNode("debug", nodeWidth * 2);
+
+ httpRequetNode.edit();
+ httpRequetNode.setMethod("get");
+ httpRequetNode.setUrl(helper.url() + "/settings");
+ httpRequetNode.setRet("bin");
+ httpRequetNode.clickOk();
+
+ injectNode.connect(httpRequetNode);
+ httpRequetNode.connect(debugNode);
+
+ workspace.deploy();
+
+ debugTab.open();
+ debugTab.clearMessage();
+ injectNode.clickLeftButton();
+
+ debugTab.getMessage().should.eql(['123', '34', '104', '116', '116', '112', '78', '111', '100', '101']);
+ });
+
+ it('set a request header', function() {
+ var injectNode = workspace.addNode("inject");
+ var functionNode = workspace.addNode("function", nodeWidth);
+ var httpRequetNode = workspace.addNode("httpRequest", nodeWidth * 2);
+ var debugNode = workspace.addNode("debug", nodeWidth * 3);
+
+ functionNode.edit();
+ functionNode.setCode("msg.payload = \"data to post\";");
+ functionNode.clickOk();
+
+ httpRequetNode.edit();
+ httpRequetNode.setMethod("post");
+ var url = helper.url() + httpNodeRoot + "/set-header";
+ httpRequetNode.setUrl(url);
+ httpRequetNode.clickOk();
+
+ injectNode.connect(functionNode);
+ functionNode.connect(httpRequetNode);
+ httpRequetNode.connect(debugNode);
+
+ // The code for confirmation starts from here.
+ var httpinNode = workspace.addNode("httpin", 0, nodeHeight);
+ var templateNode = workspace.addNode("template", nodeWidth * 1.5, nodeHeight);
+ var httpResponseNode = workspace.addNode("httpResponse", nodeWidth * 2.5, nodeHeight);
+
+ httpinNode.edit();
+ httpinNode.setMethod("post");
+ httpinNode.setUrl("/set-header");
+ httpinNode.clickOk();
+
+ templateNode.edit();
+ templateNode.setSyntax("mustache");
+ templateNode.setFormat("handlebars");
+ templateNode.setTemplate("{{ payload }}");
+ templateNode.clickOk();
+
+ httpinNode.connect(templateNode);
+ templateNode.connect(httpResponseNode);
+ // The code for confirmation ends here.
+
+ workspace.deploy();
+ debugTab.open();
+ debugTab.clearMessage();
+ injectNode.clickLeftButton();
+ debugTab.getMessage().should.eql('"data to post"');
+ });
+ });
});
diff --git a/test/nodes/core/core/80-template_spec.js b/test/nodes/core/core/80-template_spec.js
index 1284b7dba..62db71179 100644
--- a/test/nodes/core/core/80-template_spec.js
+++ b/test/nodes/core/core/80-template_spec.js
@@ -36,6 +36,9 @@ describe('template node', function() {
function initContext(done) {
Context.init({
contextStorage: {
+ memory0: { // do not use (for excluding effect fallback)
+ module: "memory"
+ },
memory1: {
module: "memory"
},
@@ -337,7 +340,7 @@ describe('template node', function() {
msg.should.have.property('topic', 'bar');
msg.should.have.property('payload', 'foo');
// result is in flow context
- n2.context().flow.get("payload", "memory", function (err, val) {
+ n2.context().flow.get("payload", "memory1", function (err, val) {
val.should.equal("payload=foo");
done();
});
@@ -375,7 +378,7 @@ describe('template node', function() {
msg.should.have.property('topic', 'bar');
msg.should.have.property('payload', 'foo');
// result is in global context
- n2.context().global.get("payload", "memory", function (err, val) {
+ n2.context().global.get("payload", "memory1", function (err, val) {
val.should.equal("payload=foo");
done();
});
diff --git a/test/nodes/core/core/89-trigger_spec.js b/test/nodes/core/core/89-trigger_spec.js
index 08a1757ed..5055518fa 100644
--- a/test/nodes/core/core/89-trigger_spec.js
+++ b/test/nodes/core/core/89-trigger_spec.js
@@ -35,6 +35,9 @@ describe('trigger node', function() {
},
memory1: {
module: "memory"
+ },
+ memory2: {
+ module: "memory"
}
}
});
@@ -96,6 +99,74 @@ describe('trigger node', function() {
});
});
+ function basicTest(type, val, rval) {
+ it('should output 1st value when triggered ('+type+')', function(done) {
+ var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1:val, op1type:type, op2:"", op2type:"null", duration:"20", wires:[["n2"]] },
+ {id:"n2", type:"helper"} ];
+ process.env[val] = rval;
+ helper.load(triggerNode, flow, function() {
+ var n1 = helper.getNode("n1");
+ var n2 = helper.getNode("n2");
+ n2.on("input", function(msg) {
+ try {
+ if (rval) {
+ msg.should.have.property("payload");
+ should.deepEqual(msg.payload, rval);
+ }
+ else {
+ msg.should.have.property("payload", val);
+ }
+ delete process.env[val];
+ done();
+ }
+ catch(err) { done(err); }
+ });
+ n1.emit("input", {payload:null});
+ });
+ });
+
+ it('should output 2st value when triggered ('+type+')', function(done) {
+ var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1:"foo", op1type:"str", op2:val, op2type:type, duration:"20", wires:[["n2"]] },
+ {id:"n2", type:"helper"} ];
+ process.env[val] = rval;
+ helper.load(triggerNode, flow, function() {
+ var n1 = helper.getNode("n1");
+ var n2 = helper.getNode("n2");
+ var c = 0;
+ n2.on("input", function(msg) {
+ try {
+ if (c === 0) {
+ msg.should.have.property("payload", "foo");
+ c++;
+ }
+ else {
+ if (rval) {
+ msg.should.have.property("payload");
+ should.deepEqual(msg.payload, rval);
+ }
+ else {
+ msg.should.have.property("payload", val);
+ }
+ delete process.env[val];
+ done();
+ }
+ }
+ catch(err) { done(err); }
+ });
+ n1.emit("input", {payload:null});
+ });
+ });
+ }
+
+ basicTest("num", 10);
+ basicTest("str", "10");
+ basicTest("bool", true);
+ var val_json = '{ "x":"vx", "y":"vy", "z":"vz" }';
+ basicTest("json", val_json, JSON.parse(val_json));
+ var val_buf = "[1,2,3,4,5]";
+ basicTest("bin", val_buf, Buffer.from(JSON.parse(val_buf)));
+ basicTest("env", "NR-TEST", "env-val");
+
it('should output 1 then 0 when triggered (default)', function(done) {
var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", duration:"20", wires:[["n2"]] },
{id:"n2", type:"helper"} ];
@@ -336,8 +407,8 @@ describe('trigger node', function() {
});
it('should be able to return things from persistable flow and global context variables', function (done) {
- var flow = [{"id": "n1", "type": "trigger", "name": "triggerNode", "op1": "#:(memory0)::foo", "op1type": "flow",
- "op2": "#:(memory0)::bar", "op2type": "global", "duration": "20", "wires": [["n2"]], "z": "flow" },
+ var flow = [{"id": "n1", "type": "trigger", "name": "triggerNode", "op1": "#:(memory1)::foo", "op1type": "flow",
+ "op2": "#:(memory1)::bar", "op2type": "global", "duration": "20", "wires": [["n2"]], "z": "flow" },
{"id": "n2", "type": "helper"}];
helper.load(triggerNode, flow, function () {
initContext(function () {
@@ -360,8 +431,8 @@ describe('trigger node', function() {
var context = n1.context();
var flow = context.flow;
var global = context.global;
- flow.set("foo", "foo", "memory0", function (err) {
- global.set("bar", "bar", "memory0", function (err) {
+ flow.set("foo", "foo", "memory1", function (err) {
+ global.set("bar", "bar", "memory1", function (err) {
n1.emit("input", { payload: null });
});
});
@@ -372,8 +443,8 @@ describe('trigger node', function() {
it('should be able to return things from multiple persistable global context variables', function (done) {
var flow = [{"id": "n1", "z": "flow", "type": "trigger",
"duration": "20", "wires": [["n2"]],
- "op1": "#:(memory0)::val", "op1type": "global",
- "op2": "#:(memory1)::val", "op2type": "global"
+ "op1": "#:(memory1)::val", "op1type": "global",
+ "op2": "#:(memory2)::val", "op2type": "global"
},
{"id": "n2", "type": "helper"}];
helper.load(triggerNode, flow, function () {
@@ -399,8 +470,8 @@ describe('trigger node', function() {
}
});
var global = n1.context().global;
- global.set("val", "foo", "memory0", function (err) {
- global.set("val", "bar", "memory1", function (err) {
+ global.set("val", "foo", "memory1", function (err) {
+ global.set("val", "bar", "memory2", function (err) {
n1.emit("input", { payload: null });
});
});
@@ -411,8 +482,8 @@ describe('trigger node', function() {
it('should be able to return things from multiple persistable flow context variables', function (done) {
var flow = [{"id": "n1", "z": "flow", "type": "trigger",
"duration": "20", "wires": [["n2"]],
- "op1": "#:(memory0)::val", "op1type": "flow",
- "op2": "#:(memory1)::val", "op2type": "flow"
+ "op1": "#:(memory1)::val", "op1type": "flow",
+ "op2": "#:(memory2)::val", "op2type": "flow"
},
{"id": "n2", "type": "helper"}];
helper.load(triggerNode, flow, function () {
@@ -438,8 +509,8 @@ describe('trigger node', function() {
}
});
var flow = n1.context().flow;
- flow.set("val", "foo", "memory0", function (err) {
- flow.set("val", "bar", "memory1", function (err) {
+ flow.set("val", "foo", "memory1", function (err) {
+ flow.set("val", "bar", "memory2", function (err) {
n1.emit("input", { payload: null });
});
});
@@ -450,8 +521,8 @@ describe('trigger node', function() {
it('should be able to return things from multiple persistable flow & global context variables', function (done) {
var flow = [{"id": "n1", "z": "flow", "type": "trigger",
"duration": "20", "wires": [["n2"]],
- "op1": "#:(memory0)::val", "op1type": "flow",
- "op2": "#:(memory1)::val", "op2type": "global"
+ "op1": "#:(memory1)::val", "op1type": "flow",
+ "op2": "#:(memory2)::val", "op2type": "global"
},
{"id": "n2", "type": "helper"}];
helper.load(triggerNode, flow, function () {
@@ -479,8 +550,8 @@ describe('trigger node', function() {
var context = n1.context();
var flow = context.flow;
var global = context.flow;
- flow.set("val", "foo", "memory0", function (err) {
- global.set("val", "bar", "memory1", function (err) {
+ flow.set("val", "foo", "memory1", function (err) {
+ global.set("val", "bar", "memory2", function (err) {
n1.emit("input", { payload: null });
});
});
diff --git a/test/nodes/core/logic/10-switch_spec.js b/test/nodes/core/logic/10-switch_spec.js
index d53ad3f49..f0e884fce 100644
--- a/test/nodes/core/logic/10-switch_spec.js
+++ b/test/nodes/core/logic/10-switch_spec.js
@@ -379,7 +379,7 @@ describe('switch Node', function() {
singularSwitchTest("empty", true, false, undefined, done);
});
it('should check if payload is empty (0)', function(done) {
- singularSwitchTest("empty", true, false, null, done);
+ singularSwitchTest("empty", true, false, 0, done);
});
it('should check if payload is not empty (string)', function(done) {
@@ -413,7 +413,7 @@ describe('switch Node', function() {
singularSwitchTest("nempty", true, false, undefined, done);
});
it('should check if payload is not empty (0)', function(done) {
- singularSwitchTest("nempty", true, false, null, done);
+ singularSwitchTest("nempty", true, false, 0, done);
});
diff --git a/test/nodes/core/logic/15-change_spec.js b/test/nodes/core/logic/15-change_spec.js
index b85847982..57cbb7ae5 100644
--- a/test/nodes/core/logic/15-change_spec.js
+++ b/test/nodes/core/logic/15-change_spec.js
@@ -1272,6 +1272,25 @@ describe('change Node', function() {
});
});
+ it('reports invalid fromValue', function(done) {
+ var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"null","fromt":"msg","to":"abc","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
+ {id:"helperNode1", type:"helper", wires:[]}];
+ helper.load(changeNode, flow, function() {
+ var changeNode1 = helper.getNode("changeNode1");
+ setTimeout(function() {
+ var logEvents = helper.log().args.filter(function (evt) {
+ return evt[0].type == "change";
+ });
+ logEvents.should.have.length(1);
+ var msg = logEvents[0][0];
+ msg.should.have.property('level', helper.log().ERROR);
+ msg.should.have.property('id', 'changeNode1');
+ done();
+ },25);
+ changeNode1.receive({payload:"",null:null});
+ });
+ });
+
describe('env var', function() {
before(function() {
process.env.NR_TEST_A = 'foo';
diff --git a/test/nodes/core/storage/50-file_spec.js b/test/nodes/core/storage/50-file_spec.js
index f6eb41d56..9f0c48761 100644
--- a/test/nodes/core/storage/50-file_spec.js
+++ b/test/nodes/core/storage/50-file_spec.js
@@ -53,75 +53,143 @@ describe('file Nodes', function() {
});
it('should write to a file', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":true}];
+ var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":true, wires: [["helperNode1"]]},
+ {id:"helperNode1", type:"helper"}];
helper.load(fileNode, flow, function() {
var n1 = helper.getNode("fileNode1");
- n1.emit("input", {payload:"test"});
- setTimeout(function() {
+ var n2 = helper.getNode("helperNode1");
+ n2.on("input", function(msg) {
var f = fs.readFileSync(fileToTest);
f.should.have.length(4);
fs.unlinkSync(fileToTest);
+ msg.should.have.property("payload", "test");
done();
- },wait);
+ });
+ n1.receive({payload:"test"});
});
});
it('should append to a file and add newline', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":true, "overwriteFile":false}];
+ 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) {}
+ } catch(err) {
+ }
helper.load(fileNode, flow, function() {
var n1 = helper.getNode("fileNode1");
- n1.emit("input", {payload:"test2"}); // string
+ var n2 = helper.getNode("helperNode1");
+ var count = 0;
+ var data = ["test2", true, 999, [2]];
+
+ n2.on("input", function (msg) {
+ msg.should.have.property("payload", data[count]);
+ if (count === 3) {
+ var f = fs.readFileSync(fileToTest).toString();
+ if (os.type() !== "Windows_NT") {
+ f.should.have.length(19);
+ f.should.equal("test2\ntrue\n999\n[2]\n");
+ }
+ else {
+ f.should.have.length(23);
+ f.should.equal("test2\r\ntrue\r\n999\r\n[2]\r\n");
+ }
+ done();
+ }
+ count++;
+ });
+
+ n1.receive({payload:"test2"}); // string
setTimeout(function() {
- n1.emit("input", {payload:true}); // boolean
+ n1.receive({payload:true}); // boolean
},30);
setTimeout(function() {
- n1.emit("input", {payload:999}); // number
+ n1.receive({payload:999}); // number
},60);
setTimeout(function() {
- n1.emit("input", {payload:[2]}); // object (array)
+ n1.receive({payload:[2]}); // object (array)
},90);
- setTimeout(function() {
- var f = fs.readFileSync(fileToTest).toString();
- if (os.type() !== "Windows_NT") {
- f.should.have.length(19);
- f.should.equal("test2\ntrue\n999\n[2]\n");
- }
- else {
- f.should.have.length(23);
- f.should.equal("test2\r\ntrue\r\n999\r\n[2]\r\n");
- }
- done();
- },wait);
});
});
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}];
+ var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":false, wires: [["helperNode1"]]},
+ {id:"helperNode1", type:"helper"}];
try {
fs.unlinkSync(fileToTest);
- } catch(err) {}
+ } catch(err) {
+ }
helper.load(fileNode, flow, function() {
var n1 = helper.getNode("fileNode1");
- // Send two messages to the file
- n1.emit("input", {payload:"one"});
- n1.emit("input", {payload:"two"});
- setTimeout(function() {
+ var n2 = helper.getNode("helperNode1");
+ var data = ["one", "two", "three", "four"];
+ var count = 0;
+
+ n2.on("input", function (msg) {
+ msg.should.have.property("payload", data[count]);
try {
- // Check they got appended as expected
- var f = fs.readFileSync(fileToTest).toString();
- f.should.equal("onetwo");
+ if (count === 1) {
+ // Check they got appended as expected
+ var f = fs.readFileSync(fileToTest).toString();
+ f.should.equal("onetwo");
- // Delete the file
- fs.unlinkSync(fileToTest);
+ // Delete the file
+ fs.unlinkSync(fileToTest);
+ setTimeout(function() {
+ // Send two more messages to the file
+ n1.receive({payload:"three"});
+ n1.receive({payload:"four"});
+ }, wait);
+ }
+ if (count === 3) {
+ var f = fs.readFileSync(fileToTest).toString();
+ f.should.equal("threefour");
+ fs.unlinkSync(fileToTest);
+ done();
+ }
+ } catch(err) {
+ done(err);
+ }
+ count++;
+ });
+
+ // Send two messages to the file
+ n1.receive({payload:"one"});
+ n1.receive({payload:"two"});
+ });
+ });
- // Send two more messages to the file
- n1.emit("input", {payload:"three"});
- n1.emit("input", {payload:"four"});
+ it('should append to a file after it has been recreated ', function(done) {
+ var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "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 data = ["one", "two", "three", "four"];
+ var count = 0;
+
+ n2.on("input", function (msg) {
+ try {
+ msg.should.have.property("payload", data[count]);
+ if (count == 1) {
+ // Check they got appended as expected
+ var f = fs.readFileSync(fileToTest).toString();
+ f.should.equal("onetwo");
- setTimeout(function() {
+ if (os.type() === "Windows_NT") {
+ var dummyFile = path.join(resourcesDir,"50-file-test-dummy.txt");
+ fs.rename(fileToTest, dummyFile, function() {
+ recreateTest(n1, dummyFile);
+ });
+ } else {
+ recreateTest(n1, fileToTest);
+ }
+ }
+ if (count == 3) {
// Check the file was updated
try {
var f = fs.readFileSync(fileToTest).toString();
@@ -131,42 +199,16 @@ describe('file Nodes', function() {
} catch(err) {
done(err);
}
- },wait);
- } catch(err) {
- done(err);
- }
- },wait);
- });
- });
-
- it('should append to a file after it has been recreated ', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":false}];
- try {
- fs.unlinkSync(fileToTest);
- } catch(err) {}
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- // Send two messages to the file
- n1.emit("input", {payload:"one"});
- n1.emit("input", {payload:"two"});
- setTimeout(function() {
- try {
- // Check they got appended as expected
- var f = fs.readFileSync(fileToTest).toString();
- f.should.equal("onetwo");
-
- if (os.type() === "Windows_NT") {
- var dummyFile = path.join(resourcesDir,"50-file-test-dummy.txt");
- fs.rename(fileToTest, dummyFile, function() {
- recreateTest(n1, dummyFile);
- });
- } else {
- recreateTest(n1, fileToTest);
}
} catch(err) {
done(err);
}
- },wait);
+ count++;
+ });
+
+ // Send two messages to the file
+ n1.receive({payload:"one"});
+ n1.receive({payload:"two"});
});
function recreateTest(n1, fileToDelete) {
@@ -177,30 +219,23 @@ describe('file Nodes', function() {
fs.writeFileSync(fileToTest,"");
// Send two more messages to the file
- n1.emit("input", {payload:"three"});
- n1.emit("input", {payload:"four"});
-
- setTimeout(function() {
- // Check the file was updated
- try {
- var f = fs.readFileSync(fileToTest).toString();
- f.should.equal("threefour");
- fs.unlinkSync(fileToTest);
- done();
- } catch(err) {
- done(err);
- }
- },wait);
+ n1.receive({payload:"three"});
+ n1.receive({payload:"four"});
}
});
it('should use msg.filename if filename not set in node', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "appendNewline":true, "overwriteFile":true}];
+ var flow = [{id:"fileNode1", type:"file", name: "fileNode", "appendNewline":true, "overwriteFile":true, wires: [["helperNode1"]]},
+ {id:"helperNode1", type:"helper"}];
helper.load(fileNode, flow, function() {
var n1 = helper.getNode("fileNode1");
- n1.emit("input", {payload:"fine", filename:fileToTest});
- setTimeout(function() {
+ var n2 = helper.getNode("helperNode1");
+
+ n2.on("input", function (msg) {
+ msg.should.have.property("payload", "fine");
+ msg.should.have.property("filename", fileToTest);
+
var f = fs.readFileSync(fileToTest).toString();
if (os.type() !== "Windows_NT") {
f.should.have.length(5);
@@ -211,16 +246,20 @@ describe('file Nodes', function() {
f.should.equal("fine\r\n");
}
done();
- },wait);
+ });
+
+ n1.receive({payload:"fine", filename:fileToTest});
});
});
it('should be able to delete the file', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":"delete"}];
+ var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":"delete", wires: [["helperNode1"]]},
+ {id:"helperNode1", type:"helper"}];
helper.load(fileNode, flow, function() {
var n1 = helper.getNode("fileNode1");
- n1.emit("input", {payload:"fine"});
- setTimeout(function() {
+ var n2 = helper.getNode("helperNode1");
+
+ n2.on("input", function (msg) {
try {
var f = fs.readFileSync(fileToTest).toString();
f.should.not.equal("fine");
@@ -230,7 +269,9 @@ describe('file Nodes', function() {
e.code.should.equal("ENOENT");
done();
}
- },wait);
+ });
+
+ n1.receive({payload:"fine"});
});
});
diff --git a/test/red/runtime/nodes/context/index_spec.js b/test/red/runtime/nodes/context/index_spec.js
index 3500896c9..693b9be16 100644
--- a/test/red/runtime/nodes/context/index_spec.js
+++ b/test/red/runtime/nodes/context/index_spec.js
@@ -308,13 +308,21 @@ describe('context', function() {
});
it('should fail when using invalid store name', function(done) {
- Context.init({contextStorage:{'Invalid name':"noexist"}});
+ Context.init({contextStorage:{'Invalid name':{module:testPlugin}}});
Context.load().then(function(){
done("An error was not thrown");
}).catch(function(){
done();
});
});
+ it('should fail when using invalid sign character', function (done) {
+ Context.init({ contextStorage:{'abc-123':{module:testPlugin}}});
+ Context.load().then(function () {
+ done("An error was not thrown");
+ }).catch(function () {
+ done();
+ });
+ });
it('should fail when using invalid default context', function(done) {
Context.init({contextStorage:{default:"noexist"}});
Context.load().then(function(){
@@ -339,6 +347,20 @@ describe('context', function() {
done();
});
});
+ it('should fail to load invalid module', function (done) {
+ Context.init({contextStorage: {
+ test: {
+ module: function (config) {
+ throw new Error("invalid plugin was loaded.");
+ }
+ }
+ }});
+ Context.load().then(function () {
+ done("An error was not thrown");
+ }).catch(function () {
+ done();
+ });
+ });
});
describe('close modules',function(){
@@ -419,7 +441,7 @@ describe('context', function() {
Context.load().then(function(){
var context = Context.get("1","flow");
var cb = function(){done("An error occurred")}
- context.set("foo","bar","defaultt",cb);
+ context.set("foo","bar","default",cb);
context.get("foo","default",cb);
context.keys("default",cb);
stubGet.called.should.be.false();
@@ -763,6 +785,93 @@ describe('context', function() {
});
}).catch(function(err){ done(err); });
});
+
+ it('should throw an error if callback of context.get is not a function', function (done) {
+ Context.init({ contextStorage: memoryStorage });
+ Context.load().then(function () {
+ var context = Context.get("1", "flow");
+ context.get("foo", "memory", "callback");
+ done("should throw an error.");
+ }).catch(function () {
+ done();
+ });
+ });
+
+ it('should throw an error if callback of context.get is not specified', function (done) {
+ Context.init({ contextStorage: memoryStorage });
+ Context.load().then(function () {
+ var context = Context.get("1", "flow");
+ context.get("foo", "memory");
+ done("should throw an error.");
+ }).catch(function () {
+ done();
+ });
+ });
+
+ it('should throw an error if callback of context.set is not a function', function (done) {
+ Context.init({ contextStorage: memoryStorage });
+ Context.load().then(function () {
+ var context = Context.get("1", "flow");
+ context.set("foo", "bar", "memory", "callback");
+ done("should throw an error.");
+ }).catch(function () {
+ done();
+ });
+ });
+
+ it('should not throw an error if callback of context.set is not specified', function (done) {
+ Context.init({ contextStorage: memoryStorage });
+ Context.load().then(function () {
+ var context = Context.get("1", "flow");
+ context.set("foo", "bar", "memory");
+ done();
+ }).catch(done);
+ });
+
+ it('should throw an error if callback of context.keys is not a function', function (done) {
+ Context.init({ contextStorage: memoryStorage });
+ Context.load().then(function () {
+ var context = Context.get("1", "flow");
+ context.keys("memory", "callback");
+ done("should throw an error.");
+ }).catch(function () {
+ done();
+ });
+ });
+
+ it('should throw an error if callback of context.keys is not specified', function (done) {
+ Context.init({ contextStorage: memoryStorage });
+ Context.load().then(function () {
+ var context = Context.get("1", "flow");
+ context.keys("memory");
+ done("should throw an error.");
+ }).catch(function () {
+ done();
+ });
+ });
+
+ });
+
+ describe('listStores', function () {
+ it('should list context storages', function (done) {
+ Context.init({ contextStorage: contextDefaultStorage });
+ Context.load().then(function () {
+ var list = Context.listStores();
+ list.default.should.equal("default");
+ list.stores.should.eql(["default", "test"]);
+ done();
+ }).catch(done);
+ });
+
+ it('should list context storages without default storage', function (done) {
+ Context.init({ contextStorage: contextStorage });
+ Context.load().then(function () {
+ var list = Context.listStores();
+ list.default.should.equal("test");
+ list.stores.should.eql(["test"]);
+ done();
+ }).catch(done);
+ });
});
describe('delete context',function(){
diff --git a/test/red/runtime/nodes/context/localfilesystem_spec.js b/test/red/runtime/nodes/context/localfilesystem_spec.js
index 84a33982e..f461dace6 100644
--- a/test/red/runtime/nodes/context/localfilesystem_spec.js
+++ b/test/red/runtime/nodes/context/localfilesystem_spec.js
@@ -63,6 +63,15 @@ describe('localfilesystem',function() {
});
});
+ it('should store local scope property', function (done) {
+ context.set("abc:def", "foo.bar", "test", function (err) {
+ context.get("abc:def", "foo", function (err, value) {
+ value.should.be.eql({ bar: "test" });
+ done();
+ });
+ });
+ });
+
it('should delete property',function(done) {
context.set("nodeX","foo.abc.bar1","test1",function(err){
context.set("nodeX","foo.abc.bar2","test2",function(err){
@@ -240,6 +249,81 @@ describe('localfilesystem',function() {
});
});
});
+
+ it('should throw an error when getting a value with invalid key', function (done) {
+ context.set("nodeX","foo","bar",function(err) {
+ context.get("nodeX"," ",function(err,value) {
+ should.exist(err);
+ done();
+ });
+ });
+ });
+
+ it('should throw an error when setting a value with invalid key',function (done) {
+ context.set("nodeX"," ","bar",function (err) {
+ should.exist(err);
+ done();
+ });
+ });
+
+ it('should throw an error when callback of get() is not a function',function (done) {
+ try {
+ context.get("nodeX","foo","callback");
+ done("should throw an error.");
+ } catch (err) {
+ done();
+ };
+ });
+
+ it('should throw an error when callback of get() is not specified',function (done) {
+ try {
+ context.get("nodeX","foo");
+ done("should throw an error.");
+ } catch (err) {
+ done();
+ };
+ });
+
+ it('should throw an error when callback of set() is not a function',function (done) {
+ try {
+ context.set("nodeX","foo","bar","callback");
+ done("should throw an error.");
+ } catch (err) {
+ done();
+ };
+ });
+
+ it('should not throw an error when callback of set() is not specified', function (done) {
+ try {
+ context.set("nodeX"," ","bar");
+ done();
+ } catch (err) {
+ done("should not throw an error.");
+ };
+ });
+
+ it('should handle empty context file', function (done) {
+ fs.outputFile(path.join(resourcesDir,"contexts","nodeX","flow.json"),"",function(){
+ context.get("nodeX", "foo", function (err, value) {
+ should.not.exist(value);
+ context.set("nodeX", "foo", "test", function (err) {
+ context.get("nodeX", "foo", function (err, value) {
+ value.should.be.equal("test");
+ done();
+ });
+ });
+ });
+ });
+ });
+
+ it('should throw an error when reading corrupt context file', function (done) {
+ fs.outputFile(path.join(resourcesDir, "contexts", "nodeX", "flow.json"),"{abc",function(){
+ context.get("nodeX", "foo", function (err, value) {
+ should.exist(err);
+ done();
+ });
+ });
+ });
});
describe('#keys',function() {
@@ -286,6 +370,24 @@ describe('localfilesystem',function() {
});
});
});
+
+ it('should throw an error when callback of keys() is not a function', function (done) {
+ try {
+ context.keys("nodeX", "callback");
+ done("should throw an error.");
+ } catch (err) {
+ done();
+ };
+ });
+
+ it('should throw an error when callback of keys() is not specified', function (done) {
+ try {
+ context.keys("nodeX");
+ done("should throw an error.");
+ } catch (err) {
+ done();
+ };
+ });
});
describe('#delete',function() {
@@ -497,4 +599,131 @@ describe('localfilesystem',function() {
});
});
+ describe('Configuration', function () {
+ it('should change a base directory', function (done) {
+ var differentBaseContext = LocalFileSystem({
+ base: "contexts2",
+ dir: resourcesDir,
+ cache: false
+ });
+ differentBaseContext.open().then(function () {
+ differentBaseContext.set("node2", "foo2", "bar2", function (err) {
+ differentBaseContext.get("node2", "foo2", function (err, value) {
+ value.should.be.equal("bar2");
+ context.get("node2", "foo2", function(err, value) {
+ should.not.exist(value);
+ done();
+ });
+ });
+ });
+ });
+ });
+
+ it('should use userDir', function (done) {
+ var userDirContext = LocalFileSystem({
+ base: "contexts2",
+ cache: false,
+ settings: {
+ userDir: resourcesDir
+ }
+ });
+ userDirContext.open().then(function () {
+ userDirContext.set("node2", "foo2", "bar2", function (err) {
+ userDirContext.get("node2", "foo2", function (err, value) {
+ value.should.be.equal("bar2");
+ context.get("node2", "foo2", function (err, value) {
+ should.not.exist(value);
+ done();
+ });
+ });
+ });
+ });
+ });
+
+ it('should use NODE_RED_HOME', function (done) {
+ var oldNRH = process.env.NODE_RED_HOME;
+ process.env.NODE_RED_HOME = resourcesDir;
+ fs.mkdirSync(resourcesDir);
+ fs.writeFileSync(path.join(resourcesDir,".config.json"),"");
+ var nrHomeContext = LocalFileSystem({
+ base: "contexts2",
+ cache: false
+ });
+ try {
+ nrHomeContext.open().then(function () {
+ nrHomeContext.set("node2", "foo2", "bar2", function (err) {
+ nrHomeContext.get("node2", "foo2", function (err, value) {
+ value.should.be.equal("bar2");
+ context.get("node2", "foo2", function (err, value) {
+ should.not.exist(value);
+ done();
+ });
+ });
+ });
+ });
+ } finally {
+ process.env.NODE_RED_HOME = oldNRH;
+ }
+ });
+
+ it('should use HOME_PATH', function (done) {
+ var oldNRH = process.env.NODE_RED_HOME;
+ var oldHOMEPATH = process.env.HOMEPATH;
+ process.env.NODE_RED_HOME = resourcesDir;
+ process.env.HOMEPATH = resourcesDir;
+ var homePath = path.join(resourcesDir, ".node-red");
+ fs.outputFile(path.join(homePath, ".config.json"),"",function(){
+ var homeContext = LocalFileSystem({
+ base: "contexts2",
+ cache: false
+ });
+ try {
+ homeContext.open().then(function () {
+ homeContext.set("node2", "foo2", "bar2", function (err) {
+ homeContext.get("node2", "foo2", function (err, value) {
+ value.should.be.equal("bar2");
+ context.get("node2", "foo2", function (err, value) {
+ should.not.exist(value);
+ done();
+ });
+ });
+ });
+ });
+ } finally {
+ process.env.NODE_RED_HOME = oldNRH;
+ process.env.HOMEPATH = oldHOMEPATH;
+ }
+ });
+ });
+
+ it('should use HOME_PATH', function (done) {
+ var oldNRH = process.env.NODE_RED_HOME;
+ var oldHOMEPATH = process.env.HOMEPATH;
+ var oldHOME = process.env.HOME;
+ process.env.NODE_RED_HOME = resourcesDir;
+ process.env.HOMEPATH = resourcesDir;
+ process.env.HOME = resourcesDir;
+ var homeContext = LocalFileSystem({
+ base: "contexts2",
+ cache: false
+ });
+ try {
+ homeContext.open().then(function () {
+ homeContext.set("node2", "foo2", "bar2", function (err) {
+ homeContext.get("node2", "foo2", function (err, value) {
+ value.should.be.equal("bar2");
+ context.get("node2", "foo2", function (err, value) {
+ should.not.exist(value);
+ done();
+ });
+ });
+ });
+ });
+ } finally {
+ process.env.NODE_RED_HOME = oldNRH;
+ process.env.HOMEPATH = oldHOMEPATH;
+ process.env.HOME = oldHOME;
+ }
+ });
+ });
});
diff --git a/test/red/runtime/nodes/context/memory_spec.js b/test/red/runtime/nodes/context/memory_spec.js
index 00582d986..95bb0674f 100644
--- a/test/red/runtime/nodes/context/memory_spec.js
+++ b/test/red/runtime/nodes/context/memory_spec.js
@@ -144,6 +144,32 @@ describe('memory',function() {
keysY.should.have.length(1);
keysY[0].should.equal("hoge");
});
+
+ it('should enumerate global context keys', function () {
+ var keys = context.keys("global");
+ keys.should.be.an.Array();
+ keys.should.be.empty();
+
+ context.set("global", "foo", "bar");
+ keys = context.keys("global");
+ keys.should.have.length(1);
+ keys[0].should.equal("foo");
+
+ context.set("global", "abc.def", "bar");
+ keys = context.keys("global");
+ keys.should.have.length(2);
+ keys[1].should.equal("abc");
+ });
+
+ it('should not return specific keys as global context keys', function () {
+ var keys = context.keys("global");
+
+ context.set("global", "set", "bar");
+ context.set("global", "get", "bar");
+ context.set("global", "keys", "bar");
+ keys = context.keys("global");
+ keys.should.have.length(0);
+ });
});
describe('async',function() {
@@ -212,6 +238,14 @@ describe('memory',function() {
should.not.exist(context.get("nodeY","foo"));
});
});
+ it('should not clean global context', function () {
+ context.set("global", "foo", "abc");
+ context.get("global", "foo").should.equal("abc");
+
+ return context.clean(["global"]).then(function () {
+ should.exist(context.get("global", "foo"));
+ });
+ });
});
});