Fix Node._findSchema() (#651)
* Add test setup function for simulating browser globals * Add tests for Node._findSchema Some of the tests currently fail, which will be helpful in fixing the incorrect behavior of the `_findSchema` function. The current failures are: - the last schema in the pattern properties object is always returned - when pattern properties are present, wrong object schemas are returned * Add schema-based tooltip to field names Using the `title` and `description` properties from the schema, create and set a tooltip on each field name. When the user hovers over a field name, it will show the applicable information: title, description, both, or neither, depending on what data is present in the schema. * Remove redundant setting of field name title * Remove accidental .only() from Node tests * Fix Node._findSchema for pattern properties The method now checks the key against the RegExp specified by the pattern properties instead of always returning the last pattern property in the object. * Fix path used for recursive calls in Node._findSchema * Add failing Node._findSchema tests for multi-level pattern properties * Fix Node._findSchema for schemas with properties and patternProperties
This commit is contained in:
parent
53a4f57dda
commit
f8279537d0
File diff suppressed because it is too large
Load Diff
|
@ -38,6 +38,7 @@
|
||||||
"gulp-concat-css": "2.3.0",
|
"gulp-concat-css": "2.3.0",
|
||||||
"gulp-shell": "0.6.3",
|
"gulp-shell": "0.6.3",
|
||||||
"gulp-util": "3.0.8",
|
"gulp-util": "3.0.8",
|
||||||
|
"jsdom": "^13.2.0",
|
||||||
"json-loader": "0.5.7",
|
"json-loader": "0.5.7",
|
||||||
"mkdirp": "0.5.1",
|
"mkdirp": "0.5.1",
|
||||||
"mocha": "5.2.0",
|
"mocha": "5.2.0",
|
||||||
|
|
|
@ -2610,36 +2610,39 @@ Node._findSchema = function (schema, schemaRefs, path) {
|
||||||
childSchema = allSchemas[j];
|
childSchema = allSchemas[j];
|
||||||
|
|
||||||
for (var i = 0; i < path.length && childSchema; i++) {
|
for (var i = 0; i < path.length && childSchema; i++) {
|
||||||
|
var nextPath = path.slice(i + 1, path.length);
|
||||||
var key = path[i];
|
var key = path[i];
|
||||||
|
|
||||||
// fix childSchema with $ref, and not display the select element on the child schema because of not found enum
|
// fix childSchema with $ref, and not display the select element on the child schema because of not found enum
|
||||||
if (typeof key === 'string' && childSchema['$ref']) {
|
if (typeof key === 'string' && childSchema['$ref']) {
|
||||||
childSchema = schemaRefs[childSchema['$ref']];
|
childSchema = schemaRefs[childSchema['$ref']];
|
||||||
if (childSchema) {
|
if (childSchema) {
|
||||||
foundSchema = Node._findSchema(childSchema, schemaRefs, path.slice(i, path.length));
|
foundSchema = Node._findSchema(childSchema, schemaRefs, nextPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (typeof key === 'string' && childSchema.patternProperties && i == path.length - 1) {
|
else if (typeof key === 'string' && childSchema.patternProperties && !(childSchema.properties && key in childSchema.properties)) {
|
||||||
for (var prop in childSchema.patternProperties) {
|
for (var prop in childSchema.patternProperties) {
|
||||||
foundSchema = Node._findSchema(childSchema.patternProperties[prop], schemaRefs, path.slice(i, path.length));
|
if (key.match(prop)) {
|
||||||
|
foundSchema = Node._findSchema(childSchema.patternProperties[prop], schemaRefs, nextPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (childSchema.items && childSchema.items.properties) {
|
else if (childSchema.items && childSchema.items.properties) {
|
||||||
childSchema = childSchema.items.properties[key];
|
childSchema = childSchema.items.properties[key];
|
||||||
if (childSchema) {
|
if (childSchema) {
|
||||||
foundSchema = Node._findSchema(childSchema, schemaRefs, path.slice(i, path.length));
|
foundSchema = Node._findSchema(childSchema, schemaRefs, nextPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (typeof key === 'string' && childSchema.properties) {
|
else if (typeof key === 'string' && childSchema.properties) {
|
||||||
childSchema = childSchema.properties[key] || null;
|
childSchema = childSchema.properties[key] || null;
|
||||||
if (childSchema) {
|
if (childSchema) {
|
||||||
foundSchema = Node._findSchema(childSchema, schemaRefs, path.slice(i, path.length));
|
foundSchema = Node._findSchema(childSchema, schemaRefs, nextPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (typeof key === 'number' && childSchema.items) {
|
else if (typeof key === 'number' && childSchema.items) {
|
||||||
childSchema = childSchema.items;
|
childSchema = childSchema.items;
|
||||||
if (childSchema) {
|
if (childSchema) {
|
||||||
foundSchema = Node._findSchema(childSchema, schemaRefs, path.slice(i, path.length));
|
foundSchema = Node._findSchema(childSchema, schemaRefs, nextPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,198 @@
|
||||||
|
var assert = require('assert');
|
||||||
|
var setUpTestEnvironment = require('./setup');
|
||||||
|
setUpTestEnvironment();
|
||||||
|
|
||||||
|
var JSONEditor = require('../src/js/JSONEditor');
|
||||||
|
var Node = require('../src/js/Node');
|
||||||
|
|
||||||
|
describe('Node', function () {
|
||||||
|
var node;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
var editor = new JSONEditor(document.createElement('foo'));
|
||||||
|
node = new Node(editor);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_findSchema', function () {
|
||||||
|
it('should find schema', function () {
|
||||||
|
var schema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
child: {
|
||||||
|
type: 'string'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var path = ['child'];
|
||||||
|
assert.strictEqual(Node._findSchema(schema, {}, path), schema.properties.child);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find schema within multi-level object properties', function () {
|
||||||
|
var schema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
levelTwo: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
levelThree: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
bool: {
|
||||||
|
type: 'boolean'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var path = [];
|
||||||
|
assert.strictEqual(Node._findSchema(schema, {}, path), schema);
|
||||||
|
path = ['levelTwo'];
|
||||||
|
assert.strictEqual(Node._findSchema(schema, {}, path), schema.properties.levelTwo);
|
||||||
|
path = ['levelTwo', 'levelThree'];
|
||||||
|
assert.strictEqual(Node._findSchema(schema, {}, path), schema.properties.levelTwo.properties.levelThree);
|
||||||
|
path = ['levelTwo', 'levelThree', 'bool'];
|
||||||
|
assert.strictEqual(
|
||||||
|
Node._findSchema(schema, {}, path),
|
||||||
|
schema.properties.levelTwo.properties.levelThree.properties.bool
|
||||||
|
);
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('with pattern properties', function () {
|
||||||
|
it('should find schema', function () {
|
||||||
|
var schema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
str: {
|
||||||
|
title: 'str',
|
||||||
|
type: 'boolean'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
patternProperties: {
|
||||||
|
'^foo[0-9]': {
|
||||||
|
title: 'foo[0-] pattern property',
|
||||||
|
type: 'string'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var path = [];
|
||||||
|
assert.strictEqual(Node._findSchema(schema, {}, path), schema, 'top level');
|
||||||
|
path = ['str'];
|
||||||
|
assert.strictEqual(Node._findSchema(schema, {}, path), schema.properties.str, 'normal property');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find schema within multi-level object properties', function () {
|
||||||
|
var schema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
levelTwo: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
levelThree: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
bool: {
|
||||||
|
title: 'bool',
|
||||||
|
type: 'boolean'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
patternProperties: {
|
||||||
|
'^foo[0-9]': {
|
||||||
|
title: 'foo[0-9] pattern property',
|
||||||
|
type: 'string'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var path = [];
|
||||||
|
assert.strictEqual(Node._findSchema(schema, {}, path), schema, 'top level');
|
||||||
|
path = ['levelTwo'];
|
||||||
|
assert.strictEqual(Node._findSchema(schema, {}, path), schema.properties.levelTwo, 'level two');
|
||||||
|
path = ['levelTwo', 'levelThree'];
|
||||||
|
assert.strictEqual(Node._findSchema(schema, {}, path), schema.properties.levelTwo.properties.levelThree, 'level three');
|
||||||
|
path = ['levelTwo', 'levelThree', 'bool'];
|
||||||
|
assert.strictEqual(
|
||||||
|
Node._findSchema(schema, {}, path),
|
||||||
|
schema.properties.levelTwo.properties.levelThree.properties.bool,
|
||||||
|
'normal property'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find schema for pattern properties', function () {
|
||||||
|
var schema = {
|
||||||
|
type: 'object',
|
||||||
|
patternProperties: {
|
||||||
|
'^foo[0-9]': {
|
||||||
|
title: 'foo[0-9] pattern property',
|
||||||
|
type: 'string'
|
||||||
|
},
|
||||||
|
'^bar[0-9]': {
|
||||||
|
title: 'bar[0-9] pattern property',
|
||||||
|
type: 'string'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var path = ['foo1'];
|
||||||
|
assert.strictEqual(
|
||||||
|
Node._findSchema(schema, {}, path),
|
||||||
|
schema.patternProperties['^foo[0-9]'],
|
||||||
|
'first pattern property'
|
||||||
|
);
|
||||||
|
path = ['bar5'];
|
||||||
|
assert.strictEqual(
|
||||||
|
Node._findSchema(schema, {}, path),
|
||||||
|
schema.patternProperties['^bar[0-9]'],
|
||||||
|
'second pattern property'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should find schema for multi-level pattern properties', function () {
|
||||||
|
var schema = {
|
||||||
|
type: 'object',
|
||||||
|
patternProperties: {
|
||||||
|
'^foo[0-9]': {
|
||||||
|
title: 'foo[0-9] pattern property',
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
fooChild: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
fooChild2: {
|
||||||
|
type: 'string'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'^bar[0-9]': {
|
||||||
|
title: 'bar[0-9] pattern property',
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
barChild: {
|
||||||
|
type: 'string'
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var path = ['foo1', 'fooChild', 'fooChild2'];
|
||||||
|
assert.strictEqual(
|
||||||
|
Node._findSchema(schema, {}, path),
|
||||||
|
schema.patternProperties['^foo[0-9]'].properties.fooChild.properties.fooChild2,
|
||||||
|
'first pattern property child of child'
|
||||||
|
);
|
||||||
|
path = ['bar5', 'barChild'];
|
||||||
|
assert.strictEqual(
|
||||||
|
Node._findSchema(schema, {}, path),
|
||||||
|
schema.patternProperties['^bar[0-9]'].properties.barChild,
|
||||||
|
'second pattern property child'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,11 @@
|
||||||
|
var JSDOM = require('jsdom').JSDOM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the test environment by simulating browser globals.
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
module.exports = function setUpTestEnvironment() {
|
||||||
|
var dom = new JSDOM('...');
|
||||||
|
global.window = dom.window;
|
||||||
|
global.document = dom.window.document;
|
||||||
|
};
|
Loading…
Reference in New Issue