diff --git a/src/js/Node.js b/src/js/Node.js index aabf1ee01..a8e82297a 100644 --- a/src/js/Node.js +++ b/src/js/Node.js @@ -4482,7 +4482,12 @@ Node._findSchema = (topLevelSchema, schemaRefs, path, currentSchema = topLevelSc if (schemaUrl in schemaRefs) { const referencedSchema = schemaRefs[schemaUrl] const reference = { $ref: '#/'.concat(relativePath) } - return Node._findSchema(referencedSchema, schemaRefs, nextPath, reference) + const auxNextPath = [] + auxNextPath.push(nextKey) + if (nextPath.length > 0) { + auxNextPath.push(...nextPath) + } + return Node._findSchema(referencedSchema, schemaRefs, auxNextPath, reference) } else { throw Error(`Unable to resolve reference ${ref}`) } diff --git a/test/Node.test.js b/test/Node.test.js index 70b43298f..181b6fbd9 100644 --- a/test/Node.test.js +++ b/test/Node.test.js @@ -77,6 +77,69 @@ describe('Node', () => { ) }) + it('should find referenced schema within multi-level object properties', () => { + const schema = { + type: 'object', + properties: { + aProperty: { + $ref: 'second_schema#/definitions/some_def' + } + } + } + const schemaRefs = { + second_schema: { + definitions: { + some_def: { + type: 'object', + properties: { + enumProp: { + enum: [1, 2, 3] + } + } + } + } + } + } + const path = ['aProperty', 'enumProp'] + const expectedSchema = { + enum: [1, 2, 3] + } + assert.deepStrictEqual(Node._findSchema(schema, schemaRefs, path), expectedSchema) + }) + + it('should find array referenced schema within multi-level object properties', () => { + const schema = { + type: 'object', + properties: { + aProperty: { + type: 'array', + items: { + $ref: 'second_schema#/definitions/some_def' + } + } + } + } + const schemaRefs = { + second_schema: { + definitions: { + some_def: { + type: 'object', + properties: { + enumProp: { + enum: [1, 2, 3] + } + } + } + } + } + } + const path = ['aProperty', 0, 'enumProp'] + const expectedSchema = { + enum: [1, 2, 3] + } + assert.deepStrictEqual(Node._findSchema(schema, schemaRefs, path), expectedSchema) + }) + it('should return null for path that has no schema', () => { const schema = { type: 'object', @@ -152,6 +215,121 @@ describe('Node', () => { const path = ['foo'] assert.strictEqual(Node._findSchema(schema, { foo: fooSchema }, path), fooSchema) }) + + it('should find a referenced schema property', () => { + const schema = { + type: 'object', + properties: { + foo: { + $ref: 'foo' + } + } + } + const fooSchema = { + type: 'object', + properties: { + levelTwo: { + type: 'string' + } + } + } + const path = ['foo', 'levelTwo'] + assert.strictEqual(Node._findSchema(schema, { foo: fooSchema }, path), fooSchema.properties.levelTwo) + }) + + it('should find a referenced schema definition', () => { + const schema = { + type: 'object', + properties: { + foo: { + type: 'array', + items: { + $ref: 'foo#/definitions/some_def' + } + } + } + } + const fooSchema = { + definitions: { + some_def: { + type: 'object', + properties: { + propA: { + type: 'string' + }, + propB: { + type: 'string' + } + } + } + } + } + const path = ['foo', 0] + assert.strictEqual(Node._findSchema(schema, { foo: fooSchema }, path), fooSchema.definitions.some_def) + }) + + it('should find a referenced schema definition 2', () => { + const schema = { + type: 'object', + properties: { + foo: { + type: 'array', + items: { + $ref: 'foo#/definitions/some_def' + } + } + } + } + const fooSchema = { + definitions: { + some_def: { + type: 'object', + properties: { + propA: { + type: 'string' + }, + propB: { + type: 'string' + } + } + } + } + } + const path = ['foo', 0, 'propA'] + assert.strictEqual(Node._findSchema(schema, { foo: fooSchema }, path), fooSchema.definitions.some_def.properties.propA) + }) + + it('should find a referenced schema definition 3', () => { + const schema = { + type: 'object', + properties: { + foo: { + type: 'array', + items: { + $ref: 'foo#/definitions/some_def' + } + } + } + } + const fooSchema = { + definitions: { + some_def: { + type: 'object', + properties: { + propA: { + type: 'object', + properties: { + propA1: { type: 'boolean' } + } + }, + propB: { type: 'string' } + } + } + } + } + const path = ['foo', 0, 'propA', 'propA1'] + assert.strictEqual(Node._findSchema(schema, { foo: fooSchema }, path), fooSchema.definitions.some_def.properties.propA.properties.propA1) + }) }) describe('with $ref to internal definition', () => { @@ -423,4 +601,13 @@ describe('Node', () => { }) }) }) + describe('_findEnum', () => { + it('should find enum', () => { + const schema = { + type: 'object', + enum: [1, 2, 3] + } + assert.strictEqual(Node._findEnum(schema), schema.enum) + }) + }) }) diff --git a/test/test_enum.html b/test/test_enum.html new file mode 100644 index 000000000..399f88d3b --- /dev/null +++ b/test/test_enum.html @@ -0,0 +1,62 @@ + + + + JSONEditor | template + enums + + + + + + + + +
+ + + + diff --git a/test/test_enum_2.html b/test/test_enum_2.html new file mode 100644 index 000000000..6f27f033f --- /dev/null +++ b/test/test_enum_2.html @@ -0,0 +1,123 @@ + + + + JSONEditor | template + enums + + + + + + + +

Demonstrates a template with JSON schema validation. To use: click the context menu of the first or second employee, click insert or append, click "Employee".

+

See github issue #473

+ +
+ + + +