Merge branch 'dev' into pr_2165

This commit is contained in:
Nick O'Leary
2019-07-10 09:30:48 +01:00
282 changed files with 4009 additions and 1538 deletions

View File

@@ -77,7 +77,6 @@ module.exports = {
browser.call(function () {
return new Promise(function(resolve, reject) {
cleanup(flowFilename);
app.use("/",express.static("public"));
server = http.createServer(app);
var settings = {
httpAdminRoot: "/",
@@ -102,7 +101,7 @@ module.exports = {
});
});
browser.url(url);
browser.waitForExist('#red-ui-palette-node_inject');
browser.waitForExist(".red-ui-palette-node[data-palette-type='inject']")
} catch (err) {
console.log(err);
throw err;

View File

@@ -16,23 +16,23 @@
var idMap = {
// input
"inject": "#red-ui-palette-node_inject",
"httpin": "#red-ui-palette-node_http_in",
"mqttIn": "#red-ui-palette-node_mqtt_in",
"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_debug",
"httpResponse": "#red-ui-palette-node_http_response",
"mqttOut": "#red-ui-palette-node_mqtt_out",
"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_function",
"template": "#red-ui-palette-node_template",
"change": "#red-ui-palette-node_change",
"range": "#red-ui-palette-node_range",
"httpRequest": "#red-ui-palette-node_http_request",
"html": "#red-ui-palette-node_html",
"json": "#red-ui-palette-node_json",
"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']",
"httpRequest": ".red-ui-palette-node[data-palette-type='http request']",
"html": ".red-ui-palette-node[data-palette-type='html']",
"json": ".red-ui-palette-node[data-palette-type='json']",
// storage
"filein": "#red-ui-palette-node_file_in",
"filein": ".red-ui-palette-node[data-palette-type='file in']",
};
function getId(type) {

View File

@@ -49,14 +49,14 @@ function addNode(type, x, y) {
browser.moveToObject("#red-ui-palette-search", previousX + 300, previousY + 100); // adjust to the top-left corner of workspace.
browser.buttonUp();
// Last node is the one that has been created right now.
var nodeElement = browser.elements('//*[@class="red-ui-flow-node red-ui-flow-node-group"][last()]');
var nodeElement = browser.elements('//*[contains(concat(" ", normalize-space(@class), " "), " red-ui-flow-node-group ")][last()]');
var nodeId = nodeElement.getAttribute('id');
var node = nodeFactory.create(type, nodeId);
return node;
}
function deleteAllNodes() {
browser.click('.innerCanvas');
browser.click('.red-ui-workspace-chart-event-layer');
browser.keys(['Control', 'a', 'a', 'Control']); // call twice to release the keys.
browser.keys(['Delete']);
}

View File

@@ -979,6 +979,29 @@ describe('HTTP Request Node', function() {
n1.receive({payload:"foo", requestTimeout: -4});
});
});
it('should show a warning if msg.requestTimeout is set to 0', function(done) {
var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/text')},
{id:"n2", type:"helper"}];
helper.load(httpRequestNode, flow, function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
try {
msg.should.have.property('statusCode', 200);
var logEvents = helper.log().args.filter(function(evt) {
return evt[0].type == 'http request';
});
logEvents.should.have.length(2);
var tstmp = logEvents[0][0].timestamp;
logEvents[0][0].should.eql({level:helper.log().WARN, id:'n1',type:'http request',msg:'httpin.errors.timeout-isnegative', timestamp:tstmp});
done();
} catch(err) {
done(err);
}
});
n1.receive({payload:"foo", requestTimeout: 0});
});
});
it('should pass if response time is faster than timeout set via msg.requestTimeout', function(done) {
var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/timeout50ms')},
{id:"n2", type:"helper"}];
@@ -1268,6 +1291,7 @@ describe('HTTP Request Node', function() {
var n1 = helper.getNode("n1");
var n2 = helper.getNode("n2");
n2.on("input", function(msg) {
console.log(msg.payload);
try {
msg.payload.headers.should.have.property('content-type').which.startWith('application/json');
msg.payload.headers.should.not.have.property('x-node-red-request-node');
@@ -1278,7 +1302,11 @@ describe('HTTP Request Node', function() {
});
// Pass in a headers property with an unmodified x-node-red-request-node hash
// This should cause the node to ignore the headers
n1.receive({payload:{foo:"bar"}, headers: { 'content-type': 'text/plain', "x-node-red-request-node":"67690139"}});
var headers = { 'content-type': 'text/plain' };
headers['x-node-red-request-node'] = require("hash-sum")(headers);
n1.receive({payload:{foo:"bar"}, headers: headers});
});
});

View File

@@ -179,6 +179,24 @@ describe('websocket Node', function() {
});
});
it('should receive wholemsg when data not object', function(done) {
var flow = [
{ id: "n1", type: "websocket-listener", path: "/ws", wholemsg: "true" },
{ id: "n2", type: "websocket in", server: "n1", wires: [["n3"]] },
{ id: "n3", type: "helper" }];
helper.load(websocketNode, flow, function() {
createClient("n1").then(function(sock) {
helper.getNode("n3").on("input", function(msg) {
msg.should.have.property("payload", 123);
done();
});
sock.send(123);
}).catch(function(err) {
done(err);
});
});
});
it('should send', function(done) {
var flow = [
{ id: "n1", type: "websocket-listener", path: "/ws" },

View File

@@ -818,6 +818,14 @@ describe('switch Node', function() {
});
});
it('should handle env var expression', function(done) {
var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"VAR",propertyType:"env",rules:[{"t":"eq","v":"VAL"}],checkall:true,outputs:1,wires:[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
process.env.VAR = "VAL";
customFlowSwitchTest(flow, true, "OK", done);
});
it('should take head of message sequence (no repair)', function(done) {
var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"head","v":3}],checkall:false,repair:false,outputs:1,wires:[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];

View File

@@ -677,6 +677,9 @@ describe('JOIN node', function() {
n1.receive({payload:{f:1}, topic:"f", complete:true});
n1.receive({payload:{g:2}, topic:"g"});
n1.receive({payload:{h:1}, topic:"h"});
n1.receive({reset:true});
n1.receive({payload:{g:2}, topic:"g"});
n1.receive({payload:{h:1}, topic:"h"});
n1.receive({payload:{i:3}, topic:"i"});
});
});
@@ -700,6 +703,9 @@ describe('JOIN node', function() {
}
catch(e) { done(e) }
});
n1.receive({payload:2, foo:"b"});
n1.receive({payload:3, foo:"c"});
n1.receive({reset:true});
n1.receive({payload:1, foo:"a"});
n1.receive({payload:2, foo:"b"});
n1.receive({payload:3, foo:"c"});

