mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Merge branch 'master' of https://github.com/node-red/node-red
This commit is contained in:
		| @@ -193,7 +193,8 @@ module.exports = function(grunt) { | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-migrate-3.0.1.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-ui.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery.ui.touch-punch.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/marked/marked.min.js", | ||||
|                         "node_modules/marked/marked.min.js", | ||||
|                         "node_modules/dompurify/dist/purify.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/d3/d3.v3.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/i18next/i18next.min.js", | ||||
|                         "node_modules/jsonata/jsonata-es5.min.js", | ||||
|   | ||||
| @@ -41,13 +41,13 @@ | ||||
|         "fs-extra": "8.1.0", | ||||
|         "fs.notify": "0.0.4", | ||||
|         "hash-sum": "2.0.0", | ||||
|         "https-proxy-agent": "2.2.4", | ||||
|         "https-proxy-agent": "5.0.0", | ||||
|         "i18next": "15.1.2", | ||||
|         "iconv-lite": "0.5.0", | ||||
|         "is-utf8": "0.2.1", | ||||
|         "js-yaml": "3.13.1", | ||||
|         "json-stringify-safe": "5.0.1", | ||||
|         "jsonata": "1.8.0", | ||||
|         "jsonata": "1.8.1", | ||||
|         "media-typer": "1.1.0", | ||||
|         "memorystore": "1.6.1", | ||||
|         "mime": "2.4.4", | ||||
| @@ -75,6 +75,8 @@ | ||||
|         "bcrypt": "3.0.6" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "marked": "0.8.0", | ||||
|         "dompurify": "2.0.8", | ||||
|         "grunt": "~1.0.4", | ||||
|         "grunt-chmod": "~1.1.1", | ||||
|         "grunt-cli": "~1.3.2", | ||||
|   | ||||
| @@ -100,7 +100,10 @@ function login(req,res) { | ||||
|             } | ||||
|         } else if (mergedAdminAuth.type === "strategy") { | ||||
|  | ||||
|             var urlPrefix = (settings.httpAdminRoot==='/')?"":settings.httpAdminRoot; | ||||
|             var urlPrefix = (settings.httpAdminRoot||"").replace(/\/$/,""); | ||||
|             if (urlPrefix.length > 0) { | ||||
|                 urlPrefix += "/"; | ||||
|             } | ||||
|             response = { | ||||
|                 "type":"strategy", | ||||
|                 "prompts":[{type:"button",label:mergedAdminAuth.strategy.label, url: urlPrefix + "auth/strategy"}] | ||||
|   | ||||
| @@ -431,7 +431,7 @@ var RED = (function() { | ||||
|             '<img width="50px" src="red/images/node-red-icon.svg" />'+ | ||||
|             '</div>'; | ||||
|  | ||||
|             RED.sidebar.info.set(aboutHeader+marked(data)); | ||||
|             RED.sidebar.info.set(aboutHeader+RED.utils.renderMarkdown(data)); | ||||
|             RED.sidebar.info.show(); | ||||
|         }); | ||||
|     } | ||||
|   | ||||
| @@ -102,7 +102,7 @@ | ||||
|                         var f = $(this).val(); | ||||
|                         var args = RED._('jsonata:'+f+".args",{defaultValue:''}); | ||||
|                         var title = "<h5>"+f+"("+args+")</h5>"; | ||||
|                         var body = marked(RED._('jsonata:'+f+'.desc',{defaultValue:''})); | ||||
|                         var body = RED.utils.renderMarkdown(RED._('jsonata:'+f+'.desc',{defaultValue:''})); | ||||
|                         $("#red-ui-editor-type-expression-help").html(title+"<p>"+body+"</p>"); | ||||
|  | ||||
|                     }) | ||||
|   | ||||
| @@ -107,7 +107,7 @@ | ||||
|                         clearTimeout(changeTimer); | ||||
|                         changeTimer = setTimeout(function() { | ||||
|                             var currentScrollTop = $(".red-ui-editor-type-markdown-panel-preview").scrollTop(); | ||||
|                             $(".red-ui-editor-type-markdown-panel-preview").html(marked(expressionEditor.getValue())); | ||||
|                             $(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue())); | ||||
|                             $(".red-ui-editor-type-markdown-panel-preview").scrollTop(currentScrollTop); | ||||
|                         },200); | ||||
|                     }) | ||||
| @@ -116,7 +116,7 @@ | ||||
|                     } | ||||
|  | ||||
|                     if (value) { | ||||
|                         $(".red-ui-editor-type-markdown-panel-preview").html(marked(expressionEditor.getValue())); | ||||
|                         $(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue())); | ||||
|                     } | ||||
|                     panels = RED.panels.create({ | ||||
|                         id:"red-ui-editor-type-markdown-panels", | ||||
|   | ||||
| @@ -269,7 +269,7 @@ RED.palette = (function() { | ||||
|                 RED.view.focus(); | ||||
|                 var helpText; | ||||
|                 if (nt.indexOf("subflow:") === 0) { | ||||
|                     helpText = marked(RED.nodes.subflow(nt.substring(8)).info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>'); | ||||
|                     helpText = RED.utils.renderMarkdown(RED.nodes.subflow(nt.substring(8)).info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>'); | ||||
|                 } else { | ||||
|                     helpText = $("script[data-help-name='"+d.attr("data-palette-type")+"']").html()||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>'); | ||||
|                 } | ||||
| @@ -370,7 +370,7 @@ RED.palette = (function() { | ||||
|                     RED.workspaces.show(nt.substring(8)); | ||||
|                     e.preventDefault(); | ||||
|                 }); | ||||
|                 nodeInfo = marked(def.info||""); | ||||
|                 nodeInfo = RED.utils.renderMarkdown(def.info||""); | ||||
|             } | ||||
|             setLabel(nt,d,label,nodeInfo); | ||||
|  | ||||
| @@ -440,7 +440,7 @@ RED.palette = (function() { | ||||
|             } else if (portOutput.length !== 0 && sf.out.length === 0) { | ||||
|                 portOutput.remove(); | ||||
|             } | ||||
|             setLabel(sf.type+":"+sf.id,paletteNode,sf.name,marked(sf.info||"")); | ||||
|             setLabel(sf.type+":"+sf.id,paletteNode,sf.name,RED.utils.renderMarkdown(sf.info||"")); | ||||
|             setIcon(paletteNode,sf); | ||||
|  | ||||
|             var currentCategory = paletteNode.data('category'); | ||||
|   | ||||
| @@ -158,7 +158,7 @@ RED.projects.settings = (function() { | ||||
|         container.empty(); | ||||
|         var desc; | ||||
|         if (activeProject.description) { | ||||
|             desc = marked(activeProject.description); | ||||
|             desc = RED.utils.renderMarkdown(activeProject.description); | ||||
|         } else { | ||||
|             desc = '<span class="red-ui-help-info-none">' + RED._("sidebar.project.noDescriptionAvailable") + '</span>'; | ||||
|         } | ||||
|   | ||||
| @@ -15,17 +15,6 @@ | ||||
|  **/ | ||||
| RED.sidebar.info = (function() { | ||||
|  | ||||
|     marked.setOptions({ | ||||
|         renderer: new marked.Renderer(), | ||||
|         gfm: true, | ||||
|         tables: true, | ||||
|         breaks: false, | ||||
|         pedantic: false, | ||||
|         sanitize: true, | ||||
|         smartLists: true, | ||||
|         smartypants: false | ||||
|     }); | ||||
|  | ||||
|     var content; | ||||
|     var sections; | ||||
|     var propertiesSection; | ||||
| @@ -314,7 +303,7 @@ RED.sidebar.info = (function() { | ||||
|                 if (subflowNode && node.type !== "subflow") { | ||||
|                     // Selected a subflow instance node. | ||||
|                     // - The subflow template info goes into help | ||||
|                     helpText = (marked(subflowNode.info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>')); | ||||
|                     helpText = (RED.utils.renderMarkdown(subflowNode.info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>')); | ||||
|                 } else { | ||||
|                     helpText = $("script[data-help-name='"+node.type+"']").html()||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>'); | ||||
|                 } | ||||
| @@ -326,10 +315,10 @@ RED.sidebar.info = (function() { | ||||
|             if (node._def && node._def.info) { | ||||
|                 var info = node._def.info; | ||||
|                 var textInfo = (typeof info === "function" ? info.call(node) : info); | ||||
|                 infoText = infoText + marked(textInfo); | ||||
|                 infoText = infoText + RED.utils.renderMarkdown(textInfo); | ||||
|             } | ||||
|             if (node.info) { | ||||
|                 infoText = infoText + marked(node.info || "") | ||||
|                 infoText = infoText + RED.utils.renderMarkdown(node.info || "") | ||||
|             } | ||||
|             setInfoText(infoText, infoSection.content); | ||||
|  | ||||
|   | ||||
| @@ -16,6 +16,28 @@ | ||||
|  | ||||
| RED.utils = (function() { | ||||
|  | ||||
|     window._marked = window.marked; | ||||
|     window.marked = function(txt) { | ||||
|         console.warn("Use of 'marked()' is deprecated. Use RED.utils.renderMarkdown() instead"); | ||||
|         return renderMarkdown(txt); | ||||
|     } | ||||
|  | ||||
|     _marked.setOptions({ | ||||
|         renderer: new _marked.Renderer(), | ||||
|         gfm: true, | ||||
|         tables: true, | ||||
|         breaks: false, | ||||
|         pedantic: false, | ||||
|         smartLists: true, | ||||
|         smartypants: false | ||||
|     }); | ||||
|  | ||||
|     function renderMarkdown(txt) { | ||||
|         var rendered = _marked(txt); | ||||
|         var cleaned = DOMPurify.sanitize(rendered, {SAFE_FOR_JQUERY: true}) | ||||
|         return cleaned; | ||||
|     } | ||||
|  | ||||
|     function formatString(str) { | ||||
|         return str.replace(/\r?\n/g,"↵").replace(/\t/g,"→"); | ||||
|     } | ||||
| @@ -1053,6 +1075,7 @@ RED.utils = (function() { | ||||
|         decodeObject: decodeObject, | ||||
|         parseContextKey: parseContextKey, | ||||
|         createIconElement: createIconElement, | ||||
|         sanitize: sanitize | ||||
|         sanitize: sanitize, | ||||
|         renderMarkdown: renderMarkdown | ||||
|     } | ||||
| })(); | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
|         var length = str.length; | ||||
|         var start = 0; | ||||
|         var inString = false; | ||||
|         var inRegex = false; | ||||
|         var inBox = false; | ||||
|         var quoteChar; | ||||
|         var list = []; | ||||
| @@ -24,8 +25,13 @@ | ||||
|         } | ||||
|         for (var i=0;i<length;i++) { | ||||
|             var c = str[i]; | ||||
|             if (!inString) { | ||||
|                 if (c === "'" || c === '"') { | ||||
|             if (!inString && !inRegex) { | ||||
|                 if (c === "/") { | ||||
|                     inRegex = true; | ||||
|                     frame = {type:"regex",pos:i}; | ||||
|                     list.push(frame); | ||||
|                     stack.push(frame); | ||||
|                 } else if (c === "'" || c === '"') { | ||||
|                     inString = true; | ||||
|                     quoteChar = c; | ||||
|                     frame = {type:"string",pos:i}; | ||||
| @@ -37,6 +43,9 @@ | ||||
|                 } else if (c === ",") { | ||||
|                     frame = {type:",",pos:i}; | ||||
|                     list.push(frame); | ||||
|                 } else if (c === "&") { | ||||
|                     frame = {type:"&",pos:i}; | ||||
|                     list.push(frame); | ||||
|                 } else if (/[\(\[\{]/.test(c)) { | ||||
|                     frame = {type:"open-block",char:c,pos:i}; | ||||
|                     list.push(frame); | ||||
| @@ -44,7 +53,8 @@ | ||||
|                 } else if (/[\}\)\]]/.test(c)) { | ||||
|                     var oldFrame = stack.pop(); | ||||
|                     if (matchingBrackets[oldFrame.char] !== c) { | ||||
|                         //console.log("Stack frame mismatch",c,"at",i,"expected",matchingBrackets[oldFrame.char],"from",oldFrame.pos); | ||||
|                         // console.log("Stack frame mismatch",c,"at",i,"expected",matchingBrackets[oldFrame.char],"from",oldFrame.pos); | ||||
|                         // console.log(list); | ||||
|                         return str; | ||||
|                     } | ||||
|                     //console.log("Closing",c,"at",i,"compare",oldFrame.type,oldFrame.pos); | ||||
| @@ -53,19 +63,32 @@ | ||||
|                     list.push(frame); | ||||
|                 } | ||||
|             } else { | ||||
|                 if (c === quoteChar) { | ||||
|                     // Next char must be a ] | ||||
|                     inString = false; | ||||
|                     stack.pop(); | ||||
|                 if (c === "\\") { | ||||
|                     // an escaped char - stay in current mode and skip the next char | ||||
|                     i++; | ||||
|                 } | ||||
|                 if (inString) { | ||||
|                     if (c === quoteChar) { | ||||
|                         // Next char must be a ] | ||||
|                         inString = false; | ||||
|                         var f = stack.pop(); | ||||
|                         f.end = i; | ||||
|                     } | ||||
|                 } else if (inRegex) { | ||||
|                     if (c === "/") { | ||||
|                         inRegex = false; | ||||
|                         var f = stack.pop(); | ||||
|                         f.end = i; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|         } | ||||
|         // console.log(stack); | ||||
|         // console.log("list",list); | ||||
|  | ||||
|         var result = str; | ||||
|         var indent = 0; | ||||
|         var offset = 0; | ||||
|         var pre,post,indented; | ||||
|         var pre,post,indented,hasNewline; | ||||
|         var longStack = []; | ||||
|         list.forEach(function(f) { | ||||
|             if (f.type === ";" || f.type === ",") { | ||||
| @@ -73,29 +96,51 @@ | ||||
|                     pre = result.substring(0,offset+f.pos+1); | ||||
|                     post = result.substring(offset+f.pos+1); | ||||
|                     indented = indentLine(post,indent); | ||||
|                     result = pre+"\n"+indented; | ||||
|                     offset += indented.length-post.length+1; | ||||
|                     hasNewline = /\n$/.test(pre); | ||||
|                     // console.log("A§"+pre+"§\n§"+indented+"§",hasNewline); | ||||
|                     result = pre+(hasNewline?"":"\n")+indented; | ||||
|                     offset += indented.length-post.length+(hasNewline?0:1); | ||||
|                 } | ||||
|             } else if (f.type === "&") { | ||||
|                 pre = result.substring(0,offset+f.pos+1); | ||||
|                 var lastLineBreak = pre.lastIndexOf("\n"); | ||||
|                 var lineLength = pre.length - lastLineBreak; | ||||
|                 if (lineLength > 70) { | ||||
|                     post = result.substring(offset+f.pos+1); | ||||
|                     if (!/^\n/.test(post)) { | ||||
|                         indented = indentLine(post,indent); | ||||
|                         hasNewline = /\n$/.test(pre); | ||||
|                         result = pre+(hasNewline?"":"\n")+indented; | ||||
|                         offset += indented.length-post.length+(hasNewline?0:1); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|             } else if (f.type === "open-block") { | ||||
|                 if (f.width > 30) { | ||||
|                 if (f.width > 40) { | ||||
|                     longStack.push(true); | ||||
|                     indent += 4; | ||||
|                     pre = result.substring(0,offset+f.pos+1); | ||||
|                     post = result.substring(offset+f.pos+1); | ||||
|                     hasNewline = /\n$/.test(pre); | ||||
|                     indented = indentLine(post,indent); | ||||
|                     result = pre+"\n"+indented; | ||||
|                     offset += indented.length-post.length+1; | ||||
|                     result = pre+(hasNewline?"":"\n")+indented; | ||||
|                     offset += indented.length-post.length+(hasNewline?0:1); | ||||
|                 } else { | ||||
|                     longStack.push(false); | ||||
|                 } | ||||
|             } else if (f.type === "close-block") { | ||||
|                 if (f.width > 30) { | ||||
|                 if (f.width > 40) { | ||||
|                     indent -= 4; | ||||
|                     pre = result.substring(0,offset+f.pos); | ||||
|                     post = result.substring(offset+f.pos); | ||||
|                     indented = indentLine(post,indent); | ||||
|                     result = pre+"\n"+indented; | ||||
|                     offset += indented.length-post.length+1; | ||||
|                     hasNewline = /\n *$/.test(pre); | ||||
|                     if (hasNewline) { | ||||
|                         result = pre + post; | ||||
|                     } else { | ||||
|                         result = pre+"\n"+indented; | ||||
|                         offset += indented.length-post.length+1; | ||||
|                     } | ||||
|                 } | ||||
|                 longStack.pop(); | ||||
|             } | ||||
|   | ||||
| @@ -28,6 +28,11 @@ ace.define("ace/mode/jsonata",["require","exports","module","ace/lib/oop","ace/m | ||||
|         }, "identifier"); | ||||
|         this.$rules = { | ||||
|             "start" : [ | ||||
|                 { | ||||
|                     token: "string.regexp", | ||||
|                     regex: "\\/", | ||||
|                     next: "regex" | ||||
|                 }, | ||||
|                 { | ||||
|                     token : "string", | ||||
|                     regex : "'(?=.)", | ||||
| @@ -46,34 +51,35 @@ ace.define("ace/mode/jsonata",["require","exports","module","ace/lib/oop","ace/m | ||||
|                     token : "constant.numeric", // float | ||||
|                     regex : /[+-]?\d[\d_]*(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/ | ||||
|                 }, | ||||
|                 {   token: "keyword", | ||||
|                 regex: /λ/ | ||||
|             }, | ||||
|             { | ||||
|                 token: "keyword", | ||||
|                 regex: jsonataFunctions | ||||
|             }, | ||||
|             { | ||||
|                 token : keywordMapper, | ||||
|                 regex : "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*" | ||||
|             }, | ||||
|             { | ||||
|                 token : "punctuation.operator", | ||||
|                 regex : /[.](?![.])/ | ||||
|             }, | ||||
|             { | ||||
|                 token : "keyword.operator", | ||||
|                 regex : /\|\||<=|>=|\.\.|\*\*|!=|:=|[=<>`!$%&*+\-~\/^]/, | ||||
|                 next  : "start" | ||||
|             }, | ||||
|             { | ||||
|                 token : "punctuation.operator", | ||||
|                 regex : /[?:,;.]/, | ||||
|                 next  : "start" | ||||
|             }, | ||||
|             { | ||||
|                 token : "paren.lparen", | ||||
|                 regex : /[\[({]/, | ||||
|                 { | ||||
|                     token: "keyword", | ||||
|                     regex: /λ/ | ||||
|                 }, | ||||
|                 { | ||||
|                     token: "keyword", | ||||
|                     regex: jsonataFunctions | ||||
|                 }, | ||||
|                 { | ||||
|                     token : keywordMapper, | ||||
|                     regex : "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*" | ||||
|                 }, | ||||
|                 { | ||||
|                     token : "punctuation.operator", | ||||
|                     regex : /[.](?![.])/ | ||||
|                 }, | ||||
|                 { | ||||
|                     token : "keyword.operator", | ||||
|                     regex : /\|\||<=|>=|\.\.|\*\*|!=|:=|[=<>`!$%&*+\-~\/^]/, | ||||
|                     next  : "start" | ||||
|                 }, | ||||
|                 { | ||||
|                     token : "punctuation.operator", | ||||
|                     regex : /[?:,;.]/, | ||||
|                     next  : "start" | ||||
|                 }, | ||||
|                 { | ||||
|                     token : "paren.lparen", | ||||
|                     regex : /[\[({]/, | ||||
|                     next  : "start" | ||||
|                 }, | ||||
|                 { | ||||
| @@ -86,7 +92,8 @@ ace.define("ace/mode/jsonata",["require","exports","module","ace/lib/oop","ace/m | ||||
|                     token : "string", | ||||
|                     regex : '"|$', | ||||
|                     next  : "start" | ||||
|                 }, { | ||||
|                 }, | ||||
|                 { | ||||
|                     defaultToken: "string" | ||||
|                 } | ||||
|             ], | ||||
| @@ -95,9 +102,24 @@ ace.define("ace/mode/jsonata",["require","exports","module","ace/lib/oop","ace/m | ||||
|                     token : "string", | ||||
|                     regex : "'|$", | ||||
|                     next  : "start" | ||||
|                 }, { | ||||
|                 }, | ||||
|                 { | ||||
|                     defaultToken: "string" | ||||
|                 } | ||||
|             ], | ||||
|             "regex" : [ | ||||
|                 { | ||||
|                     token: "string.regexp", | ||||
|                     regex: "\\\\/" | ||||
|                 }, | ||||
|                 { | ||||
|                     token: "string.regexp", | ||||
|                     regex: "/[sxngimy]*", | ||||
|                     next: "start" | ||||
|                 }, | ||||
|                 { | ||||
|                     defaultToken: "string.regexp" | ||||
|                 } | ||||
|             ] | ||||
|         }; | ||||
|     }; | ||||
|   | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -27,7 +27,7 @@ | ||||
|         "fs-extra": "8.1.0", | ||||
|         "fs.notify": "0.0.4", | ||||
|         "hash-sum": "2.0.0", | ||||
|         "https-proxy-agent": "2.2.4", | ||||
|         "https-proxy-agent": "5.0.0", | ||||
|         "is-utf8": "0.2.1", | ||||
|         "js-yaml": "3.13.1", | ||||
|         "media-typer": "1.1.0", | ||||
|   | ||||
| @@ -57,6 +57,8 @@ var api = module.exports = { | ||||
|     * Sets the current flow configuration | ||||
|     * @param {Object} opts | ||||
|     * @param {User} opts.user - the user calling the api | ||||
|     * @param {Object} opts.flows - the flow configuration: `{flows: [..], credentials: {}}` | ||||
|     * @param {Object} opts.deploymentType - the type of deployment - "full", "nodes", "flows", "reload" | ||||
|     * @param {Object} opts.req - the request to log (optional) | ||||
|     * @return {Promise<Flows>} - the active flow configuration | ||||
|     * @memberof @node-red/runtime_flows | ||||
| @@ -83,7 +85,7 @@ var api = module.exports = { | ||||
|                         return reject(err); | ||||
|                     } | ||||
|                 } | ||||
|                 apiPromise = runtime.nodes.setFlows(flows.flows,deploymentType); | ||||
|                 apiPromise = runtime.nodes.setFlows(flows.flows,flows.credentials,deploymentType); | ||||
|             } | ||||
|             apiPromise.then(function(flowId) { | ||||
|                 return resolve({rev:flowId}); | ||||
|   | ||||
| @@ -106,15 +106,20 @@ function load(forceStart) { | ||||
|         // This is a force reload from the API - disable safeMode | ||||
|         delete settings.safeMode; | ||||
|     } | ||||
|     return setFlows(null,"load",false,forceStart); | ||||
|     return setFlows(null,null,"load",false,forceStart); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * _config - new node array configuration | ||||
|  * _credentials - new credentials configuration (optional) | ||||
|  * type - full/nodes/flows/load (default full) | ||||
|  * muteLog - don't emit the standard log messages (used for individual flow api) | ||||
|  */ | ||||
| function setFlows(_config,type,muteLog,forceStart) { | ||||
| function setFlows(_config,_credentials,type,muteLog,forceStart) { | ||||
|     if (typeof _credentials === "string") { | ||||
|         type = _credentials; | ||||
|         _credentials = null; | ||||
|     } | ||||
|     type = type||"full"; | ||||
|     if (settings.safeMode) { | ||||
|         if (type !== "load") { | ||||
| @@ -155,16 +160,27 @@ function setFlows(_config,type,muteLog,forceStart) { | ||||
|                 delete newFlowConfig.allNodes[id].credentials; | ||||
|             } | ||||
|         } | ||||
|         var credsDirty; | ||||
|  | ||||
|         // Allow the credential store to remove anything no longer needed | ||||
|         credentials.clean(config); | ||||
|         if (_credentials) { | ||||
|             // A full set of credentials have been provided. Use those instead | ||||
|             configSavePromise = credentials.load(_credentials); | ||||
|             credsDirty = true; | ||||
|         } else { | ||||
|             // Allow the credential store to remove anything no longer needed | ||||
|             credentials.clean(config); | ||||
|  | ||||
|         // Remember whether credentials need saving or not | ||||
|         var credsDirty = credentials.dirty(); | ||||
|             // Remember whether credentials need saving or not | ||||
|             var credsDirty = credentials.dirty(); | ||||
|  | ||||
|             configSavePromise = Promise.resolve(); | ||||
|         } | ||||
|  | ||||
|         // Get the latest credentials and ask storage to save them (if needed) | ||||
|         // as well as the new flow configuration. | ||||
|         configSavePromise = credentials.export().then(function(creds) { | ||||
|         configSavePromise = configSavePromise.then(function() { | ||||
|             return credentials.export() | ||||
|         }).then(function(creds) { | ||||
|             var saveConfig = { | ||||
|                 flows: config, | ||||
|                 credentialsDirty:credsDirty, | ||||
| @@ -515,7 +531,7 @@ function addFlow(flow) { | ||||
|     var newConfig = clone(activeConfig.flows); | ||||
|     newConfig = newConfig.concat(nodes); | ||||
|  | ||||
|     return setFlows(newConfig,'flows',true).then(function() { | ||||
|     return setFlows(newConfig,null,'flows',true).then(function() { | ||||
|         log.info(log._("nodes.flows.added-flow",{label:(flow.label?flow.label+" ":"")+"["+flow.id+"]"})); | ||||
|         return flow.id; | ||||
|     }); | ||||
| @@ -646,7 +662,7 @@ function updateFlow(id,newFlow) { | ||||
|     } | ||||
|  | ||||
|     newConfig = newConfig.concat(nodes); | ||||
|     return setFlows(newConfig,'flows',true).then(function() { | ||||
|     return setFlows(newConfig,null,'flows',true).then(function() { | ||||
|         log.info(log._("nodes.flows.updated-flow",{label:(label?label+" ":"")+"["+id+"]"})); | ||||
|     }) | ||||
| } | ||||
| @@ -668,7 +684,7 @@ function removeFlow(id) { | ||||
|         return node.z !== id && node.id !== id; | ||||
|     }); | ||||
|  | ||||
|     return setFlows(newConfig,'flows',true).then(function() { | ||||
|     return setFlows(newConfig,null,'flows',true).then(function() { | ||||
|         log.info(log._("nodes.flows.removed-flow",{label:(flow.label?flow.label+" ":"")+"["+flow.id+"]"})); | ||||
|     }); | ||||
| } | ||||
|   | ||||
| @@ -18,7 +18,7 @@ | ||||
|         "clone": "2.1.2", | ||||
|         "i18next": "15.1.2", | ||||
|         "json-stringify-safe": "5.0.1", | ||||
|         "jsonata": "1.8.0", | ||||
|         "jsonata": "1.8.1", | ||||
|         "when": "3.7.8" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -15,22 +15,29 @@ | ||||
|  **/ | ||||
|  | ||||
| var idMap = { | ||||
|     // input | ||||
|     // common | ||||
|     "inject": ".red-ui-palette-node[data-palette-type='inject']", | ||||
|     "httpIn": ".red-ui-palette-node[data-palette-type='http in']", | ||||
|     "mqttIn": ".red-ui-palette-node[data-palette-type='mqtt in']", | ||||
|     // output | ||||
|     "debug": ".red-ui-palette-node[data-palette-type='debug']", | ||||
|     "httpResponse": ".red-ui-palette-node[data-palette-type='http response']", | ||||
|     "mqttOut": ".red-ui-palette-node[data-palette-type='mqtt out']", | ||||
|     // function | ||||
|     "function": ".red-ui-palette-node[data-palette-type='function']", | ||||
|     "template": ".red-ui-palette-node[data-palette-type='template']", | ||||
|     "change": ".red-ui-palette-node[data-palette-type='change']", | ||||
|     "range": ".red-ui-palette-node[data-palette-type='range']", | ||||
|     "template": ".red-ui-palette-node[data-palette-type='template']", | ||||
|     // network | ||||
|     "mqttIn": ".red-ui-palette-node[data-palette-type='mqtt in']", | ||||
|     "mqttOut": ".red-ui-palette-node[data-palette-type='mqtt out']", | ||||
|     "httpIn": ".red-ui-palette-node[data-palette-type='http in']", | ||||
|     "httpResponse": ".red-ui-palette-node[data-palette-type='http response']", | ||||
|     "httpRequest": ".red-ui-palette-node[data-palette-type='http request']", | ||||
|     // sequence | ||||
|     "join": ".red-ui-palette-node[data-palette-type='join']", | ||||
|     "split": ".red-ui-palette-node[data-palette-type='split']", | ||||
|     // parser | ||||
|     "csv": ".red-ui-palette-node[data-palette-type='csv']", | ||||
|     "html": ".red-ui-palette-node[data-palette-type='html']", | ||||
|     "json": ".red-ui-palette-node[data-palette-type='json']", | ||||
|     "xml": ".red-ui-palette-node[data-palette-type='xml']", | ||||
|     "yaml": ".red-ui-palette-node[data-palette-type='yaml']", | ||||
|     // storage | ||||
|     "fileIn": ".red-ui-palette-node[data-palette-type='file in']", | ||||
| }; | ||||
|   | ||||
| @@ -42,7 +42,7 @@ function addNode(type, x, y) { | ||||
|         } | ||||
|     } | ||||
|     browser.waitForVisible('#red-ui-palette-search'); | ||||
|     browser.setValue('//*[@id="red-ui-palette-search"]/div/input', type.replace(/([A-Z])/g,' $1').toLowerCase()); | ||||
|     browser.setValue('//*[@id="red-ui-palette-search"]/div/form/input', type.replace(/([A-Z])/g, ' $1').toLowerCase()); | ||||
|     browser.pause(300); | ||||
|     browser.waitForVisible(palette.getId(type)); | ||||
|     browser.moveToObject(palette.getId(type)); | ||||
| @@ -66,8 +66,8 @@ function deleteAllNodes() { | ||||
|  | ||||
| function deploy() { | ||||
|     browser.call(function () { | ||||
|         return when.promise(function(resolve, reject) { | ||||
|             events.on("runtime-event", function(event) { | ||||
|         return when.promise(function (resolve, reject) { | ||||
|             events.on("runtime-event", function (event) { | ||||
|                 if (event.id === 'runtime-deploy') { | ||||
|                     events.removeListener("runtime-event", arguments.callee); | ||||
|                     resolve(); | ||||
|   | ||||
| @@ -14,9 +14,9 @@ | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| var util = require("util"); | ||||
| var util = require('util'); | ||||
|  | ||||
| var nodePage = require("../../node_page"); | ||||
| var nodePage = require('../../node_page'); | ||||
|  | ||||
| function changeNode(id) { | ||||
|     nodePage.call(this, id); | ||||
| @@ -85,7 +85,7 @@ changeNode.prototype.ruleMove = function (p, to, index) { | ||||
| } | ||||
|  | ||||
| changeNode.prototype.addRule = function () { | ||||
|     browser.clickWithWait('//*[@id="dialog-form"]/div[3]/div/a'); | ||||
|     browser.clickWithWait('//*[@id="dialog-form"]/div[5]/div/a'); | ||||
| } | ||||
|  | ||||
| module.exports = changeNode; | ||||
|   | ||||
							
								
								
									
										51
									
								
								test/editor/pageobjects/nodes/core/parsers/70-CSV_page.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								test/editor/pageobjects/nodes/core/parsers/70-CSV_page.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| /** | ||||
|  * 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 csvNode(id) { | ||||
|     nodePage.call(this, id); | ||||
| } | ||||
|  | ||||
| util.inherits(csvNode, nodePage); | ||||
|  | ||||
| csvNode.prototype.setColumns = function (columns) { | ||||
|     browser.setValue('#node-input-temp', columns); | ||||
| } | ||||
|  | ||||
| csvNode.prototype.setSkipLines = function (skip) { | ||||
|     browser.setValue('#node-input-skip', skip); | ||||
| } | ||||
|  | ||||
| csvNode.prototype.setFirstRow4Names = function (checkbox) { | ||||
|     if (browser.isSelected('#node-input-hdrin') !== checkbox) { | ||||
|         browser.click('#node-input-hdrin'); | ||||
|     } | ||||
| } | ||||
|  | ||||
| csvNode.prototype.setOutput = function (output) { | ||||
|     browser.selectWithWait('#node-input-multi', output); | ||||
| } | ||||
|  | ||||
| csvNode.prototype.setIncludeRow = function (checkbox) { | ||||
|     if (browser.isSelected('#node-input-hdrout') !== checkbox) { | ||||
|         browser.click('#node-input-hdrout'); | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = csvNode; | ||||
| @@ -14,9 +14,9 @@ | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| var util = require("util"); | ||||
| var util = require('util'); | ||||
|  | ||||
| var nodePage = require("../../node_page"); | ||||
| var nodePage = require('../../node_page'); | ||||
|  | ||||
| function htmlNode(id) { | ||||
|     nodePage.call(this, id); | ||||
| @@ -24,7 +24,7 @@ function htmlNode(id) { | ||||
|  | ||||
| util.inherits(htmlNode, nodePage); | ||||
|  | ||||
| htmlNode.prototype.setSelector = function(tag) { | ||||
| htmlNode.prototype.setSelector = function (tag) { | ||||
|     browser.setValue('#node-input-tag', tag); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -14,9 +14,9 @@ | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| var util = require("util"); | ||||
| var util = require('util'); | ||||
|  | ||||
| var nodePage = require("../../node_page"); | ||||
| var nodePage = require('../../node_page'); | ||||
|  | ||||
| function jsonNode(id) { | ||||
|     nodePage.call(this, id); | ||||
| @@ -28,8 +28,8 @@ 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); | ||||
| jsonNode.prototype.setProperty = function (property) { | ||||
|     browser.setValue('//*[@id="dialog-form"]/div[4]/div/div[1]/input', property); | ||||
| } | ||||
|  | ||||
| module.exports = jsonNode; | ||||
|   | ||||
							
								
								
									
										35
									
								
								test/editor/pageobjects/nodes/core/parsers/70-XML_page.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								test/editor/pageobjects/nodes/core/parsers/70-XML_page.js
									
									
									
									
									
										Normal file
									
								
							| @@ -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 xmlNode(id) { | ||||
|     nodePage.call(this, id); | ||||
| } | ||||
|  | ||||
| util.inherits(xmlNode, nodePage); | ||||
|  | ||||
| xmlNode.prototype.setAction = function (action) { | ||||
|     browser.setValue('node-input-action', action); | ||||
| } | ||||
|  | ||||
| xmlNode.prototype.setProperty = function (property) { | ||||
|     browser.setValue('//*[@id="dialog-form"]/div[3]/div/div[1]/input', property); | ||||
| } | ||||
|  | ||||
| module.exports = xmlNode; | ||||
							
								
								
									
										35
									
								
								test/editor/pageobjects/nodes/core/parsers/70-YAML_page.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								test/editor/pageobjects/nodes/core/parsers/70-YAML_page.js
									
									
									
									
									
										Normal file
									
								
							| @@ -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 yamlNode(id) { | ||||
|     nodePage.call(this, id); | ||||
| } | ||||
|  | ||||
| util.inherits(yamlNode, nodePage); | ||||
|  | ||||
| yamlNode.prototype.setAction = function (action) { | ||||
|     browser.setValue('node-input-action', action); | ||||
| } | ||||
|  | ||||
| yamlNode.prototype.setProperty = function (property) { | ||||
|     browser.setValue('//*[@id="dialog-form"]/div[3]/div/div[1]/input', property); | ||||
| } | ||||
|  | ||||
| module.exports = yamlNode; | ||||
							
								
								
									
										35
									
								
								test/editor/pageobjects/nodes/core/sequence/17-split_page.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								test/editor/pageobjects/nodes/core/sequence/17-split_page.js
									
									
									
									
									
										Normal file
									
								
							| @@ -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 joinNode(id) { | ||||
|     nodePage.call(this, id); | ||||
| } | ||||
|  | ||||
| util.inherits(joinNode, nodePage); | ||||
|  | ||||
| module.exports = joinNode; | ||||
|  | ||||
| function joinNode(id) { | ||||
|     nodePage.call(this, id); | ||||
| } | ||||
|  | ||||
| util.inherits(joinNode, nodePage); | ||||
|  | ||||
| module.exports = joinNode; | ||||
| @@ -25,8 +25,13 @@ var mqttOutNode = require('./core/network/10-mqttout_page'); | ||||
| var httpInNode = require('./core/network/21-httpin_page'); | ||||
| var httpResponseNode = require('./core/network/21-httpresponse_page'); | ||||
| var httpRequestNode = require('./core/network/21-httprequest_page'); | ||||
| var splitNode = require('./core/sequence/17-split_page'); | ||||
| var joinNode = require('./core/sequence/17-split_page'); | ||||
| var csvNode = require('./core/parsers/70-CSV_page'); | ||||
| var htmlNode = require('./core/parsers/70-HTML_page'); | ||||
| var jsonNode = require('./core/parsers/70-JSON_page'); | ||||
| var xmlNode = require('./core/parsers/70-XML_page'); | ||||
| var yamlNode = require('./core/parsers/70-YAML_page'); | ||||
| var fileInNode = require('./core/storage/10-filein_page'); | ||||
|  | ||||
| var nodeCatalog = { | ||||
| @@ -44,9 +49,15 @@ var nodeCatalog = { | ||||
|     "httpIn": httpInNode, | ||||
|     "httpResponse": httpResponseNode, | ||||
|     "httpRequest": httpRequestNode, | ||||
|     // sequence | ||||
|     "split": splitNode, | ||||
|     "join": joinNode, | ||||
|     // parser | ||||
|     "csv": csvNode, | ||||
|     "html": htmlNode, | ||||
|     "json": jsonNode, | ||||
|     "xml": xmlNode, | ||||
|     "yaml": yamlNode, | ||||
|     // storage | ||||
|     "fileIn": fileInNode | ||||
| }; | ||||
|   | ||||
							
								
								
									
										364
									
								
								test/editor/specs/scenario/cookbook_dataformats_uispec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										364
									
								
								test/editor/specs/scenario/cookbook_dataformats_uispec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,364 @@ | ||||
| /** | ||||
|  * 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 httpNodeRoot = '/api'; | ||||
|  | ||||
| // https://cookbook.nodered.org/ | ||||
| describe('cookbook', function () { | ||||
|     beforeEach(function () { | ||||
|         workspace.init(); | ||||
|     }); | ||||
|  | ||||
|     before(function () { | ||||
|         helper.startServer(); | ||||
|     }); | ||||
|  | ||||
|     after(function () { | ||||
|         helper.stopServer(); | ||||
|     }); | ||||
|  | ||||
|     describe('working with data formats', function () { | ||||
|         it('convert to/from JSON', function () { | ||||
|             var injectNode1 = workspace.addNode('inject'); | ||||
|             var jsonNode1 = workspace.addNode('json'); | ||||
|             var debugNode1 = workspace.addNode('debug'); | ||||
|  | ||||
|             injectNode1.edit(); | ||||
|             injectNode1.setPayload('str', '{"a":1}'); | ||||
|             injectNode1.clickOk(); | ||||
|  | ||||
|             jsonNode1.edit(); | ||||
|             jsonNode1.setProperty('payload'); | ||||
|             jsonNode1.clickOk(); | ||||
|  | ||||
|             injectNode1.connect(jsonNode1); | ||||
|             jsonNode1.connect(debugNode1); | ||||
|  | ||||
|             var injectNode2 = workspace.addNode('inject'); | ||||
|             var jsonNode2 = workspace.addNode('json'); | ||||
|             var debugNode2 = workspace.addNode('debug'); | ||||
|  | ||||
|             injectNode2.edit(); | ||||
|             injectNode2.setPayload('json', '{"a":1}'); | ||||
|             injectNode2.clickOk(); | ||||
|  | ||||
|             jsonNode2.edit(); | ||||
|             jsonNode2.setProperty('payload'); | ||||
|             jsonNode2.clickOk(); | ||||
|  | ||||
|             injectNode2.connect(jsonNode2); | ||||
|             jsonNode2.connect(debugNode2); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode1.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('1'); | ||||
|             debugTab.clearMessage(); | ||||
|             injectNode2.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"{"a":1}"'); | ||||
|         }); | ||||
|  | ||||
|         it('convert to/from XML', function () { | ||||
|             var injectNode1 = workspace.addNode('inject', 0); | ||||
|             var templateNode1 = workspace.addNode('template', 200); | ||||
|             var xmlNode1 = workspace.addNode('xml', 400); | ||||
|             var debugNode1 = workspace.addNode('debug', 600); | ||||
|  | ||||
|             injectNode1.edit(); | ||||
|             injectNode1.setPayload('str', '{"a":1}'); | ||||
|             injectNode1.clickOk(); | ||||
|  | ||||
|             templateNode1.edit(); | ||||
|             templateNode1.setFormat('text'); | ||||
|             templateNode1.setSyntax('plain'); | ||||
|             templateNode1.setTemplate('<note priority="high">' | ||||
|                                     + '  <to>Nick</to>' | ||||
|                                     + '  <from>Dave</from>' | ||||
|                                     + '  <heading>Reminder</heading>' | ||||
|                                     + '  <body>Update the website</body>' | ||||
|                                     + '</note>'); | ||||
|             templateNode1.clickOk(); | ||||
|  | ||||
|             xmlNode1.edit(); | ||||
|             xmlNode1.setProperty('payload'); | ||||
|             xmlNode1.clickOk(); | ||||
|  | ||||
|             injectNode1.connect(templateNode1); | ||||
|             templateNode1.connect(xmlNode1); | ||||
|             xmlNode1.connect(debugNode1); | ||||
|  | ||||
|             var injectNode2 = workspace.addNode('inject'); | ||||
|             var xmlNode2 = workspace.addNode('xml'); | ||||
|             var debugNode2 = workspace.addNode('debug'); | ||||
|  | ||||
|             injectNode2.edit(); | ||||
|             injectNode2.setPayload('json', '{' | ||||
|                                          + '    "note": {' | ||||
|                                          + '        "$": { "priority": "high" },' | ||||
|                                          + '        "to": [ "Nick" ],' | ||||
|                                          + '        "from": [ "Dave" ],' | ||||
|                                          + '        "heading": [ "Reminder" ],' | ||||
|                                          + '        "body": [ "Update the website" ]' | ||||
|                                          + '    }' | ||||
|                                          + '}'); | ||||
|             injectNode2.clickOk(); | ||||
|  | ||||
|             xmlNode2.edit(); | ||||
|             xmlNode2.setProperty('payload'); | ||||
|             xmlNode2.clickOk(); | ||||
|  | ||||
|             injectNode2.connect(xmlNode2); | ||||
|             xmlNode2.connect(debugNode2); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode1.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('object'); | ||||
|             debugTab.clearMessage(); | ||||
|             injectNode2.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' | ||||
|                                             + '<note priority="high">' | ||||
|                                             + '<to>Nick</to>' | ||||
|                                             + '<from>Dave</from>' | ||||
|                                             + '<heading>Reminder</heading>' | ||||
|                                             + '<body>Update the website</body>' | ||||
|                                             + '</note>"'); | ||||
|         }); | ||||
|  | ||||
|         it('convert to/from YAML', function () { | ||||
|             var injectNode1 = workspace.addNode('inject', 0); | ||||
|             var templateNode1 = workspace.addNode('template', 200); | ||||
|             var yamlNode1 = workspace.addNode('yaml', 400); | ||||
|             var debugNode1 = workspace.addNode('debug', 600); | ||||
|  | ||||
|             injectNode1.edit(); | ||||
|             injectNode1.setPayload('str', '{"a":1}'); | ||||
|             injectNode1.clickOk(); | ||||
|  | ||||
|             templateNode1.edit(); | ||||
|             templateNode1.setFormat('yaml'); | ||||
|             templateNode1.setSyntax('plain'); | ||||
|             templateNode1.setTemplate('a: 1\n' | ||||
|                                     + 'b:\n' | ||||
|                                     + '  - 1\n' | ||||
|                                     + '- 2\n' | ||||
|                                     + '- 3'); | ||||
|             templateNode1.clickOk(); | ||||
|  | ||||
|             yamlNode1.edit(); | ||||
|             yamlNode1.setProperty('payload'); | ||||
|             yamlNode1.clickOk(); | ||||
|  | ||||
|             injectNode1.connect(templateNode1); | ||||
|             templateNode1.connect(yamlNode1); | ||||
|             yamlNode1.connect(debugNode1); | ||||
|  | ||||
|             var injectNode2 = workspace.addNode('inject'); | ||||
|             var yamlNode2 = workspace.addNode('yaml'); | ||||
|             var debugNode2 = workspace.addNode('debug'); | ||||
|  | ||||
|             injectNode2.edit(); | ||||
|             injectNode2.setPayload('json', '{"a":1, "b":[1,2,3]}'); | ||||
|             injectNode2.clickOk(); | ||||
|  | ||||
|             yamlNode2.edit(); | ||||
|             yamlNode2.setProperty('payload'); | ||||
|             yamlNode2.clickOk(); | ||||
|  | ||||
|             injectNode2.connect(yamlNode2); | ||||
|             yamlNode2.connect(debugNode2); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode1.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql([ '1', 'array[3]' ]); | ||||
|             debugTab.clearMessage(); | ||||
|             injectNode2.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"a: 1↵b:↵ - 1↵ - 2↵ - 3↵"'); | ||||
|         }); | ||||
|  | ||||
|         it('generate CSV output', function () { | ||||
|             var injectNode1 = workspace.addNode('inject', 0); | ||||
|             var changeNode1 = workspace.addNode('change', 200); | ||||
|             var csvNode1 = workspace.addNode('csv', 400); | ||||
|             var debugNode1 = workspace.addNode('debug', 600); | ||||
|  | ||||
|             changeNode1.edit(); | ||||
|             changeNode1.ruleSet('payload', 'msg', '{' | ||||
|                                                 + '  "a": $floor(100*$random()),' | ||||
|                                                 + '  "b": $floor(100*$random()),' | ||||
|                                                 + '  "c": $floor(100*$random())' | ||||
|                                                 + '}', 'jsonata'); | ||||
|             changeNode1.clickOk(); | ||||
|  | ||||
|             csvNode1.edit(); | ||||
|             csvNode1.setColumns('a,b,c'); | ||||
|             csvNode1.clickOk(); | ||||
|  | ||||
|             injectNode1.connect(changeNode1); | ||||
|             changeNode1.connect(csvNode1); | ||||
|             csvNode1.connect(debugNode1); | ||||
|  | ||||
|             var injectNode2 = workspace.addNode('inject', 0, 80); | ||||
|             var changeNode2 = workspace.addNode('change', 200, 80); | ||||
|             var csvNode2 = workspace.addNode('csv', 400, 80); | ||||
|             var debugNode2 = workspace.addNode('debug', 600, 80); | ||||
|  | ||||
|             changeNode2.edit(); | ||||
|             changeNode2.ruleSet('payload', 'msg', '[' | ||||
|                                                 + '  {' | ||||
|                                                 + '    "a": $floor(100*$random()),' | ||||
|                                                 + '    "b": $floor(100*$random()),' | ||||
|                                                 + '    "c": $floor(100*$random())' | ||||
|                                                 + '  }, {' | ||||
|                                                 + '    "a": $floor(100*$random()),' | ||||
|                                                 + '    "b": $floor(100*$random()),' | ||||
|                                                 + '    "c": $floor(100*$random())' | ||||
|                                                 + '  }, {' | ||||
|                                                 + '    "a": $floor(100*$random()),' | ||||
|                                                 + '    "b": $floor(100*$random()),' | ||||
|                                                 + '    "c": $floor(100*$random())' | ||||
|                                                 + '  }, {' | ||||
|                                                 + '    "a": $floor(100*$random()),' | ||||
|                                                 + '    "b": $floor(100*$random()),' | ||||
|                                                 + '    "c": $floor(100*$random())' | ||||
|                                                 + '  }' | ||||
|                                                 + ']', 'jsonata'); | ||||
|             changeNode2.clickOk(); | ||||
|  | ||||
|             csvNode2.edit(); | ||||
|             csvNode2.setColumns('a,b,c'); | ||||
|             csvNode2.setIncludeRow(true); | ||||
|             csvNode2.clickOk(); | ||||
|  | ||||
|             injectNode2.connect(changeNode2); | ||||
|             changeNode2.connect(csvNode2); | ||||
|             csvNode2.connect(debugNode2); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode1.clickLeftButton(); | ||||
|             debugTab.getMessage().should.match(/^"([1-9]?[0-9],){2}[1-9]?[0-9]↵"$/); | ||||
|             debugTab.clearMessage(); | ||||
|             injectNode2.clickLeftButton(); | ||||
|             debugTab.getMessage().should.match(/^"a,b,c↵(([1-9]?[0-9],){2}[1-9]?[0-9]↵){4}"$/); | ||||
|         }); | ||||
|  | ||||
|         it('parse CSV input', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var templateNode = workspace.addNode('template'); | ||||
|             var csvNode = workspace.addNode('csv'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             templateNode.edit(); | ||||
|             templateNode.setFormat('handlebars'); | ||||
|             templateNode.setSyntax('mustache'); | ||||
|             templateNode.setTemplate('# This is some random data\n' | ||||
|                                    + 'a,b,c\n' | ||||
|                                    + '80,18,2\n' | ||||
|                                    + '52,36,10\n' | ||||
|                                    + '91,18,61\n' | ||||
|                                    + '32,47,65'); | ||||
|             templateNode.clickOk(); | ||||
|  | ||||
|             csvNode.edit(); | ||||
|             csvNode.setSkipLines(1); | ||||
|             csvNode.setFirstRow4Names(true); | ||||
|             csvNode.setOutput('mult'); | ||||
|             csvNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(templateNode); | ||||
|             templateNode.connect(csvNode); | ||||
|             csvNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql([ 'object', 'object', 'object', 'object' ]); | ||||
|         }); | ||||
|  | ||||
|         it('simple GET request', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var httpRequestNode = workspace.addNode('httpRequest'); | ||||
|             var htmlNode = workspace.addNode('html'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             httpRequestNode.edit(); | ||||
|             httpRequestNode.setMethod('GET'); | ||||
|             httpRequestNode.setUrl('https://nodered.org'); | ||||
|             httpRequestNode.clickOk(); | ||||
|  | ||||
|             htmlNode.edit(); | ||||
|             htmlNode.setSelector('.node-red-latest-version'); | ||||
|             htmlNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(httpRequestNode); | ||||
|             httpRequestNode.connect(htmlNode); | ||||
|             htmlNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.match(/^"v[0-9]+\.[0-9]+\.[0-9]"$/); | ||||
|         }); | ||||
|  | ||||
|         it('split text into one message per line', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var templateNode = workspace.addNode('template'); | ||||
|             var splitNode = workspace.addNode('split'); | ||||
|             var changeNode = workspace.addNode('change'); | ||||
|             var joinNode = workspace.addNode('join'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             templateNode.edit(); | ||||
|             templateNode.setFormat('handlebars'); | ||||
|             templateNode.setSyntax('mustache'); | ||||
|             templateNode.setTemplate('one\ntwo\nthree\nfour\nfive'); | ||||
|             templateNode.clickOk(); | ||||
|  | ||||
|             changeNode.edit(); | ||||
|             changeNode.ruleSet('payload', 'msg', '(parts.index+1) & ": " & payload', 'jsonata'); | ||||
|             changeNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(templateNode); | ||||
|             templateNode.connect(splitNode); | ||||
|             splitNode.connect(changeNode); | ||||
|             changeNode.connect(joinNode); | ||||
|             joinNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"1: one↵2: two↵3: three↵4: four↵5: five"'); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										81
									
								
								test/editor/specs/scenario/cookbook_flowcontrol_uispec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								test/editor/specs/scenario/cookbook_flowcontrol_uispec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| /** | ||||
|  * 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 httpNodeRoot = '/api'; | ||||
|  | ||||
| // https://cookbook.nodered.org/ | ||||
| describe('cookbook', function () { | ||||
|     beforeEach(function () { | ||||
|         workspace.init(); | ||||
|     }); | ||||
|  | ||||
|     before(function () { | ||||
|         helper.startServer(); | ||||
|     }); | ||||
|  | ||||
|     after(function () { | ||||
|         helper.stopServer(); | ||||
|     }); | ||||
|  | ||||
|     describe('flow control', function () { | ||||
|         it('trigger a flow whenever Node-RED starts', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             injectNode.edit(); | ||||
|             injectNode.setPayload('str', 'Started!'); | ||||
|             injectNode.setOnce(true); | ||||
|             injectNode.clickOk(); | ||||
|             injectNode.connect(debugNode); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             workspace.deploy(); | ||||
|             debugTab.getMessage().should.eql('"Started!"'); | ||||
|         }); | ||||
|  | ||||
|         it('trigger a flow at regular intervals', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             injectNode.edit(); | ||||
|             injectNode.setRepeat('interval'); | ||||
|             injectNode.setRepeatInterval(1); | ||||
|             injectNode.clickOk(); | ||||
|             injectNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             specUtil.pause(1000); | ||||
|             var t1 = Number(debugTab.getMessage(1)); | ||||
|             t1.should.within(1500000000000, 3000000000000); | ||||
|             specUtil.pause(1000); | ||||
|             debugTab.getMessage(2).should.within(t1 + 900, 3000000000000); | ||||
|         }); | ||||
|  | ||||
|         // skip this case since it needs up to one minite. | ||||
|         it.skip('trigger a flow at a specific time'); | ||||
|     }); | ||||
| }); | ||||
| @@ -23,16 +23,16 @@ var workspace = require('../../pageobjects/editor/workspace_page'); | ||||
| var httpNodeRoot = "/api"; | ||||
| 
 | ||||
| // https://cookbook.nodered.org/
 | ||||
| describe('cookbook', function() { | ||||
|     beforeEach(function() { | ||||
| describe('cookbook', function () { | ||||
|     beforeEach(function () { | ||||
|         workspace.init(); | ||||
|     }); | ||||
| 
 | ||||
|     before(function() { | ||||
|     before(function () { | ||||
|         helper.startServer(); | ||||
|     }); | ||||
| 
 | ||||
|     after(function() { | ||||
|     after(function () { | ||||
|         helper.stopServer(); | ||||
|     }); | ||||
| 
 | ||||
| @@ -359,7 +359,7 @@ describe('cookbook', function() { | ||||
|             debugTab.getMessage().indexOf('Text file').should.not.eql(-1); | ||||
|         }); | ||||
| 
 | ||||
|         it('post raw data to a flow', function() { | ||||
|         it('post raw data to a flow', function () { | ||||
|             var httpInNode = workspace.addNode("httpIn"); | ||||
|             var templateNode = workspace.addNode("template"); | ||||
|             var httpResponseNode = workspace.addNode("httpResponse"); | ||||
| @@ -383,7 +383,7 @@ describe('cookbook', function() { | ||||
|             var httpRequestNode = workspace.addNode("httpRequest"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
| 
 | ||||
|             injectNode.edit() | ||||
|             injectNode.edit(); | ||||
|             injectNode.setPayload("str", "Nick"); | ||||
|             injectNode.clickOk(); | ||||
| 
 | ||||
| @@ -427,7 +427,7 @@ describe('cookbook', function() { | ||||
|             var httpRequestNode = workspace.addNode("httpRequest"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
| 
 | ||||
|             injectNode.edit() | ||||
|             injectNode.edit(); | ||||
|             injectNode.setPayload("str", "name=Nick"); | ||||
|             injectNode.clickOk(); | ||||
| 
 | ||||
| @@ -451,7 +451,7 @@ describe('cookbook', function() { | ||||
|             debugTab.getMessage().indexOf('Hello Nick!').should.not.eql(-1); | ||||
|         }); | ||||
| 
 | ||||
|         it('post JSON data to a flow', function() { | ||||
|         it('post JSON data to a flow', function () { | ||||
|             var httpInNode = workspace.addNode("httpIn"); | ||||
|             var templateNode = workspace.addNode("template"); | ||||
|             var httpResponseNode = workspace.addNode("httpResponse"); | ||||
| @@ -476,7 +476,7 @@ describe('cookbook', function() { | ||||
|             var httpRequestNode = workspace.addNode("httpRequest"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
| 
 | ||||
|             injectNode.edit() | ||||
|             injectNode.edit(); | ||||
|             injectNode.setPayload("json", '{"name":"Nick"}'); | ||||
|             injectNode.clickOk(); | ||||
| 
 | ||||
							
								
								
									
										300
									
								
								test/editor/specs/scenario/cookbook_httprequests_uispec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								test/editor/specs/scenario/cookbook_httprequests_uispec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,300 @@ | ||||
| /** | ||||
|  * 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 httpNodeRoot = '/api'; | ||||
|  | ||||
| // https://cookbook.nodered.org/ | ||||
| describe('cookbook', function () { | ||||
|     beforeEach(function () { | ||||
|         workspace.init(); | ||||
|     }); | ||||
|  | ||||
|     before(function () { | ||||
|         helper.startServer(); | ||||
|     }); | ||||
|  | ||||
|     after(function () { | ||||
|         helper.stopServer(); | ||||
|     }); | ||||
|  | ||||
|     describe('HTTP requests', function () { | ||||
|         it('simple get request', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var httpRequestNode = workspace.addNode('httpRequest'); | ||||
|             var htmlNode = workspace.addNode('html'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             httpRequestNode.edit(); | ||||
|             httpRequestNode.setMethod('GET'); | ||||
|             httpRequestNode.setUrl(helper.url()); | ||||
|             httpRequestNode.clickOk(); | ||||
|  | ||||
|             htmlNode.edit(); | ||||
|             htmlNode.setSelector('title'); | ||||
|             htmlNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(httpRequestNode); | ||||
|             httpRequestNode.connect(htmlNode); | ||||
|             htmlNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"Node-RED"'); | ||||
|         }); | ||||
|  | ||||
|         it('set the URL of a request', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var changeNode = workspace.addNode('change'); | ||||
|             var httpRequestNode = workspace.addNode('httpRequest'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             injectNode.edit(); | ||||
|             injectNode.setPayload('str', helper.url()); | ||||
|             injectNode.clickOk(); | ||||
|  | ||||
|             changeNode.edit(); | ||||
|             changeNode.ruleSet('url', 'msg', 'payload', 'msg'); | ||||
|             changeNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(changeNode); | ||||
|             changeNode.connect(httpRequestNode); | ||||
|             httpRequestNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.containEql('<title>Node-RED</title>'); | ||||
|         }); | ||||
|  | ||||
|         it('set the URL of a request using a template', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var changeNode = workspace.addNode('change'); | ||||
|             var httpRequestNode = workspace.addNode('httpRequest'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             injectNode.edit(); | ||||
|             injectNode.setPayload('str', 'settings'); | ||||
|             injectNode.clickOk(); | ||||
|  | ||||
|             changeNode.edit(); | ||||
|             changeNode.ruleSet('query', 'msg', 'payload', 'msg'); | ||||
|             changeNode.clickOk(); | ||||
|  | ||||
|             httpRequestNode.edit(); | ||||
|             httpRequestNode.setUrl(helper.url() + '/{{{query}}}'); | ||||
|             httpRequestNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(changeNode); | ||||
|             changeNode.connect(httpRequestNode); | ||||
|             httpRequestNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.containEql('httpNodeRoot'); | ||||
|         }); | ||||
|  | ||||
|         it('set the query string parameters', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var changeNode = workspace.addNode('change'); | ||||
|             var httpRequestNode = workspace.addNode('httpRequest'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             injectNode.edit(); | ||||
|             injectNode.setPayload('str', 'Nick'); | ||||
|             injectNode.clickOk(); | ||||
|  | ||||
|             changeNode.edit(); | ||||
|             changeNode.ruleSet('query', 'msg', 'payload', 'msg'); | ||||
|             changeNode.clickOk(); | ||||
|  | ||||
|             httpRequestNode.edit(); | ||||
|             httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/set-query?q={{{query}}}'); | ||||
|             httpRequestNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(changeNode); | ||||
|             changeNode.connect(httpRequestNode); | ||||
|             httpRequestNode.connect(debugNode); | ||||
|  | ||||
|             // The code for confirmation starts from here. | ||||
|             var httpInNode = workspace.addNode('httpIn', 0, 200); | ||||
|             var templateNode = workspace.addNode('template'); | ||||
|             var httpResponseNode = workspace.addNode('httpResponse'); | ||||
|  | ||||
|             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(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"Hello Nick"'); | ||||
|         }); | ||||
|  | ||||
|         it('get a parsed JSON response', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var changeNodeSetPost = workspace.addNode('change'); | ||||
|             var httpRequestNode = workspace.addNode('httpRequest'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             injectNode.edit(); | ||||
|             injectNode.setPayload('str', 'json-response'); | ||||
|             injectNode.clickOk(); | ||||
|  | ||||
|             changeNodeSetPost.edit(); | ||||
|             changeNodeSetPost.ruleSet('post', 'msg', 'payload', 'msg'); | ||||
|             changeNodeSetPost.clickOk(); | ||||
|  | ||||
|             httpRequestNode.edit(); | ||||
|             httpRequestNode.setMethod('GET'); | ||||
|             var url = helper.url() + httpNodeRoot + '/{{post}}'; | ||||
|             httpRequestNode.setUrl(url); | ||||
|             httpRequestNode.setReturn('obj'); | ||||
|             httpRequestNode.clickOk(); | ||||
|  | ||||
|             debugNode.edit(); | ||||
|             debugNode.setOutput('.title'); | ||||
|             debugNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(changeNodeSetPost); | ||||
|             changeNodeSetPost.connect(httpRequestNode); | ||||
|             httpRequestNode.connect(debugNode); | ||||
|  | ||||
|             // The code for confirmation starts from here. | ||||
|             var httpInNode = workspace.addNode('httpIn', 0, 200); | ||||
|             var templateNode = workspace.addNode('template'); | ||||
|             var changeNodeSetHeader = workspace.addNode('change'); | ||||
|             var httpResponseNode = workspace.addNode('httpResponse'); | ||||
|  | ||||
|             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(); | ||||
|  | ||||
|             changeNodeSetHeader.edit(); | ||||
|             changeNodeSetHeader.ruleSet('headers', 'msg', '{"content-type":"application/json"}', 'json'); | ||||
|             changeNodeSetHeader.clickOk(); | ||||
|  | ||||
|             httpInNode.connect(templateNode); | ||||
|             templateNode.connect(changeNodeSetHeader); | ||||
|             changeNodeSetHeader.connect(httpResponseNode); | ||||
|             // The code for confirmation ends here. | ||||
|  | ||||
|             workspace.deploy(); | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"Hello"'); | ||||
|         }); | ||||
|  | ||||
|         it('get a binary response', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var httpRequestNode = workspace.addNode('httpRequest'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             httpRequestNode.edit(); | ||||
|             httpRequestNode.setMethod('GET'); | ||||
|             httpRequestNode.setUrl(helper.url() + '/settings'); | ||||
|             httpRequestNode.setReturn('bin'); | ||||
|             httpRequestNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(httpRequestNode); | ||||
|             httpRequestNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             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'); | ||||
|             var httpRequestNode = workspace.addNode('httpRequest'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             functionNode.edit(); | ||||
|             functionNode.setFunction('msg.payload = "data to post";\nreturn msg;'); | ||||
|             functionNode.clickOk(); | ||||
|  | ||||
|             httpRequestNode.edit(); | ||||
|             httpRequestNode.setMethod('POST'); | ||||
|             var url = helper.url() + httpNodeRoot + '/set-header'; | ||||
|             httpRequestNode.setUrl(url); | ||||
|             httpRequestNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(functionNode); | ||||
|             functionNode.connect(httpRequestNode); | ||||
|             httpRequestNode.connect(debugNode); | ||||
|  | ||||
|             // The code for confirmation starts from here. | ||||
|             var httpInNode = workspace.addNode('httpIn', 0, 200); | ||||
|             var templateNode = workspace.addNode('template'); | ||||
|             var httpResponseNode = workspace.addNode('httpResponse'); | ||||
|  | ||||
|             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(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"data to post"'); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										142
									
								
								test/editor/specs/scenario/cookbook_messages_uispec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								test/editor/specs/scenario/cookbook_messages_uispec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | ||||
| /** | ||||
|  * 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 httpNodeRoot = '/api'; | ||||
|  | ||||
| // https://cookbook.nodered.org/ | ||||
| describe('cookbook', function () { | ||||
|     beforeEach(function () { | ||||
|         workspace.init(); | ||||
|     }); | ||||
|  | ||||
|     before(function () { | ||||
|         helper.startServer(); | ||||
|     }); | ||||
|  | ||||
|     after(function () { | ||||
|         helper.stopServer(); | ||||
|     }); | ||||
|  | ||||
|     describe('messages', function () { | ||||
|         it('set a message property to a fixed value', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var changeNode = workspace.addNode('change'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             changeNode.edit(); | ||||
|             changeNode.ruleSet('payload', 'msg', 'Hello World!'); | ||||
|             changeNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(changeNode); | ||||
|             changeNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"Hello World!"'); | ||||
|         }); | ||||
|  | ||||
|         it('delete a message property', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var changeNode = workspace.addNode('change'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             changeNode.edit(); | ||||
|             changeNode.ruleDelete(); | ||||
|             changeNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(changeNode); | ||||
|             changeNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('undefined'); | ||||
|         }); | ||||
|  | ||||
|         it('move a message property', function () { | ||||
|             var injectNode = workspace.addNode('inject'); | ||||
|             var changeNode = workspace.addNode('change'); | ||||
|             var debugNode = workspace.addNode('debug'); | ||||
|  | ||||
|             injectNode.edit(); | ||||
|             injectNode.setTopic('Hello'); | ||||
|             injectNode.clickOk(); | ||||
|  | ||||
|             changeNode.edit(); | ||||
|             changeNode.ruleMove('topic', 'payload'); | ||||
|             changeNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(changeNode); | ||||
|             changeNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"Hello"'); | ||||
|         }); | ||||
|  | ||||
|         it('map a property between different numeric ranges', function () { | ||||
|             var injectNode1 = workspace.addNode('inject'); | ||||
|             var injectNode2 = workspace.addNode('inject', 0, 100); | ||||
|             var injectNode3 = workspace.addNode('inject', 0, 200); | ||||
|             var rangeNode = workspace.addNode('range', 200, 100); | ||||
|             var debugNode = workspace.addNode('debug', 400); | ||||
|  | ||||
|             injectNode1.edit(); | ||||
|             injectNode1.setPayload('num', 0); | ||||
|             injectNode1.clickOk(); | ||||
|             injectNode2.edit(); | ||||
|             injectNode2.setPayload('num', 512); | ||||
|             injectNode2.clickOk(); | ||||
|             injectNode3.edit(); | ||||
|             injectNode3.setPayload('num', 1023); | ||||
|             injectNode3.clickOk(); | ||||
|  | ||||
|             rangeNode.edit(); | ||||
|             rangeNode.setAction('clamp'); | ||||
|             rangeNode.setRange(0, 1023, 0, 5); | ||||
|             rangeNode.clickOk(); | ||||
|  | ||||
|             injectNode1.connect(rangeNode); | ||||
|             injectNode2.connect(rangeNode); | ||||
|             injectNode3.connect(rangeNode); | ||||
|             rangeNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode1.clickLeftButton(); | ||||
|             debugTab.getMessage(1).should.eql('0'); | ||||
|             injectNode2.clickLeftButton(); | ||||
|             debugTab.getMessage(2).should.eql('2.5024437927663734'); | ||||
|             injectNode3.clickLeftButton(); | ||||
|             debugTab.getMessage(3).should.eql('5'); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -1,441 +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 httpNodeRoot = "/api"; | ||||
|  | ||||
| // https://cookbook.nodered.org/ | ||||
| describe('cookbook', function() { | ||||
|     beforeEach(function() { | ||||
|         workspace.init(); | ||||
|     }); | ||||
|  | ||||
|     before(function() { | ||||
|         helper.startServer(); | ||||
|     }); | ||||
|  | ||||
|     after(function() { | ||||
|         helper.stopServer(); | ||||
|     }); | ||||
|  | ||||
|     describe('messages', function() { | ||||
|         it('set a message property to a fixed value', function() { | ||||
|             var injectNode = workspace.addNode("inject"); | ||||
|             var changeNode = workspace.addNode("change"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
|  | ||||
|             changeNode.edit(); | ||||
|             changeNode.ruleSet("payload", "msg", "Hello World!"); | ||||
|             changeNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(changeNode); | ||||
|             changeNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"Hello World!"'); | ||||
|         }); | ||||
|  | ||||
|         it('delete a message property', function() { | ||||
|             var injectNode = workspace.addNode("inject"); | ||||
|             var changeNode = workspace.addNode("change"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
|  | ||||
|             changeNode.edit(); | ||||
|             changeNode.ruleDelete(); | ||||
|             changeNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(changeNode); | ||||
|             changeNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql("undefined"); | ||||
|         }); | ||||
|  | ||||
|         it('move a message property', function() { | ||||
|             var injectNode = workspace.addNode("inject"); | ||||
|             var changeNode = workspace.addNode("change"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
|  | ||||
|             injectNode.edit(); | ||||
|             injectNode.setTopic("Hello"); | ||||
|             injectNode.clickOk(); | ||||
|  | ||||
|             changeNode.edit(); | ||||
|             changeNode.ruleMove("topic", "payload"); | ||||
|             changeNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(changeNode); | ||||
|             changeNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"Hello"'); | ||||
|         }); | ||||
|  | ||||
|         it('map a property between different numeric ranges', function() { | ||||
|             var injectNode1 = workspace.addNode("inject"); | ||||
|             var injectNode2 = workspace.addNode("inject", 0, 100); | ||||
|             var injectNode3 = workspace.addNode("inject", 0, 200); | ||||
|             var rangeNode = workspace.addNode("range", 200, 100); | ||||
|             var debugNode = workspace.addNode("debug", 400); | ||||
|  | ||||
|             injectNode1.edit(); | ||||
|             injectNode1.setPayload("num", 0); | ||||
|             injectNode1.clickOk(); | ||||
|             injectNode2.edit(); | ||||
|             injectNode2.setPayload("num", 512); | ||||
|             injectNode2.clickOk(); | ||||
|             injectNode3.edit(); | ||||
|             injectNode3.setPayload("num", 1023); | ||||
|             injectNode3.clickOk(); | ||||
|  | ||||
|             rangeNode.edit(); | ||||
|             rangeNode.setAction("clamp"); | ||||
|             rangeNode.setRange(0, 1023, 0, 5); | ||||
|             rangeNode.clickOk(); | ||||
|  | ||||
|             injectNode1.connect(rangeNode); | ||||
|             injectNode2.connect(rangeNode); | ||||
|             injectNode3.connect(rangeNode); | ||||
|             rangeNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode1.clickLeftButton(); | ||||
|             debugTab.getMessage(1).should.eql('0'); | ||||
|             injectNode2.clickLeftButton(); | ||||
|             debugTab.getMessage(2).should.eql('2.5024437927663734'); | ||||
|             injectNode3.clickLeftButton(); | ||||
|             debugTab.getMessage(3).should.eql('5'); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('flow control', function() { | ||||
|         it('trigger a flow whenever Node-RED starts', function() { | ||||
|             var injectNode = workspace.addNode("inject"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
|  | ||||
|             injectNode.edit(); | ||||
|             injectNode.setPayload("str", "Started!") | ||||
|             injectNode.setOnce(true); | ||||
|             injectNode.clickOk(); | ||||
|             injectNode.connect(debugNode); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             workspace.deploy(); | ||||
|             debugTab.getMessage().should.eql('"Started!"'); | ||||
|         }); | ||||
|  | ||||
|         it('trigger a flow at regular intervals', function() { | ||||
|             var injectNode = workspace.addNode("inject"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
|  | ||||
|             injectNode.edit(); | ||||
|             injectNode.setRepeat("interval"); | ||||
|             injectNode.setRepeatInterval(1); | ||||
|             injectNode.clickOk(); | ||||
|             injectNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             specUtil.pause(1000); | ||||
|             var t1 = Number(debugTab.getMessage(1)); | ||||
|             t1.should.within(1500000000000, 3000000000000); | ||||
|             specUtil.pause(1000); | ||||
|             debugTab.getMessage(2).should.within(t1 + 900, 3000000000000); | ||||
|         }); | ||||
|  | ||||
|         // skip this case since it needs up to one minite. | ||||
|         it.skip('trigger a flow at a specific time'); | ||||
|     }); | ||||
|  | ||||
|     describe('HTTP requests', function() { | ||||
|         it('simple get request', function() { | ||||
|             var injectNode = workspace.addNode("inject"); | ||||
|             var httpRequetNode = workspace.addNode("httpRequest"); | ||||
|             var htmlNode = workspace.addNode("html"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
|  | ||||
|             httpRequetNode.edit(); | ||||
|             httpRequetNode.setMethod("GET"); | ||||
|             httpRequetNode.setUrl(helper.url()); | ||||
|             httpRequetNode.clickOk(); | ||||
|  | ||||
|             htmlNode.edit(); | ||||
|             htmlNode.setSelector("title"); | ||||
|             htmlNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(httpRequetNode); | ||||
|             httpRequetNode.connect(htmlNode); | ||||
|             htmlNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"Node-RED"'); | ||||
|         }); | ||||
|  | ||||
|         it('set the URL of a request', function() { | ||||
|             var injectNode = workspace.addNode("inject"); | ||||
|             var changeNode = workspace.addNode("change"); | ||||
|             var httpRequetNode = workspace.addNode("httpRequest"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
|  | ||||
|             injectNode.edit(); | ||||
|             injectNode.setPayload("str", helper.url()); | ||||
|             injectNode.clickOk(); | ||||
|  | ||||
|             changeNode.edit(); | ||||
|             changeNode.ruleSet("url", "msg", "payload", "msg"); | ||||
|             changeNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(changeNode); | ||||
|             changeNode.connect(httpRequetNode); | ||||
|             httpRequetNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.containEql('<title>Node-RED</title>'); | ||||
|         }); | ||||
|  | ||||
|         it('set the URL of a request using a template', function() { | ||||
|             var injectNode = workspace.addNode("inject"); | ||||
|             var changeNode = workspace.addNode("change"); | ||||
|             var httpRequetNode = workspace.addNode("httpRequest"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
|  | ||||
|             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(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.containEql('httpNodeRoot'); | ||||
|         }); | ||||
|  | ||||
|         it('set the query string parameters', function() { | ||||
|             var injectNode = workspace.addNode("inject"); | ||||
|             var changeNode = workspace.addNode("change"); | ||||
|             var httpRequetNode = workspace.addNode("httpRequest"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
|  | ||||
|             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, 200); | ||||
|             var templateNode = workspace.addNode("template"); | ||||
|             var httpResponseNode = workspace.addNode("httpResponse"); | ||||
|  | ||||
|             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(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"Hello Nick"'); | ||||
|         }); | ||||
|  | ||||
|         it('get a parsed JSON response', function() { | ||||
|             var injectNode = workspace.addNode("inject"); | ||||
|             var changeNodeSetPost = workspace.addNode("change"); | ||||
|             var httpRequetNode = workspace.addNode("httpRequest"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
|  | ||||
|             injectNode.edit(); | ||||
|             injectNode.setPayload("str", "json-response"); | ||||
|             injectNode.clickOk(); | ||||
|  | ||||
|             changeNodeSetPost.edit(); | ||||
|             changeNodeSetPost.ruleSet("post", "msg", "payload", "msg"); | ||||
|             changeNodeSetPost.clickOk(); | ||||
|  | ||||
|             httpRequetNode.edit(); | ||||
|             httpRequetNode.setMethod("GET"); | ||||
|             var url = helper.url() + httpNodeRoot + "/{{post}}"; | ||||
|             httpRequetNode.setUrl(url); | ||||
|             httpRequetNode.setReturn("obj"); | ||||
|             httpRequetNode.clickOk(); | ||||
|  | ||||
|             debugNode.edit(); | ||||
|             debugNode.setOutput(".title"); | ||||
|             debugNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(changeNodeSetPost); | ||||
|             changeNodeSetPost.connect(httpRequetNode); | ||||
|             httpRequetNode.connect(debugNode); | ||||
|  | ||||
|             // The code for confirmation starts from here. | ||||
|             var httpInNode = workspace.addNode("httpIn", 0, 200); | ||||
|             var templateNode = workspace.addNode("template"); | ||||
|             var changeNodeSetHeader = workspace.addNode("change"); | ||||
|             var httpResponseNode = workspace.addNode("httpResponse"); | ||||
|  | ||||
|             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(); | ||||
|  | ||||
|             changeNodeSetHeader.edit(); | ||||
|             changeNodeSetHeader.ruleSet("headers", "msg", '{"content-type":"application/json"}', "json"); | ||||
|             changeNodeSetHeader.clickOk(); | ||||
|  | ||||
|             httpInNode.connect(templateNode); | ||||
|             templateNode.connect(changeNodeSetHeader); | ||||
|             changeNodeSetHeader.connect(httpResponseNode); | ||||
|             // The code for confirmation ends here. | ||||
|  | ||||
|             workspace.deploy(); | ||||
|             debugTab.open(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"Hello"'); | ||||
|         }); | ||||
|  | ||||
|         it('get a binary response', function() { | ||||
|             var injectNode = workspace.addNode("inject"); | ||||
|             var httpRequetNode = workspace.addNode("httpRequest"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
|  | ||||
|             httpRequetNode.edit(); | ||||
|             httpRequetNode.setMethod("GET"); | ||||
|             httpRequetNode.setUrl(helper.url() + "/settings"); | ||||
|             httpRequetNode.setReturn("bin"); | ||||
|             httpRequetNode.clickOk(); | ||||
|  | ||||
|             injectNode.connect(httpRequetNode); | ||||
|             httpRequetNode.connect(debugNode); | ||||
|  | ||||
|             workspace.deploy(); | ||||
|  | ||||
|             debugTab.open(); | ||||
|             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"); | ||||
|             var httpRequetNode = workspace.addNode("httpRequest"); | ||||
|             var debugNode = workspace.addNode("debug"); | ||||
|  | ||||
|             functionNode.edit(); | ||||
|             functionNode.setFunction('msg.payload = "data to post";\nreturn msg;'); | ||||
|             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, 200); | ||||
|             var templateNode = workspace.addNode("template"); | ||||
|             var httpResponseNode = workspace.addNode("httpResponse"); | ||||
|  | ||||
|             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(); | ||||
|             injectNode.clickLeftButton(); | ||||
|             debugTab.getMessage().should.eql('"data to post"'); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -53,7 +53,7 @@ describe("runtime-api/flows", function() { | ||||
|         var loadFlows; | ||||
|         var reloadError = false; | ||||
|         beforeEach(function() { | ||||
|             setFlows = sinon.spy(function(flows,type) { | ||||
|             setFlows = sinon.spy(function(flows,credentials,type) { | ||||
|                 if (flows[0] === "error") { | ||||
|                     var err = new Error("error"); | ||||
|                     err.code = "error"; | ||||
| @@ -91,7 +91,19 @@ describe("runtime-api/flows", function() { | ||||
|                 result.should.eql({rev:"newRev"}); | ||||
|                 setFlows.called.should.be.true(); | ||||
|                 setFlows.lastCall.args[0].should.eql([4,5,6]); | ||||
|                 setFlows.lastCall.args[1].should.eql("full"); | ||||
|                 setFlows.lastCall.args[2].should.eql("full"); | ||||
|                 done(); | ||||
|             }).catch(done); | ||||
|         }); | ||||
|         it("includes credentials when part of the request", function(done) { | ||||
|             flows.setFlows({ | ||||
|                 flows: {flows:[4,5,6], credentials: {$:"creds"}}, | ||||
|             }).then(function(result) { | ||||
|                 result.should.eql({rev:"newRev"}); | ||||
|                 setFlows.called.should.be.true(); | ||||
|                 setFlows.lastCall.args[0].should.eql([4,5,6]); | ||||
|                 setFlows.lastCall.args[1].should.eql({$:"creds"}); | ||||
|                 setFlows.lastCall.args[2].should.eql("full"); | ||||
|                 done(); | ||||
|             }).catch(done); | ||||
|         }); | ||||
| @@ -103,7 +115,7 @@ describe("runtime-api/flows", function() { | ||||
|                 result.should.eql({rev:"newRev"}); | ||||
|                 setFlows.called.should.be.true(); | ||||
|                 setFlows.lastCall.args[0].should.eql([4,5,6]); | ||||
|                 setFlows.lastCall.args[1].should.eql("nodes"); | ||||
|                 setFlows.lastCall.args[2].should.eql("nodes"); | ||||
|                 done(); | ||||
|             }).catch(done); | ||||
|         }); | ||||
| @@ -125,7 +137,7 @@ describe("runtime-api/flows", function() { | ||||
|                 result.should.eql({rev:"newRev"}); | ||||
|                 setFlows.called.should.be.true(); | ||||
|                 setFlows.lastCall.args[0].should.eql([4,5,6]); | ||||
|                 setFlows.lastCall.args[1].should.eql("nodes"); | ||||
|                 setFlows.lastCall.args[2].should.eql("nodes"); | ||||
|                 done(); | ||||
|             }).catch(done); | ||||
|         }); | ||||
|   | ||||
| @@ -67,7 +67,10 @@ describe('flows/index', function() { | ||||
|             }); | ||||
|             return when.resolve(); | ||||
|         }); | ||||
|         credentialsLoad = sinon.stub(credentials,"load",function() { | ||||
|         credentialsLoad = sinon.stub(credentials,"load",function(creds) { | ||||
|             if (creds && creds.hasOwnProperty("$") && creds['$'] === "fail") { | ||||
|                 return when.reject("creds error"); | ||||
|             } | ||||
|             return when.resolve(); | ||||
|         }); | ||||
|         flowCreate = sinon.stub(Flow,"create",function(parent, global, flow) { | ||||
| @@ -177,6 +180,23 @@ describe('flows/index', function() { | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('sets the full flow including credentials', function(done) { | ||||
|             var originalConfig = [ | ||||
|                 {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]}, | ||||
|                 {id:"t1",type:"tab"} | ||||
|             ]; | ||||
|             var credentials = {"t1-1":{"a":1}}; | ||||
|  | ||||
|             flows.init({log:mockLog, settings:{},storage:storage}); | ||||
|             flows.setFlows(originalConfig,credentials).then(function() { | ||||
|                 credentialsClean.called.should.be.false(); | ||||
|                 credentialsLoad.called.should.be.true(); | ||||
|                 credentialsLoad.lastCall.args[0].should.eql(credentials); | ||||
|                 flows.getFlows().flows.should.eql(originalConfig); | ||||
|                 done(); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('updates existing flows with partial deployment - nodes', function(done) { | ||||
|             var originalConfig = [ | ||||
|                 {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]}, | ||||
| @@ -235,6 +255,20 @@ describe('flows/index', function() { | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('returns error if it cannot decrypt credentials', function(done) { | ||||
|             var originalConfig = [ | ||||
|                 {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]}, | ||||
|                 {id:"t1",type:"tab"} | ||||
|             ]; | ||||
|             var credentials = {"$":"fail"}; | ||||
|  | ||||
|             flows.init({log:mockLog, settings:{},storage:storage}); | ||||
|             flows.setFlows(originalConfig,credentials).then(function() { | ||||
|                 done("Unexpected success when credentials couldn't be decrypted") | ||||
|             }).catch(function(err) { | ||||
|                 done(); | ||||
|             }); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('#load', function() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user