Parent nodes now display an error when a child node is invalid

This commit is contained in:
jos 2016-01-11 17:06:12 +01:00
parent e21aad3e69
commit 4b5ac7434f
3 changed files with 69 additions and 11 deletions

View File

@ -109,6 +109,21 @@ Node.prototype.findNode = function (jsonPath) {
return node;
};
/**
* Find all parents of this node. The parents are ordered from root node towards
* the original node.
* @return {Array.<Node>}
*/
Node.prototype.findParents = function () {
var parents = [];
var parent = this.parent;
while (parent) {
parents.unshift(parent);
parent = parent.parent;
}
return parents;
};
/**
*
* @param {{dataPath: string, keyword: string, message: string, params: Object, schemaPath: string} | null} error

View File

@ -370,17 +370,38 @@ treemode.validate = function () {
// apply all new errors
var root = this.node;
if (!valid) {
this.errorNodes = this._validate.errors
.map(function (error) {
var node = root.findNode(error.dataPath);
if (node) {
node.setError(error);
}
return node;
})
.filter(function (node) {
return node != null
});
this.errorNodes = this._validate.errors
.map(function findNode (error) {
return {
node: root.findNode(error.dataPath),
error: error
}
})
.filter(function hasNode (entry) {
return entry.node != null
})
.reduce(function expandParents (all, entry) {
// expand parents, then merge such that parents come first and
// original entries last
return entry.node
.findParents()
.map(function (parent) {
return {
node: parent,
error: {
message: parent.type === 'object'
? 'Contains invalid properties' // object
: 'Contains invalid items' // array
}
};
})
.concat(all, [entry]);
}, [])
// TODO: dedupe
.map(function setError (entry) {
entry.node.setError(entry.error);
return entry.node;
});
}
else {
this.errorNodes = [];

View File

@ -57,5 +57,27 @@ describe('util', function () {
});
describe('jsonPath', function () {
it ('should parse a json path', function () {
assert.deepEqual(util.parsePath(''), []);
assert.deepEqual(util.parsePath('.foo'), ['foo']);
assert.deepEqual(util.parsePath('.foo.bar'), ['foo', 'bar']);
assert.deepEqual(util.parsePath('.foo[2]'), ['foo', 2]);
assert.deepEqual(util.parsePath('.foo[2].bar'), ['foo', 2, 'bar']);
assert.deepEqual(util.parsePath('.foo["prop with spaces"]'), ['foo', 'prop with spaces']);
});
it ('should throw an exception in case of an invalid path', function () {
assert.throws(function () {util.parsePath('.')}, /Error/);
assert.throws(function () {util.parsePath('[')}, /Error/);
assert.throws(function () {util.parsePath('[]')}, /Error/);
assert.throws(function () {util.parsePath('.[]')}, /Error/);
assert.throws(function () {util.parsePath('["23]')}, /Error/);
assert.throws(function () {util.parsePath('.foo bar')}, /Error/);
});
});
// TODO: thoroughly test all util methods
});