mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
2 Commits
messaging-
...
Handle-Rea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
376db60acc | ||
|
|
ffa65afbb2 |
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,19 +1,3 @@
|
||||
#### 0.19.3: Maintenance Release
|
||||
|
||||
- Split node - fix complete to send msg for k/v object
|
||||
- Remove unused Join node merged object key typed input
|
||||
- Set the JavaScript editor to full-screen
|
||||
- Filter global modules installed locally
|
||||
- Add svg to permitted icon extension list
|
||||
- Debug node - indicate status all the time if selected to do so
|
||||
- pi nodes - increase test coverage slightly
|
||||
- TCP-request node - only write payload
|
||||
- JSON schema: perform validation when obj -> obj or str -> str
|
||||
- JSON schema: add draft-06 support (via $schema keyword)
|
||||
- Mqtt proxy configuration for websocket connection, #1651.
|
||||
- Allows MQTT Shared Subscriptions for MQTT-In core node
|
||||
- Fix use of HTML tag or CSS class specification as icon of typedInput
|
||||
|
||||
#### 0.19.2: Maintenance Release
|
||||
|
||||
- Ensure node default colour is used if palette.theme has no match
|
||||
|
||||
@@ -522,18 +522,10 @@
|
||||
this.selectLabel.empty();
|
||||
var image;
|
||||
if (opt.icon) {
|
||||
if (opt.icon.indexOf("<") === 0) {
|
||||
$(opt.icon).prependTo(this.selectLabel);
|
||||
}
|
||||
else if (opt.icon.indexOf("/") !== -1) {
|
||||
image = new Image();
|
||||
image.name = opt.icon;
|
||||
image.src = opt.icon;
|
||||
$('<img>',{src:opt.icon,style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel);
|
||||
}
|
||||
else {
|
||||
$('<i>',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(this.selectLabel);
|
||||
}
|
||||
image = new Image();
|
||||
image.name = opt.icon;
|
||||
image.src = opt.icon;
|
||||
$('<img>',{src:opt.icon,style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel);
|
||||
} else {
|
||||
this.selectLabel.text(opt.label);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ RED.editor.types._js = (function() {
|
||||
|
||||
var trayOptions = {
|
||||
title: options.title,
|
||||
width: options.width||"inherit",
|
||||
width: "inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
|
||||
@@ -1004,7 +1004,7 @@ RED.sidebar.versionControl = (function() {
|
||||
RED.sidebar.addTab({
|
||||
id: "version-control",
|
||||
label: RED._("sidebar.project.versionControl.history"),
|
||||
name: RED._("sidebar.project.versionControl.projectHistory"),
|
||||
name: "Project History",
|
||||
content: sidebarContent,
|
||||
enableOnEdit: false,
|
||||
pinned: true,
|
||||
|
||||
@@ -19,11 +19,7 @@ module.exports = function(RED) {
|
||||
if (this.tosidebar === undefined) { this.tosidebar = true; }
|
||||
this.severity = n.severity || 40;
|
||||
this.active = (n.active === null || typeof n.active === "undefined") || n.active;
|
||||
if (this.tostatus) {
|
||||
this.oldStatus = {fill:"grey", shape:"ring"};
|
||||
this.status(this.oldStatus);
|
||||
}
|
||||
else { this.status({}); }
|
||||
this.status({});
|
||||
|
||||
var node = this;
|
||||
var levels = {
|
||||
@@ -126,12 +122,12 @@ module.exports = function(RED) {
|
||||
if (state === "enable") {
|
||||
node.active = true;
|
||||
res.sendStatus(200);
|
||||
if (node.tostatus) { node.status({fill:"grey", shape:"dot"}); }
|
||||
if (node.tostatus) { node.status({}); }
|
||||
} else if (state === "disable") {
|
||||
node.active = false;
|
||||
res.sendStatus(201);
|
||||
if (node.tostatus && node.hasOwnProperty("oldStatus")) {
|
||||
node.oldStatus.shape = "dot";
|
||||
node.oldStatus.shape = "ring";
|
||||
node.status(node.oldStatus);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -53,14 +53,12 @@
|
||||
<p>The Catch node can also be used to handle errors. To invoke a Catch node,
|
||||
pass <code>msg</code> as a second argument to <code>node.error</code>:</p>
|
||||
<pre>node.error("Error",msg);</pre>
|
||||
<h4>Accessing Node Information</h4>
|
||||
<h4>Referring Node Information</h4>
|
||||
<p>In the function block, id and name of the node can be referenced using the following properties:</p>
|
||||
<ul>
|
||||
<li><code>node.id</code> - id of the node</li>
|
||||
<li><code>node.name</code> - name of the node</li>
|
||||
</ul>
|
||||
<h4>Using environment variables</h4>
|
||||
<p>Environment variables can be accessed using <code>env.get("MY_ENV_VAR")</code>.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@@ -128,7 +126,6 @@
|
||||
var value = that.editor.getValue();
|
||||
RED.editor.editJavaScript({
|
||||
value: value,
|
||||
width: "Infinity",
|
||||
cursor: that.editor.getCursorPosition(),
|
||||
complete: function(v,cursor) {
|
||||
that.editor.setValue(v, -1);
|
||||
|
||||
@@ -42,7 +42,7 @@ module.exports = function(RED) {
|
||||
if (type === 'object') {
|
||||
type = Buffer.isBuffer(msg)?'Buffer':(util.isArray(msg)?'Array':'Date');
|
||||
}
|
||||
node.error(RED._("function.error.non-message-returned",{ type: type }));
|
||||
node.error(RED._("function.error.non-message-returned",{ type: type }))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,13 +156,6 @@ module.exports = function(RED) {
|
||||
return node.context().global.keys.apply(node,arguments);
|
||||
}
|
||||
},
|
||||
env: {
|
||||
get: function(envVar) {
|
||||
// For now, just return the env var. This will eventually
|
||||
// also return project settings and subflow instance properties
|
||||
return process.env[envVar]
|
||||
}
|
||||
},
|
||||
setTimeout: function () {
|
||||
var func = arguments[0];
|
||||
var timerId;
|
||||
@@ -210,9 +203,9 @@ module.exports = function(RED) {
|
||||
if (util.hasOwnProperty('promisify')) {
|
||||
sandbox.setTimeout[util.promisify.custom] = function(after, value) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
sandbox.setTimeout(function(){ resolve(value); }, after);
|
||||
sandbox.setTimeout(function(){ resolve(value) }, after);
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
var context = vm.createContext(sandbox);
|
||||
try {
|
||||
@@ -248,6 +241,7 @@ module.exports = function(RED) {
|
||||
|
||||
var line = 0;
|
||||
var errorMessage;
|
||||
var stack = err.stack.split(/\r?\n/);
|
||||
if (stack.length > 0) {
|
||||
while (line < stack.length && stack[line].indexOf("ReferenceError") !== 0) {
|
||||
line++;
|
||||
@@ -271,13 +265,13 @@ module.exports = function(RED) {
|
||||
});
|
||||
this.on("close", function() {
|
||||
while (node.outstandingTimers.length > 0) {
|
||||
clearTimeout(node.outstandingTimers.pop());
|
||||
clearTimeout(node.outstandingTimers.pop())
|
||||
}
|
||||
while (node.outstandingIntervals.length > 0) {
|
||||
clearInterval(node.outstandingIntervals.pop());
|
||||
clearInterval(node.outstandingIntervals.pop())
|
||||
}
|
||||
this.status({});
|
||||
});
|
||||
})
|
||||
} catch(err) {
|
||||
// eg SyntaxError - which v8 doesn't include line number information
|
||||
// so we can't do better than this
|
||||
@@ -286,4 +280,4 @@ module.exports = function(RED) {
|
||||
}
|
||||
RED.nodes.registerType("function",FunctionNode);
|
||||
RED.library.register("functions");
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,26 +19,11 @@ module.exports = function(RED) {
|
||||
var mqtt = require("mqtt");
|
||||
var util = require("util");
|
||||
var isUtf8 = require('is-utf8');
|
||||
var HttpsProxyAgent = require('https-proxy-agent');
|
||||
var url = require('url');
|
||||
|
||||
function matchTopic(ts,t) {
|
||||
if (ts == "#") {
|
||||
return true;
|
||||
}
|
||||
/* The following allows shared subscriptions (as in MQTT v5)
|
||||
http://docs.oasis-open.org/mqtt/mqtt/v5.0/cs02/mqtt-v5.0-cs02.html#_Toc514345522
|
||||
|
||||
4.8.2 describes shares like:
|
||||
$share/{ShareName}/{filter}
|
||||
$share is a literal string that marks the Topic Filter as being a Shared Subscription Topic Filter.
|
||||
{ShareName} is a character string that does not include "/", "+" or "#"
|
||||
{filter} The remainder of the string has the same syntax and semantics as a Topic Filter in a non-shared subscription. Refer to section 4.7.
|
||||
*/
|
||||
else if(ts.startsWith("$share")){
|
||||
ts = ts.replace(/^\$share\/[^#+/]+\/(.*)/g,"$1");
|
||||
|
||||
}
|
||||
var re = new RegExp("^"+ts.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$");
|
||||
return re.test(t);
|
||||
}
|
||||
@@ -111,29 +96,12 @@ module.exports = function(RED) {
|
||||
if (typeof this.cleansession === 'undefined') {
|
||||
this.cleansession = true;
|
||||
}
|
||||
var prox;
|
||||
if (process.env.http_proxy != null) { prox = process.env.http_proxy; }
|
||||
if (process.env.HTTP_PROXY != null) { prox = process.env.HTTP_PROXY; }
|
||||
|
||||
// Create the URL to pass in to the MQTT.js library
|
||||
if (this.brokerurl === "") {
|
||||
// if the broker may be ws:// or wss:// or even tcp://
|
||||
if (this.broker.indexOf("://") > -1) {
|
||||
this.brokerurl = this.broker;
|
||||
// Only for ws or wss, check if proxy env var for additional configuration
|
||||
if (this.brokerurl.indexOf("wss://") > -1 || this.brokerurl.indexOf("ws://") > -1 )
|
||||
// check if proxy is set in env
|
||||
if (prox) {
|
||||
var parsedUrl = url.parse(this.brokerurl);
|
||||
var proxyOpts = url.parse(prox);
|
||||
// true for wss
|
||||
proxyOpts.secureEndpoint = parsedUrl.protocol ? parsedUrl.protocol === 'wss:' : true;
|
||||
// Set Agent for wsOption in MQTT
|
||||
var agent = new HttpsProxyAgent(proxyOpts);
|
||||
this.options.wsOptions = {
|
||||
agent: agent
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// construct the std mqtt:// url
|
||||
if (this.usetls) {
|
||||
@@ -467,4 +435,4 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
RED.nodes.registerType("mqtt out",MQTTOutNode);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -33,7 +33,9 @@ module.exports = function(RED) {
|
||||
*/
|
||||
const enqueue = (queue, item) => {
|
||||
// drop msgs from front of queue if size is going to be exceeded
|
||||
if (queue.size() === msgQueueSize) { queue.shift(); }
|
||||
if (queue.size() === msgQueueSize) {
|
||||
queue.shift();
|
||||
}
|
||||
queue.push(item);
|
||||
return queue;
|
||||
};
|
||||
@@ -644,7 +646,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
else if (!clients[connection_id].connecting && clients[connection_id].connected) {
|
||||
if (clients[connection_id] && clients[connection_id].client) {
|
||||
clients[connection_id].client.write(dequeue(clients[connection_id].msgQueue).payload);
|
||||
clients[connection_id].client.write(dequeue(clients[connection_id].msgQueue));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -295,8 +295,7 @@
|
||||
For object outputs, once this count has been reached, the node can be configured to send a message for each subsequent message
|
||||
received.</p>
|
||||
<p>A <i>timeout</i> can be set to trigger sending the new message using whatever has been received so far.</p>
|
||||
<p>If a message is received with the <b>msg.complete</b> property set, the output message is finalised and sent.
|
||||
This resets any part counts.</p>
|
||||
<p>If a message is received with the <b>msg.complete</b> property set, the output message is sent.</p>
|
||||
|
||||
<h4>Reduce Sequence mode</h4>
|
||||
<p>When configured to join in reduce mode, an expression is applied to each
|
||||
@@ -440,7 +439,10 @@
|
||||
$("#node-input-joiner").typedInput({
|
||||
default: 'str',
|
||||
typeField: $("#node-input-joinerType"),
|
||||
types:['str', 'bin']
|
||||
types:[
|
||||
'str',
|
||||
'bin'
|
||||
]
|
||||
});
|
||||
|
||||
$("#node-input-property").typedInput({
|
||||
@@ -449,7 +451,7 @@
|
||||
});
|
||||
|
||||
$("#node-input-key").typedInput({
|
||||
types:['msg']
|
||||
types:['msg', {value:"merge", label:"", hasValue:false}]
|
||||
});
|
||||
|
||||
$("#node-input-build").change();
|
||||
|
||||
@@ -586,10 +586,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
else {
|
||||
if (msg.hasOwnProperty('complete')) {
|
||||
if (inflight[partId]) {
|
||||
inflight[partId].msg.complete = msg.complete;
|
||||
completeSend(partId);
|
||||
}
|
||||
completeSend(partId);
|
||||
}
|
||||
else {
|
||||
node.warn("Message missing key property 'msg."+node.key+"' - cannot add to object")
|
||||
@@ -597,7 +594,6 @@ module.exports = function(RED) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!inflight.hasOwnProperty(partId)) {
|
||||
if (payloadType === 'object' || payloadType === 'merged') {
|
||||
inflight[partId] = {
|
||||
@@ -608,6 +604,19 @@ module.exports = function(RED) {
|
||||
msg:RED.util.cloneMessage(msg)
|
||||
};
|
||||
}
|
||||
else if (node.accumulate === true) {
|
||||
if (msg.hasOwnProperty("reset")) { delete inflight[partId]; }
|
||||
inflight[partId] = inflight[partId] || {
|
||||
currentCount:0,
|
||||
payload:{},
|
||||
targetCount:targetCount,
|
||||
type:payloadType,
|
||||
msg:RED.util.cloneMessage(msg)
|
||||
}
|
||||
if (payloadType === 'string' || payloadType === 'array' || payloadType === 'buffer') {
|
||||
inflight[partId].payload = [];
|
||||
}
|
||||
}
|
||||
else {
|
||||
inflight[partId] = {
|
||||
currentCount:0,
|
||||
|
||||
@@ -196,10 +196,9 @@ module.exports = function(RED) {
|
||||
}).catch(err => {
|
||||
node.error(err,msg);
|
||||
});
|
||||
return;
|
||||
}
|
||||
var parts = msg.parts;
|
||||
if (!parts || !parts.hasOwnProperty("id") || !parts.hasOwnProperty("index")) {
|
||||
if (!parts.hasOwnProperty("id") || !parts.hasOwnProperty("index")) {
|
||||
return;
|
||||
}
|
||||
var gid = parts.id;
|
||||
@@ -243,8 +242,7 @@ module.exports = function(RED) {
|
||||
delete pending[key];
|
||||
}
|
||||
}
|
||||
pending_count = 0;
|
||||
});
|
||||
pending_count = 0; })
|
||||
}
|
||||
|
||||
RED.nodes.registerType("sort", SortNode);
|
||||
|
||||
@@ -19,7 +19,6 @@ module.exports = function(RED) {
|
||||
const Ajv = require('ajv');
|
||||
const ajv = new Ajv({allErrors: true, schemaId: 'auto'});
|
||||
ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json'));
|
||||
ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json'));
|
||||
|
||||
function JSONNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
@@ -30,7 +29,6 @@ module.exports = function(RED) {
|
||||
this.compiledSchema = null;
|
||||
|
||||
var node = this;
|
||||
|
||||
this.on("input", function(msg) {
|
||||
var validate = false;
|
||||
if (msg.schema) {
|
||||
@@ -67,17 +65,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
catch(e) { node.error(e.message,msg); }
|
||||
} else {
|
||||
// If node.action is str and value is str
|
||||
if (validate) {
|
||||
if (this.compiledSchema(JSON.parse(msg[node.property]))) {
|
||||
node.send(msg);
|
||||
} else {
|
||||
msg.schemaError = this.compiledSchema.errors;
|
||||
node.error(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`, msg);
|
||||
}
|
||||
} else {
|
||||
node.send(msg);
|
||||
}
|
||||
node.send(msg);
|
||||
}
|
||||
}
|
||||
else if (typeof value === "object") {
|
||||
@@ -96,22 +84,13 @@ module.exports = function(RED) {
|
||||
RED.util.setMessageProperty(msg,node.property,JSON.stringify(value,null,node.indent));
|
||||
node.send(msg);
|
||||
}
|
||||
|
||||
}
|
||||
catch(e) { node.error(RED._("json.errors.dropped-error")); }
|
||||
}
|
||||
else { node.warn(RED._("json.errors.dropped-object")); }
|
||||
} else {
|
||||
// If node.action is obj and value is object
|
||||
if (validate) {
|
||||
if (this.compiledSchema(value)) {
|
||||
node.send(msg);
|
||||
} else {
|
||||
msg.schemaError = this.compiledSchema.errors;
|
||||
node.error(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`, msg);
|
||||
}
|
||||
} else {
|
||||
node.send(msg);
|
||||
}
|
||||
node.send(msg);
|
||||
}
|
||||
}
|
||||
else { node.warn(RED._("json.errors.dropped")); }
|
||||
|
||||
14
package.json
14
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "0.19.3",
|
||||
"version": "0.19.2",
|
||||
"description": "A visual tool for wiring the Internet of Things",
|
||||
"homepage": "http://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -42,14 +42,13 @@
|
||||
"cookie": "0.3.1",
|
||||
"cookie-parser": "1.4.3",
|
||||
"cors": "2.8.4",
|
||||
"cron": "1.4.1",
|
||||
"cron": "1.3.0",
|
||||
"denque": "1.3.0",
|
||||
"express": "4.16.3",
|
||||
"express-session": "1.15.6",
|
||||
"fs-extra": "5.0.0",
|
||||
"fs.notify": "0.0.4",
|
||||
"hash-sum": "1.0.2",
|
||||
"https-proxy-agent": "2.2.1",
|
||||
"i18next": "11.6.0",
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "3.12.0",
|
||||
@@ -57,9 +56,9 @@
|
||||
"jsonata": "1.5.4",
|
||||
"media-typer": "0.3.0",
|
||||
"memorystore": "1.6.0",
|
||||
"mqtt": "2.18.8",
|
||||
"mqtt": "2.18.5",
|
||||
"multer": "1.3.1",
|
||||
"mustache": "2.3.2",
|
||||
"mustache": "2.3.1",
|
||||
"node-red-node-email": "0.1.*",
|
||||
"node-red-node-feedparser": "^0.1.12",
|
||||
"node-red-node-rbe": "0.2.*",
|
||||
@@ -74,7 +73,7 @@
|
||||
"request": "2.88.0",
|
||||
"semver": "5.5.1",
|
||||
"sentiment": "2.1.0",
|
||||
"uglify-js": "3.4.9",
|
||||
"uglify-js": "3.4.8",
|
||||
"when": "3.7.8",
|
||||
"ws": "1.1.5",
|
||||
"xml2js": "0.4.19"
|
||||
@@ -86,7 +85,7 @@
|
||||
"chromedriver": "^2.41.0",
|
||||
"grunt": "~1.0.3",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-cli": "~1.3.1",
|
||||
"grunt-cli": "~1.2.0",
|
||||
"grunt-concurrent": "~2.3.1",
|
||||
"grunt-contrib-clean": "~1.1.0",
|
||||
"grunt-contrib-compress": "~1.4.0",
|
||||
@@ -104,7 +103,6 @@
|
||||
"http-proxy": "^1.16.2",
|
||||
"istanbul": "0.4.5",
|
||||
"mocha": "^5.2.0",
|
||||
"mosca": "^2.8.3",
|
||||
"node-red-node-test-helper": "0.1.7",
|
||||
"should": "^8.4.0",
|
||||
"sinon": "1.17.7",
|
||||
|
||||
14
red.js
14
red.js
@@ -101,8 +101,18 @@ if (parsedArgs.settings) {
|
||||
var settingsStat = fs.statSync(defaultSettings);
|
||||
if (settingsStat.mtime.getTime() <= settingsStat.ctime.getTime()) {
|
||||
// Default settings file has not been modified - safe to copy
|
||||
fs.copySync(defaultSettings,userSettingsFile);
|
||||
settingsFile = userSettingsFile;
|
||||
try {
|
||||
fs.copySync(defaultSettings,userSettingsFile);
|
||||
settingsFile = userSettingsFile;
|
||||
}
|
||||
catch (err) {
|
||||
console.log("Failed to copy settings file to "+userSettingsFile);
|
||||
console.log("Error: "+err.toString());
|
||||
if (err.code == "EACCES") {
|
||||
console.log("You may need to set readOnly: true, in settings.js");
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
// Use default settings.js as it has been modified
|
||||
settingsFile = defaultSettings;
|
||||
|
||||
@@ -587,7 +587,6 @@
|
||||
"pullUnrelatedHistory": "<p>The remote has an unrelated history of commits.</p><p>Are you sure you want to pull the changes into your local repository?</p>",
|
||||
"pullChanges": "Pull changes",
|
||||
"history": "history",
|
||||
"projectHistory": "Project History",
|
||||
"daysAgo": "__count__ day ago",
|
||||
"daysAgo_plural": "__count__ days ago",
|
||||
"hoursAgo": "__count__ hour ago",
|
||||
|
||||
@@ -585,7 +585,6 @@
|
||||
"pullUnrelatedHistory": "<p>リモートに関連のないコミット履歴があります。</p><p>本当に変更をプルしてローカルリポジトリに反映しますか?</p>",
|
||||
"pullChanges": "プル変更",
|
||||
"history": "履歴",
|
||||
"projectHistory": "プロジェクト履歴",
|
||||
"daysAgo": "__count__ 日前",
|
||||
"daysAgo_plural": "__count__ 日前",
|
||||
"hoursAgo": "__count__ 時間前",
|
||||
|
||||
@@ -142,6 +142,7 @@
|
||||
"restore": "Restoring __type__ file backup : __path__",
|
||||
"restore-fail": "Restoring __type__ file backup failed : __message__",
|
||||
"fsync-fail": "Flushing file __path__ to disk failed : __message__",
|
||||
"fwrite-fail": "Writing backup file __path__ to disk failed : __message__",
|
||||
"projects": {
|
||||
"changing-project": "Setting active project : __project__",
|
||||
"active-project": "Active project : __project__",
|
||||
|
||||
@@ -23,7 +23,7 @@ var i18n;
|
||||
|
||||
var settings;
|
||||
var disableNodePathScan = false;
|
||||
var iconFileExtensions = [".png", ".gif", ".svg"];
|
||||
var iconFileExtensions = [".png", ".gif"];
|
||||
|
||||
function init(runtime) {
|
||||
settings = runtime.settings;
|
||||
@@ -290,33 +290,6 @@ function getNodeFiles(disableNodePathScan) {
|
||||
|
||||
if (!disableNodePathScan) {
|
||||
var moduleFiles = scanTreeForNodesModules();
|
||||
|
||||
// Filter the module list to ignore global modules
|
||||
// that have also been installed locally - allowing the user to
|
||||
// update a module they may not otherwise be able to touch
|
||||
|
||||
moduleFiles.sort(function(A,B) {
|
||||
if (A.local && !B.local) {
|
||||
return -1
|
||||
} else if (!A.local && B.local) {
|
||||
return 1
|
||||
}
|
||||
return 0;
|
||||
})
|
||||
var knownModules = {};
|
||||
moduleFiles = moduleFiles.filter(function(mod) {
|
||||
var result;
|
||||
if (!knownModules[mod.package.name]) {
|
||||
knownModules[mod.package.name] = true;
|
||||
result = true;
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
log.debug("Module: "+mod.package.name+" "+mod.package.version+(result?"":" *ignored due to local copy*"));
|
||||
log.debug(" "+mod.dir);
|
||||
return result;
|
||||
});
|
||||
|
||||
moduleFiles.forEach(function(moduleFile) {
|
||||
var nodeModuleFiles = getModuleNodeFiles(moduleFile);
|
||||
nodeList[moduleFile.package.name] = {
|
||||
|
||||
@@ -81,7 +81,11 @@ module.exports = {
|
||||
writeFile: function(path,content,backupPath) {
|
||||
if (backupPath) {
|
||||
if (fs.existsSync(path)) {
|
||||
fs.renameSync(path,backupPath);
|
||||
try {
|
||||
fs.renameSync(path,backupPath);
|
||||
} catch(e) {
|
||||
log.warn(log._("storage.localfilesystem.fwrite-fail",{path:path, message:e.toString()}));
|
||||
}
|
||||
}
|
||||
}
|
||||
return when.promise(function(resolve,reject) {
|
||||
|
||||
@@ -24,7 +24,7 @@ function injectNode(id) {
|
||||
|
||||
util.inherits(injectNode, nodePage);
|
||||
|
||||
var payloadTypeList = {
|
||||
var payloadType = {
|
||||
"flow": 1,
|
||||
"global": 2,
|
||||
"str": 3,
|
||||
@@ -36,43 +36,54 @@ var payloadTypeList = {
|
||||
"env": 9,
|
||||
};
|
||||
|
||||
var repeatTypeList = {
|
||||
var timeType = {
|
||||
"none": 1,
|
||||
"interval": 2,
|
||||
"intervalBetweenTimes": 3,
|
||||
"atASpecificTime": 4,
|
||||
};
|
||||
|
||||
injectNode.prototype.setPayload = function(payloadType, payload) {
|
||||
var timeType = {
|
||||
"none": 1,
|
||||
"interval": 2,
|
||||
"intervalBetweenTimes": 3,
|
||||
"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")]');
|
||||
// Select a payload type.
|
||||
var payloadTypeXPath = '//*[@class="red-ui-typedInput-options"]/a[' + payloadTypeList[payloadType] + ']';
|
||||
var payloadTypeXPath = '//*[@class="red-ui-typedInput-options"]/a[' + payloadType[type] + ']';
|
||||
browser.clickWithWait(payloadTypeXPath);
|
||||
if (payload) {
|
||||
if (value) {
|
||||
// Input a value.
|
||||
browser.setValue('//*[@class="red-ui-typedInput-input"]/input', payload);
|
||||
browser.setValue('//*[@class="red-ui-typedInput-input"]/input', value);
|
||||
}
|
||||
}
|
||||
|
||||
injectNode.prototype.setTopic = function(topic) {
|
||||
browser.setValue('#node-input-topic', topic);
|
||||
injectNode.prototype.setTopic = function(value) {
|
||||
browser.setValue('#node-input-topic', value);
|
||||
}
|
||||
|
||||
injectNode.prototype.setOnce = function(once) {
|
||||
var isChecked = browser.isSelected('#node-input-once');
|
||||
if (isChecked !== once) {
|
||||
browser.clickWithWait('#node-input-once');
|
||||
}
|
||||
injectNode.prototype.setOnce = function(value) {
|
||||
browser.clickWithWait('#node-input-once');
|
||||
}
|
||||
|
||||
injectNode.prototype.setRepeat = function(repeatType) {
|
||||
var repeatTypeXPath = '//*[@id="inject-time-type-select"]/option[' + repeatTypeList[repeatType] + ']';
|
||||
browser.clickWithWait(repeatTypeXPath);
|
||||
injectNode.prototype.setTimeType = function(type) {
|
||||
var timeTypeXPath = '//*[@id="inject-time-type-select"]/option[' + timeType[type] + ']';
|
||||
browser.clickWithWait(timeTypeXPath);
|
||||
}
|
||||
|
||||
injectNode.prototype.setRepeatInterval = function(repeat) {
|
||||
browser.setValue('#inject-time-interval-count', repeat);
|
||||
injectNode.prototype.setRepeat = function(sec) {
|
||||
browser.setValue('#inject-time-interval-count', sec);
|
||||
}
|
||||
|
||||
module.exports = injectNode;
|
||||
|
||||
@@ -24,20 +24,22 @@ function debugNode(id) {
|
||||
|
||||
util.inherits(debugNode, nodePage);
|
||||
|
||||
debugNode.prototype.setOutput = function(complete) {
|
||||
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');
|
||||
if (complete !== 'true') {
|
||||
// Select the "msg" type.
|
||||
browser.clickWithWait('/html/body/div[11]/a[1]');
|
||||
// Input the path in msg.
|
||||
// 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', complete);
|
||||
} else {
|
||||
// Select the "complete msg object" type.
|
||||
browser.clickWithWait('/html/body/div[11]/a[2]');
|
||||
browser.setValue('//*[contains(@class, "red-ui-typedInput-input")]/input', value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,17 +24,12 @@ function functionNode(id) {
|
||||
|
||||
util.inherits(functionNode, nodePage);
|
||||
|
||||
functionNode.prototype.setFunction = function(func) {
|
||||
functionNode.prototype.setCode = function(value) {
|
||||
browser.click('#node-input-func-editor');
|
||||
browser.keys(['Control', 'Home', 'Control']);
|
||||
for (var i = 0; i < func.length; i++) {
|
||||
browser.keys([func.charAt(i)]);
|
||||
for (var i=0; i<value.length; i++) {
|
||||
browser.keys([value.substr(i, 1)]);
|
||||
}
|
||||
// Delete the unnecessary code that ace editor does the autocompletion.
|
||||
browser.keys(['Control', 'Shift', 'End', 'Shift', 'Control']);
|
||||
browser.keys(['Delete']);
|
||||
// Need to wait until ace editor correctly checks the syntax.
|
||||
browser.pause(50);
|
||||
}
|
||||
|
||||
module.exports = functionNode;
|
||||
|
||||
@@ -24,20 +24,29 @@ function templateNode(id) {
|
||||
|
||||
util.inherits(templateNode, nodePage);
|
||||
|
||||
templateNode.prototype.setSyntax = function(syntax) {
|
||||
browser.selectWithWait('#node-input-syntax', syntax);
|
||||
var syntaxType = {
|
||||
"mustache": 1,
|
||||
"plain": 2
|
||||
};
|
||||
|
||||
templateNode.prototype.setSyntax = function(type) {
|
||||
// Open a method type list.
|
||||
browser.clickWithWait('#node-input-syntax');
|
||||
// Select a method type.
|
||||
var syntaxTypeXPath = '//*[@id="node-input-syntax"]/option[' + syntaxType[type] + ']';
|
||||
browser.clickWithWait(syntaxTypeXPath);
|
||||
}
|
||||
|
||||
templateNode.prototype.setFormat = function(format) {
|
||||
browser.selectWithWait('#node-input-format', format);
|
||||
templateNode.prototype.setFormat = function(type) {
|
||||
browser.selectByValue('#node-input-format', type);
|
||||
}
|
||||
|
||||
templateNode.prototype.setTemplate = function(template) {
|
||||
templateNode.prototype.setTemplate = function(value) {
|
||||
browser.click('#node-input-template-editor');
|
||||
browser.keys(['Control', 'a', 'Control']); // call twice to release the keys.
|
||||
// Need to add a character one by one since some words such as 'Control' are treated as a special word.
|
||||
for (var i = 0; i < template.length; i++) {
|
||||
browser.keys([template.charAt(i)]);
|
||||
for (var i=0; i<value.length; i++) {
|
||||
browser.keys([value.charAt(i)]);
|
||||
}
|
||||
browser.keys(['Control', 'Shift', 'End', 'Shift', 'Control']);
|
||||
browser.keys(['Delete']);
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
function setServer(broker, port) {
|
||||
browser.setValue('#node-config-input-broker', broker);
|
||||
port = port ? port : 1883;
|
||||
browser.setValue('#node-config-input-port', port);
|
||||
}
|
||||
|
||||
function clickOk() {
|
||||
browser.clickWithWait('#node-config-dialog-ok');
|
||||
// Wait until an config dialog closes.
|
||||
browser.waitForVisible('#node-config-dialog-ok', 2000, true);
|
||||
}
|
||||
|
||||
function edit() {
|
||||
browser.clickWithWait('#node-input-lookup-broker');
|
||||
// Wait until a config dialog opens.
|
||||
browser.waitForVisible('#node-config-dialog-ok', 2000);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setServer: setServer,
|
||||
clickOk: clickOk,
|
||||
edit: edit
|
||||
};
|
||||
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* 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 mqttInNode(id) {
|
||||
nodePage.call(this, id);
|
||||
}
|
||||
|
||||
util.inherits(mqttInNode, nodePage);
|
||||
|
||||
mqttInNode.prototype.setTopic = function (topic) {
|
||||
browser.setValue('#node-input-topic', topic);
|
||||
}
|
||||
|
||||
mqttInNode.prototype.setQoS = function (qos) {
|
||||
browser.selectWithWait('#node-input-qos', qos);
|
||||
}
|
||||
|
||||
module.exports = mqttInNode;
|
||||
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* 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 mqttOutNode(id) {
|
||||
nodePage.call(this, id);
|
||||
}
|
||||
|
||||
util.inherits(mqttOutNode, nodePage);
|
||||
|
||||
mqttOutNode.prototype.setTopic = function(topic) {
|
||||
browser.setValue('#node-input-topic', topic);
|
||||
}
|
||||
|
||||
mqttOutNode.prototype.setRetain = function (retain) {
|
||||
browser.selectWithWait('#node-input-retain', retain);
|
||||
}
|
||||
|
||||
module.exports = mqttOutNode;
|
||||
@@ -22,14 +22,30 @@ function httpinNode(id) {
|
||||
nodePage.call(this, id);
|
||||
}
|
||||
|
||||
util.inherits(httpinNode, nodePage);
|
||||
|
||||
httpinNode.prototype.setMethod = function(method) {
|
||||
browser.selectWithWait('#node-input-method', method);
|
||||
function setMethod(type) {
|
||||
browser.selectByValue('#node-input-method', type);
|
||||
}
|
||||
|
||||
httpinNode.prototype.setUrl = function(url) {
|
||||
browser.setValue('#node-input-url', url);
|
||||
util.inherits(httpinNode, nodePage);
|
||||
|
||||
var methodType = {
|
||||
"get": 1,
|
||||
"post": 2,
|
||||
"put": 3,
|
||||
"delete": 4,
|
||||
"patch": 5,
|
||||
};
|
||||
|
||||
httpinNode.prototype.setMethod = function(type) {
|
||||
// Open a method type list.
|
||||
browser.clickWithWait('#node-input-method');
|
||||
// Select a method type.
|
||||
var methodTypeXPath = '//*[@id="node-input-method"]/option[' + methodType[type] + ']';
|
||||
browser.clickWithWait(methodTypeXPath);
|
||||
}
|
||||
|
||||
httpinNode.prototype.setUrl = function(value) {
|
||||
browser.setValue('#node-input-url', value);
|
||||
}
|
||||
|
||||
module.exports = httpinNode;
|
||||
|
||||
@@ -24,16 +24,36 @@ function httpRequestNode(id) {
|
||||
|
||||
util.inherits(httpRequestNode, nodePage);
|
||||
|
||||
httpRequestNode.prototype.setUrl = function(url) {
|
||||
browser.setValue('#node-input-url', url);
|
||||
var methodType = {
|
||||
"get": 1,
|
||||
"post": 2,
|
||||
"put": 3,
|
||||
"delete": 4,
|
||||
"setByMsgMethod": 5,
|
||||
};
|
||||
|
||||
var retType = {
|
||||
"txt": 1,
|
||||
"bin": 2,
|
||||
"obj": 3,
|
||||
};
|
||||
|
||||
httpRequestNode.prototype.setUrl = function(value) {
|
||||
browser.setValue('#node-input-url', value);
|
||||
}
|
||||
|
||||
httpRequestNode.prototype.setMethod = function(method) {
|
||||
browser.selectWithWait('#node-input-method', method);
|
||||
httpRequestNode.prototype.setMethod = function(type) {
|
||||
// Open a method type list.
|
||||
browser.clickWithWait('#node-input-method');
|
||||
// Select a method type.
|
||||
var methodTypeXPath = '//*[@id="node-input-method"]/option[' + methodType[type] + ']';
|
||||
browser.clickWithWait(methodTypeXPath);
|
||||
}
|
||||
|
||||
httpRequestNode.prototype.setReturn = function(ret) {
|
||||
browser.selectWithWait('#node-input-ret', ret);
|
||||
httpRequestNode.prototype.setRet = function(type) {
|
||||
browser.clickWithWait('#node-input-ret');
|
||||
var retTypeXPath = '//*[@id="node-input-ret"]/option[' + retType[type] + ']';
|
||||
browser.clickWithWait(retTypeXPath);
|
||||
}
|
||||
|
||||
module.exports = httpRequestNode;
|
||||
|
||||
@@ -24,6 +24,13 @@ function changeNode(id) {
|
||||
|
||||
util.inherits(changeNode, nodePage);
|
||||
|
||||
var tType = {
|
||||
"set": 1,
|
||||
"change": 2,
|
||||
"delete": 3,
|
||||
"move": 4,
|
||||
};
|
||||
|
||||
var totType = {
|
||||
"msg": 1,
|
||||
"flow": 2,
|
||||
@@ -35,7 +42,6 @@ var totType = {
|
||||
"bin": 8,
|
||||
"date": 9,
|
||||
"jsonata": 10,
|
||||
"env": 11,
|
||||
};
|
||||
|
||||
var ptType = {
|
||||
@@ -44,8 +50,8 @@ var ptType = {
|
||||
"global": 3,
|
||||
};
|
||||
|
||||
function setT(t, index) {
|
||||
browser.selectWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/select', t);
|
||||
function setT(rule, index) {
|
||||
browser.selectByValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/select', rule);
|
||||
}
|
||||
|
||||
// It is better to create a function whose input value is the object type in the future,
|
||||
|
||||
@@ -24,8 +24,8 @@ function rangeNode(id) {
|
||||
|
||||
util.inherits(rangeNode, nodePage);
|
||||
|
||||
rangeNode.prototype.setAction = function(action) {
|
||||
browser.selectWithWait('#node-input-action', action);
|
||||
rangeNode.prototype.setAction = function(value) {
|
||||
browser.selectByValue('#node-input-action', value);
|
||||
}
|
||||
|
||||
rangeNode.prototype.setRange = function(minin, maxin, minout, maxout) {
|
||||
|
||||
@@ -24,8 +24,8 @@ function htmlNode(id) {
|
||||
|
||||
util.inherits(htmlNode, nodePage);
|
||||
|
||||
htmlNode.prototype.setSelector = function(tag) {
|
||||
browser.setValue('#node-input-tag', tag);
|
||||
htmlNode.prototype.setTag = function(value) {
|
||||
browser.setValue('#node-input-tag', value);
|
||||
}
|
||||
|
||||
module.exports = htmlNode;
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* 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 jsonNode(id) {
|
||||
nodePage.call(this, id);
|
||||
}
|
||||
|
||||
util.inherits(jsonNode, nodePage);
|
||||
|
||||
jsonNode.prototype.setAction = function (action) {
|
||||
browser.setValue('node-input-action', action);
|
||||
}
|
||||
|
||||
jsonNode.prototype.setProperty = function(property) {
|
||||
browser.setValue('//*[@id="dialog-form"]/div[2]/div/div/input', property);
|
||||
}
|
||||
|
||||
module.exports = jsonNode;
|
||||
@@ -31,13 +31,13 @@ var formatType = {
|
||||
"stream": 4
|
||||
};
|
||||
|
||||
fileinNode.prototype.setFilename = function(filename) {
|
||||
browser.setValue('#node-input-filename', filename);
|
||||
fileinNode.prototype.setFilename = function(value) {
|
||||
browser.setValue('#node-input-filename', value);
|
||||
}
|
||||
|
||||
fileinNode.prototype.setOutput = function(format) {
|
||||
fileinNode.prototype.setFormat = function(type) {
|
||||
browser.clickWithWait('#node-input-format');
|
||||
var formatTypeXPath = '//*[@id="node-input-format"]/option[' + formatType[format] + ']';
|
||||
var formatTypeXPath = '//*[@id="node-input-format"]/option[' + formatType[type] + ']';
|
||||
browser.clickWithWait(formatTypeXPath);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,15 +18,12 @@ var injectNode = require('./core/core/20-inject_page');
|
||||
var debugNode = require('./core/core/58-debug_page');
|
||||
var templateNode = require('./core/core/80-template_page');
|
||||
var functionNode = require('./core/core/80-function_page');
|
||||
var mqttInNode = require('./core/io/10-mqttin_page');
|
||||
var mqttOutNode = require('./core/io/10-mqttout_page');
|
||||
var httpinNode = require('./core/io/21-httpin_page');
|
||||
var httpResponseNode = require('./core/io/21-httpresponse_page');
|
||||
var changeNode = require('./core/logic/15-change_page');
|
||||
var rangeNode = require('./core/logic/16-range_page');
|
||||
var httpRequestNode = require('./core/io/21-httprequest_page');
|
||||
var htmlNode = require('./core/parsers/70-HTML_page');
|
||||
var jsonNode = require('./core/parsers/70-JSON_page');
|
||||
var fileinNode = require('./core/storage/50-filein_page');
|
||||
|
||||
|
||||
@@ -34,11 +31,9 @@ var nodeCatalog = {
|
||||
// input
|
||||
"inject": injectNode,
|
||||
"httpin": httpinNode,
|
||||
"mqttIn":mqttInNode,
|
||||
// output
|
||||
"debug": debugNode,
|
||||
"httpResponse": httpResponseNode,
|
||||
"mqttOut": mqttOutNode,
|
||||
// function
|
||||
"function": functionNode,
|
||||
"template": templateNode,
|
||||
@@ -46,7 +41,6 @@ var nodeCatalog = {
|
||||
"range": rangeNode,
|
||||
"httpRequest": httpRequestNode,
|
||||
"html": htmlNode,
|
||||
"json":jsonNode,
|
||||
// storage
|
||||
"filein": fileinNode,
|
||||
}
|
||||
|
||||
@@ -38,12 +38,6 @@ function init() {
|
||||
var ret = browser.getText(selector);
|
||||
return ret;
|
||||
}, false);
|
||||
|
||||
browser.addCommand("selectWithWait", function(selector, value) {
|
||||
browser.waitForVisible(selector, 5000);
|
||||
var ret = browser.selectByValue(selector, value);
|
||||
return ret;
|
||||
}, false);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -18,11 +18,9 @@ var idMap = {
|
||||
// input
|
||||
"inject": "#palette_node_inject",
|
||||
"httpin": "#palette_node_http_in",
|
||||
"mqttIn": "#palette_node_mqtt_in",
|
||||
// output
|
||||
"debug": "#palette_node_debug",
|
||||
"httpResponse": "#palette_node_http_response",
|
||||
"mqttOut": "#palette_node_mqtt_out",
|
||||
// function
|
||||
"function": "#palette_node_function",
|
||||
"template": "#palette_node_template",
|
||||
@@ -30,7 +28,6 @@ var idMap = {
|
||||
"range": "#palette_node_range",
|
||||
"httpRequest": "#palette_node_http_request",
|
||||
"html": "#palette_node_html",
|
||||
"json": "#palette_node_json",
|
||||
// storage
|
||||
"filein": "#palette_node_file_in",
|
||||
};
|
||||
@@ -17,8 +17,8 @@
|
||||
var should = require("should");
|
||||
|
||||
var helper = require("../../editor_helper");
|
||||
var debugTab = require('../../pageobjects/editor/debugTab_page');
|
||||
var workspace = require('../../pageobjects/editor/workspace_page');
|
||||
var debugTab = require('../../pageobjects/workspace/debugTab_page');
|
||||
var workspace = require('../../pageobjects/workspace/workspace_page');
|
||||
|
||||
var nodeWidth = 200;
|
||||
var nodeHeight = 100;
|
||||
@@ -65,7 +65,7 @@ describe('cookbook', function() {
|
||||
|
||||
httpRequestNode.edit();
|
||||
httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello');
|
||||
httpRequestNode.setMethod("GET");
|
||||
httpRequestNode.setMethod("get");
|
||||
httpRequestNode.clickOk();
|
||||
|
||||
injectNode.connect(httpRequestNode);
|
||||
@@ -105,7 +105,7 @@ describe('cookbook', function() {
|
||||
|
||||
httpRequestNode.edit();
|
||||
httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-query?name=Nick');
|
||||
httpRequestNode.setMethod("GET");
|
||||
httpRequestNode.setMethod("get");
|
||||
httpRequestNode.clickOk();
|
||||
|
||||
injectNode.connect(httpRequestNode);
|
||||
@@ -145,7 +145,7 @@ describe('cookbook', function() {
|
||||
|
||||
httpRequestNode.edit();
|
||||
httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-param/Dave');
|
||||
httpRequestNode.setMethod("GET");
|
||||
httpRequestNode.setMethod("get");
|
||||
httpRequestNode.clickOk();
|
||||
|
||||
injectNode.connect(httpRequestNode);
|
||||
@@ -185,12 +185,12 @@ describe('cookbook', function() {
|
||||
var debugNode = workspace.addNode("debug", nodeWidth * 3, nodeHeight);
|
||||
|
||||
changeNode.edit();
|
||||
changeNode.ruleSet("headers", "msg", '{"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}', "json");
|
||||
changeNode.ruleSet("headers", "msg", "{\"user-agent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\"}", "json");
|
||||
changeNode.clickOk();
|
||||
|
||||
httpRequestNode.edit();
|
||||
httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-headers');
|
||||
httpRequestNode.setMethod("GET");
|
||||
httpRequestNode.setMethod("get");
|
||||
httpRequestNode.clickOk();
|
||||
|
||||
injectNode.connect(changeNode);
|
||||
@@ -249,7 +249,7 @@ describe('cookbook', function() {
|
||||
var debugNode = workspace.addNode("debug", nodeWidth * 2, nodeHeight * 2);
|
||||
|
||||
httpRequestNode.edit();
|
||||
httpRequestNode.setMethod("GET");
|
||||
httpRequestNode.setMethod("get");
|
||||
httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-data');
|
||||
httpRequestNode.clickOk();
|
||||
|
||||
@@ -280,7 +280,7 @@ describe('cookbook', function() {
|
||||
templateNode.edit();
|
||||
templateNode.setSyntax("mustache");
|
||||
templateNode.setFormat("handlebars");
|
||||
templateNode.setTemplate('{ "Hello": "World" }');
|
||||
templateNode.setTemplate("{ \"Hello\": \"World\" }");
|
||||
templateNode.clickOk();
|
||||
|
||||
changeNode.edit();
|
||||
@@ -299,12 +299,12 @@ describe('cookbook', function() {
|
||||
var debugNode = workspace.addNode("debug", nodeWidth * 2, nodeHeight);
|
||||
|
||||
httpRequestNode.edit();
|
||||
httpRequestNode.setMethod("GET");
|
||||
httpRequestNode.setMethod("get");
|
||||
httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-json');
|
||||
httpRequestNode.clickOk();
|
||||
|
||||
debugNode.edit();
|
||||
debugNode.setOutput("headers");
|
||||
debugNode.setTarget("msg", "headers");
|
||||
debugNode.clickOk();
|
||||
|
||||
injectNode.connect(httpRequestNode);
|
||||
@@ -332,7 +332,7 @@ describe('cookbook', function() {
|
||||
|
||||
fileinNode.edit();
|
||||
fileinNode.setFilename("test/resources/file-in-node/test.txt");
|
||||
fileinNode.setOutput("");
|
||||
fileinNode.setFormat("");
|
||||
fileinNode.clickOk();
|
||||
|
||||
changeNode.edit();
|
||||
@@ -352,7 +352,7 @@ describe('cookbook', function() {
|
||||
|
||||
httpRequestNode.edit();
|
||||
httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-file');
|
||||
httpRequestNode.setMethod("GET");
|
||||
httpRequestNode.setMethod("get");
|
||||
httpRequestNode.clickOk();
|
||||
|
||||
injectNode.connect(httpRequestNode);
|
||||
@@ -396,7 +396,7 @@ describe('cookbook', function() {
|
||||
|
||||
httpRequestNode.edit();
|
||||
httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-raw');
|
||||
httpRequestNode.setMethod("POST");
|
||||
httpRequestNode.setMethod("post");
|
||||
httpRequestNode.clickOk();
|
||||
|
||||
injectNode.connect(httpRequestNode);
|
||||
@@ -440,12 +440,12 @@ describe('cookbook', function() {
|
||||
injectNode.clickOk();
|
||||
|
||||
changeNode.edit();
|
||||
changeNode.ruleSet("headers", "msg", '{"content-type":"application/x-www-form-urlencoded"}', "json");
|
||||
changeNode.ruleSet("headers", "msg", "{\"content-type\":\"application/x-www-form-urlencoded\"}", "json");
|
||||
changeNode.clickOk();
|
||||
|
||||
httpRequestNode.edit();
|
||||
httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-form');
|
||||
httpRequestNode.setMethod("POST");
|
||||
httpRequestNode.setMethod("post");
|
||||
httpRequestNode.clickOk();
|
||||
|
||||
injectNode.connect(changeNode);
|
||||
@@ -486,16 +486,16 @@ describe('cookbook', function() {
|
||||
var debugNode = workspace.addNode("debug", nodeWidth * 3, nodeHeight);
|
||||
|
||||
injectNode.edit()
|
||||
injectNode.setPayload("json", '{"name":"Nick"}');
|
||||
injectNode.setPayload("json", "{\"name\":\"Nick\"}");
|
||||
injectNode.clickOk();
|
||||
|
||||
changeNode.edit();
|
||||
changeNode.ruleSet("headers", "msg", '{"content-type":"application/json"}', "json");
|
||||
changeNode.ruleSet("headers", "msg", "{\"content-type\":\"application/json\"}", "json");
|
||||
changeNode.clickOk();
|
||||
|
||||
httpRequestNode.edit();
|
||||
httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-json');
|
||||
httpRequestNode.setMethod("POST");
|
||||
httpRequestNode.setMethod("post");
|
||||
httpRequestNode.clickOk();
|
||||
|
||||
injectNode.connect(changeNode);
|
||||
@@ -531,13 +531,13 @@ describe('cookbook', function() {
|
||||
httpinNodeFormat.clickOk();
|
||||
|
||||
functionNodeFormat.edit();
|
||||
functionNodeFormat.setFunction("msg.payload = JSON.stringify(msg.req.cookies,null,4);\nreturn msg;");
|
||||
functionNodeFormat.setCode("msg.payload = JSON.stringify(msg.req.cookies,null,4);");
|
||||
functionNodeFormat.clickOk();
|
||||
|
||||
templateNode.edit();
|
||||
templateNode.setSyntax("mustache");
|
||||
templateNode.setFormat("handlebars");
|
||||
templateNode.setTemplate('<html>\n<head></head>\n<body>\n<h1>Cookies</h1>\n<p></p><a href="hello-cookie/add">Add a cookie</a> • <a href="hello-cookie/clear">Clear cookies</a></p>\n<pre>{{ payload }}</pre>\n</body>\n</html>');
|
||||
templateNode.setTemplate("<html>\n<head></head>\n<body>\n<h1>Cookies</h1>\n<p></p><a href=\"hello-cookie/add\">Add a cookie</a> • <a href=\"hello-cookie/clear\">Clear cookies</a></p>\n<pre>{{ payload }}</pre>\n</body>\n</html>");
|
||||
templateNode.clickOk();
|
||||
|
||||
httpinNodeFormat.connect(functionNodeFormat);
|
||||
@@ -550,7 +550,7 @@ describe('cookbook', function() {
|
||||
httpinNodeAdd.clickOk();
|
||||
|
||||
functionNodeAdd.edit();
|
||||
functionNodeAdd.setFunction('msg.cookies = { };\n msg.cookies["demo-"+(Math.floor(Math.random()*1000))] = Date.now();\nreturn msg;');
|
||||
functionNodeAdd.setCode("msg.cookies = { };\n msg.cookies[\"demo-\"+(Math.floor(Math.random()*1000))] = Date.now();");
|
||||
functionNodeAdd.clickOk();
|
||||
|
||||
changeNode.edit();
|
||||
@@ -571,7 +571,7 @@ describe('cookbook', function() {
|
||||
httpinNodeClear.clickOk();
|
||||
|
||||
functionNodeClear.edit();
|
||||
functionNodeClear.setFunction("var cookieNames = Object.keys(msg.req.cookies).filter(function(cookieName) { return /^demo-/.test(cookieName);});\nmsg.cookies = {};\n\ncookieNames.forEach(function(cookieName) {\n msg.cookies[cookieName] = null;\n});\nreturn msg;\n");
|
||||
functionNodeClear.setCode("var cookieNames = Object.keys(msg.req.cookies).filter(function(cookieName) { return /^demo-/.test(cookieName);});\nmsg.cookies = {};\n\ncookieNames.forEach(function(cookieName) {\n msg.cookies[cookieName] = null;\n});\n\n");
|
||||
functionNodeClear.clickOk();
|
||||
|
||||
httpinNodeClear.connect(functionNodeClear);
|
||||
|
||||
@@ -1,228 +0,0 @@
|
||||
/**
|
||||
* 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 when = require('when');
|
||||
var should = require("should");
|
||||
var fs = require('fs-extra');
|
||||
|
||||
var helper = require("../../editor_helper");
|
||||
var debugTab = require('../../pageobjects/editor/debugTab_page');
|
||||
var workspace = require('../../pageobjects/editor/workspace_page');
|
||||
var specUtil = require('../../pageobjects/util/spec_util_page');
|
||||
var mqttConfig = require('../../pageobjects/nodes/core/io/10-mqttconfig_page.js');
|
||||
|
||||
var nodeWidth = 200;
|
||||
var nodeHeight = 100;
|
||||
var httpNodeRoot = "/api";
|
||||
|
||||
var mqttServer;
|
||||
var mosca = require('mosca');
|
||||
var moscaSettings = {
|
||||
port: 1883,
|
||||
persistence: {
|
||||
// Needs for retaining messages.
|
||||
factory: mosca.persistence.Memory
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// https://cookbook.nodered.org/
|
||||
describe('cookbook', function() {
|
||||
beforeEach(function() {
|
||||
workspace.deleteAllNodes();
|
||||
});
|
||||
|
||||
before(function() {
|
||||
browser.call(function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
mqttServer = new mosca.Server(moscaSettings, function() {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
helper.startServer();
|
||||
});
|
||||
|
||||
after(function() {
|
||||
browser.call(function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
mqttServer.close(function() {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
helper.stopServer();
|
||||
});
|
||||
|
||||
describe('MQTT', function() {
|
||||
it('Add an MQTT broker to prepare for UI test', function() {
|
||||
var mqttOutNode = workspace.addNode("mqttOut", nodeWidth);
|
||||
|
||||
mqttOutNode.edit();
|
||||
mqttConfig.edit();
|
||||
mqttConfig.setServer("localhost");
|
||||
mqttConfig.clickOk();
|
||||
mqttOutNode.clickOk();
|
||||
|
||||
workspace.deploy();
|
||||
});
|
||||
|
||||
it('Connect to an MQTT broker', function() {
|
||||
var injectNode = workspace.addNode("inject");
|
||||
var mqttOutNode = workspace.addNode("mqttOut", nodeWidth);
|
||||
|
||||
var mqttInNode = workspace.addNode("mqttIn", 0, nodeHeight);
|
||||
var debugNode = workspace.addNode("debug", nodeWidth * 2, nodeHeight);
|
||||
|
||||
injectNode.edit();
|
||||
injectNode.setPayload("num", 22);
|
||||
injectNode.clickOk();
|
||||
|
||||
mqttOutNode.edit();
|
||||
mqttOutNode.setTopic("sensors/livingroom/temp");
|
||||
mqttOutNode.clickOk();
|
||||
|
||||
injectNode.connect(mqttOutNode);
|
||||
|
||||
mqttInNode.edit();
|
||||
mqttInNode.setTopic("sensors/livingroom/temp");
|
||||
mqttInNode.setQoS("2");
|
||||
mqttInNode.clickOk();
|
||||
|
||||
mqttInNode.connect(debugNode);
|
||||
|
||||
workspace.deploy();
|
||||
|
||||
debugTab.open();
|
||||
debugTab.clearMessage();
|
||||
injectNode.clickLeftButton();
|
||||
debugTab.getMessage().should.eql('"22"');
|
||||
});
|
||||
|
||||
// skip this case since it is same as other cases.
|
||||
it.skip('Publish messages to a topic');
|
||||
|
||||
it('Set the topic of a published message', function() {
|
||||
var injectNode = workspace.addNode("inject");
|
||||
var mqttOutNode = workspace.addNode("mqttOut", nodeWidth * 2);
|
||||
|
||||
injectNode.edit();
|
||||
injectNode.setPayload("num", 22);
|
||||
injectNode.setTopic("sensors/kitchen/temperature");
|
||||
injectNode.clickOk();
|
||||
|
||||
mqttOutNode.edit();
|
||||
mqttOutNode.clickOk();
|
||||
|
||||
injectNode.connect(mqttOutNode);
|
||||
|
||||
// The code for confirmation starts from here.
|
||||
var mqttInNode = workspace.addNode("mqttIn", 0, nodeHeight);
|
||||
var debugNode = workspace.addNode("debug", nodeWidth * 2, nodeHeight);
|
||||
|
||||
mqttInNode.edit();
|
||||
mqttInNode.setTopic("sensors/kitchen/temperature");
|
||||
mqttInNode.clickOk();
|
||||
|
||||
mqttInNode.connect(debugNode);
|
||||
// The code for confirmation ends here.
|
||||
|
||||
workspace.deploy();
|
||||
|
||||
debugTab.open();
|
||||
debugTab.clearMessage();
|
||||
injectNode.clickLeftButton();
|
||||
debugTab.getMessage().should.eql('"22"');
|
||||
});
|
||||
|
||||
it('Publish a retained message to a topic', function() {
|
||||
var injectNode = workspace.addNode("inject");
|
||||
var mqttOutNode = workspace.addNode("mqttOut", nodeWidth);
|
||||
|
||||
injectNode.edit();
|
||||
injectNode.setPayload("num", 22);
|
||||
injectNode.clickOk();
|
||||
|
||||
mqttOutNode.edit();
|
||||
mqttOutNode.setTopic("sensors/livingroom/temp");
|
||||
mqttOutNode.setRetain("true");
|
||||
mqttOutNode.clickOk();
|
||||
|
||||
injectNode.connect(mqttOutNode);
|
||||
|
||||
workspace.deploy();
|
||||
debugTab.open();
|
||||
injectNode.clickLeftButton();
|
||||
debugTab.clearMessage();
|
||||
|
||||
// The code for confirmation starts from here.
|
||||
var mqttInNode = workspace.addNode("mqttIn", 0, nodeHeight);
|
||||
var debugNode = workspace.addNode("debug", nodeWidth * 2, nodeHeight);
|
||||
|
||||
mqttInNode.edit();
|
||||
mqttInNode.setTopic("sensors/livingroom/temp");
|
||||
mqttInNode.clickOk();
|
||||
|
||||
mqttInNode.connect(debugNode);
|
||||
// The code for confirmation ends here.
|
||||
|
||||
workspace.deploy();
|
||||
debugTab.open();
|
||||
debugTab.getMessage().should.eql('"22"');
|
||||
});
|
||||
|
||||
// skip this case since it is same as other cases.
|
||||
it.skip('Subscribe to a topic');
|
||||
|
||||
it('Receive a parsed JSON message', function() {
|
||||
var injectNode = workspace.addNode("inject");
|
||||
var mqttOutNode = workspace.addNode("mqttOut", nodeWidth);
|
||||
|
||||
var mqttInNode = workspace.addNode("mqttIn", 0, nodeHeight);
|
||||
var jsonNode = workspace.addNode("json", nodeWidth, nodeHeight);
|
||||
var debugNode = workspace.addNode("debug", nodeWidth * 2, nodeHeight);
|
||||
|
||||
injectNode.edit();
|
||||
injectNode.setPayload("json", '{"sensor_id": 1234, "temperature": 13 }');
|
||||
injectNode.clickOk();
|
||||
|
||||
mqttOutNode.edit();
|
||||
mqttOutNode.setTopic("sensors/livingroom/temp");
|
||||
mqttOutNode.clickOk();
|
||||
|
||||
injectNode.connect(mqttOutNode);
|
||||
|
||||
mqttInNode.edit();
|
||||
mqttInNode.setTopic("sensors/#");
|
||||
mqttInNode.setQoS("2");
|
||||
mqttInNode.clickOk();
|
||||
|
||||
jsonNode.edit();
|
||||
jsonNode.setProperty("payload");
|
||||
jsonNode.clickOk();
|
||||
|
||||
mqttInNode.connect(jsonNode);
|
||||
jsonNode.connect(debugNode);
|
||||
|
||||
workspace.deploy();
|
||||
|
||||
debugTab.open();
|
||||
debugTab.clearMessage();
|
||||
injectNode.clickLeftButton();
|
||||
debugTab.getMessage().should.eql(['1234', '13']);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -19,8 +19,8 @@ var should = require("should");
|
||||
var fs = require('fs-extra');
|
||||
|
||||
var helper = require("../../editor_helper");
|
||||
var debugTab = require('../../pageobjects/editor/debugTab_page');
|
||||
var workspace = require('../../pageobjects/editor/workspace_page');
|
||||
var debugTab = require('../../pageobjects/workspace/debugTab_page');
|
||||
var workspace = require('../../pageobjects/workspace/workspace_page');
|
||||
var specUtil = require('../../pageobjects/util/spec_util_page');
|
||||
|
||||
var nodeWidth = 200;
|
||||
@@ -168,8 +168,8 @@ describe('cookbook', function() {
|
||||
var debugNode = workspace.addNode("debug", nodeWidth * 2);
|
||||
|
||||
injectNode.edit();
|
||||
injectNode.setRepeat("interval");
|
||||
injectNode.setRepeatInterval(1);
|
||||
injectNode.setTimeType("interval");
|
||||
injectNode.setRepeat(1);
|
||||
injectNode.clickOk();
|
||||
injectNode.connect(debugNode);
|
||||
|
||||
@@ -196,12 +196,12 @@ describe('cookbook', function() {
|
||||
var debugNode = workspace.addNode("debug", nodeWidth * 3);
|
||||
|
||||
httpRequetNode.edit();
|
||||
httpRequetNode.setMethod("GET");
|
||||
httpRequetNode.setMethod("get");
|
||||
httpRequetNode.setUrl(helper.url());
|
||||
httpRequetNode.clickOk();
|
||||
|
||||
htmlNode.edit();
|
||||
htmlNode.setSelector("title");
|
||||
htmlNode.setTag("title");
|
||||
htmlNode.clickOk();
|
||||
|
||||
injectNode.connect(httpRequetNode);
|
||||
@@ -336,14 +336,14 @@ describe('cookbook', function() {
|
||||
changeNodeSetPost.clickOk();
|
||||
|
||||
httpRequetNode.edit();
|
||||
httpRequetNode.setMethod("GET");
|
||||
httpRequetNode.setMethod("get");
|
||||
var url = helper.url() + httpNodeRoot + "/{{post}}";
|
||||
httpRequetNode.setUrl(url);
|
||||
httpRequetNode.setReturn("obj");
|
||||
httpRequetNode.setRet("obj");
|
||||
httpRequetNode.clickOk();
|
||||
|
||||
debugNode.edit();
|
||||
debugNode.setOutput("payload.title");
|
||||
debugNode.setTarget("msg", "payload.title");
|
||||
debugNode.clickOk();
|
||||
|
||||
injectNode.connect(changeNodeSetPost);
|
||||
@@ -364,11 +364,11 @@ describe('cookbook', function() {
|
||||
templateNode.edit();
|
||||
templateNode.setSyntax("mustache");
|
||||
templateNode.setFormat("handlebars");
|
||||
templateNode.setTemplate('{"title": "Hello"}');
|
||||
templateNode.setTemplate("{\"title\": \"Hello\"}");
|
||||
templateNode.clickOk();
|
||||
|
||||
changeNodeSetHeader.edit();
|
||||
changeNodeSetHeader.ruleSet("headers", "msg", '{"content-type":"application/json"}', "json");
|
||||
changeNodeSetHeader.ruleSet("headers", "msg", "{\"content-type\":\"application/json\"}", "json");
|
||||
changeNodeSetHeader.clickOk();
|
||||
|
||||
httpinNode.connect(templateNode);
|
||||
@@ -389,9 +389,9 @@ describe('cookbook', function() {
|
||||
var debugNode = workspace.addNode("debug", nodeWidth * 2);
|
||||
|
||||
httpRequetNode.edit();
|
||||
httpRequetNode.setMethod("GET");
|
||||
httpRequetNode.setMethod("get");
|
||||
httpRequetNode.setUrl(helper.url() + "/settings");
|
||||
httpRequetNode.setReturn("bin");
|
||||
httpRequetNode.setRet("bin");
|
||||
httpRequetNode.clickOk();
|
||||
|
||||
injectNode.connect(httpRequetNode);
|
||||
@@ -413,11 +413,11 @@ describe('cookbook', function() {
|
||||
var debugNode = workspace.addNode("debug", nodeWidth * 3);
|
||||
|
||||
functionNode.edit();
|
||||
functionNode.setFunction('msg.payload = "data to post";\nreturn msg;');
|
||||
functionNode.setCode("msg.payload = \"data to post\";");
|
||||
functionNode.clickOk();
|
||||
|
||||
httpRequetNode.edit();
|
||||
httpRequetNode.setMethod("POST");
|
||||
httpRequetNode.setMethod("post");
|
||||
var url = helper.url() + httpNodeRoot + "/set-header";
|
||||
httpRequetNode.setUrl(url);
|
||||
httpRequetNode.clickOk();
|
||||
|
||||
@@ -19,8 +19,8 @@ var should = require("should");
|
||||
var fs = require('fs-extra');
|
||||
|
||||
var helper = require("../../editor_helper");
|
||||
var debugTab = require('../../pageobjects/editor/debugTab_page');
|
||||
var workspace = require('../../pageobjects/editor/workspace_page');
|
||||
var debugTab = require('../../pageobjects/workspace/debugTab_page');
|
||||
var workspace = require('../../pageobjects/workspace/workspace_page');
|
||||
|
||||
var nodeWidth = 200;
|
||||
|
||||
@@ -1216,7 +1216,7 @@ describe('function node', function() {
|
||||
msg.should.have.property('payload', n1.id);
|
||||
done();
|
||||
});
|
||||
n1.receive({payload:"foo",topic: "bar"});
|
||||
n1.receive({payload:"foo",topicb: "bar"});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1230,7 +1230,7 @@ describe('function node', function() {
|
||||
msg.should.have.property('payload', n1.name);
|
||||
done();
|
||||
});
|
||||
n1.receive({payload:"foo",topic: "bar"});
|
||||
n1.receive({payload:"foo",topicb: "bar"});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1249,36 +1249,6 @@ describe('function node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow accessing env vars', function(done) {
|
||||
var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload = env.get('_TEST_FOO_'); return msg;"},
|
||||
{id:"n2", type:"helper"}];
|
||||
helper.load(functionNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var count = 0;
|
||||
delete process.env._TEST_FOO_;
|
||||
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
if (count === 0) {
|
||||
msg.should.have.property('payload', undefined);
|
||||
process.env._TEST_FOO_ = "hello";
|
||||
count++;
|
||||
n1.receive({payload:"foo",topic: "bar"});
|
||||
} else {
|
||||
msg.should.have.property('payload', "hello");
|
||||
done();
|
||||
}
|
||||
} catch(err) {
|
||||
done(err);
|
||||
} finally {
|
||||
delete process.env._TEST_FOO_;
|
||||
}
|
||||
});
|
||||
n1.receive({payload:"foo",topic: "bar"});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Logger', function () {
|
||||
it('should log an Info Message', function (done) {
|
||||
var flow = [{id: "n1", type: "function", wires: [["n2"]], func: "node.log('test');"}];
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
**/
|
||||
|
||||
var should = require("should");
|
||||
var rpiNode = require("../../../../nodes/core/hardware/36-rpi-gpio.js");
|
||||
var statusNode = require("../../../../nodes/core/core/25-status.js");
|
||||
var rpi = require("../../../../nodes/core/hardware/36-rpi-gpio.js");
|
||||
var helper = require("node-red-node-test-helper");
|
||||
var fs = require("fs");
|
||||
|
||||
@@ -51,7 +50,7 @@ describe('RPI GPIO Node', function() {
|
||||
|
||||
it('should load Input node', function(done) {
|
||||
var flow = [{id:"n1", type:"rpi-gpio in", name:"rpi-gpio in" }];
|
||||
helper.load(rpiNode, flow, function() {
|
||||
helper.load(rpi, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
n1.should.have.property('name', 'rpi-gpio in');
|
||||
try {
|
||||
@@ -70,7 +69,7 @@ describe('RPI GPIO Node', function() {
|
||||
|
||||
it('should load Output node', function(done) {
|
||||
var flow = [{id:"n1", type:"rpi-gpio out", name:"rpi-gpio out" }];
|
||||
helper.load(rpiNode, flow, function() {
|
||||
helper.load(rpi, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
n1.should.have.property('name', 'rpi-gpio out');
|
||||
try {
|
||||
@@ -87,68 +86,4 @@ describe('RPI GPIO Node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should read a dummy value high (not on Pi)', function(done) {
|
||||
var flow = [{id:"n1", type:"rpi-gpio in", pin:"7", intype:"up", debounce:"25", read:true, wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"}];
|
||||
helper.load(rpiNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.property('topic', 'pi/7');
|
||||
msg.should.have.property('payload', 1);
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should read a dummy value low (not on Pi)', function(done) {
|
||||
var flow = [{id:"n1", type:"rpi-gpio in", pin:"11", intype:"down", debounce:"25", read:true, wires:[["n2"]] },
|
||||
{id:"n2", type:"helper"}];
|
||||
helper.load(rpiNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.property('topic', 'pi/11');
|
||||
msg.should.have.property('payload', 0);
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able preset out to a dummy value (not on Pi)', function(done) {
|
||||
var flow = [{id:"n1", type:"rpi-gpio out", pin:"7", out:"out", level:"0", set:true, freq:"", wires:[], z:"1"},
|
||||
{id:"n2", type:"status", scope:null, wires:[["n3"]], z:"1"},
|
||||
{id:"n3", type:"helper", z:"1"}];
|
||||
helper.load([rpiNode,statusNode], flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var n3 = helper.getNode("n3");
|
||||
var count = 0;
|
||||
n3.on("input", function(msg) {
|
||||
// Only check the first status message received as it may get a
|
||||
// 'closed' status as the test is tidied up.
|
||||
if (count === 0) {
|
||||
count++;
|
||||
try {
|
||||
msg.should.have.property('status');
|
||||
msg.status.should.have.property('text', "rpi-gpio.status.na");
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
n1.receive({payload:"1"});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -603,14 +603,14 @@ describe('JOIN node', function() {
|
||||
});
|
||||
|
||||
it('should accumulate a merged object', function(done) {
|
||||
var flow = [{id:"n1", type:"join", wires:[["n2"]], build:"merged",mode:"custom",accumulate:true, count:3},
|
||||
var flow = [{id:"n1", type:"join", wires:[["n2"]], build:"merged",mode:"custom",accumulate:true, count:1},
|
||||
{id:"n2", type:"helper"}];
|
||||
helper.load(joinNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
if (c === 3) {
|
||||
if (c === 5) {
|
||||
try {
|
||||
msg.should.have.property("payload");
|
||||
msg.payload.should.have.property("a",3);
|
||||
@@ -632,14 +632,14 @@ describe('JOIN node', function() {
|
||||
});
|
||||
|
||||
it('should be able to reset an accumulation', function(done) {
|
||||
var flow = [{id:"n1", type:"join", wires:[["n2"]], build:"merged",accumulate:true,mode:"custom", count:3},
|
||||
var flow = [{id:"n1", type:"join", wires:[["n2"]], build:"merged",accumulate:true,mode:"custom", count:1},
|
||||
{id:"n2", type:"helper"}];
|
||||
helper.load(joinNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
if (c === 1) {
|
||||
if (c === 3) {
|
||||
try {
|
||||
msg.should.have.property("payload");
|
||||
msg.payload.should.have.property("a",1);
|
||||
@@ -649,20 +649,11 @@ describe('JOIN node', function() {
|
||||
}
|
||||
catch(e) { done(e) }
|
||||
}
|
||||
if (c === 2) {
|
||||
if (c === 5) {
|
||||
try {
|
||||
msg.should.have.property("payload");
|
||||
msg.payload.should.have.property("e",2);
|
||||
msg.payload.should.have.property("f",1);
|
||||
}
|
||||
catch(e) { done(e) }
|
||||
}
|
||||
if (c === 3) {
|
||||
try {
|
||||
msg.should.have.property("payload");
|
||||
msg.payload.should.have.property("g",2);
|
||||
msg.payload.should.have.property("h",1);
|
||||
msg.payload.should.have.property("i",3);
|
||||
msg.payload.should.have.property("b",2);
|
||||
msg.payload.should.have.property("c",1);
|
||||
done();
|
||||
}
|
||||
catch(e) { done(e) }
|
||||
@@ -673,11 +664,8 @@ describe('JOIN node', function() {
|
||||
n1.receive({payload:{b:2}, topic:"b"});
|
||||
n1.receive({payload:{c:3}, topic:"c"});
|
||||
n1.receive({payload:{d:4}, topic:"d", complete:true});
|
||||
n1.receive({payload:{e:2}, topic:"e"});
|
||||
n1.receive({payload:{f:1}, topic:"f", complete:true});
|
||||
n1.receive({payload:{g:2}, topic:"g"});
|
||||
n1.receive({payload:{h:1}, topic:"h"});
|
||||
n1.receive({payload:{i:3}, topic:"i"});
|
||||
n1.receive({payload:{b:2}, topic:"e"});
|
||||
n1.receive({payload:{c:1}, topic:"f"});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -66,25 +66,13 @@ describe('SORT node', function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.property(target);
|
||||
var data = msg[target];
|
||||
data.length.should.equal(data_out.length);
|
||||
for(var i = 0; i < data_out.length; i++) {
|
||||
var data0 = data[i];
|
||||
var data1 = data_out[i];
|
||||
if (typeof data0 === "object") {
|
||||
data0.should.deepEqual(data1);
|
||||
}
|
||||
else {
|
||||
data0.should.equal(data1);
|
||||
}
|
||||
}
|
||||
done();
|
||||
}
|
||||
catch(e) {
|
||||
console.log(e);
|
||||
msg.should.have.property(target);
|
||||
var data = msg[target];
|
||||
data.length.should.equal(data_out.length);
|
||||
for(var i = 0; i < data_out.length; i++) {
|
||||
data[i].should.equal(data_out[i]);
|
||||
}
|
||||
done();
|
||||
});
|
||||
var msg = {};
|
||||
msg[target] = data_in;
|
||||
@@ -105,34 +93,6 @@ describe('SORT node', function() {
|
||||
}
|
||||
|
||||
function check_sort1(flow, key, key_type, data_in, data_out, done) {
|
||||
function equals(v0, v1) {
|
||||
var k0 = Object.keys(v0);
|
||||
var k1 = Object.keys(v1);
|
||||
|
||||
if (k0.length === k1.length) {
|
||||
for (var i = 0; i < k0.length; i++) {
|
||||
var k = k0[i];
|
||||
if (!v1.hasOwnProperty(k) ||
|
||||
(v0[k] !== v1[k])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function indexOf(a, v) {
|
||||
for(var i = 0; i < a.length; i++) {
|
||||
var av = a[i];
|
||||
if ((typeof v === 'object') && equals(v, av)) {
|
||||
return i;
|
||||
}
|
||||
else if (v === av) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
var sort = flow[0];
|
||||
var prop = (key_type === "msg") ? key : "payload";
|
||||
sort.targetType = "seq";
|
||||
@@ -147,7 +107,7 @@ describe('SORT node', function() {
|
||||
msg.should.have.property("parts");
|
||||
msg.parts.should.have.property("count", data_out.length);
|
||||
var data = msg[prop];
|
||||
var index = indexOf(data_out, data);
|
||||
var index = data_out.indexOf(data);
|
||||
msg.parts.should.have.property("index", index);
|
||||
count++;
|
||||
if (count === data_out.length) {
|
||||
@@ -176,6 +136,7 @@ describe('SORT node', function() {
|
||||
check_sort1(flow, exp, "jsonata", data_in, data_out, done);
|
||||
}
|
||||
|
||||
|
||||
(function() {
|
||||
var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, wires:[["n2"]]},
|
||||
{id:"n2", type:"helper"}];
|
||||
@@ -278,19 +239,6 @@ describe('SORT node', function() {
|
||||
});
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var flow = [{id:"n1", type:"sort", order:"ascending", as_num:true, wires:[["n2"]]},
|
||||
{id:"n2", type:"helper"}];
|
||||
var conv = function(x) {
|
||||
return x.map(function(v) { return { val:v }; });
|
||||
};
|
||||
var data_in = conv([ "200", "4", "30", "1000" ]);
|
||||
var data_out = conv([ "4", "30", "200", "1000" ]);
|
||||
it('should sort payload of objects', function(done) {
|
||||
check_sort0C(flow, "val", data_in, data_out, done);
|
||||
});
|
||||
})();
|
||||
|
||||
it('should sort payload by context (exp, not number, ascending)', function(done) {
|
||||
var flow = [{id:"n1", type:"sort", target:"data", targetType:"msg", msgKey:"$flowContext($)", msgKeyType:"jsonata", order:"ascending", as_num:false, wires:[["n2"]],z:"flow"},
|
||||
{id:"n2", type:"helper",z:"flow"},
|
||||
@@ -320,7 +268,7 @@ describe('SORT node', function() {
|
||||
});
|
||||
|
||||
it('should sort message group by context (exp, not number, ascending)', function(done) {
|
||||
var flow = [{id:"n1", type:"sort", target:"data", targetType:"seq", seqKey:"$globalContext(payload)", seqKeyType:"jsonata", order:"ascending", as_num:false, wires:[["n2"]],z:"flow"},
|
||||
var flow = [{id:"n1", type:"sort", target:"data", targetType:"msg", msgKey:"$globalContext(payload)", msgKeyType:"jsonata", order:"ascending", as_num:false, wires:[["n2"]],z:"flow"},
|
||||
{id:"n2", type:"helper",z:"flow"},
|
||||
{id:"flow", type:"tab"}];
|
||||
var data_in = [ "first", "second", "third", "fourth" ];
|
||||
@@ -334,20 +282,15 @@ describe('SORT node', function() {
|
||||
n1.context()["global"].set("third","3");
|
||||
n1.context()["global"].set("fourth","2");
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.property("payload");
|
||||
msg.should.have.property("parts");
|
||||
msg.parts.should.have.property("count", data_out.length);
|
||||
var data = msg["payload"];
|
||||
var index = data_out.indexOf(data);
|
||||
msg.parts.should.have.property("index", index);
|
||||
count++;
|
||||
if (count === data_out.length) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
done(e);
|
||||
msg.should.have.property("payload");
|
||||
msg.should.have.property("parts");
|
||||
msg.parts.should.have.property("count", data_out.length);
|
||||
var data = msg["payload"];
|
||||
var index = data_out.indexOf(data);
|
||||
msg.parts.should.have.property("index", index);
|
||||
count++;
|
||||
if (count === data_out.length) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
var len = data_in.length;
|
||||
@@ -389,7 +332,7 @@ describe('SORT node', function() {
|
||||
});
|
||||
|
||||
it('should sort message group by persistable context (exp, not number, descending)', function(done) {
|
||||
var flow = [{id:"n1", type:"sort", target:"data", targetType:"seq", seqKey:"$flowContext(payload,\"memory\")", seqKeyType:"jsonata", order:"descending", as_num:false, wires:[["n2"]],z:"flow"},
|
||||
var flow = [{id:"n1", type:"sort", target:"data", targetType:"msg", msgKey:"$flowContext(payload,\"memory\")", msgKeyType:"jsonata", order:"descending", as_num:false, wires:[["n2"]],z:"flow"},
|
||||
{id:"n2", type:"helper",z:"flow"},
|
||||
{id:"flow", type:"tab"}];
|
||||
var data_in = [ "first", "second", "third", "fourth" ];
|
||||
|
||||
@@ -265,23 +265,6 @@ describe('JSON node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass an object if provided a valid object and schema and action is object', function(done) {
|
||||
var flow = [{id:"jn1",type:"json",action:"obj",wires:[["jn2"]]},
|
||||
{id:"jn2", type:"helper"}];
|
||||
helper.load(jsonNode, flow, function() {
|
||||
var jn1 = helper.getNode("jn1");
|
||||
var jn2 = helper.getNode("jn2");
|
||||
jn2.on("input", function(msg) {
|
||||
should.equal(msg.payload.number, 3);
|
||||
should.equal(msg.payload.string, "allo");
|
||||
done();
|
||||
});
|
||||
var obj = {"number": 3, "string": "allo"};
|
||||
var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
|
||||
jn1.receive({payload:obj, schema:schema});
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass a string if provided a valid object and schema', function(done) {
|
||||
var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
|
||||
{id:"jn2", type:"helper"}];
|
||||
@@ -298,22 +281,6 @@ describe('JSON node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass a string if provided a valid JSON string and schema and action is string', function(done) {
|
||||
var flow = [{id:"jn1",type:"json",action:"str",wires:[["jn2"]]},
|
||||
{id:"jn2", type:"helper"}];
|
||||
helper.load(jsonNode, flow, function() {
|
||||
var jn1 = helper.getNode("jn1");
|
||||
var jn2 = helper.getNode("jn2");
|
||||
jn2.on("input", function(msg) {
|
||||
should.equal(msg.payload, '{"number":3,"string":"allo"}');
|
||||
done();
|
||||
});
|
||||
var jsonString = '{"number":3,"string":"allo"}';
|
||||
var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
|
||||
jn1.receive({payload:jsonString, schema:schema});
|
||||
});
|
||||
});
|
||||
|
||||
it('should log an error if passed an invalid object and valid schema', function(done) {
|
||||
var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
|
||||
{id:"jn2", type:"helper"}];
|
||||
@@ -338,78 +305,6 @@ describe('JSON node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should log an error if passed an invalid object and valid schema and action is object', function(done) {
|
||||
var flow = [{id:"jn1",type:"json",action:"obj",wires:[["jn2"]]},
|
||||
{id:"jn2", type:"helper"}];
|
||||
helper.load(jsonNode, flow, function() {
|
||||
try {
|
||||
var jn1 = helper.getNode("jn1");
|
||||
var jn2 = helper.getNode("jn2");
|
||||
var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
|
||||
var obj = {"number": "foo", "string": 3};
|
||||
jn1.receive({payload:obj, schema:schema});
|
||||
var logEvents = helper.log().args.filter(function(evt) {
|
||||
return evt[0].type == "json";
|
||||
});
|
||||
logEvents.should.have.length(1);
|
||||
logEvents[0][0].should.have.a.property('msg');
|
||||
logEvents[0][0].msg.should.equal("json.errors.schema-error: data.number should be number, data.string should be string");
|
||||
logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should log an error if passed an invalid JSON string and valid schema', function(done) {
|
||||
var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
|
||||
{id:"jn2", type:"helper"}];
|
||||
helper.load(jsonNode, flow, function() {
|
||||
try {
|
||||
var jn1 = helper.getNode("jn1");
|
||||
var jn2 = helper.getNode("jn2");
|
||||
var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
|
||||
var jsonString = '{"number":"Hello","string":3}';
|
||||
jn1.receive({payload:jsonString, schema:schema});
|
||||
var logEvents = helper.log().args.filter(function(evt) {
|
||||
return evt[0].type == "json";
|
||||
});
|
||||
logEvents.should.have.length(1);
|
||||
logEvents[0][0].should.have.a.property('msg');
|
||||
logEvents[0][0].msg.should.equal("json.errors.schema-error: data.number should be number, data.string should be string");
|
||||
logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should log an error if passed an invalid JSON string and valid schema and action is string', function(done) {
|
||||
var flow = [{id:"jn1",type:"json",action:"str",wires:[["jn2"]]},
|
||||
{id:"jn2", type:"helper"}];
|
||||
helper.load(jsonNode, flow, function() {
|
||||
try {
|
||||
var jn1 = helper.getNode("jn1");
|
||||
var jn2 = helper.getNode("jn2");
|
||||
var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
|
||||
var jsonString = '{"number":"Hello","string":3}';
|
||||
jn1.receive({payload:jsonString, schema:schema});
|
||||
var logEvents = helper.log().args.filter(function(evt) {
|
||||
return evt[0].type == "json";
|
||||
});
|
||||
logEvents.should.have.length(1);
|
||||
logEvents[0][0].should.have.a.property('msg');
|
||||
logEvents[0][0].msg.should.equal("json.errors.schema-error: data.number should be number, data.string should be string");
|
||||
logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should log an error if passed a valid object and invalid schema', function(done) {
|
||||
var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
|
||||
{id:"jn2", type:"helper"}];
|
||||
|
||||
@@ -128,7 +128,7 @@ describe("red/nodes/registry/localfilesystem",function() {
|
||||
}
|
||||
return _join.apply(null,arguments);
|
||||
}));
|
||||
localfilesystem.init({log:{debug:function(){}},i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{coreNodesDir:moduleDir}});
|
||||
localfilesystem.init({i18n:{registerMessageCatalog:function(){}},events:{emit:function(){}},settings:{coreNodesDir:moduleDir}});
|
||||
var nodeList = localfilesystem.getNodeFiles();
|
||||
nodeList.should.have.a.property("node-red");
|
||||
var nm = nodeList['node-red'];
|
||||
|
||||
Reference in New Issue
Block a user