Add test cases for setMessageProperty with non-object properties

This commit is contained in:
Nick O'Leary 2020-06-01 13:13:14 +01:00
parent 132254b3a5
commit 4b54a81dfd
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
4 changed files with 84 additions and 28 deletions

View File

@ -216,7 +216,7 @@ module.exports = function(RED) {
RED.util.setMessageProperty(msg,property,undefined);
} else if (rule.t === 'set') {
if (!RED.util.setMessageProperty(msg,property,value)) {
node.warn(RED._("change.errors.no-override",{prop:property}));
node.warn(RED._("change.errors.no-override",{property:property}));
}
} else if (rule.t === 'change') {
current = RED.util.getMessageProperty(msg,property);

View File

@ -672,7 +672,7 @@
"invalid-from": "Invalid 'from' property: __error__",
"invalid-json": "Invalid 'to' JSON property",
"invalid-expr": "Invalid JSONata expression: __error__",
"no-override": "Can't overwrite primitive type with object __prop__."
"no-override": "Cannot set property of non-object type: __property__"
}
},
"range": {

View File

@ -371,14 +371,14 @@ function setObjectProperty(msg,prop,value,createMissing) {
var length = msgPropParts.length;
var obj = msg;
var key;
var flag = true;
for (var i=0;i<length-1;i++) {
key = msgPropParts[i];
if (typeof key === 'string' || (typeof key === 'number' && !Array.isArray(obj))) {
if (obj.hasOwnProperty(key)) {
if (length > 1 && ((typeof obj[key] !== "object" && typeof obj[key] !== "function") || obj[key] === null)) {
//console.log("Can't override primitive type with object.");
flag = false;
// Break out early as we cannot create a property beneath
// this type of value
return false;
}
obj = obj[key];
} else if (createMissing) {
@ -389,7 +389,7 @@ function setObjectProperty(msg,prop,value,createMissing) {
}
obj = obj[key];
} else {
return null;
return false;
}
} else if (typeof key === 'number') {
// obj is an array
@ -402,7 +402,7 @@ function setObjectProperty(msg,prop,value,createMissing) {
}
obj = obj[key];
} else {
return null;
return false;
}
} else {
obj = obj[key];
@ -420,11 +420,11 @@ function setObjectProperty(msg,prop,value,createMissing) {
if (typeof obj === "object" && obj !== null) {
obj[key] = value;
} else {
//console.log("Can't override primitive type with object.");
flag = false;
}
// Cannot set a property of a non-object/array
return false;
}
}
return flag;
return true;
}
/*!

View File

@ -189,7 +189,8 @@ describe("@node-red/util/util", function() {
// setMessageProperty strips off `msg.` prefixes.
// setObjectProperty does not
var obj = {};
util.setObjectProperty(obj,"msg.a","bar");
var result = util.setObjectProperty(obj,"msg.a","bar");
result.should.be.true();
obj.should.have.property("msg");
obj.msg.should.have.property("a","bar");
})
@ -197,59 +198,111 @@ describe("@node-red/util/util", function() {
describe('setMessageProperty', function() {
it('sets a property', function() {
var msg = {a:"foo"};
util.setMessageProperty(msg,"msg.a","bar");
var result = util.setMessageProperty(msg,"msg.a","bar");
result.should.be.true();
msg.a.should.eql('bar');
});
it('sets a deep level property', function() {
var msg = {a:{b:{c:"foo"}}};
util.setMessageProperty(msg,"msg.a.b.c","bar");
var result = util.setMessageProperty(msg,"msg.a.b.c","bar");
result.should.be.true();
msg.a.b.c.should.eql('bar');
});
it('creates missing parent properties by default', function() {
var msg = {a:{}};
util.setMessageProperty(msg,"msg.a.b.c","bar");
var result = util.setMessageProperty(msg,"msg.a.b.c","bar");
result.should.be.true();
msg.a.b.c.should.eql('bar');
})
it('does not create missing parent properties', function() {
var msg = {a:{}};
util.setMessageProperty(msg,"msg.a.b.c","bar",false);
var result = util.setMessageProperty(msg,"msg.a.b.c","bar",false);
result.should.be.false();
should.not.exist(msg.a.b);
})
it('does not create missing parent properties with array', function () {
it('does not create missing parent properties of array', function () {
var msg = {a:{}};
util.setMessageProperty(msg, "msg.a.b[1].c", "bar", false);
var result = util.setMessageProperty(msg, "msg.a.b[1].c", "bar", false);
result.should.be.false();
should.not.exist(msg.a.b);
})
it('does not create missing parent properties of string', function() {
var msg = {a:"foo"};
var result = util.setMessageProperty(msg, "msg.a.b.c", "bar", false);
result.should.be.false();
should.not.exist(msg.a.b);
})
it('does not set property of existing string property', function() {
var msg = {a:"foo"};
var result = util.setMessageProperty(msg, "msg.a.b", "bar", false);
result.should.be.false();
should.not.exist(msg.a.b);
})
it('does not set property of existing number property', function() {
var msg = {a:123};
var result = util.setMessageProperty(msg, "msg.a.b", "bar", false);
result.should.be.false();
should.not.exist(msg.a.b);
})
it('does not create missing parent properties of number', function() {
var msg = {a:123};
var result = util.setMessageProperty(msg, "msg.a.b.c", "bar", false);
result.should.be.false();
should.not.exist(msg.a.b);
})
it('does not set property of existing boolean property', function() {
var msg = {a:true};
var result = util.setMessageProperty(msg, "msg.a.b", "bar", false);
result.should.be.false();
should.not.exist(msg.a.b);
})
it('does not create missing parent properties of boolean', function() {
var msg = {a:true};
var result = util.setMessageProperty(msg, "msg.a.b.c", "bar", false);
result.should.be.false();
should.not.exist(msg.a.b);
})
it('deletes property if value is undefined', function() {
var msg = {a:{b:{c:"foo"}}};
util.setMessageProperty(msg,"msg.a.b.c",undefined);
var result = util.setMessageProperty(msg,"msg.a.b.c",undefined);
result.should.be.true();
should.not.exist(msg.a.b.c);
})
it('does not create missing parent properties if value is undefined', function() {
var msg = {a:{}};
util.setMessageProperty(msg,"msg.a.b.c",undefined);
var result = util.setMessageProperty(msg,"msg.a.b.c",undefined);
result.should.be.false();
should.not.exist(msg.a.b);
});
it('sets a property with array syntax', function() {
var msg = {a:{b:["foo",{c:["",""]}]}};
util.setMessageProperty(msg,"msg.a.b[1].c[1]","bar");
var result = util.setMessageProperty(msg,"msg.a.b[1].c[1]","bar");
result.should.be.true();
msg.a.b[1].c[1].should.eql('bar');
});
it('creates missing array elements - final property', function() {
var msg = {a:[]};
util.setMessageProperty(msg,"msg.a[2]","bar");
var result = util.setMessageProperty(msg,"msg.a[2]","bar");
result.should.be.true();
msg.a.should.have.length(3);
msg.a[2].should.eql("bar");
});
it('creates missing array elements - mid property', function() {
var msg = {};
util.setMessageProperty(msg,"msg.a[2].b","bar");
var result = util.setMessageProperty(msg,"msg.a[2].b","bar");
result.should.be.true();
msg.a.should.have.length(3);
msg.a[2].b.should.eql("bar");
});
it('creates missing array elements - multi-arrays', function() {
var msg = {};
util.setMessageProperty(msg,"msg.a[2][2]","bar");
var result = util.setMessageProperty(msg,"msg.a[2][2]","bar");
result.should.be.true();
msg.a.should.have.length(3);
msg.a.should.be.instanceOf(Array);
msg.a[2].should.have.length(3);
@ -258,19 +311,22 @@ describe("@node-red/util/util", function() {
});
it('does not create missing array elements - mid property', function () {
var msg = {a:[]};
util.setMessageProperty(msg, "msg.a[1][1]", "bar", false);
var result = util.setMessageProperty(msg, "msg.a[1][1]", "bar", false);
result.should.be.false();
msg.a.should.empty();
});
it('does not create missing array elements - final property', function() {
var msg = {a:{}};
util.setMessageProperty(msg,"msg.a.b[2]","bar",false);
var result = util.setMessageProperty(msg,"msg.a.b[2]","bar",false);
result.should.be.false();
should.not.exist(msg.a.b);
// check it has not been misinterpreted
msg.a.should.not.have.property("b[2]");
});
it('deletes property inside array if value is undefined', function() {
var msg = {a:[1,2,3]};
util.setMessageProperty(msg,"msg.a[1]",undefined);
var result = util.setMessageProperty(msg,"msg.a[1]",undefined);
result.should.be.true();
msg.a.should.have.length(2);
msg.a[0].should.eql(1);
msg.a[1].should.eql(3);
@ -511,7 +567,7 @@ describe("@node-red/util/util", function() {
result.should.eql('foo');
});
it('accesses moment from an expression', function() {
var expr = util.prepareJSONataExpression('$moment("2020-05-27", "YYYY-MM-DD").add("days", 7).add("months", 1).format("YYYY-MM-DD")',{});
var expr = util.prepareJSONataExpression('$moment("2020-05-27", "YYYY-MM-DD").add(7, "days").add(1, "months").format("YYYY-MM-DD")',{});
var result = util.evaluateJSONataExpression(expr,{});
result.should.eql('2020-07-03');
});