You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							362 lines
						
					
					
						
							5.4 KiB
						
					
					
				
			
		
		
	
	
							362 lines
						
					
					
						
							5.4 KiB
						
					
					
				'use strict'
 | 
						|
 | 
						|
const test = require('tap').test
 | 
						|
const validator = require('is-my-json-valid')
 | 
						|
const build = require('..')
 | 
						|
 | 
						|
function buildTest (schema, toStringify) {
 | 
						|
  test(`render a ${schema.title} as JSON`, (t) => {
 | 
						|
    t.plan(3)
 | 
						|
 | 
						|
    const validate = validator(schema)
 | 
						|
    const stringify = build(schema)
 | 
						|
    const output = stringify(toStringify)
 | 
						|
 | 
						|
    t.same(JSON.parse(output), toStringify)
 | 
						|
    t.equal(output, JSON.stringify(toStringify))
 | 
						|
    t.ok(validate(JSON.parse(output)), 'valid schema')
 | 
						|
  })
 | 
						|
}
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'basic',
 | 
						|
  type: 'object',
 | 
						|
  properties: {
 | 
						|
    firstName: {
 | 
						|
      type: 'string'
 | 
						|
    },
 | 
						|
    lastName: {
 | 
						|
      type: 'string'
 | 
						|
    },
 | 
						|
    age: {
 | 
						|
      description: 'Age in years',
 | 
						|
      type: 'integer',
 | 
						|
      minimum: 0
 | 
						|
    },
 | 
						|
    magic: {
 | 
						|
      type: 'number'
 | 
						|
    }
 | 
						|
  },
 | 
						|
  required: ['firstName', 'lastName']
 | 
						|
}, {
 | 
						|
  firstName: 'Matteo',
 | 
						|
  lastName: 'Collina',
 | 
						|
  age: 32,
 | 
						|
  magic: 42.42
 | 
						|
})
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'string',
 | 
						|
  type: 'string'
 | 
						|
}, 'hello world')
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'string',
 | 
						|
  type: 'string'
 | 
						|
}, 'hello\nworld')
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'string with quotes',
 | 
						|
  type: 'string'
 | 
						|
}, 'hello """" world')
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'boolean true',
 | 
						|
  type: 'boolean'
 | 
						|
}, true)
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'boolean false',
 | 
						|
  type: 'boolean'
 | 
						|
}, false)
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'an integer',
 | 
						|
  type: 'integer'
 | 
						|
}, 42)
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'a number',
 | 
						|
  type: 'number'
 | 
						|
}, 42.42)
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'deep',
 | 
						|
  type: 'object',
 | 
						|
  properties: {
 | 
						|
    firstName: {
 | 
						|
      type: 'string'
 | 
						|
    },
 | 
						|
    lastName: {
 | 
						|
      type: 'string'
 | 
						|
    },
 | 
						|
    more: {
 | 
						|
      description: 'more properties',
 | 
						|
      type: 'object',
 | 
						|
      properties: {
 | 
						|
        something: {
 | 
						|
          type: 'string'
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}, {
 | 
						|
  firstName: 'Matteo',
 | 
						|
  lastName: 'Collina',
 | 
						|
  more: {
 | 
						|
    something: 'else'
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'null',
 | 
						|
  type: 'null'
 | 
						|
}, null)
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'deep object with weird keys',
 | 
						|
  type: 'object',
 | 
						|
  properties: {
 | 
						|
    '@version': {
 | 
						|
      type: 'integer'
 | 
						|
    }
 | 
						|
  }
 | 
						|
}, {
 | 
						|
  '@version': 1
 | 
						|
})
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'deep object with weird keys of type object',
 | 
						|
  type: 'object',
 | 
						|
  properties: {
 | 
						|
    '@data': {
 | 
						|
      type: 'object',
 | 
						|
      properties: {
 | 
						|
        id: {
 | 
						|
          type: 'string'
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}, {
 | 
						|
  '@data': {
 | 
						|
    id: 'string'
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'deep object with spaces in key',
 | 
						|
  type: 'object',
 | 
						|
  properties: {
 | 
						|
    'spaces in key': {
 | 
						|
      type: 'object',
 | 
						|
      properties: {
 | 
						|
        something: {
 | 
						|
          type: 'integer'
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}, {
 | 
						|
  'spaces in key': {
 | 
						|
    something: 1
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'with null',
 | 
						|
  type: 'object',
 | 
						|
  properties: {
 | 
						|
    firstName: {
 | 
						|
      type: 'null'
 | 
						|
    }
 | 
						|
  }
 | 
						|
}, {
 | 
						|
  firstName: null
 | 
						|
})
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'array with objects',
 | 
						|
  type: 'array',
 | 
						|
  items: {
 | 
						|
    type: 'object',
 | 
						|
    properties: {
 | 
						|
      name: {
 | 
						|
        type: 'string'
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}, [{
 | 
						|
  name: 'Matteo'
 | 
						|
}, {
 | 
						|
  name: 'Dave'
 | 
						|
}])
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'array with strings',
 | 
						|
  type: 'array',
 | 
						|
  items: {
 | 
						|
    type: 'string'
 | 
						|
  }
 | 
						|
}, [
 | 
						|
  'Matteo',
 | 
						|
  'Dave'
 | 
						|
])
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'array with numbers',
 | 
						|
  type: 'array',
 | 
						|
  items: {
 | 
						|
    type: 'number'
 | 
						|
  }
 | 
						|
}, [
 | 
						|
  42.42,
 | 
						|
  24
 | 
						|
])
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'array with integers',
 | 
						|
  type: 'array',
 | 
						|
  items: {
 | 
						|
    type: 'number'
 | 
						|
  }
 | 
						|
}, [
 | 
						|
  42,
 | 
						|
  24
 | 
						|
])
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'nested array with objects',
 | 
						|
  type: 'object',
 | 
						|
  properties: {
 | 
						|
    data: {
 | 
						|
      type: 'array',
 | 
						|
      items: {
 | 
						|
        type: 'object',
 | 
						|
        properties: {
 | 
						|
          name: {
 | 
						|
            type: 'string'
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}, {
 | 
						|
  data: [{
 | 
						|
    name: 'Matteo'
 | 
						|
  }, {
 | 
						|
    name: 'Dave'
 | 
						|
  }]
 | 
						|
})
 | 
						|
 | 
						|
buildTest({
 | 
						|
  title: 'object with boolean',
 | 
						|
  type: 'object',
 | 
						|
  properties: {
 | 
						|
    readonly: {
 | 
						|
      type: 'boolean'
 | 
						|
    }
 | 
						|
  }
 | 
						|
}, {
 | 
						|
  readonly: true
 | 
						|
})
 | 
						|
 | 
						|
test('skip or coerce numbers and integers that are not numbers', (t) => {
 | 
						|
  const stringify = build({
 | 
						|
    title: 'basic',
 | 
						|
    type: 'object',
 | 
						|
    properties: {
 | 
						|
      age: {
 | 
						|
        type: 'number'
 | 
						|
      },
 | 
						|
      distance: {
 | 
						|
        type: 'integer'
 | 
						|
      }
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  let result = stringify({
 | 
						|
    age: 'hello  ',
 | 
						|
    distance: 'long'
 | 
						|
  })
 | 
						|
 | 
						|
  t.same(JSON.parse(result), {})
 | 
						|
 | 
						|
  result = stringify({
 | 
						|
    age: '42',
 | 
						|
    distance: true
 | 
						|
  })
 | 
						|
 | 
						|
  t.same(JSON.parse(result), { age: 42, distance: 1 })
 | 
						|
  t.end()
 | 
						|
})
 | 
						|
 | 
						|
test('Should throw on invalid schema', t => {
 | 
						|
  t.plan(1)
 | 
						|
  try {
 | 
						|
    build({
 | 
						|
      type: 'Dinosaur',
 | 
						|
      properties: {
 | 
						|
        claws: { type: 'sharp' }
 | 
						|
      }
 | 
						|
    })
 | 
						|
    t.fail('should be an invalid schema')
 | 
						|
  } catch (err) {
 | 
						|
    t.ok(err)
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
test('additionalProperties - throw on unknown type', (t) => {
 | 
						|
  t.plan(1)
 | 
						|
 | 
						|
  try {
 | 
						|
    build({
 | 
						|
      title: 'check array coerce',
 | 
						|
      type: 'object',
 | 
						|
      properties: {},
 | 
						|
      additionalProperties: {
 | 
						|
        type: 'strangetype'
 | 
						|
      }
 | 
						|
    })
 | 
						|
    t.fail('should be an invalid schema')
 | 
						|
  } catch (err) {
 | 
						|
    t.ok(err)
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
test('patternProperties - throw on unknown type', (t) => {
 | 
						|
  t.plan(1)
 | 
						|
 | 
						|
  try {
 | 
						|
    build({
 | 
						|
      title: 'check array coerce',
 | 
						|
      type: 'object',
 | 
						|
      properties: {},
 | 
						|
      patternProperties: {
 | 
						|
        foo: {
 | 
						|
          type: 'strangetype'
 | 
						|
        }
 | 
						|
      }
 | 
						|
    })
 | 
						|
    t.fail('should be an invalid schema')
 | 
						|
  } catch (err) {
 | 
						|
    t.ok(err)
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
test('render a single quote as JSON', (t) => {
 | 
						|
  t.plan(2)
 | 
						|
 | 
						|
  const schema = {
 | 
						|
    type: 'string'
 | 
						|
  }
 | 
						|
  const toStringify = '" double quote'
 | 
						|
 | 
						|
  const validate = validator(schema)
 | 
						|
  const stringify = build(schema)
 | 
						|
  const output = stringify(toStringify)
 | 
						|
 | 
						|
  t.equal(output, JSON.stringify(toStringify))
 | 
						|
  t.ok(validate(JSON.parse(output)), 'valid schema')
 | 
						|
})
 |