View File

@@ -96,9 +96,9 @@ describe("api/editor/index", function() {
});
it('serves icons', function(done) {
request(app)
.get("/red/images/icons/node-changed.png")
.get("/red/images/icons/arrow-in.svg")
.expect(200)
.expect("Content-Type", /image\/png/)
.expect("Content-Type", /image\/svg\+xml/)
.end(function(err,res) {
done(err);
});

View File

@@ -45,7 +45,7 @@ describe("api/editor/theme", function () {
context.page.should.have.a.property("tabicon", "red/images/node-red-icon-black.svg");
context.should.have.a.property("header");
context.header.should.have.a.property("title", "Node-RED");
context.header.should.have.a.property("image", "red/images/node-red.png");
context.header.should.have.a.property("image", "red/images/node-red.svg");
context.should.have.a.property("asset");
context.asset.should.have.a.property("red", "red/red.min.js");
context.asset.should.have.a.property("main", "red/main.min.js");

View File

@@ -33,7 +33,7 @@ describe("api/editor/ui", function() {
nodes: {
getIcon: function(opts) {
return new Promise(function(resolve,reject) {
fs.readFile(NR_TEST_UTILS.resolve("@node-red/editor-client/src/images/icons/arrow-in.png"), function(err,data) {
fs.readFile(NR_TEST_UTILS.resolve("@node-red/editor-client/src/images/icons/arrow-in.svg"), function(err,data) {
resolve(data);
})
});
@@ -94,7 +94,7 @@ describe("api/editor/ui", function() {
}
}
it('returns the requested icon', function(done) {
var defaultIcon = fs.readFileSync(NR_TEST_UTILS.resolve("@node-red/editor-client/src/images/icons/arrow-in.png"));
var defaultIcon = fs.readFileSync(NR_TEST_UTILS.resolve("@node-red/editor-client/src/images/icons/arrow-in.svg"));
request(app)
.get("/icons/module/icon.png")
.expect("Content-Type", /image\/png/)

View File

@@ -319,6 +319,57 @@ describe('Flow', function() {
});
});
it("ignores disabled nodes",function(done) {
var config = flowUtils.parseConfig([
{id:"t1",type:"tab"},
{id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
{id:"2",x:10,y:10,z:"t1",d:true,type:"test",foo:"a",wires:["3"]},
{id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
{id:"4",z:"t1",type:"test",foo:"a"},
{id:"5",z:"t1",type:"test",d:true,foo:"a"}
]);
var flow = Flow.create({},config,config.flows["t1"]);
flow.start();
Object.keys(flow.getActiveNodes()).should.have.length(3);
flow.getNode('1').should.have.a.property('id','1');
should.not.exist(flow.getNode('2'));
flow.getNode('3').should.have.a.property('id','3');
flow.getNode('4').should.have.a.property('id','4');
should.not.exist(flow.getNode('5'));
currentNodes.should.have.a.property("1");
currentNodes.should.not.have.a.property("2");
currentNodes.should.have.a.property("3");
currentNodes.should.have.a.property("4");
currentNodes["1"].should.have.a.property("handled",0);
currentNodes["3"].should.have.a.property("handled",0);
currentNodes["1"].receive({payload:"test"});
currentNodes["1"].should.have.a.property("handled",1);
// Message doesn't reach 3 as 2 is disabled
currentNodes["3"].should.have.a.property("handled",0);
flow.stop().then(function() {
try {
currentNodes.should.not.have.a.property("1");
currentNodes.should.not.have.a.property("2");
currentNodes.should.not.have.a.property("3");
currentNodes.should.not.have.a.property("4");
stoppedNodes.should.have.a.property("1");
stoppedNodes.should.not.have.a.property("2");
stoppedNodes.should.have.a.property("3");
stoppedNodes.should.have.a.property("4");
done();
} catch(err) {
done(err);
}
});
});
});