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