fatsify核心功能示例测试!!!

This commit is contained in:
2025-09-21 14:50:41 +08:00
commit 9145aea047
1958 changed files with 230098 additions and 0 deletions

View File

@@ -0,0 +1,332 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('additionalProperties', (t) => {
t.plan(1)
const stringify = build({
title: 'additionalProperties',
type: 'object',
properties: {
str: {
type: 'string'
}
},
additionalProperties: {
type: 'string'
}
})
const obj = { str: 'test', foo: 42, ofoo: true, foof: 'string', objfoo: { a: true } }
t.assert.equal(stringify(obj), '{"str":"test","foo":"42","ofoo":"true","foof":"string","objfoo":"[object Object]"}')
})
test('additionalProperties should not change properties', (t) => {
t.plan(1)
const stringify = build({
title: 'patternProperties should not change properties',
type: 'object',
properties: {
foo: {
type: 'string'
}
},
additionalProperties: {
type: 'number'
}
})
const obj = { foo: '42', ofoo: 42 }
t.assert.equal(stringify(obj), '{"foo":"42","ofoo":42}')
})
test('additionalProperties should not change properties and patternProperties', (t) => {
t.plan(1)
const stringify = build({
title: 'patternProperties should not change properties',
type: 'object',
properties: {
foo: {
type: 'string'
}
},
patternProperties: {
foo: {
type: 'string'
}
},
additionalProperties: {
type: 'number'
}
})
const obj = { foo: '42', ofoo: 42, test: '42' }
t.assert.equal(stringify(obj), '{"foo":"42","ofoo":"42","test":42}')
})
test('additionalProperties set to true, use of fast-safe-stringify', (t) => {
t.plan(1)
const stringify = build({
title: 'check string coerce',
type: 'object',
properties: {},
additionalProperties: true
})
const obj = { foo: true, ofoo: 42, arrfoo: ['array', 'test'], objfoo: { a: 'world' } }
t.assert.equal(stringify(obj), '{"foo":true,"ofoo":42,"arrfoo":["array","test"],"objfoo":{"a":"world"}}')
})
test('additionalProperties - string coerce', (t) => {
t.plan(1)
const stringify = build({
title: 'check string coerce',
type: 'object',
properties: {},
additionalProperties: {
type: 'string'
}
})
const obj = { foo: true, ofoo: 42, arrfoo: ['array', 'test'], objfoo: { a: 'world' } }
t.assert.equal(stringify(obj), '{"foo":"true","ofoo":"42","arrfoo":"array,test","objfoo":"[object Object]"}')
})
test('additionalProperties - number skip', (t) => {
t.plan(1)
const stringify = build({
title: 'check number coerce',
type: 'object',
properties: {},
additionalProperties: {
type: 'number'
}
})
// const obj = { foo: true, ofoo: '42', xfoo: 'string', arrfoo: [1, 2], objfoo: { num: 42 } }
const obj = { foo: true, ofoo: '42' }
t.assert.equal(stringify(obj), '{"foo":1,"ofoo":42}')
})
test('additionalProperties - boolean coerce', (t) => {
t.plan(1)
const stringify = build({
title: 'check boolean coerce',
type: 'object',
properties: {},
additionalProperties: {
type: 'boolean'
}
})
const obj = { foo: 'true', ofoo: 0, arrfoo: [1, 2], objfoo: { a: true } }
t.assert.equal(stringify(obj), '{"foo":true,"ofoo":false,"arrfoo":true,"objfoo":true}')
})
test('additionalProperties - object coerce', (t) => {
t.plan(1)
const stringify = build({
title: 'check object coerce',
type: 'object',
properties: {},
additionalProperties: {
type: 'object',
properties: {
answer: {
type: 'number'
}
}
}
})
const obj = { objfoo: { answer: 42 } }
t.assert.equal(stringify(obj), '{"objfoo":{"answer":42}}')
})
test('additionalProperties - array coerce', (t) => {
t.plan(2)
const stringify = build({
title: 'check array coerce',
type: 'object',
properties: {},
additionalProperties: {
type: 'array',
items: {
type: 'string'
}
}
})
const coercibleValues = { arrfoo: [1, 2] }
t.assert.equal(stringify(coercibleValues), '{"arrfoo":["1","2"]}')
const incoercibleValues = { foo: 'true', ofoo: 0, objfoo: { tyrion: 'lannister' } }
t.assert.throws(() => stringify(incoercibleValues))
})
test('additionalProperties with empty schema', (t) => {
t.plan(1)
const stringify = build({
type: 'object',
additionalProperties: {}
})
const obj = { a: 1, b: true, c: null }
t.assert.equal(stringify(obj), '{"a":1,"b":true,"c":null}')
})
test('additionalProperties with nested empty schema', (t) => {
t.plan(1)
const stringify = build({
type: 'object',
properties: {
data: { type: 'object', additionalProperties: {} }
},
required: ['data']
})
const obj = { data: { a: 1, b: true, c: null } }
t.assert.equal(stringify(obj), '{"data":{"a":1,"b":true,"c":null}}')
})
test('nested additionalProperties', (t) => {
t.plan(1)
const stringify = build({
title: 'additionalProperties',
type: 'array',
items: {
type: 'object',
properties: {
ap: {
type: 'object',
additionalProperties: { type: 'string' }
}
}
}
})
const obj = [{ ap: { value: 'string' } }]
t.assert.equal(stringify(obj), '[{"ap":{"value":"string"}}]')
})
test('very nested additionalProperties', (t) => {
t.plan(1)
const stringify = build({
title: 'additionalProperties',
type: 'array',
items: {
type: 'object',
properties: {
ap: {
type: 'object',
properties: {
nested: {
type: 'object',
properties: {
moarNested: {
type: 'object',
properties: {
finally: {
type: 'object',
additionalProperties: {
type: 'string'
}
}
}
}
}
}
}
}
}
}
})
const obj = [{ ap: { nested: { moarNested: { finally: { value: 'str' } } } } }]
t.assert.equal(stringify(obj), '[{"ap":{"nested":{"moarNested":{"finally":{"value":"str"}}}}}]')
})
test('nested additionalProperties set to true', (t) => {
t.plan(1)
const stringify = build({
title: 'nested additionalProperties=true',
type: 'object',
properties: {
ap: {
type: 'object',
additionalProperties: true
}
}
})
const obj = { ap: { value: 'string', someNumber: 42 } }
t.assert.equal(stringify(obj), '{"ap":{"value":"string","someNumber":42}}')
})
test('field passed to fastSafeStringify as undefined should be removed', (t) => {
t.plan(1)
const stringify = build({
title: 'nested additionalProperties=true',
type: 'object',
properties: {
ap: {
type: 'object',
additionalProperties: true
}
}
})
const obj = { ap: { value: 'string', someNumber: undefined } }
t.assert.equal(stringify(obj), '{"ap":{"value":"string"}}')
})
test('property without type but with enum, will acts as additionalProperties', (t) => {
t.plan(1)
const stringify = build({
title: 'automatic additionalProperties',
type: 'object',
properties: {
ap: {
enum: ['foobar', 42, ['foo', 'bar'], {}]
}
}
})
const obj = { ap: { additional: 'field' } }
t.assert.equal(stringify(obj), '{"ap":{"additional":"field"}}')
})
test('property without type but with enum, will acts as additionalProperties without overwriting', (t) => {
t.plan(1)
const stringify = build({
title: 'automatic additionalProperties',
type: 'object',
properties: {
ap: {
additionalProperties: false,
enum: ['foobar', 42, ['foo', 'bar'], {}]
}
}
})
const obj = { ap: { additional: 'field' } }
t.assert.equal(stringify(obj), '{"ap":{}}')
})
test('function and symbol references are not serialized as undefined', (t) => {
t.plan(1)
const stringify = build({
title: 'additionalProperties',
type: 'object',
additionalProperties: true,
properties: {
str: {
type: 'string'
}
}
})
const obj = { str: 'x', test: 'test', meth: () => 'x', sym: Symbol('x') }
t.assert.equal(stringify(obj), '{"str":"x","test":"test"}')
})

751
node_modules/fast-json-stringify/test/allof.test.js generated vendored Normal file
View File

@@ -0,0 +1,751 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
process.env.TZ = 'UTC'
test('allOf: combine type and format ', (t) => {
t.plan(1)
const schema = {
allOf: [
{ type: 'string' },
{ format: 'time' }
]
}
const stringify = build(schema)
const date = new Date(1674263005800)
const value = stringify(date)
t.assert.equal(value, '"01:03:25"')
})
test('allOf: combine additional properties ', (t) => {
t.plan(1)
const schema = {
allOf: [
{ type: 'object' },
{
type: 'object',
additionalProperties: { type: 'boolean' }
}
]
}
const stringify = build(schema)
const data = { property: true }
const value = stringify(data)
t.assert.equal(value, JSON.stringify(data))
})
test('allOf: combine pattern properties', (t) => {
t.plan(1)
const schema = {
allOf: [
{ type: 'object' },
{
type: 'object',
patternProperties: {
foo: {
type: 'number'
}
}
}
]
}
const stringify = build(schema)
const data = { foo: 42 }
const value = stringify(data)
t.assert.equal(value, JSON.stringify(data))
})
test('object with allOf and multiple schema on the allOf', (t) => {
t.plan(4)
const schema = {
title: 'object with allOf and multiple schema on the allOf',
type: 'object',
allOf: [
{
type: 'object',
required: [
'name'
],
properties: {
name: {
type: 'string'
},
tag: {
type: 'string'
}
}
},
{
required: [
'id'
],
type: 'object',
properties: {
id: {
type: 'integer'
}
}
}
]
}
const stringify = build(schema)
try {
stringify({
id: 1
})
} catch (e) {
t.assert.equal(e.message, '"name" is required!')
}
try {
stringify({
name: 'string'
})
} catch (e) {
t.assert.equal(e.message, '"id" is required!')
}
t.assert.equal(stringify({
id: 1,
name: 'string'
}), '{"name":"string","id":1}')
t.assert.equal(stringify({
id: 1,
name: 'string',
tag: 'otherString'
}), '{"name":"string","id":1,"tag":"otherString"}')
})
test('object with allOf and one schema on the allOf', (t) => {
t.plan(1)
const schema = {
title: 'object with allOf and one schema on the allOf',
type: 'object',
allOf: [
{
required: [
'id'
],
type: 'object',
properties: {
id: {
type: 'integer'
}
}
}
]
}
const stringify = build(schema)
const value = stringify({
id: 1
})
t.assert.equal(value, '{"id":1}')
})
test('object with allOf and no schema on the allOf', (t) => {
t.plan(1)
const schema = {
title: 'object with allOf and no schema on the allOf',
type: 'object',
allOf: []
}
try {
build(schema)
t.fail()
} catch (e) {
t.assert.equal(e.message, 'schema is invalid: data/allOf must NOT have fewer than 1 items')
}
})
test('object with nested allOfs', (t) => {
t.plan(1)
const schema = {
title: 'object with nested allOfs',
type: 'object',
allOf: [
{
required: [
'id1'
],
type: 'object',
properties: {
id1: {
type: 'integer'
}
}
},
{
allOf: [
{
type: 'object',
properties: {
id2: {
type: 'integer'
}
}
},
{
type: 'object',
properties: {
id3: {
type: 'integer'
}
}
}
]
}
]
}
const stringify = build(schema)
const value = stringify({
id1: 1,
id2: 2,
id3: 3,
id4: 4 // extra prop shouldn't be in result
})
t.assert.equal(value, '{"id1":1,"id2":2,"id3":3}')
})
test('object with anyOf nested inside allOf', (t) => {
t.plan(1)
const schema = {
title: 'object with anyOf nested inside allOf',
type: 'object',
allOf: [
{
required: ['id1', 'obj'],
type: 'object',
properties: {
id1: {
type: 'integer'
},
obj: {
type: 'object',
properties: {
nested: { type: 'string' }
}
}
}
},
{
anyOf: [
{
type: 'object',
properties: {
id2: { type: 'string' }
},
required: ['id2']
},
{
type: 'object',
properties: {
id3: {
type: 'integer'
},
nestedObj: {
type: 'object',
properties: {
nested: { type: 'string' }
}
}
},
required: ['id3']
},
{
type: 'object',
properties: {
id4: { type: 'integer' }
},
required: ['id4']
}
]
}
]
}
const stringify = build(schema)
const value = stringify({
id1: 1,
id3: 3,
id4: 4, // extra prop shouldn't be in result
obj: { nested: 'yes' },
nestedObj: { nested: 'yes' }
})
t.assert.equal(value, '{"id1":1,"obj":{"nested":"yes"},"id3":3,"nestedObj":{"nested":"yes"}}')
})
test('object with $ref in allOf', (t) => {
t.plan(1)
const schema = {
title: 'object with $ref in allOf',
type: 'object',
definitions: {
id1: {
type: 'object',
properties: {
id1: {
type: 'integer'
}
}
}
},
allOf: [
{
$ref: '#/definitions/id1'
}
]
}
const stringify = build(schema)
const value = stringify({
id1: 1,
id2: 2 // extra prop shouldn't be in result
})
t.assert.equal(value, '{"id1":1}')
})
test('object with $ref and other object in allOf', (t) => {
t.plan(1)
const schema = {
title: 'object with $ref in allOf',
type: 'object',
definitions: {
id1: {
type: 'object',
properties: {
id1: {
type: 'integer'
}
}
}
},
allOf: [
{
$ref: '#/definitions/id1'
},
{
type: 'object',
properties: {
id2: {
type: 'integer'
}
}
}
]
}
const stringify = build(schema)
const value = stringify({
id1: 1,
id2: 2,
id3: 3 // extra prop shouldn't be in result
})
t.assert.equal(value, '{"id1":1,"id2":2}')
})
test('object with multiple $refs in allOf', (t) => {
t.plan(1)
const schema = {
title: 'object with $ref in allOf',
type: 'object',
definitions: {
id1: {
type: 'object',
properties: {
id1: {
type: 'integer'
}
}
},
id2: {
type: 'object',
properties: {
id2: {
type: 'integer'
}
}
}
},
allOf: [
{
$ref: '#/definitions/id1'
},
{
$ref: '#/definitions/id2'
}
]
}
const stringify = build(schema)
const value = stringify({
id1: 1,
id2: 2,
id3: 3 // extra prop shouldn't be in result
})
t.assert.equal(value, '{"id1":1,"id2":2}')
})
test('allOf with nested allOf in $ref', (t) => {
t.plan(1)
const schema = {
title: 'allOf with nested allOf in $ref',
type: 'object',
definitions: {
group: {
type: 'object',
allOf: [{
properties: {
id2: {
type: 'integer'
}
}
}, {
properties: {
id3: {
type: 'integer'
}
}
}]
}
},
allOf: [
{
type: 'object',
properties: {
id1: {
type: 'integer'
}
},
required: [
'id1'
]
},
{
$ref: '#/definitions/group'
}
]
}
const stringify = build(schema)
const value = stringify({
id1: 1,
id2: 2,
id3: 3,
id4: 4 // extra prop shouldn't be in result
})
t.assert.equal(value, '{"id1":1,"id2":2,"id3":3}')
})
test('object with external $refs in allOf', (t) => {
t.plan(1)
const externalSchema = {
first: {
definitions: {
id1: {
type: 'object',
properties: {
id1: {
type: 'integer'
}
}
}
}
},
second: {
definitions: {
id2: {
$id: '#id2',
type: 'object',
properties: {
id2: {
type: 'integer'
}
}
}
}
}
}
const schema = {
title: 'object with $ref in allOf',
type: 'object',
allOf: [
{
$ref: 'first#/definitions/id1'
},
{
$ref: 'second#/definitions/id2'
}
]
}
const stringify = build(schema, { schema: externalSchema })
const value = stringify({
id1: 1,
id2: 2,
id3: 3 // extra prop shouldn't be in result
})
t.assert.equal(value, '{"id1":1,"id2":2}')
})
test('allof with local anchor reference', (t) => {
t.plan(1)
const externalSchemas = {
Test: {
$id: 'Test',
definitions: {
Problem: {
type: 'object',
properties: {
type: {
type: 'string'
}
}
},
ValidationFragment: {
type: 'string'
},
ValidationErrorProblem: {
type: 'object',
allOf: [
{
$ref: '#/definitions/Problem'
},
{
type: 'object',
properties: {
validation: {
$ref: '#/definitions/ValidationFragment'
}
}
}
]
}
}
}
}
const schema = { $ref: 'Test#/definitions/ValidationErrorProblem' }
const stringify = build(schema, { schema: externalSchemas })
const data = { type: 'foo', validation: 'bar' }
t.assert.equal(stringify(data), JSON.stringify(data))
})
test('allOf: multiple nested $ref properties', (t) => {
t.plan(2)
const externalSchema1 = {
$id: 'externalSchema1',
oneOf: [
{ $ref: '#/definitions/id1' }
],
definitions: {
id1: {
type: 'object',
properties: {
id1: {
type: 'integer'
}
},
additionalProperties: false
}
}
}
const externalSchema2 = {
$id: 'externalSchema2',
oneOf: [
{ $ref: '#/definitions/id2' }
],
definitions: {
id2: {
type: 'object',
properties: {
id2: {
type: 'integer'
}
},
additionalProperties: false
}
}
}
const schema = {
anyOf: [
{ $ref: 'externalSchema1' },
{ $ref: 'externalSchema2' }
]
}
const stringify = build(schema, { schema: [externalSchema1, externalSchema2] })
t.assert.equal(stringify({ id1: 1 }), JSON.stringify({ id1: 1 }))
t.assert.equal(stringify({ id2: 2 }), JSON.stringify({ id2: 2 }))
})
test('allOf: throw Error if types mismatch ', (t) => {
t.plan(1)
const schema = {
allOf: [
{ type: 'string' },
{ type: 'number' }
]
}
t.assert.throws(() => {
build(schema)
}, {
message: 'Failed to merge "type" keyword schemas.',
schemas: [['string'], ['number']]
})
})
test('allOf: throw Error if format mismatch ', (t) => {
t.plan(1)
const schema = {
allOf: [
{ format: 'date' },
{ format: 'time' }
]
}
t.assert.throws(() => {
build(schema)
}, {
message: 'Failed to merge "format" keyword schemas.'
// schemas: ['date', 'time']
})
})
test('recursive nested allOfs', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
foo: {
additionalProperties: false,
allOf: [{ $ref: '#' }]
}
}
}
const data = { foo: {} }
const stringify = build(schema)
t.assert.equal(stringify(data), JSON.stringify(data))
})
test('recursive nested allOfs', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
foo: {
additionalProperties: false,
allOf: [{ allOf: [{ $ref: '#' }] }]
}
}
}
const data = { foo: {} }
const stringify = build(schema)
t.assert.equal(stringify(data), JSON.stringify(data))
})
test('external recursive allOfs', (t) => {
t.plan(1)
const externalSchema = {
type: 'object',
properties: {
foo: {
properties: {
bar: { type: 'string' }
},
allOf: [{ $ref: '#' }]
}
}
}
const schema = {
type: 'object',
properties: {
a: { $ref: 'externalSchema#/properties/foo' },
b: { $ref: 'externalSchema#/properties/foo' }
}
}
const data = {
a: {
foo: {},
bar: '42',
baz: 42
},
b: {
foo: {},
bar: '42',
baz: 42
}
}
const stringify = build(schema, { schema: { externalSchema } })
t.assert.equal(stringify(data), '{"a":{"bar":"42","foo":{}},"b":{"bar":"42","foo":{}}}')
})
test('do not crash with $ref prop', (t) => {
t.plan(1)
const schema = {
title: 'object with $ref',
type: 'object',
properties: {
outside: {
$ref: '#/$defs/outside'
}
},
$defs: {
inside: {
type: 'object',
properties: {
$ref: {
type: 'string'
}
}
},
outside: {
allOf: [{
$ref: '#/$defs/inside'
}]
}
}
}
const stringify = build(schema)
const value = stringify({
outside: {
$ref: 'true'
}
})
t.assert.equal(value, '{"outside":{"$ref":"true"}}')
})

231
node_modules/fast-json-stringify/test/any.test.js generated vendored Normal file
View File

@@ -0,0 +1,231 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('object with nested random property', (t) => {
t.plan(4)
const schema = {
title: 'empty schema to allow any object',
type: 'object',
properties: {
id: { type: 'number' },
name: {}
}
}
const stringify = build(schema)
t.assert.equal(stringify({
id: 1, name: 'string'
}), '{"id":1,"name":"string"}')
t.assert.equal(stringify({
id: 1, name: { first: 'name', last: 'last' }
}), '{"id":1,"name":{"first":"name","last":"last"}}')
t.assert.equal(stringify({
id: 1, name: null
}), '{"id":1,"name":null}')
t.assert.equal(stringify({
id: 1, name: ['first', 'last']
}), '{"id":1,"name":["first","last"]}')
})
// reference: https://github.com/fastify/fast-json-stringify/issues/259
test('object with empty schema with $id: undefined set', (t) => {
t.plan(1)
const schema = {
title: 'empty schema to allow any object with $id: undefined set',
type: 'object',
properties: {
name: { $id: undefined }
}
}
const stringify = build(schema)
t.assert.equal(stringify({
name: 'string'
}), '{"name":"string"}')
})
test('array with random items', (t) => {
t.plan(1)
const schema = {
title: 'empty schema to allow any object',
type: 'array',
items: {}
}
const stringify = build(schema)
const value = stringify([1, 'string', null])
t.assert.equal(value, '[1,"string",null]')
})
test('empty schema', (t) => {
t.plan(7)
const schema = { }
const stringify = build(schema)
t.assert.equal(stringify(null), 'null')
t.assert.equal(stringify(1), '1')
t.assert.equal(stringify(true), 'true')
t.assert.equal(stringify('hello'), '"hello"')
t.assert.equal(stringify({}), '{}')
t.assert.equal(stringify({ x: 10 }), '{"x":10}')
t.assert.equal(stringify([true, 1, 'hello']), '[true,1,"hello"]')
})
test('empty schema on nested object', (t) => {
t.plan(7)
const schema = {
type: 'object',
properties: {
x: {}
}
}
const stringify = build(schema)
t.assert.equal(stringify({ x: null }), '{"x":null}')
t.assert.equal(stringify({ x: 1 }), '{"x":1}')
t.assert.equal(stringify({ x: true }), '{"x":true}')
t.assert.equal(stringify({ x: 'hello' }), '{"x":"hello"}')
t.assert.equal(stringify({ x: {} }), '{"x":{}}')
t.assert.equal(stringify({ x: { x: 10 } }), '{"x":{"x":10}}')
t.assert.equal(stringify({ x: [true, 1, 'hello'] }), '{"x":[true,1,"hello"]}')
})
test('empty schema on array', (t) => {
t.plan(1)
const schema = {
type: 'array',
items: {}
}
const stringify = build(schema)
t.assert.equal(stringify([1, true, 'hello', [], { x: 1 }]), '[1,true,"hello",[],{"x":1}]')
})
test('empty schema on anyOf', (t) => {
t.plan(4)
// any on Foo codepath.
const schema = {
anyOf: [
{
type: 'object',
properties: {
kind: {
type: 'string',
enum: ['Foo']
},
value: {}
}
},
{
type: 'object',
properties: {
kind: {
type: 'string',
enum: ['Bar']
},
value: {
type: 'number'
}
}
}
]
}
const stringify = build(schema)
t.assert.equal(stringify({ kind: 'Bar', value: 1 }), '{"kind":"Bar","value":1}')
t.assert.equal(stringify({ kind: 'Foo', value: 1 }), '{"kind":"Foo","value":1}')
t.assert.equal(stringify({ kind: 'Foo', value: true }), '{"kind":"Foo","value":true}')
t.assert.equal(stringify({ kind: 'Foo', value: 'hello' }), '{"kind":"Foo","value":"hello"}')
})
test('should throw a TypeError with the path to the key of the invalid value /1', (t) => {
t.plan(1)
// any on Foo codepath.
const schema = {
anyOf: [
{
type: 'object',
properties: {
kind: {
type: 'string',
enum: ['Foo']
},
value: {}
}
},
{
type: 'object',
properties: {
kind: {
type: 'string',
enum: ['Bar']
},
value: {
type: 'number'
}
}
}
]
}
const stringify = build(schema)
t.assert.throws(() => stringify({ kind: 'Baz', value: 1 }), new TypeError('The value of \'#\' does not match schema definition.'))
})
test('should throw a TypeError with the path to the key of the invalid value /2', (t) => {
t.plan(1)
// any on Foo codepath.
const schema = {
type: 'object',
properties: {
data: {
anyOf: [
{
type: 'object',
properties: {
kind: {
type: 'string',
enum: ['Foo']
},
value: {}
}
},
{
type: 'object',
properties: {
kind: {
type: 'string',
enum: ['Bar']
},
value: {
type: 'number'
}
}
}
]
}
}
}
const stringify = build(schema)
t.assert.throws(() => stringify({ data: { kind: 'Baz', value: 1 } }), new TypeError('The value of \'#/properties/data\' does not match schema definition.'))
})

792
node_modules/fast-json-stringify/test/anyof.test.js generated vendored Normal file
View File

@@ -0,0 +1,792 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
process.env.TZ = 'UTC'
test('object with multiple types field', (t) => {
t.plan(2)
const schema = {
title: 'object with multiple types field',
type: 'object',
properties: {
str: {
anyOf: [{
type: 'string'
}, {
type: 'boolean'
}]
}
}
}
const stringify = build(schema)
t.assert.equal(stringify({
str: 'string'
}), '{"str":"string"}')
t.assert.equal(stringify({
str: true
}), '{"str":true}')
})
test('object with field of type object or null', (t) => {
t.plan(2)
const schema = {
title: 'object with field of type object or null',
type: 'object',
properties: {
prop: {
anyOf: [{
type: 'object',
properties: {
str: {
type: 'string'
}
}
}, {
type: 'null'
}]
}
}
}
const stringify = build(schema)
t.assert.equal(stringify({
prop: null
}), '{"prop":null}')
t.assert.equal(stringify({
prop: {
str: 'string'
}
}), '{"prop":{"str":"string"}}')
})
test('object with field of type object or array', (t) => {
t.plan(2)
const schema = {
title: 'object with field of type object or array',
type: 'object',
properties: {
prop: {
anyOf: [{
type: 'object',
properties: {},
additionalProperties: true
}, {
type: 'array',
items: {
type: 'string'
}
}]
}
}
}
const stringify = build(schema)
t.assert.equal(stringify({
prop: {
str: 'string'
}
}), '{"prop":{"str":"string"}}')
t.assert.equal(stringify({
prop: ['string']
}), '{"prop":["string"]}')
})
test('object with field of type string and coercion disable ', (t) => {
t.plan(1)
const schema = {
title: 'object with field of type string',
type: 'object',
properties: {
str: {
anyOf: [{
type: 'string'
}]
}
}
}
const stringify = build(schema)
t.assert.throws(() => stringify({ str: 1 }))
})
test('object with field of type string and coercion enable ', (t) => {
t.plan(1)
const schema = {
title: 'object with field of type string',
type: 'object',
properties: {
str: {
anyOf: [{
type: 'string'
}]
}
}
}
const options = {
ajv: {
coerceTypes: true
}
}
const stringify = build(schema, options)
const value = stringify({
str: 1
})
t.assert.equal(value, '{"str":"1"}')
})
test('object with field with type union of multiple objects', (t) => {
t.plan(2)
const schema = {
title: 'object with anyOf property value containing objects',
type: 'object',
properties: {
anyOfSchema: {
anyOf: [
{
type: 'object',
properties: {
baz: { type: 'number' }
},
required: ['baz']
},
{
type: 'object',
properties: {
bar: { type: 'string' }
},
required: ['bar']
}
]
}
},
required: ['anyOfSchema']
}
const stringify = build(schema)
t.assert.equal(stringify({ anyOfSchema: { baz: 5 } }), '{"anyOfSchema":{"baz":5}}')
t.assert.equal(stringify({ anyOfSchema: { bar: 'foo' } }), '{"anyOfSchema":{"bar":"foo"}}')
})
test('null value in schema', (t) => {
t.plan(0)
const schema = {
title: 'schema with null child',
type: 'string',
nullable: true,
enum: [null]
}
build(schema)
})
test('symbol value in schema', (t) => {
t.plan(4)
const ObjectKind = Symbol('LiteralKind')
const UnionKind = Symbol('UnionKind')
const LiteralKind = Symbol('LiteralKind')
const schema = {
kind: ObjectKind,
type: 'object',
properties: {
value: {
kind: UnionKind,
anyOf: [
{ kind: LiteralKind, type: 'string', enum: ['foo'] },
{ kind: LiteralKind, type: 'string', enum: ['bar'] },
{ kind: LiteralKind, type: 'string', enum: ['baz'] }
]
}
},
required: ['value']
}
const stringify = build(schema)
t.assert.equal(stringify({ value: 'foo' }), '{"value":"foo"}')
t.assert.equal(stringify({ value: 'bar' }), '{"value":"bar"}')
t.assert.equal(stringify({ value: 'baz' }), '{"value":"baz"}')
t.assert.throws(() => stringify({ value: 'qux' }))
})
test('anyOf and $ref together', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
cs: {
anyOf: [
{
$ref: '#/definitions/Option'
},
{
type: 'boolean'
}
]
}
},
definitions: {
Option: {
type: 'string'
}
}
}
const stringify = build(schema)
t.assert.equal(stringify({ cs: 'franco' }), '{"cs":"franco"}')
t.assert.equal(stringify({ cs: true }), '{"cs":true}')
})
test('anyOf and $ref: 2 levels are fine', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
cs: {
anyOf: [
{
$ref: '#/definitions/Option'
},
{
type: 'boolean'
}
]
}
},
definitions: {
Option: {
anyOf: [
{
type: 'number'
},
{
type: 'boolean'
}
]
}
}
}
const stringify = build(schema)
const value = stringify({ cs: 3 })
t.assert.equal(value, '{"cs":3}')
})
test('anyOf and $ref: multiple levels should throw at build.', (t) => {
t.plan(3)
const schema = {
type: 'object',
properties: {
cs: {
anyOf: [
{
$ref: '#/definitions/Option'
},
{
type: 'boolean'
}
]
}
},
definitions: {
Option: {
anyOf: [
{
$ref: '#/definitions/Option2'
},
{
type: 'string'
}
]
},
Option2: {
type: 'number'
}
}
}
const stringify = build(schema)
t.assert.equal(stringify({ cs: 3 }), '{"cs":3}')
t.assert.equal(stringify({ cs: true }), '{"cs":true}')
t.assert.equal(stringify({ cs: 'pippo' }), '{"cs":"pippo"}')
})
test('anyOf and $ref - multiple external $ref', (t) => {
t.plan(2)
const externalSchema = {
external: {
definitions: {
def: {
type: 'object',
properties: {
prop: { anyOf: [{ $ref: 'external2#/definitions/other' }] }
}
}
}
},
external2: {
definitions: {
internal: {
type: 'string'
},
other: {
type: 'object',
properties: {
prop2: { $ref: '#/definitions/internal' }
}
}
}
}
}
const schema = {
title: 'object with $ref',
type: 'object',
properties: {
obj: {
$ref: 'external#/definitions/def'
}
}
}
const object = {
obj: {
prop: {
prop2: 'test'
}
}
}
const stringify = build(schema, { schema: externalSchema })
const output = stringify(object)
t.assert.doesNotThrow(() => JSON.parse(output))
t.assert.equal(output, '{"obj":{"prop":{"prop2":"test"}}}')
})
test('anyOf looks for all of the array items', (t) => {
t.plan(1)
const schema = {
title: 'type array that may have any of declared items',
type: 'array',
items: {
anyOf: [
{
type: 'object',
properties: {
savedId: {
type: 'string'
}
},
required: ['savedId']
},
{
type: 'object',
properties: {
error: {
type: 'string'
}
},
required: ['error']
}
]
}
}
const stringify = build(schema)
const value = stringify([{ savedId: 'great' }, { error: 'oops' }])
t.assert.equal(value, '[{"savedId":"great"},{"error":"oops"}]')
})
test('anyOf with enum with more than 100 entries', (t) => {
t.plan(1)
const schema = {
title: 'type array that may have any of declared items',
type: 'array',
items: {
anyOf: [
{
type: 'string',
enum: ['EUR', 'USD', ...(new Set([...new Array(200)].map(() => Math.random().toString(36).substr(2, 3)))).values()]
},
{ type: 'null' }
]
}
}
const stringify = build(schema)
const value = stringify(['EUR', 'USD', null])
t.assert.equal(value, '["EUR","USD",null]')
})
test('anyOf object with field date-time of type string with format or null', (t) => {
t.plan(1)
const toStringify = new Date()
const withOneOfSchema = {
type: 'object',
properties: {
prop: {
anyOf: [{
type: 'string',
format: 'date-time'
}, {
type: 'null'
}]
}
}
}
const withOneOfStringify = build(withOneOfSchema)
t.assert.equal(withOneOfStringify({
prop: toStringify
}), `{"prop":"${toStringify.toISOString()}"}`)
})
test('anyOf object with nested field date-time of type string with format or null', (t) => {
t.plan(1)
const withOneOfSchema = {
type: 'object',
properties: {
prop: {
anyOf: [{
type: 'object',
properties: {
nestedProp: {
type: 'string',
format: 'date-time'
}
}
}]
}
}
}
const withOneOfStringify = build(withOneOfSchema)
const data = {
prop: { nestedProp: new Date() }
}
t.assert.equal(withOneOfStringify(data), JSON.stringify(data))
})
test('anyOf object with nested field date of type string with format or null', (t) => {
t.plan(1)
const withOneOfSchema = {
type: 'object',
properties: {
prop: {
anyOf: [{
type: 'object',
properties: {
nestedProp: {
type: 'string',
format: 'date'
}
}
}]
}
}
}
const withOneOfStringify = build(withOneOfSchema)
const data = {
prop: { nestedProp: new Date(1674263005800) }
}
t.assert.equal(withOneOfStringify(data), '{"prop":{"nestedProp":"2023-01-21"}}')
})
test('anyOf object with nested field time of type string with format or null', (t) => {
t.plan(1)
const withOneOfSchema = {
type: 'object',
properties: {
prop: {
anyOf: [{
type: 'object',
properties: {
nestedProp: {
type: 'string',
format: 'time'
}
}
}]
}
}
}
const withOneOfStringify = build(withOneOfSchema)
const data = {
prop: { nestedProp: new Date(1674263005800) }
}
t.assert.equal(withOneOfStringify(data), '{"prop":{"nestedProp":"01:03:25"}}')
})
test('anyOf object with field date of type string with format or null', (t) => {
t.plan(1)
const toStringify = '2011-01-01'
const withOneOfSchema = {
type: 'object',
properties: {
prop: {
anyOf: [{
type: 'string',
format: 'date'
}, {
type: 'null'
}]
}
}
}
const withOneOfStringify = build(withOneOfSchema)
t.assert.equal(withOneOfStringify({
prop: toStringify
}), '{"prop":"2011-01-01"}')
})
test('anyOf object with invalid field date of type string with format or null', (t) => {
t.plan(1)
const toStringify = 'foo bar'
const withOneOfSchema = {
type: 'object',
properties: {
prop: {
anyOf: [{
type: 'string',
format: 'date'
}, {
type: 'null'
}]
}
}
}
const withOneOfStringify = build(withOneOfSchema)
t.assert.throws(() => withOneOfStringify({ prop: toStringify }))
})
test('anyOf with a nested external schema', (t) => {
t.plan(1)
const externalSchemas = {
schema1: {
definitions: {
def1: {
$id: 'external',
type: 'string'
}
},
type: 'number'
}
}
const schema = { anyOf: [{ $ref: 'external' }] }
const stringify = build(schema, { schema: externalSchemas })
t.assert.equal(stringify('foo'), '"foo"')
})
test('object with ref and validated properties', (t) => {
t.plan(1)
const externalSchemas = {
RefSchema: {
$id: 'RefSchema',
type: 'string'
}
}
const schema = {
$id: 'root',
type: 'object',
properties: {
id: {
anyOf: [
{ type: 'string' },
{ type: 'number' }
]
},
reference: { $ref: 'RefSchema' }
}
}
const stringify = build(schema, { schema: externalSchemas })
t.assert.equal(stringify({ id: 1, reference: 'hi' }), '{"id":1,"reference":"hi"}')
})
test('anyOf required props', (t) => {
t.plan(3)
const schema = {
type: 'object',
properties: {
prop1: { type: 'string' },
prop2: { type: 'string' },
prop3: { type: 'string' }
},
required: ['prop1'],
anyOf: [{ required: ['prop2'] }, { required: ['prop3'] }]
}
const stringify = build(schema)
t.assert.equal(stringify({ prop1: 'test', prop2: 'test2' }), '{"prop1":"test","prop2":"test2"}')
t.assert.equal(stringify({ prop1: 'test', prop3: 'test3' }), '{"prop1":"test","prop3":"test3"}')
t.assert.equal(stringify({ prop1: 'test', prop2: 'test2', prop3: 'test3' }), '{"prop1":"test","prop2":"test2","prop3":"test3"}')
})
test('anyOf required props', (t) => {
t.plan(3)
const schema = {
type: 'object',
properties: {
prop1: { type: 'string' }
},
anyOf: [
{
properties: {
prop2: { type: 'string' }
}
},
{
properties: {
prop3: { type: 'string' }
}
}
]
}
const stringify = build(schema)
t.assert.equal(stringify({ prop1: 'test1' }), '{"prop1":"test1"}')
t.assert.equal(stringify({ prop2: 'test2' }), '{"prop2":"test2"}')
t.assert.equal(stringify({ prop1: 'test1', prop2: 'test2' }), '{"prop1":"test1","prop2":"test2"}')
})
test('recursive nested anyOfs', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
foo: {
additionalProperties: false,
anyOf: [{ $ref: '#' }]
}
}
}
const data = { foo: {} }
const stringify = build(schema)
t.assert.equal(stringify(data), JSON.stringify(data))
})
test('recursive nested anyOfs', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
foo: {
additionalProperties: false,
anyOf: [{ anyOf: [{ $ref: '#' }] }]
}
}
}
const data = { foo: {} }
const stringify = build(schema)
t.assert.equal(stringify(data), JSON.stringify(data))
})
test('external recursive anyOfs', (t) => {
t.plan(1)
const externalSchema = {
type: 'object',
properties: {
foo: {
properties: {
bar: { type: 'string' }
},
anyOf: [{ $ref: '#' }]
}
}
}
const schema = {
type: 'object',
properties: {
a: { $ref: 'externalSchema#/properties/foo' },
b: { $ref: 'externalSchema#/properties/foo' }
}
}
const data = {
a: {
foo: {},
bar: '42',
baz: 42
},
b: {
foo: {},
bar: '42',
baz: 42
}
}
const stringify = build(schema, { schema: { externalSchema } })
t.assert.equal(stringify(data), '{"a":{"bar":"42","foo":{}},"b":{"bar":"42","foo":{}}}')
})
test('should build merged schemas twice', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
enums: {
type: 'string',
anyOf: [
{ type: 'string', const: 'FOO' },
{ type: 'string', const: 'BAR' }
]
}
}
}
{
const stringify = build(schema)
t.assert.equal(stringify({ enums: 'FOO' }), '{"enums":"FOO"}')
}
{
const stringify = build(schema)
t.assert.equal(stringify({ enums: 'BAR' }), '{"enums":"BAR"}')
}
})

638
node_modules/fast-json-stringify/test/array.test.js generated vendored Normal file
View File

@@ -0,0 +1,638 @@
'use strict'
const { test } = require('node:test')
const validator = require('is-my-json-valid')
const build = require('..')
const Ajv = require('ajv')
test('error on invalid largeArrayMechanism', (t) => {
t.plan(1)
t.assert.throws(() => build({
title: 'large array of null values with default mechanism',
type: 'object',
properties: {
ids: {
type: 'array',
items: { type: 'null' }
}
}
}, {
largeArraySize: 2e4,
largeArrayMechanism: 'invalid'
}), Error('Unsupported large array mechanism invalid'))
})
function buildTest (schema, toStringify, options) {
test(`render a ${schema.title} as JSON`, (t) => {
t.plan(3)
const validate = validator(schema)
const stringify = build(schema, options)
const output = stringify(toStringify)
t.assert.deepStrictEqual(JSON.parse(output), JSON.parse(JSON.stringify(toStringify)))
t.assert.equal(output, JSON.stringify(toStringify))
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
}
buildTest({
title: 'dates tuple',
type: 'object',
properties: {
dates: {
type: 'array',
minItems: 2,
maxItems: 2,
items: [
{
type: 'string',
format: 'date-time'
},
{
type: 'string',
format: 'date-time'
}
]
}
}
}, {
dates: [new Date(1), new Date(2)]
})
buildTest({
title: 'string array',
type: 'object',
properties: {
ids: {
type: 'array',
items: {
type: 'string'
}
}
}
}, {
ids: ['test']
})
buildTest({
title: 'number array',
type: 'object',
properties: {
ids: {
type: 'array',
items: {
type: 'number'
}
}
}
}, {
ids: [1]
})
buildTest({
title: 'mixed array',
type: 'object',
properties: {
ids: {
type: 'array',
items: [
{
type: 'null'
},
{
type: 'string'
},
{
type: 'integer'
},
{
type: 'number'
},
{
type: 'boolean'
},
{
type: 'object',
properties: {
a: {
type: 'string'
}
}
},
{
type: 'array',
items: {
type: 'string'
}
}
]
}
}
}, {
ids: [null, 'test', 1, 1.1, true, { a: 'test' }, ['test']]
})
buildTest({
title: 'repeated types',
type: 'object',
properties: {
ids: {
type: 'array',
items: [
{
type: 'number'
},
{
type: 'number'
}
]
}
}
}, { ids: [1, 2] })
buildTest({
title: 'pattern properties array',
type: 'object',
properties: {
args: {
type: 'array',
items: [
{
type: 'object',
patternProperties: {
'.*': {
type: 'string'
}
}
},
{
type: 'object',
patternProperties: {
'.*': {
type: 'number'
}
}
}
]
}
}
}, { args: [{ a: 'test' }, { b: 1 }] })
buildTest({
title: 'array with weird key',
type: 'object',
properties: {
'@data': {
type: 'array',
items: {
type: 'string'
}
}
}
}, {
'@data': ['test']
})
test('invalid items throw', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
args: {
type: 'array',
items: [
{
type: 'object',
patternProperties: {
'.*': {
type: 'string'
}
}
}
]
}
}
}
const stringify = build(schema)
t.assert.throws(() => stringify({ args: ['invalid'] }))
})
buildTest({
title: 'item types in array default to any',
type: 'object',
properties: {
foo: {
type: 'array'
}
}
}, {
foo: [1, 'string', {}, null]
})
test('array items is a list of schema and additionalItems is true, just the described item is validated', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
foo: {
type: 'array',
items: [
{
type: 'string'
}
],
additionalItems: true
}
}
}
const stringify = build(schema)
const result = stringify({
foo: [
'foo',
'bar',
1
]
})
t.assert.equal(result, '{"foo":["foo","bar",1]}')
})
test('array items is a list of schema and additionalItems is true, just the described item is validated', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
foo: {
type: 'array',
items: [
{
type: 'string'
},
{
type: 'number'
}
],
additionalItems: true
}
}
}
const stringify = build(schema)
const result = stringify({
foo: ['foo']
})
t.assert.equal(result, '{"foo":["foo"]}')
})
test('array items is a list of schema and additionalItems is false /1', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
foo: {
type: 'array',
items: [
{ type: 'string' }
],
additionalItems: false
}
}
}
const stringify = build(schema)
t.assert.throws(() => stringify({ foo: ['foo', 'bar'] }), new Error('Item at 1 does not match schema definition.'))
})
test('array items is a list of schema and additionalItems is false /2', (t) => {
t.plan(3)
const schema = {
type: 'object',
properties: {
foo: {
type: 'array',
items: [
{ type: 'string' },
{ type: 'string' }
],
additionalItems: false
}
}
}
const stringify = build(schema)
t.assert.throws(() => stringify({ foo: [1, 'bar'] }), new Error('Item at 0 does not match schema definition.'))
t.assert.throws(() => stringify({ foo: ['foo', 1] }), new Error('Item at 1 does not match schema definition.'))
t.assert.throws(() => stringify({ foo: ['foo', 'bar', 'baz'] }), new Error('Item at 2 does not match schema definition.'))
})
test('array items is a schema and additionalItems is false', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: {
type: 'array',
items: { type: 'string' },
additionalItems: false
}
}
}
const stringify = build(schema)
// ajv ignores additionalItems if items is not an Array
const ajv = new Ajv({ allErrors: true, strict: false })
const validate = ajv.compile(schema)
t.assert.equal(stringify({ foo: ['foo', 'bar'] }), '{"foo":["foo","bar"]}')
t.assert.equal(validate({ foo: ['foo', 'bar'] }), true)
})
// https://github.com/fastify/fast-json-stringify/issues/279
test('object array with anyOf and symbol', (t) => {
t.plan(1)
const ArrayKind = Symbol('ArrayKind')
const ObjectKind = Symbol('LiteralKind')
const UnionKind = Symbol('UnionKind')
const LiteralKind = Symbol('LiteralKind')
const StringKind = Symbol('StringKind')
const schema = {
kind: ArrayKind,
type: 'array',
items: {
kind: ObjectKind,
type: 'object',
properties: {
name: {
kind: StringKind,
type: 'string'
},
option: {
kind: UnionKind,
anyOf: [
{
kind: LiteralKind,
type: 'string',
enum: ['Foo']
},
{
kind: LiteralKind,
type: 'string',
enum: ['Bar']
}
]
}
},
required: ['name', 'option']
}
}
const stringify = build(schema)
const value = stringify([
{ name: 'name-0', option: 'Foo' },
{ name: 'name-1', option: 'Bar' }
])
t.assert.equal(value, '[{"name":"name-0","option":"Foo"},{"name":"name-1","option":"Bar"}]')
})
test('different arrays with same item schemas', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
array1: {
type: 'array',
items: [{ type: 'string' }],
additionalItems: false
},
array2: {
type: 'array',
items: { $ref: '#/properties/array1/items' },
additionalItems: true
}
}
}
const stringify = build(schema)
const data = { array1: ['bar'], array2: ['foo', 'bar'] }
t.assert.equal(stringify(data), '{"array1":["bar"],"array2":["foo","bar"]}')
})
const largeArray = new Array(2e4).fill({ a: 'test', b: 1 })
buildTest({
title: 'large array with default mechanism',
type: 'object',
properties: {
ids: {
type: 'array',
items: {
type: 'object',
properties: {
a: { type: 'string' },
b: { type: 'number' }
}
}
}
}
}, {
ids: largeArray
}, {
largeArraySize: 2e4,
largeArrayMechanism: 'default'
})
buildTest({
title: 'large array of objects with json-stringify mechanism',
type: 'object',
properties: {
ids: {
type: 'array',
items: {
type: 'object',
properties: {
a: { type: 'string' },
b: { type: 'number' }
}
}
}
}
}, {
ids: largeArray
}, {
largeArrayMechanism: 'json-stringify'
})
buildTest({
title: 'large array of strings with default mechanism',
type: 'object',
properties: {
ids: {
type: 'array',
items: { type: 'string' }
}
}
}, {
ids: new Array(2e4).fill('string')
}, {
largeArraySize: 2e4,
largeArrayMechanism: 'default'
})
buildTest({
title: 'large array of numbers with default mechanism',
type: 'object',
properties: {
ids: {
type: 'array',
items: { type: 'number' }
}
}
}, {
ids: new Array(2e4).fill(42)
}, {
largeArraySize: 2e4,
largeArrayMechanism: 'default'
})
buildTest({
title: 'large array of integers with default mechanism',
type: 'object',
properties: {
ids: {
type: 'array',
items: { type: 'integer' }
}
}
}, {
ids: new Array(2e4).fill(42)
}, {
largeArraySize: 2e4,
largeArrayMechanism: 'default'
})
buildTest({
title: 'large array of booleans with default mechanism',
type: 'object',
properties: {
ids: {
type: 'array',
items: { type: 'boolean' }
}
}
}, {
ids: new Array(2e4).fill(true)
}, {
largeArraySize: 2e4,
largeArrayMechanism: 'default'
})
buildTest({
title: 'large array of null values with default mechanism',
type: 'object',
properties: {
ids: {
type: 'array',
items: { type: 'null' }
}
}
}, {
ids: new Array(2e4).fill(null)
}, {
largeArraySize: 2e4,
largeArrayMechanism: 'default'
})
test('error on invalid value for largeArraySize /1', (t) => {
t.plan(1)
t.assert.throws(() => build({
title: 'large array of null values with default mechanism',
type: 'object',
properties: {
ids: {
type: 'array',
items: { type: 'null' }
}
}
}, {
largeArraySize: 'invalid'
}), Error('Unsupported large array size. Expected integer-like, got string with value invalid'))
})
test('error on invalid value for largeArraySize /2', (t) => {
t.plan(1)
t.assert.throws(() => build({
title: 'large array of null values with default mechanism',
type: 'object',
properties: {
ids: {
type: 'array',
items: { type: 'null' }
}
}
}, {
largeArraySize: Infinity
}), Error('Unsupported large array size. Expected integer-like, got number with value Infinity'))
})
test('error on invalid value for largeArraySize /3', (t) => {
t.plan(1)
t.assert.throws(() => build({
title: 'large array of null values with default mechanism',
type: 'object',
properties: {
ids: {
type: 'array',
items: { type: 'null' }
}
}
}, {
largeArraySize: [200]
}), Error('Unsupported large array size. Expected integer-like, got object with value 200'))
})
buildTest({
title: 'large array of integers with largeArraySize is bigint',
type: 'object',
properties: {
ids: {
type: 'array',
items: { type: 'integer' }
}
}
}, {
ids: new Array(2e4).fill(42)
}, {
largeArraySize: 20000n,
largeArrayMechanism: 'default'
})
buildTest({
title: 'large array of integers with largeArraySize is valid string',
type: 'object',
properties: {
ids: {
type: 'array',
items: { type: 'integer' }
}
}
}, {
ids: new Array(1e4).fill(42)
}, {
largeArraySize: '10000',
largeArrayMechanism: 'default'
})

13
node_modules/fast-json-stringify/test/asNumber.test.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
'use strict'
const { test } = require('node:test')
test('asNumber should convert BigInt', (t) => {
t.plan(1)
const Serializer = require('../lib/serializer')
const serializer = new Serializer()
const number = serializer.asNumber(11753021440n)
t.assert.equal(number, '11753021440')
})

400
node_modules/fast-json-stringify/test/basic.test.js generated vendored Normal file
View File

@@ -0,0 +1,400 @@
'use strict'
const { test } = require('node: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.assert.deepStrictEqual(JSON.parse(output), toStringify)
t.assert.equal(output, JSON.stringify(toStringify))
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
}
buildTest({
title: 'string',
type: 'string',
format: 'unsafe'
}, 'hello world')
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('throw an error or coerce numbers and integers that are not numbers', (t) => {
const stringify = build({
title: 'basic',
type: 'object',
properties: {
age: {
type: 'number'
},
distance: {
type: 'integer'
}
}
})
t.assert.throws(() => {
stringify({ age: 'hello ', distance: 'long' })
}, { message: 'The value "hello " cannot be converted to a number.' })
const result = stringify({
age: '42',
distance: true
})
t.assert.deepStrictEqual(JSON.parse(result), { age: 42, distance: 1 })
})
test('Should throw on invalid schema', t => {
t.plan(1)
t.assert.throws(() => {
build({
type: 'Dinosaur',
properties: {
claws: { type: 'sharp' }
}
})
}, { message: 'schema is invalid: data/properties/claws/type must be equal to one of the allowed values' })
})
test('additionalProperties - throw on unknown type', (t) => {
t.plan(1)
t.assert.throws(() => {
build({
title: 'check array coerce',
type: 'object',
properties: {},
additionalProperties: {
type: 'strangetype'
}
})
t.fail('should be an invalid schema')
}, { message: 'schema is invalid: data/additionalProperties/type must be equal to one of the allowed values' })
})
test('patternProperties - throw on unknown type', (t) => {
t.plan(1)
t.assert.throws(() => {
build({
title: 'check array coerce',
type: 'object',
properties: {},
patternProperties: {
foo: {
type: 'strangetype'
}
}
})
}, { message: 'schema is invalid: data/patternProperties/foo/type must be equal to one of the allowed values' })
})
test('render a double quote as JSON /1', (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.assert.equal(output, JSON.stringify(toStringify))
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a double quote as JSON /2', (t) => {
t.plan(2)
const schema = {
type: 'string'
}
const toStringify = 'double quote " 2'
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
t.assert.equal(output, JSON.stringify(toStringify))
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a long string', (t) => {
t.plan(2)
const schema = {
type: 'string'
}
const toStringify = 'the Ultimate Question of Life, the Universe, and Everything.'
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
t.assert.equal(output, JSON.stringify(toStringify))
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('returns JSON.stringify if schema type is boolean', t => {
t.plan(1)
const schema = {
type: 'array',
items: true
}
const array = [1, true, 'test']
const stringify = build(schema)
t.assert.equal(stringify(array), JSON.stringify(array))
})

76
node_modules/fast-json-stringify/test/bigint.test.js generated vendored Normal file
View File

@@ -0,0 +1,76 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('render a bigint as JSON', (t) => {
t.plan(1)
const schema = {
title: 'bigint',
type: 'integer'
}
const stringify = build(schema)
const output = stringify(1615n)
t.assert.equal(output, '1615')
})
test('render an object with a bigint as JSON', (t) => {
t.plan(1)
const schema = {
title: 'object with bigint',
type: 'object',
properties: {
id: {
type: 'integer'
}
}
}
const stringify = build(schema)
const output = stringify({
id: 1615n
})
t.assert.equal(output, '{"id":1615}')
})
test('render an array with a bigint as JSON', (t) => {
t.plan(1)
const schema = {
title: 'array with bigint',
type: 'array',
items: {
type: 'integer'
}
}
const stringify = build(schema)
const output = stringify([1615n])
t.assert.equal(output, '[1615]')
})
test('render an object with an additionalProperty of type bigint as JSON', (t) => {
t.plan(1)
const schema = {
title: 'object with bigint',
type: 'object',
additionalProperties: {
type: 'integer'
}
}
const stringify = build(schema)
const output = stringify({
num: 1615n
})
t.assert.equal(output, '{"num":1615}')
})

View File

@@ -0,0 +1,47 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('Should clean the cache', (t) => {
t.plan(1)
const schema = {
$id: 'test',
type: 'string'
}
t.assert.doesNotThrow(() => {
build(schema)
build(schema)
})
})
test('Should clean the cache with external schemas', (t) => {
t.plan(1)
const schema = {
$id: 'test',
definitions: {
def: {
type: 'object',
properties: {
str: {
type: 'string'
}
}
}
},
type: 'object',
properties: {
obj: {
$ref: '#/definitions/def'
}
}
}
t.assert.doesNotThrow(() => {
build(schema)
build(schema)
})
})

314
node_modules/fast-json-stringify/test/const.test.js generated vendored Normal file
View File

@@ -0,0 +1,314 @@
'use strict'
const { test } = require('node:test')
const validator = require('is-my-json-valid')
const build = require('..')
test('schema with const string', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: { const: 'bar' }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
foo: 'bar'
})
t.assert.equal(output, '{"foo":"bar"}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('schema with const string and different input', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: { const: 'bar' }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
foo: 'baz'
})
t.assert.equal(output, '{"foo":"bar"}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('schema with const string and different type input', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: { const: 'bar' }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
foo: 1
})
t.assert.equal(output, '{"foo":"bar"}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('schema with const string and no input', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: { const: 'bar' }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({})
t.assert.equal(output, '{}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('schema with const string that contains \'', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: { const: "'bar'" }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
foo: "'bar'"
})
t.assert.equal(output, '{"foo":"\'bar\'"}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('schema with const number', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: { const: 1 }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
foo: 1
})
t.assert.equal(output, '{"foo":1}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('schema with const number and different input', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: { const: 1 }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
foo: 2
})
t.assert.equal(output, '{"foo":1}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('schema with const bool', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: { const: true }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
foo: true
})
t.assert.equal(output, '{"foo":true}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('schema with const number', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: { const: 1 }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
foo: 1
})
t.assert.equal(output, '{"foo":1}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('schema with const null', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: { const: null }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
foo: null
})
t.assert.equal(output, '{"foo":null}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('schema with const array', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: { const: [1, 2, 3] }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
foo: [1, 2, 3]
})
t.assert.equal(output, '{"foo":[1,2,3]}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('schema with const object', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: { const: { bar: 'baz' } }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
foo: { bar: 'baz' }
})
t.assert.equal(output, '{"foo":{"bar":"baz"}}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('schema with const and null as type', (t) => {
t.plan(4)
const schema = {
type: 'object',
properties: {
foo: { type: ['string', 'null'], const: 'baz' }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
foo: null
})
t.assert.equal(output, '{"foo":null}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
const output2 = stringify({ foo: 'baz' })
t.assert.equal(output2, '{"foo":"baz"}')
t.assert.ok(validate(JSON.parse(output2)), 'valid schema')
})
test('schema with const as nullable', (t) => {
t.plan(4)
const schema = {
type: 'object',
properties: {
foo: { nullable: true, const: 'baz' }
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
foo: null
})
t.assert.equal(output, '{"foo":null}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
const output2 = stringify({
foo: 'baz'
})
t.assert.equal(output2, '{"foo":"baz"}')
t.assert.ok(validate(JSON.parse(output2)), 'valid schema')
})
test('schema with const and invalid object', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
foo: { const: { foo: 'bar' } }
},
required: ['foo']
}
const validate = validator(schema)
const stringify = build(schema)
const result = stringify({
foo: { foo: 'baz' }
})
t.assert.equal(result, '{"foo":{"foo":"bar"}}')
t.assert.ok(validate(JSON.parse(result)), 'valid schema')
})

639
node_modules/fast-json-stringify/test/date.test.js generated vendored Normal file
View File

@@ -0,0 +1,639 @@
'use strict'
const { test } = require('node:test')
const validator = require('is-my-json-valid')
const build = require('..')
process.env.TZ = 'UTC'
test('render a date in a string as JSON', (t) => {
t.plan(2)
const schema = {
title: 'a date in a string',
type: 'string'
}
const toStringify = new Date(1674263005800)
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
t.assert.equal(output, JSON.stringify(toStringify))
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a date in a string when format is date-format as ISOString', (t) => {
t.plan(2)
const schema = {
title: 'a date in a string',
type: 'string',
format: 'date-time'
}
const toStringify = new Date(1674263005800)
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
t.assert.equal(output, JSON.stringify(toStringify))
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a nullable date in a string when format is date-format as ISOString', (t) => {
t.plan(2)
const schema = {
title: 'a date in a string',
type: 'string',
format: 'date-time',
nullable: true
}
const toStringify = new Date(1674263005800)
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
t.assert.equal(output, JSON.stringify(toStringify))
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a date in a string when format is date as YYYY-MM-DD', (t) => {
t.plan(2)
const schema = {
title: 'a date in a string',
type: 'string',
format: 'date'
}
const toStringify = new Date(1674263005800)
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
t.assert.equal(output, '"2023-01-21"')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a nullable date in a string when format is date as YYYY-MM-DD', (t) => {
t.plan(2)
const schema = {
title: 'a date in a string',
type: 'string',
format: 'date',
nullable: true
}
const toStringify = new Date(1674263005800)
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
t.assert.equal(output, '"2023-01-21"')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('verify padding for rendered date in a string when format is date', (t) => {
t.plan(2)
const schema = {
title: 'a date in a string',
type: 'string',
format: 'date'
}
const toStringify = new Date(2020, 0, 1, 0, 0, 0, 0)
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
t.assert.equal(output, '"2020-01-01"')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a date in a string when format is time as kk:mm:ss', (t) => {
t.plan(3)
const schema = {
title: 'a date in a string',
type: 'string',
format: 'time'
}
const toStringify = new Date(1674263005800)
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
validate(JSON.parse(output))
t.assert.equal(validate.errors, null)
t.assert.equal(output, '"01:03:25"')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a nullable date in a string when format is time as kk:mm:ss', (t) => {
t.plan(3)
const schema = {
title: 'a date in a string',
type: 'string',
format: 'time',
nullable: true
}
const toStringify = new Date(1674263005800)
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
validate(JSON.parse(output))
t.assert.equal(validate.errors, null)
t.assert.equal(output, '"01:03:25"')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a midnight time', (t) => {
t.plan(3)
const schema = {
title: 'a date in a string',
type: 'string',
format: 'time'
}
const midnight = new Date(new Date(1674263005800).setHours(24))
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(midnight)
validate(JSON.parse(output))
t.assert.equal(validate.errors, null)
t.assert.equal(output, '"00:03:25"')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('verify padding for rendered date in a string when format is time', (t) => {
t.plan(3)
const schema = {
title: 'a date in a string',
type: 'string',
format: 'time'
}
const toStringify = new Date(2020, 0, 1, 1, 1, 1, 1)
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
validate(JSON.parse(output))
t.assert.equal(validate.errors, null)
t.assert.equal(output, '"01:01:01"')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a nested object in a string when type is date-format as ISOString', (t) => {
t.plan(2)
const schema = {
title: 'an object in a string',
type: 'object',
properties: {
date: {
type: 'string',
format: 'date-time'
}
}
}
const toStringify = { date: new Date(1674263005800) }
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
t.assert.equal(output, JSON.stringify(toStringify))
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('serializing null value', async t => {
const input = { updatedAt: null }
function createSchema (properties) {
return {
title: 'an object in a string',
type: 'object',
properties
}
}
function serialize (schema, input) {
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(input)
return {
validate,
output
}
}
t.plan(3)
await t.test('type::string', async t => {
t.plan(3)
await t.test('format::date-time', t => {
t.plan(2)
const prop = {
updatedAt: {
type: 'string',
format: 'date-time'
}
}
const {
output,
validate
} = serialize(createSchema(prop), input)
t.assert.equal(output, '{"updatedAt":""}')
t.assert.equal(validate(JSON.parse(output)), false, 'an empty string is not a date-time format')
})
await t.test('format::date', t => {
t.plan(2)
const prop = {
updatedAt: {
type: 'string',
format: 'date'
}
}
const {
output,
validate
} = serialize(createSchema(prop), input)
t.assert.equal(output, '{"updatedAt":""}')
t.assert.equal(validate(JSON.parse(output)), false, 'an empty string is not a date format')
})
await t.test('format::time', t => {
t.plan(2)
const prop = {
updatedAt: {
type: 'string',
format: 'time'
}
}
const {
output,
validate
} = serialize(createSchema(prop), input)
t.assert.equal(output, '{"updatedAt":""}')
t.assert.equal(validate(JSON.parse(output)), false, 'an empty string is not a time format')
})
})
await t.test('type::array', async t => {
t.plan(6)
await t.test('format::date-time', t => {
t.plan(2)
const prop = {
updatedAt: {
type: ['string'],
format: 'date-time'
}
}
const {
output,
validate
} = serialize(createSchema(prop), input)
t.assert.equal(output, '{"updatedAt":""}')
t.assert.equal(validate(JSON.parse(output)), false, 'an empty string is not a date-time format')
})
await t.test('format::date', t => {
t.plan(2)
const prop = {
updatedAt: {
type: ['string'],
format: 'date'
}
}
const {
output,
validate
} = serialize(createSchema(prop), input)
t.assert.equal(output, '{"updatedAt":""}')
t.assert.equal(validate(JSON.parse(output)), false, 'an empty string is not a date format')
})
await t.test('format::date', t => {
t.plan(2)
const prop = {
updatedAt: {
type: ['string'],
format: 'date'
}
}
const {
output,
validate
} = serialize(createSchema(prop), input)
t.assert.equal(output, '{"updatedAt":""}')
t.assert.equal(validate(JSON.parse(output)), false, 'an empty string is not a date format')
})
await t.test('format::time, Date object', t => {
t.plan(1)
const schema = {
oneOf: [
{
type: 'object',
properties: {
updatedAt: {
type: ['string', 'number'],
format: 'time'
}
}
}
]
}
const date = new Date(1674263005800)
const input = { updatedAt: date }
const { output } = serialize(schema, input)
t.assert.equal(output, JSON.stringify({ updatedAt: '01:03:25' }))
})
await t.test('format::time, Date object', t => {
t.plan(1)
const schema = {
oneOf: [
{
type: ['string', 'number'],
format: 'time'
}
]
}
const date = new Date(1674263005800)
const { output } = serialize(schema, date)
t.assert.equal(output, '"01:03:25"')
})
await t.test('format::time, Date object', t => {
t.plan(1)
const schema = {
oneOf: [
{
type: ['string', 'number'],
format: 'time'
}
]
}
const { output } = serialize(schema, 42)
t.assert.equal(output, JSON.stringify(42))
})
})
await t.test('type::array::nullable', async t => {
t.plan(3)
await t.test('format::date-time', t => {
t.plan(2)
const prop = {
updatedAt: {
type: ['string', 'null'],
format: 'date-time'
}
}
const {
output,
validate
} = serialize(createSchema(prop), input)
t.assert.equal(output, '{"updatedAt":null}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
await t.test('format::date', t => {
t.plan(2)
const prop = {
updatedAt: {
type: ['string', 'null'],
format: 'date'
}
}
const {
output,
validate
} = serialize(createSchema(prop), input)
t.assert.equal(output, '{"updatedAt":null}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
await t.test('format::time', t => {
t.plan(2)
const prop = {
updatedAt: {
type: ['string', 'null'],
format: 'time'
}
}
const {
output,
validate
} = serialize(createSchema(prop), input)
t.assert.equal(output, '{"updatedAt":null}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
})
})
test('Validate Date object as string type', (t) => {
t.plan(1)
const schema = {
oneOf: [
{ type: 'string' }
]
}
const toStringify = new Date(1674263005800)
const stringify = build(schema)
const output = stringify(toStringify)
t.assert.equal(output, JSON.stringify(toStringify))
})
test('nullable date', (t) => {
t.plan(1)
const schema = {
anyOf: [
{
format: 'date',
type: 'string',
nullable: true
}
]
}
const stringify = build(schema)
const data = new Date(1674263005800)
const result = stringify(data)
t.assert.equal(result, '"2023-01-21"')
})
test('non-date format should not affect data serialization (issue #491)', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
hello: {
type: 'string',
format: 'int64',
pattern: '^[0-9]*$'
}
}
}
const stringify = build(schema)
const data = { hello: 123n }
t.assert.equal(stringify(data), '{"hello":"123"}')
})
test('should serialize also an invalid string value, even if it is not a valid date', (t) => {
t.plan(2)
const schema = {
title: 'a date in a string',
type: 'string',
format: 'date-time',
nullable: true
}
const toStringify = 'invalid'
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
t.assert.equal(output, JSON.stringify(toStringify))
t.assert.equal(validate(JSON.parse(output)), false, 'valid schema')
})
test('should throw an error if value can not be transformed to date-time', (t) => {
t.plan(2)
const schema = {
title: 'a date in a string',
type: 'string',
format: 'date-time',
nullable: true
}
const toStringify = true
const validate = validator(schema)
const stringify = build(schema)
t.assert.throws(() => stringify(toStringify), new Error('The value "true" cannot be converted to a date-time.'))
t.assert.equal(validate(toStringify), false)
})
test('should throw an error if value can not be transformed to date', (t) => {
t.plan(2)
const schema = {
title: 'a date in a string',
type: 'string',
format: 'date',
nullable: true
}
const toStringify = true
const validate = validator(schema)
const stringify = build(schema)
t.assert.throws(() => stringify(toStringify), new Error('The value "true" cannot be converted to a date.'))
t.assert.equal(validate(toStringify), false)
})
test('should throw an error if value can not be transformed to time', (t) => {
t.plan(2)
const schema = {
title: 'a time in a string',
type: 'string',
format: 'time',
nullable: true
}
const toStringify = true
const validate = validator(schema)
const stringify = build(schema)
t.assert.throws(() => stringify(toStringify), new Error('The value "true" cannot be converted to a time.'))
t.assert.equal(validate(toStringify), false)
})
test('should serialize also an invalid string value, even if it is not a valid time', (t) => {
t.plan(2)
const schema = {
title: 'a time in a string',
type: 'string',
format: 'time',
nullable: true
}
const toStringify = 'invalid'
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(toStringify)
t.assert.equal(output, JSON.stringify(toStringify))
t.assert.equal(validate(JSON.parse(output)), false, 'valid schema')
})

View File

@@ -0,0 +1,121 @@
'use strict'
const { test } = require('node:test')
const fjs = require('..')
const Ajv = require('ajv').default
const Validator = require('../lib/validator')
const Serializer = require('../lib/serializer')
function build (opts) {
return fjs({
title: 'default string',
type: 'object',
properties: {
firstName: {
type: 'string'
}
},
required: ['firstName']
}, opts)
}
test('activate debug mode', t => {
t.plan(5)
const debugMode = build({ debugMode: true })
t.assert.ok(typeof debugMode === 'object')
t.assert.ok(debugMode.ajv instanceof Ajv)
t.assert.ok(debugMode.validator instanceof Validator)
t.assert.ok(debugMode.serializer instanceof Serializer)
t.assert.ok(typeof debugMode.code === 'string')
})
test('activate debug mode truthy', t => {
t.plan(5)
const debugMode = build({ debugMode: 'yes' })
t.assert.ok(typeof debugMode === 'object')
t.assert.ok(typeof debugMode.code === 'string')
t.assert.ok(debugMode.ajv instanceof Ajv)
t.assert.ok(debugMode.validator instanceof Validator)
t.assert.ok(debugMode.serializer instanceof Serializer)
})
test('to string auto-consistent', t => {
t.plan(6)
const debugMode = build({ debugMode: 1 })
t.assert.ok(typeof debugMode === 'object')
t.assert.ok(typeof debugMode.code === 'string')
t.assert.ok(debugMode.ajv instanceof Ajv)
t.assert.ok(debugMode.serializer instanceof Serializer)
t.assert.ok(debugMode.validator instanceof Validator)
const compiled = fjs.restore(debugMode)
const tobe = JSON.stringify({ firstName: 'Foo' })
t.assert.equal(compiled({ firstName: 'Foo', surname: 'bar' }), tobe, 'surname evicted')
})
test('to string auto-consistent with ajv', t => {
t.plan(6)
const debugMode = fjs({
title: 'object with multiple types field',
type: 'object',
properties: {
str: {
anyOf: [{
type: 'string'
}, {
type: 'boolean'
}]
}
}
}, { debugMode: 1 })
t.assert.ok(typeof debugMode === 'object')
t.assert.ok(typeof debugMode.code === 'string')
t.assert.ok(debugMode.ajv instanceof Ajv)
t.assert.ok(debugMode.validator instanceof Validator)
t.assert.ok(debugMode.serializer instanceof Serializer)
const compiled = fjs.restore(debugMode)
const tobe = JSON.stringify({ str: 'Foo' })
t.assert.equal(compiled({ str: 'Foo', void: 'me' }), tobe)
})
test('to string auto-consistent with ajv-formats', t => {
t.plan(3)
const debugMode = fjs({
title: 'object with multiple types field and format keyword',
type: 'object',
properties: {
str: {
anyOf: [{
type: 'string',
format: 'email'
}, {
type: 'boolean'
}]
}
}
}, { debugMode: 1 })
t.assert.ok(typeof debugMode === 'object')
const compiled = fjs.restore(debugMode)
const tobe = JSON.stringify({ str: 'foo@bar.com' })
t.assert.equal(compiled({ str: 'foo@bar.com' }), tobe)
t.assert.throws(() => compiled({ str: 'foo' }))
})
test('debug should restore the same serializer instance', t => {
t.plan(1)
const debugMode = fjs({ type: 'integer' }, { debugMode: 1, rounding: 'ceil' })
const compiled = fjs.restore(debugMode)
t.assert.equal(compiled(3.95), 4)
})

376
node_modules/fast-json-stringify/test/defaults.test.js generated vendored Normal file
View File

@@ -0,0 +1,376 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
function buildTest (schema, toStringify, expected) {
test(`render a ${schema.title} with default as JSON`, (t) => {
t.plan(1)
const stringify = build(schema)
const output = stringify(toStringify)
t.assert.equal(output, JSON.stringify(expected))
})
}
buildTest({
title: 'default string',
type: 'object',
properties: {
firstName: {
type: 'string'
},
lastName: {
type: 'string',
default: 'Collina'
},
age: {
description: 'Age in years',
type: 'integer',
minimum: 0
},
magic: {
type: 'number'
}
},
required: ['firstName', 'lastName']
}, {
firstName: 'Matteo',
magic: 42,
age: 32
}, {
firstName: 'Matteo',
lastName: 'Collina',
age: 32,
magic: 42
})
buildTest({
title: 'default string with value',
type: 'object',
properties: {
firstName: {
type: 'string'
},
lastName: {
type: 'string',
default: 'Collina'
},
age: {
description: 'Age in years',
type: 'integer',
minimum: 0
},
magic: {
type: 'number'
}
},
required: ['firstName', 'lastName']
}, {
firstName: 'Matteo',
lastName: 'collina',
magic: 42,
age: 32
}, {
firstName: 'Matteo',
lastName: 'collina',
age: 32,
magic: 42
})
buildTest({
title: 'default number',
type: 'object',
properties: {
firstName: {
type: 'string'
},
lastName: {
type: 'string'
},
age: {
description: 'Age in years',
type: 'integer',
minimum: 0
},
magic: {
type: 'number',
default: 42
}
},
required: ['firstName', 'lastName']
}, {
firstName: 'Matteo',
lastName: 'Collina',
age: 32
}, {
firstName: 'Matteo',
lastName: 'Collina',
age: 32,
magic: 42
})
buildTest({
title: 'default number with value',
type: 'object',
properties: {
firstName: {
type: 'string'
},
lastName: {
type: 'string'
},
age: {
description: 'Age in years',
type: 'integer',
minimum: 0
},
magic: {
type: 'number',
default: 42
}
},
required: ['firstName', 'lastName']
}, {
firstName: 'Matteo',
lastName: 'Collina',
age: 32,
magic: 66
}, {
firstName: 'Matteo',
lastName: 'Collina',
age: 32,
magic: 66
})
buildTest({
title: 'default object',
type: 'object',
properties: {
firstName: {
type: 'string'
},
lastName: {
type: 'string'
},
age: {
description: 'Age in years',
type: 'integer',
minimum: 0
},
otherProps: {
type: 'object',
default: { foo: 'bar' }
}
},
required: ['firstName', 'lastName']
}, {
firstName: 'Matteo',
lastName: 'Collina',
age: 32
}, {
firstName: 'Matteo',
lastName: 'Collina',
age: 32,
otherProps: { foo: 'bar' }
})
buildTest({
title: 'default object with value',
type: 'object',
properties: {
firstName: {
type: 'string'
},
lastName: {
type: 'string'
},
age: {
description: 'Age in years',
type: 'integer',
minimum: 0
},
otherProps: {
type: 'object',
additionalProperties: true,
default: { foo: 'bar' }
}
},
required: ['firstName', 'lastName']
}, {
firstName: 'Matteo',
lastName: 'Collina',
age: 32,
otherProps: { hello: 'world' }
}, {
firstName: 'Matteo',
lastName: 'Collina',
age: 32,
otherProps: { hello: 'world' }
})
buildTest({
title: 'default array',
type: 'object',
properties: {
firstName: {
type: 'string'
},
lastName: {
type: 'string'
},
age: {
description: 'Age in years',
type: 'integer',
minimum: 0
},
otherProps: {
type: 'array',
items: { type: 'string' },
default: ['FOO']
}
},
required: ['firstName', 'lastName']
}, {
firstName: 'Matteo',
lastName: 'Collina',
age: 32
}, {
firstName: 'Matteo',
lastName: 'Collina',
age: 32,
otherProps: ['FOO']
})
buildTest({
title: 'default array with value',
type: 'object',
properties: {
firstName: {
type: 'string'
},
lastName: {
type: 'string'
},
age: {
description: 'Age in years',
type: 'integer',
minimum: 0
},
otherProps: {
type: 'array',
items: { type: 'string' },
default: ['FOO']
}
},
required: ['firstName', 'lastName']
}, {
firstName: 'Matteo',
lastName: 'Collina',
age: 32,
otherProps: ['BAR']
}, {
firstName: 'Matteo',
lastName: 'Collina',
age: 32,
otherProps: ['BAR']
})
buildTest({
title: 'default deeper value',
type: 'object',
properties: {
level1: {
type: 'object',
properties: {
level2: {
type: 'object',
properties: {
level3: {
type: 'object',
properties: {
level4: {
type: 'object',
default: { foo: 'bar' }
}
}
}
}
}
}
}
}
}, {
level1: { level2: { level3: { } } }
}, {
level1: { level2: { level3: { level4: { foo: 'bar' } } } }
})
buildTest({
title: 'default deeper value with value',
type: 'object',
properties: {
level1: {
type: 'object',
properties: {
level2: {
type: 'object',
properties: {
level3: {
type: 'object',
properties: {
level4: {
type: 'object',
default: { foo: 'bar' }
}
}
}
}
}
}
}
}
}, {
level1: { level2: { level3: { level4: { } } } }
}, {
level1: { level2: { level3: { level4: { } } } }
})
buildTest({
type: 'object',
properties: {
name: {
type: 'string',
default: 'foo'
},
dev: {
type: 'boolean',
default: false
}
},
required: [
'name', 'dev'
]
}, {}, { name: 'foo', dev: false })
buildTest({
type: 'object',
properties: {
name: {
type: 'string',
default: 'foo'
},
dev: {
type: 'boolean'
},
job: {
type: 'string',
default: 'awesome'
}
},
required: [
'name', 'dev'
]
}, { dev: true }, { name: 'foo', dev: true, job: 'awesome' })

37
node_modules/fast-json-stringify/test/enum.test.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('use enum without type', (t) => {
t.plan(1)
const stringify = build({
title: 'Example Schema',
type: 'object',
properties: {
order: {
type: 'string',
enum: ['asc', 'desc']
}
}
})
const obj = { order: 'asc' }
t.assert.equal('{"order":"asc"}', stringify(obj))
})
test('use enum without type', (t) => {
t.plan(1)
const stringify = build({
title: 'Example Schema',
type: 'object',
properties: {
order: {
enum: ['asc', 'desc']
}
}
})
const obj = { order: 'asc' }
t.assert.equal('{"order":"asc"}', stringify(obj))
})

25
node_modules/fast-json-stringify/test/fix-604.test.js generated vendored Normal file
View File

@@ -0,0 +1,25 @@
'use strict'
const { test } = require('node:test')
const fjs = require('..')
test('fix-604', t => {
const schema = {
type: 'object',
properties: {
fullName: { type: 'string' },
phone: { type: 'number' }
}
}
const input = {
fullName: 'Jone',
phone: 'phone'
}
const render = fjs(schema)
t.assert.throws(() => {
render(input)
}, { message: 'The value "phone" cannot be converted to a number.' })
})

0
node_modules/fast-json-stringify/test/fixtures/.keep generated vendored Normal file
View File

View File

@@ -0,0 +1,468 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
process.env.TZ = 'UTC'
const schema = {
type: 'object',
properties: {
},
if: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['foobar'] }
}
},
then: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['foobar'] },
foo: { type: 'string' },
bar: { type: 'number' },
list: {
type: 'array',
items: {
type: 'object',
properties: {
name: { type: 'string' },
value: { type: 'string' }
}
}
}
}
},
else: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['greeting'] },
hi: { type: 'string' },
hello: { type: 'number' },
list: {
type: 'array',
items: {
type: 'object',
properties: {
name: { type: 'string' },
value: { type: 'string' }
}
}
}
}
}
}
const nestedIfSchema = {
type: 'object',
properties: { },
if: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['foobar', 'greeting'] }
}
},
then: {
if: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['foobar'] }
}
},
then: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['foobar'] },
foo: { type: 'string' },
bar: { type: 'number' },
list: {
type: 'array',
items: {
type: 'object',
properties: {
name: { type: 'string' },
value: { type: 'string' }
}
}
}
}
},
else: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['greeting'] },
hi: { type: 'string' },
hello: { type: 'number' }
}
}
},
else: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['alphabet'] },
a: { type: 'string' },
b: { type: 'number' }
}
}
}
const nestedElseSchema = {
type: 'object',
properties: { },
if: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['foobar'] }
}
},
then: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['foobar'] },
foo: { type: 'string' },
bar: { type: 'number' },
list: {
type: 'array',
items: {
type: 'object',
properties: {
name: { type: 'string' },
value: { type: 'string' }
}
}
}
}
},
else: {
if: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['greeting'] }
}
},
then: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['greeting'] },
hi: { type: 'string' },
hello: { type: 'number' }
}
},
else: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['alphabet'] },
a: { type: 'string' },
b: { type: 'number' }
}
}
}
}
const nestedDeepElseSchema = {
type: 'object',
additionalProperties: schema
}
const noElseSchema = {
type: 'object',
properties: {
},
if: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['foobar'] }
}
},
then: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['foobar'] },
foo: { type: 'string' },
bar: { type: 'number' },
list: {
type: 'array',
items: {
type: 'object',
properties: {
name: { type: 'string' },
value: { type: 'string' }
}
}
}
}
}
}
const fooBarInput = {
kind: 'foobar',
foo: 'FOO',
list: [{
name: 'name',
value: 'foo'
}],
bar: 42,
hi: 'HI',
hello: 45,
a: 'A',
b: 35
}
const greetingInput = {
kind: 'greeting',
foo: 'FOO',
bar: 42,
hi: 'HI',
hello: 45,
a: 'A',
b: 35
}
const alphabetInput = {
kind: 'alphabet',
foo: 'FOO',
bar: 42,
hi: 'HI',
hello: 45,
a: 'A',
b: 35
}
const deepFoobarInput = {
foobar: fooBarInput
}
const foobarOutput = JSON.stringify({
kind: 'foobar',
foo: 'FOO',
bar: 42,
list: [{
name: 'name',
value: 'foo'
}]
})
const greetingOutput = JSON.stringify({
kind: 'greeting',
hi: 'HI',
hello: 45
})
const alphabetOutput = JSON.stringify({
kind: 'alphabet',
a: 'A',
b: 35
})
const deepFoobarOutput = JSON.stringify({
foobar: JSON.parse(foobarOutput)
})
const noElseGreetingOutput = JSON.stringify({})
test('if-then-else', async t => {
const tests = [
{
name: 'foobar',
schema,
input: fooBarInput,
expected: foobarOutput
},
{
name: 'greeting',
schema,
input: greetingInput,
expected: greetingOutput
},
{
name: 'if nested - then then',
schema: nestedIfSchema,
input: fooBarInput,
expected: foobarOutput
},
{
name: 'if nested - then else',
schema: nestedIfSchema,
input: greetingInput,
expected: greetingOutput
},
{
name: 'if nested - else',
schema: nestedIfSchema,
input: alphabetInput,
expected: alphabetOutput
},
{
name: 'else nested - then',
schema: nestedElseSchema,
input: fooBarInput,
expected: foobarOutput
},
{
name: 'else nested - else then',
schema: nestedElseSchema,
input: greetingInput,
expected: greetingOutput
},
{
name: 'else nested - else else',
schema: nestedElseSchema,
input: alphabetInput,
expected: alphabetOutput
},
{
name: 'deep then - else',
schema: nestedDeepElseSchema,
input: deepFoobarInput,
expected: deepFoobarOutput
},
{
name: 'no else',
schema: noElseSchema,
input: greetingInput,
expected: noElseGreetingOutput
}
]
for (const { name, schema, input, expected } of tests) {
await t.test(name + ' - normal', async t => {
t.plan(1)
const stringify = build(JSON.parse(JSON.stringify(schema)), { ajv: { strictTypes: false } })
const serialized = stringify(input)
t.assert.equal(serialized, expected)
})
}
})
test('nested if/then', t => {
t.plan(2)
const schema = {
type: 'object',
properties: { a: { type: 'string' } },
if: {
type: 'object',
properties: { foo: { type: 'string' } }
},
then: {
properties: { bar: { type: 'string' } },
if: {
type: 'object',
properties: { foo1: { type: 'string' } }
},
then: {
properties: { bar1: { type: 'string' } }
}
}
}
const stringify = build(schema)
t.assert.equal(
stringify({ a: 'A', foo: 'foo', bar: 'bar' }),
JSON.stringify({ a: 'A', bar: 'bar' })
)
t.assert.equal(
stringify({ a: 'A', foo: 'foo', bar: 'bar', foo1: 'foo1', bar1: 'bar1' }),
JSON.stringify({ a: 'A', bar: 'bar', bar1: 'bar1' })
)
})
test('if/else with string format', (t) => {
t.plan(2)
const schema = {
if: { type: 'string' },
then: { type: 'string', format: 'date' },
else: { const: 'Invalid' }
}
const stringify = build(schema)
const date = new Date(1674263005800)
t.assert.equal(stringify(date), '"2023-01-21"')
t.assert.equal(stringify('Invalid'), '"Invalid"')
})
test('if/else with const integers', (t) => {
t.plan(2)
const schema = {
type: 'number',
if: { type: 'number', minimum: 42 },
then: { const: 66 },
else: { const: 33 }
}
const stringify = build(schema)
t.assert.equal(stringify(100.32), '66')
t.assert.equal(stringify(10.12), '33')
})
test('if/else with array', (t) => {
t.plan(2)
const schema = {
type: 'array',
if: { type: 'array', maxItems: 1 },
then: { items: { type: 'string' } },
else: { items: { type: 'number' } }
}
const stringify = build(schema)
t.assert.equal(stringify(['1']), JSON.stringify(['1']))
t.assert.equal(stringify(['1', '2']), JSON.stringify([1, 2]))
})
test('external recursive if/then/else', (t) => {
t.plan(1)
const externalSchema = {
type: 'object',
properties: {
base: { type: 'string' },
self: { $ref: 'externalSchema#' }
},
if: {
type: 'object',
properties: {
foo: { type: 'string', const: '41' }
}
},
then: {
type: 'object',
properties: {
bar: { type: 'string', const: '42' }
}
},
else: {
type: 'object',
properties: {
baz: { type: 'string', const: '43' }
}
}
}
const schema = {
type: 'object',
properties: {
a: { $ref: 'externalSchema#/properties/self' },
b: { $ref: 'externalSchema#/properties/self' }
}
}
const data = {
a: {
base: 'a',
foo: '41',
bar: '42',
baz: '43',
ignore: 'ignored'
},
b: {
base: 'b',
foo: 'not-41',
bar: '42',
baz: '43',
ignore: 'ignored'
}
}
const stringify = build(schema, { schema: { externalSchema } })
t.assert.equal(stringify(data), '{"a":{"base":"a","bar":"42"},"b":{"base":"b","baz":"43"}}')
})

View File

@@ -0,0 +1,92 @@
'use strict'
const { test } = require('node: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.assert.deepStrictEqual(JSON.parse(output), toStringify)
t.assert.equal(output, JSON.stringify(toStringify))
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
}
buildTest({
title: 'infer type object by keyword',
// 'type': 'object',
properties: {
name: {
type: 'string'
}
}
}, {
name: 'foo'
})
buildTest({
title: 'infer type of nested object by keyword',
// 'type': 'object',
properties: {
more: {
description: 'more properties',
// 'type': 'object',
properties: {
something: {
type: 'string'
}
}
}
}
}, {
more: {
something: 'else'
}
})
buildTest({
title: 'infer type array by keyword',
type: 'object',
properties: {
ids: {
// 'type': 'array',
items: {
type: 'string'
}
}
}
}, {
ids: ['test']
})
buildTest({
title: 'infer type string by keyword',
type: 'object',
properties: {
name: {
// 'type': 'string',
maxLength: 3
}
}
}, {
name: 'foo'
})
buildTest({
title: 'infer type number by keyword',
type: 'object',
properties: {
age: {
// 'type': 'number',
maximum: 18
}
}
}, {
age: 18
})

55
node_modules/fast-json-stringify/test/infinity.test.js generated vendored Normal file
View File

@@ -0,0 +1,55 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('Finite numbers', t => {
const values = [-5, 0, -0, 1.33, 99, 100.0,
Math.E, Number.EPSILON,
Number.MAX_SAFE_INTEGER, Number.MAX_VALUE,
Number.MIN_SAFE_INTEGER, Number.MIN_VALUE]
t.plan(values.length)
const schema = {
type: 'number'
}
const stringify = build(schema)
values.forEach(v => t.assert.equal(stringify(v), JSON.stringify(v)))
})
test('Infinite integers', t => {
const values = [Infinity, -Infinity]
t.plan(values.length)
const schema = {
type: 'integer'
}
const stringify = build(schema)
values.forEach(v => {
try {
stringify(v)
} catch (err) {
t.assert.equal(err.message, `The value "${v}" cannot be converted to an integer.`)
}
})
})
test('Infinite numbers', t => {
const values = [Infinity, -Infinity]
t.plan(values.length)
const schema = {
type: 'number'
}
const stringify = build(schema)
values.forEach(v => t.assert.equal(stringify(v), JSON.stringify(v)))
})

194
node_modules/fast-json-stringify/test/integer.test.js generated vendored Normal file
View File

@@ -0,0 +1,194 @@
'use strict'
const { test } = require('node:test')
const validator = require('is-my-json-valid')
const build = require('..')
const ROUNDING_TYPES = ['ceil', 'floor', 'round']
test('render an integer as JSON', (t) => {
t.plan(2)
const schema = {
title: 'integer',
type: 'integer'
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify(1615)
t.assert.equal(output, '1615')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a float as an integer', (t) => {
t.plan(2)
try {
build({
title: 'float as integer',
type: 'integer'
}, { rounding: 'foobar' })
} catch (error) {
t.assert.ok(error)
t.assert.equal(error.message, 'Unsupported integer rounding method foobar')
}
})
test('throws on NaN', (t) => {
t.plan(1)
const schema = {
title: 'integer',
type: 'integer'
}
const stringify = build(schema)
t.assert.throws(() => stringify(NaN), new Error('The value "NaN" cannot be converted to an integer.'))
})
test('render a float as an integer', (t) => {
const cases = [
{ input: Math.PI, output: '3' },
{ input: 5.0, output: '5' },
{ input: null, output: '0' },
{ input: 0, output: '0' },
{ input: 0.0, output: '0' },
{ input: 42, output: '42' },
{ input: 1.99999, output: '1' },
{ input: -45.05, output: '-45' },
{ input: 3333333333333333, output: '3333333333333333' },
{ input: Math.PI, output: '3', rounding: 'trunc' },
{ input: 5.0, output: '5', rounding: 'trunc' },
{ input: null, output: '0', rounding: 'trunc' },
{ input: 0, output: '0', rounding: 'trunc' },
{ input: 0.0, output: '0', rounding: 'trunc' },
{ input: 42, output: '42', rounding: 'trunc' },
{ input: 1.99999, output: '1', rounding: 'trunc' },
{ input: -45.05, output: '-45', rounding: 'trunc' },
{ input: 0.95, output: '1', rounding: 'ceil' },
{ input: 0.2, output: '1', rounding: 'ceil' },
{ input: 45.95, output: '45', rounding: 'floor' },
{ input: -45.05, output: '-46', rounding: 'floor' },
{ input: 45.44, output: '45', rounding: 'round' },
{ input: 45.95, output: '46', rounding: 'round' }
]
t.plan(cases.length * 2)
cases.forEach(checkInteger)
function checkInteger ({ input, output, rounding }) {
const schema = {
title: 'float as integer',
type: 'integer'
}
const validate = validator(schema)
const stringify = build(schema, { rounding })
const str = stringify(input)
t.assert.equal(str, output)
t.assert.ok(validate(JSON.parse(str)), 'valid schema')
}
})
test('render an object with an integer as JSON', (t) => {
t.plan(2)
const schema = {
title: 'object with integer',
type: 'object',
properties: {
id: {
type: 'integer'
}
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
id: 1615
})
t.assert.equal(output, '{"id":1615}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render an array with an integer as JSON', (t) => {
t.plan(2)
const schema = {
title: 'array with integer',
type: 'array',
items: {
type: 'integer'
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify([1615])
t.assert.equal(output, '[1615]')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render an object with an additionalProperty of type integer as JSON', (t) => {
t.plan(2)
const schema = {
title: 'object with integer',
type: 'object',
additionalProperties: {
type: 'integer'
}
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({
num: 1615
})
t.assert.equal(output, '{"num":1615}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('should round integer object parameter', t => {
t.plan(2)
const schema = { type: 'object', properties: { magic: { type: 'integer' } } }
const validate = validator(schema)
const stringify = build(schema, { rounding: 'ceil' })
const output = stringify({ magic: 4.2 })
t.assert.equal(output, '{"magic":5}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('should not stringify a property if it does not exist', t => {
t.plan(2)
const schema = { title: 'Example Schema', type: 'object', properties: { age: { type: 'integer' } } }
const validate = validator(schema)
const stringify = build(schema)
const output = stringify({})
t.assert.equal(output, '{}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
ROUNDING_TYPES.forEach((rounding) => {
test(`should not stringify a property if it does not exist (rounding: ${rounding})`, t => {
t.plan(2)
const schema = { type: 'object', properties: { magic: { type: 'integer' } } }
const validate = validator(schema)
const stringify = build(schema, { rounding })
const output = stringify({})
t.assert.equal(output, '{}')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
})

View File

@@ -0,0 +1,18 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
// Covers issue #139
test('Should throw on invalid schema', t => {
t.plan(1)
t.assert.throws(() => {
build({}, {
schema: {
invalid: {
type: 'Dinosaur'
}
}
})
}, { message: /^"invalid" schema is invalid:.*/ })
})

View File

@@ -0,0 +1,57 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('should validate anyOf after allOf merge', (t) => {
t.plan(1)
const schema = {
$id: 'schema',
type: 'object',
allOf: [
{
$id: 'base',
type: 'object',
properties: {
name: {
type: 'string'
}
},
required: [
'name'
]
},
{
$id: 'inner_schema',
type: 'object',
properties: {
union: {
$id: '#id',
anyOf: [
{
$id: 'guid',
type: 'string'
},
{
$id: 'email',
type: 'string'
}
]
}
},
required: [
'union'
]
}
]
}
const stringify = build(schema)
t.assert.equal(
stringify({ name: 'foo', union: 'a8f1cc50-5530-5c62-9109-5ba9589a6ae1' }),
'{"name":"foo","union":"a8f1cc50-5530-5c62-9109-5ba9589a6ae1"}')
})

View File

@@ -0,0 +1,10 @@
# JSON-Schema-Test-Suite
You can find all test cases [here](https://github.com/json-schema-org/JSON-Schema-Test-Suite).
It contains a set of JSON objects that implementors of JSON Schema validation libraries can use to test their validators.
# How to add another test case?
1. Navigate to [JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite/tree/master/tests)
2. Choose a draft `draft4`, `draft6` or `draft7`
3. Copy & paste the `test-case.json` to the project and add a test like in the `draft4.test.js`

View File

@@ -0,0 +1,12 @@
'use strict'
const { test } = require('node:test')
const { counTests, runTests } = require('./util')
const requiredTestSuite = require('./draft4/required.json')
test('required', async (t) => {
const skippedTests = ['ignores arrays', 'ignores strings', 'ignores other non-objects']
t.plan(counTests(requiredTestSuite, skippedTests))
await runTests(t, requiredTestSuite, skippedTests)
})

View File

@@ -0,0 +1,54 @@
[
{
"description": "required validation",
"schema": {
"properties": {
"foo": {},
"bar": {}
},
"required": ["foo"]
},
"tests": [
{
"description": "present required property is valid",
"data": {"foo": 1},
"valid": true
},
{
"description": "non-present required property is invalid",
"data": {"bar": 1},
"valid": false
},
{
"description": "ignores arrays",
"data": [],
"valid": true
},
{
"description": "ignores strings",
"data": "",
"valid": true
},
{
"description": "ignores other non-objects",
"data": 12,
"valid": true
}
]
},
{
"description": "required default validation",
"schema": {
"properties": {
"foo": {}
}
},
"tests": [
{
"description": "not required by default",
"data": {},
"valid": true
}
]
}
]

View File

@@ -0,0 +1,12 @@
'use strict'
const { test } = require('node:test')
const { counTests, runTests } = require('./util')
const requiredTestSuite = require('./draft6/required.json')
test('required', async (t) => {
const skippedTests = ['ignores arrays', 'ignores strings', 'ignores other non-objects']
t.plan(counTests(requiredTestSuite, skippedTests))
await runTests(t, requiredTestSuite, skippedTests)
})

View File

@@ -0,0 +1,70 @@
[
{
"description": "required validation",
"schema": {
"properties": {
"foo": {},
"bar": {}
},
"required": ["foo"]
},
"tests": [
{
"description": "present required property is valid",
"data": {"foo": 1},
"valid": true
},
{
"description": "non-present required property is invalid",
"data": {"bar": 1},
"valid": false
},
{
"description": "ignores arrays",
"data": [],
"valid": true
},
{
"description": "ignores strings",
"data": "",
"valid": true
},
{
"description": "ignores other non-objects",
"data": 12,
"valid": true
}
]
},
{
"description": "required default validation",
"schema": {
"properties": {
"foo": {}
}
},
"tests": [
{
"description": "not required by default",
"data": {},
"valid": true
}
]
},
{
"description": "required with empty array",
"schema": {
"properties": {
"foo": {}
},
"required": []
},
"tests": [
{
"description": "property not required",
"data": {},
"valid": true
}
]
}
]

View File

@@ -0,0 +1,12 @@
'use strict'
const { test } = require('node:test')
const { counTests, runTests } = require('./util')
const requiredTestSuite = require('./draft7/required.json')
test('required', async (t) => {
const skippedTests = ['ignores arrays', 'ignores strings', 'ignores other non-objects']
t.plan(counTests(requiredTestSuite, skippedTests))
await runTests(t, requiredTestSuite, skippedTests)
})

View File

@@ -0,0 +1,70 @@
[
{
"description": "required validation",
"schema": {
"properties": {
"foo": {},
"bar": {}
},
"required": ["foo"]
},
"tests": [
{
"description": "present required property is valid",
"data": {"foo": 1},
"valid": true
},
{
"description": "non-present required property is invalid",
"data": {"bar": 1},
"valid": false
},
{
"description": "ignores arrays",
"data": [],
"valid": true
},
{
"description": "ignores strings",
"data": "",
"valid": true
},
{
"description": "ignores other non-objects",
"data": 12,
"valid": true
}
]
},
{
"description": "required default validation",
"schema": {
"properties": {
"foo": {}
}
},
"tests": [
{
"description": "not required by default",
"data": {},
"valid": true
}
]
},
{
"description": "required with empty array",
"schema": {
"properties": {
"foo": {}
},
"required": []
},
"tests": [
{
"description": "property not required",
"data": {},
"valid": true
}
]
}
]

View File

@@ -0,0 +1,31 @@
'use strict'
const build = require('../..')
async function runTests (t, testsuite, skippedTests) {
for (const scenario of testsuite) {
const stringify = build(scenario.schema)
for (const test of scenario.tests) {
if (skippedTests.indexOf(test.description) !== -1) {
console.log(`skip ${test.description}`)
continue
}
await t.test(test.description, (t) => {
t.plan(1)
try {
const output = stringify(test.data)
t.assert.equal(output, JSON.stringify(test.data), 'compare payloads')
} catch (err) {
t.assert.ok(test.valid === false, 'payload should be valid: ' + err.message)
}
})
}
}
}
function counTests (ts, skippedTests) {
return ts.reduce((a, b) => a + b.tests.length, 0) - skippedTests.length
}
module.exports = { runTests, counTests }

View File

@@ -0,0 +1,88 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('missing values', (t) => {
t.plan(3)
const stringify = build({
title: 'object with missing values',
type: 'object',
properties: {
str: {
type: 'string'
},
num: {
type: 'number'
},
val: {
type: 'string'
}
}
})
t.assert.equal('{"val":"value"}', stringify({ val: 'value' }))
t.assert.equal('{"str":"string","val":"value"}', stringify({ str: 'string', val: 'value' }))
t.assert.equal('{"str":"string","num":42,"val":"value"}', stringify({ str: 'string', num: 42, val: 'value' }))
})
test('handle null when value should be string', (t) => {
t.plan(1)
const stringify = build({
type: 'object',
properties: {
str: {
type: 'string'
}
}
})
t.assert.equal('{"str":""}', stringify({ str: null }))
})
test('handle null when value should be integer', (t) => {
t.plan(1)
const stringify = build({
type: 'object',
properties: {
int: {
type: 'integer'
}
}
})
t.assert.equal('{"int":0}', stringify({ int: null }))
})
test('handle null when value should be number', (t) => {
t.plan(1)
const stringify = build({
type: 'object',
properties: {
num: {
type: 'number'
}
}
})
t.assert.equal('{"num":0}', stringify({ num: null }))
})
test('handle null when value should be boolean', (t) => {
t.plan(1)
const stringify = build({
type: 'object',
properties: {
bool: {
type: 'boolean'
}
}
})
t.assert.equal('{"bool":false}', stringify({ bool: null }))
})

View File

@@ -0,0 +1,19 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('should throw a TypeError with the path to the key of the invalid value', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
num: {
type: ['number']
}
}
}
const stringify = build(schema)
t.assert.throws(() => stringify({ num: { bla: 123 } }), new TypeError('The value of \'#/properties/num\' does not match schema definition.'))
})

View File

@@ -0,0 +1,63 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('nested objects with same properties', (t) => {
t.plan(1)
const schema = {
title: 'nested objects with same properties',
type: 'object',
properties: {
stringProperty: {
type: 'string'
},
objectProperty: {
type: 'object',
additionalProperties: true
}
}
}
const stringify = build(schema)
const value = stringify({
stringProperty: 'string1',
objectProperty: {
stringProperty: 'string2',
numberProperty: 42
}
})
t.assert.equal(value, '{"stringProperty":"string1","objectProperty":{"stringProperty":"string2","numberProperty":42}}')
})
test('names collision', (t) => {
t.plan(1)
const schema = {
title: 'nested objects with same properties',
type: 'object',
properties: {
test: {
type: 'object',
properties: {
a: { type: 'string' }
}
},
tes: {
type: 'object',
properties: {
b: { type: 'string' },
t: { type: 'object' }
}
}
}
}
const stringify = build(schema)
const data = {
test: { a: 'a' },
tes: { b: 'b', t: {} }
}
t.assert.equal(stringify(data), JSON.stringify(data))
})

543
node_modules/fast-json-stringify/test/nullable.test.js generated vendored Normal file
View File

@@ -0,0 +1,543 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
const nullable = true
const complexObject = {
type: 'object',
properties: {
nullableString: { type: 'string', nullable },
nullableNumber: { type: 'number', nullable },
nullableInteger: { type: 'integer', nullable },
nullableBoolean: { type: 'boolean', nullable },
nullableNull: { type: 'null', nullable },
nullableArray: {
type: 'array',
nullable: true,
items: {}
},
nullableObject: { type: 'object', nullable: true },
objectWithNullableProps: {
type: 'object',
nullable: false,
additionalProperties: true,
properties: {
nullableString: { type: 'string', nullable },
nullableNumber: { type: 'number', nullable },
nullableInteger: { type: 'integer', nullable },
nullableBoolean: { type: 'boolean', nullable },
nullableNull: { type: 'null', nullable },
nullableArray: {
type: 'array',
nullable: true,
items: {}
}
}
},
arrayWithNullableItems: {
type: 'array',
nullable: true,
items: { type: ['integer', 'string'], nullable: true }
}
}
}
const complexData = {
nullableString: null,
nullableNumber: null,
nullableInteger: null,
nullableBoolean: null,
nullableNull: null,
nullableArray: null,
nullableObject: null,
objectWithNullableProps: {
additionalProp: null,
nullableString: null,
nullableNumber: null,
nullableInteger: null,
nullableBoolean: null,
nullableNull: null,
nullableArray: null
},
arrayWithNullableItems: [1, 2, null]
}
const complexExpectedResult = {
nullableString: null,
nullableNumber: null,
nullableInteger: null,
nullableBoolean: null,
nullableNull: null,
nullableArray: null,
nullableObject: null,
objectWithNullableProps: {
additionalProp: null,
nullableString: null,
nullableNumber: null,
nullableInteger: null,
nullableBoolean: null,
nullableNull: null,
nullableArray: null
},
arrayWithNullableItems: [1, 2, null]
}
const testSet = {
nullableString: [{ type: 'string', nullable }, null, null],
nullableNumber: [{ type: 'number', nullable }, null, null],
nullableInteger: [{ type: 'integer', nullable }, null, null],
nullableBoolean: [{ type: 'boolean', nullable }, null, null],
nullableNull: [{ type: 'null', nullable }, null, null],
nullableArray: [{
type: 'array',
nullable: true,
items: {}
}, null, null],
nullableObject: [{ type: 'object', nullable: true }, null, null],
complexObject: [complexObject, complexData, complexExpectedResult, { ajv: { allowUnionTypes: true } }]
}
Object.keys(testSet).forEach(key => {
test(`handle nullable:true in ${key} correctly`, (t) => {
t.plan(1)
const [
schema,
data,
expected,
extraOptions
] = testSet[key]
const stringifier = build(schema, extraOptions)
const result = stringifier(data)
t.assert.deepStrictEqual(JSON.parse(result), expected)
})
})
test('handle nullable number correctly', (t) => {
t.plan(2)
const schema = {
type: 'number',
nullable: true
}
const stringify = build(schema)
const data = null
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.equal(JSON.parse(result), data)
})
test('handle nullable integer correctly', (t) => {
t.plan(2)
const schema = {
type: 'integer',
nullable: true
}
const stringify = build(schema)
const data = null
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.equal(JSON.parse(result), data)
})
test('handle nullable boolean correctly', (t) => {
t.plan(2)
const schema = {
type: 'boolean',
nullable: true
}
const stringify = build(schema)
const data = null
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.equal(JSON.parse(result), data)
})
test('handle nullable string correctly', (t) => {
t.plan(2)
const schema = {
type: 'string',
nullable: true
}
const stringify = build(schema)
const data = null
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.equal(JSON.parse(result), data)
})
test('handle nullable date-time correctly', (t) => {
t.plan(2)
const schema = {
type: 'string',
format: 'date-time',
nullable: true
}
const stringify = build(schema)
const data = null
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.equal(JSON.parse(result), data)
})
test('handle nullable date correctly', (t) => {
t.plan(2)
const schema = {
type: 'string',
format: 'date',
nullable: true
}
const stringify = build(schema)
const data = null
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.equal(JSON.parse(result), data)
})
test('handle nullable time correctly', (t) => {
t.plan(2)
const schema = {
type: 'string',
format: 'time',
nullable: true
}
const stringify = build(schema)
const data = null
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.equal(JSON.parse(result), data)
})
test('large array of nullable strings with default mechanism', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
ids: {
type: 'array',
items: {
type: 'string',
nullable: true
}
}
}
}
const options = {
largeArraySize: 2e4,
largeArrayMechanism: 'default'
}
const stringify = build(schema, options)
const data = { ids: new Array(2e4).fill(null) }
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.deepStrictEqual(JSON.parse(result), data)
})
test('large array of nullable date-time strings with default mechanism', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
ids: {
type: 'array',
items: {
type: 'string',
format: 'date-time',
nullable: true
}
}
}
}
const options = {
largeArraySize: 2e4,
largeArrayMechanism: 'default'
}
const stringify = build(schema, options)
const data = { ids: new Array(2e4).fill(null) }
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.deepStrictEqual(JSON.parse(result), data)
})
test('large array of nullable date-time strings with default mechanism', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
ids: {
type: 'array',
items: {
type: 'string',
format: 'date',
nullable: true
}
}
}
}
const options = {
largeArraySize: 2e4,
largeArrayMechanism: 'default'
}
const stringify = build(schema, options)
const data = { ids: new Array(2e4).fill(null) }
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.deepStrictEqual(JSON.parse(result), data)
})
test('large array of nullable date-time strings with default mechanism', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
ids: {
type: 'array',
items: {
type: 'string',
format: 'time',
nullable: true
}
}
}
}
const options = {
largeArraySize: 2e4,
largeArrayMechanism: 'default'
}
const stringify = build(schema, options)
const data = { ids: new Array(2e4).fill(null) }
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.deepStrictEqual(JSON.parse(result), data)
})
test('large array of nullable numbers with default mechanism', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
ids: {
type: 'array',
items: {
type: 'number',
nullable: true
}
}
}
}
const options = {
largeArraySize: 2e4,
largeArrayMechanism: 'default'
}
const stringify = build(schema, options)
const data = { ids: new Array(2e4).fill(null) }
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.deepStrictEqual(JSON.parse(result), data)
})
test('large array of nullable integers with default mechanism', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
ids: {
type: 'array',
items: {
type: 'integer',
nullable: true
}
}
}
}
const options = {
largeArraySize: 2e4,
largeArrayMechanism: 'default'
}
const stringify = build(schema, options)
const data = { ids: new Array(2e4).fill(null) }
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.deepStrictEqual(JSON.parse(result), data)
})
test('large array of nullable booleans with default mechanism', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
ids: {
type: 'array',
items: {
type: 'boolean',
nullable: true
}
}
}
}
const options = {
largeArraySize: 2e4,
largeArrayMechanism: 'default'
}
const stringify = build(schema, options)
const data = { ids: new Array(2e4).fill(null) }
const result = stringify(data)
t.assert.equal(result, JSON.stringify(data))
t.assert.deepStrictEqual(JSON.parse(result), data)
})
test('nullable type in the schema', (t) => {
t.plan(2)
const schema = {
type: ['object', 'null'],
properties: {
foo: {
type: 'string'
}
}
}
const stringify = build(schema)
const data = { foo: 'bar' }
t.assert.equal(stringify(data), JSON.stringify(data))
t.assert.equal(stringify(null), JSON.stringify(null))
})
test('throw an error if the value doesn\'t match the type', (t) => {
t.plan(2)
const schema = {
type: 'object',
additionalProperties: false,
required: ['data'],
properties: {
data: {
type: 'array',
minItems: 1,
items: {
oneOf: [
{
type: 'string'
},
{
type: 'number'
}
]
}
}
}
}
const stringify = build(schema)
const validData = { data: [1, 'testing'] }
t.assert.equal(stringify(validData), JSON.stringify(validData))
const invalidData = { data: [false, 'testing'] }
t.assert.throws(() => stringify(invalidData))
})
test('nullable value in oneOf', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
data: {
oneOf: [
{
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'integer', minimum: 1 }
},
additionalProperties: false,
required: ['id']
}
},
{
type: 'array',
items: {
type: 'object',
properties: {
job: { type: 'string', nullable: true }
},
additionalProperties: false,
required: ['job']
}
}
]
}
},
required: ['data'],
additionalProperties: false
}
const stringify = build(schema)
const data = { data: [{ job: null }] }
t.assert.equal(stringify(data), JSON.stringify(data))
})

490
node_modules/fast-json-stringify/test/oneof.test.js generated vendored Normal file
View File

@@ -0,0 +1,490 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('object with multiple types field', (t) => {
t.plan(2)
const schema = {
title: 'object with multiple types field',
type: 'object',
properties: {
str: {
oneOf: [{
type: 'string'
}, {
type: 'boolean'
}]
}
}
}
const stringify = build(schema)
t.assert.equal(stringify({ str: 'string' }), '{"str":"string"}')
t.assert.equal(stringify({ str: true }), '{"str":true}')
})
test('object with field of type object or null', (t) => {
t.plan(2)
const schema = {
title: 'object with field of type object or null',
type: 'object',
properties: {
prop: {
oneOf: [{
type: 'object',
properties: {
str: {
type: 'string'
}
}
}, {
type: 'null'
}]
}
}
}
const stringify = build(schema)
t.assert.equal(stringify({ prop: null }), '{"prop":null}')
t.assert.equal(stringify({
prop: {
str: 'string', remove: 'this'
}
}), '{"prop":{"str":"string"}}')
})
test('object with field of type object or array', (t) => {
t.plan(2)
const schema = {
title: 'object with field of type object or array',
type: 'object',
properties: {
prop: {
oneOf: [{
type: 'object',
properties: {},
additionalProperties: true
}, {
type: 'array',
items: {
type: 'string'
}
}]
}
}
}
const stringify = build(schema)
t.assert.equal(stringify({
prop: { str: 'string' }
}), '{"prop":{"str":"string"}}')
t.assert.equal(stringify({
prop: ['string']
}), '{"prop":["string"]}')
})
test('object with field of type string and coercion disable ', (t) => {
t.plan(1)
const schema = {
title: 'object with field of type string',
type: 'object',
properties: {
str: {
oneOf: [{
type: 'string'
}]
}
}
}
const stringify = build(schema)
t.assert.throws(() => stringify({ str: 1 }))
})
test('object with field of type string and coercion enable ', (t) => {
t.plan(1)
const schema = {
title: 'object with field of type string',
type: 'object',
properties: {
str: {
oneOf: [{
type: 'string'
}]
}
}
}
const options = {
ajv: {
coerceTypes: true
}
}
const stringify = build(schema, options)
const value = stringify({
str: 1
})
t.assert.equal(value, '{"str":"1"}')
})
test('object with field with type union of multiple objects', (t) => {
t.plan(2)
const schema = {
title: 'object with oneOf property value containing objects',
type: 'object',
properties: {
oneOfSchema: {
oneOf: [
{
type: 'object',
properties: {
baz: { type: 'number' }
},
required: ['baz']
},
{
type: 'object',
properties: {
bar: { type: 'string' }
},
required: ['bar']
}
]
}
},
required: ['oneOfSchema']
}
const stringify = build(schema)
t.assert.equal(stringify({ oneOfSchema: { baz: 5 } }), '{"oneOfSchema":{"baz":5}}')
t.assert.equal(stringify({ oneOfSchema: { bar: 'foo' } }), '{"oneOfSchema":{"bar":"foo"}}')
})
test('null value in schema', (t) => {
t.plan(0)
const schema = {
title: 'schema with null child',
type: 'string',
nullable: true,
enum: [null]
}
build(schema)
})
test('oneOf and $ref together', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
cs: {
oneOf: [
{
$ref: '#/definitions/Option'
},
{
type: 'boolean'
}
]
}
},
definitions: {
Option: {
type: 'string'
}
}
}
const stringify = build(schema)
t.assert.equal(stringify({ cs: 'franco' }), '{"cs":"franco"}')
t.assert.equal(stringify({ cs: true }), '{"cs":true}')
})
test('oneOf and $ref: 2 levels are fine', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
cs: {
oneOf: [
{
$ref: '#/definitions/Option'
},
{
type: 'boolean'
}
]
}
},
definitions: {
Option: {
oneOf: [
{
type: 'number'
},
{
type: 'boolean'
}
]
}
}
}
const stringify = build(schema)
const value = stringify({
cs: 3
})
t.assert.equal(value, '{"cs":3}')
})
test('oneOf and $ref: multiple levels should throw at build.', (t) => {
t.plan(3)
const schema = {
type: 'object',
properties: {
cs: {
oneOf: [
{
$ref: '#/definitions/Option'
},
{
type: 'boolean'
}
]
}
},
definitions: {
Option: {
oneOf: [
{
$ref: '#/definitions/Option2'
},
{
type: 'string'
}
]
},
Option2: {
type: 'number'
}
}
}
const stringify = build(schema)
t.assert.equal(stringify({ cs: 3 }), '{"cs":3}')
t.assert.equal(stringify({ cs: true }), '{"cs":true}')
t.assert.equal(stringify({ cs: 'pippo' }), '{"cs":"pippo"}')
})
test('oneOf and $ref - multiple external $ref', (t) => {
t.plan(2)
const externalSchema = {
external: {
definitions: {
def: {
type: 'object',
properties: {
prop: { oneOf: [{ $ref: 'external2#/definitions/other' }] }
}
}
}
},
external2: {
definitions: {
internal: {
type: 'string'
},
other: {
type: 'object',
properties: {
prop2: { $ref: '#/definitions/internal' }
}
}
}
}
}
const schema = {
title: 'object with $ref',
type: 'object',
properties: {
obj: {
$ref: 'external#/definitions/def'
}
}
}
const object = {
obj: {
prop: {
prop2: 'test'
}
}
}
const stringify = build(schema, { schema: externalSchema })
const output = stringify(object)
t.assert.doesNotThrow(() => JSON.parse(output))
t.assert.equal(output, '{"obj":{"prop":{"prop2":"test"}}}')
})
test('oneOf with enum with more than 100 entries', (t) => {
t.plan(1)
const schema = {
title: 'type array that may have one of declared items',
type: 'array',
items: {
oneOf: [
{
type: 'string',
enum: ['EUR', 'USD', ...(new Set([...new Array(200)].map(() => Math.random().toString(36).substr(2, 3)))).values()]
},
{ type: 'null' }
]
}
}
const stringify = build(schema)
const value = stringify(['EUR', 'USD', null])
t.assert.equal(value, '["EUR","USD",null]')
})
test('oneOf object with field of type string with format or null', (t) => {
t.plan(1)
const toStringify = new Date()
const withOneOfSchema = {
type: 'object',
properties: {
prop: {
oneOf: [{
type: 'string',
format: 'date-time'
}, {
type: 'null'
}]
}
}
}
const withOneOfStringify = build(withOneOfSchema)
t.assert.equal(withOneOfStringify({
prop: toStringify
}), `{"prop":"${toStringify.toISOString()}"}`)
})
test('one array item match oneOf types', (t) => {
t.plan(3)
const schema = {
type: 'object',
additionalProperties: false,
required: ['data'],
properties: {
data: {
type: 'array',
minItems: 1,
items: {
oneOf: [
{
type: 'string'
},
{
type: 'number'
}
]
}
}
}
}
const stringify = build(schema)
t.assert.equal(stringify({ data: ['foo'] }), '{"data":["foo"]}')
t.assert.equal(stringify({ data: [1] }), '{"data":[1]}')
t.assert.throws(() => stringify({ data: [false, 'foo'] }))
})
test('some array items match oneOf types', (t) => {
t.plan(2)
const schema = {
type: 'object',
additionalProperties: false,
required: ['data'],
properties: {
data: {
type: 'array',
minItems: 1,
items: {
oneOf: [
{
type: 'string'
},
{
type: 'number'
}
]
}
}
}
}
const stringify = build(schema)
t.assert.equal(stringify({ data: ['foo', 5] }), '{"data":["foo",5]}')
t.assert.throws(() => stringify({ data: [false, 'foo', true, 5] }))
})
test('all array items does not match oneOf types', (t) => {
t.plan(1)
const schema = {
type: 'object',
additionalProperties: false,
required: ['data'],
properties: {
data: {
type: 'array',
minItems: 1,
items: {
oneOf: [
{
type: 'string'
},
{
type: 'number'
}
]
}
}
}
}
const stringify = build(schema)
t.assert.throws(() => stringify({ data: [null, false, true, undefined, [], {}] }))
})

View File

@@ -0,0 +1,168 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('patternProperties', (t) => {
t.plan(1)
const stringify = build({
title: 'patternProperties',
type: 'object',
properties: {
str: {
type: 'string'
}
},
patternProperties: {
foo: {
type: 'string'
}
}
})
const obj = { str: 'test', foo: 42, ofoo: true, foof: 'string', objfoo: { a: true }, notMe: false }
t.assert.equal(stringify(obj), '{"str":"test","foo":"42","ofoo":"true","foof":"string","objfoo":"[object Object]"}')
})
test('patternProperties should not change properties', (t) => {
t.plan(1)
const stringify = build({
title: 'patternProperties should not change properties',
type: 'object',
properties: {
foo: {
type: 'string'
}
},
patternProperties: {
foo: {
type: 'number'
}
}
})
const obj = { foo: '42', ofoo: 42 }
t.assert.equal(stringify(obj), '{"foo":"42","ofoo":42}')
})
test('patternProperties - string coerce', (t) => {
t.plan(1)
const stringify = build({
title: 'check string coerce',
type: 'object',
properties: {},
patternProperties: {
foo: {
type: 'string'
}
}
})
const obj = { foo: true, ofoo: 42, arrfoo: ['array', 'test'], objfoo: { a: 'world' } }
t.assert.equal(stringify(obj), '{"foo":"true","ofoo":"42","arrfoo":"array,test","objfoo":"[object Object]"}')
})
test('patternProperties - number coerce', (t) => {
t.plan(2)
const stringify = build({
title: 'check number coerce',
type: 'object',
properties: {},
patternProperties: {
foo: {
type: 'number'
}
}
})
const coercibleValues = { foo: true, ofoo: '42' }
t.assert.equal(stringify(coercibleValues), '{"foo":1,"ofoo":42}')
const incoercibleValues = { xfoo: 'string', arrfoo: [1, 2], objfoo: { num: 42 } }
try {
stringify(incoercibleValues)
t.fail('should throw an error')
} catch (err) {
t.assert.ok(err)
}
})
test('patternProperties - boolean coerce', (t) => {
t.plan(1)
const stringify = build({
title: 'check boolean coerce',
type: 'object',
properties: {},
patternProperties: {
foo: {
type: 'boolean'
}
}
})
const obj = { foo: 'true', ofoo: 0, arrfoo: [1, 2], objfoo: { a: true } }
t.assert.equal(stringify(obj), '{"foo":true,"ofoo":false,"arrfoo":true,"objfoo":true}')
})
test('patternProperties - object coerce', (t) => {
t.plan(1)
const stringify = build({
title: 'check object coerce',
type: 'object',
properties: {},
patternProperties: {
foo: {
type: 'object',
properties: {
answer: {
type: 'number'
}
}
}
}
})
const obj = { objfoo: { answer: 42 } }
t.assert.equal(stringify(obj), '{"objfoo":{"answer":42}}')
})
test('patternProperties - array coerce', (t) => {
t.plan(2)
const stringify = build({
title: 'check array coerce',
type: 'object',
properties: {},
patternProperties: {
foo: {
type: 'array',
items: {
type: 'string'
}
}
}
})
const coercibleValues = { arrfoo: [1, 2] }
t.assert.equal(stringify(coercibleValues), '{"arrfoo":["1","2"]}')
const incoercibleValues = { foo: 'true', ofoo: 0, objfoo: { tyrion: 'lannister' } }
t.assert.throws(() => stringify(incoercibleValues))
})
test('patternProperties - fail on invalid regex, handled by ajv', (t) => {
t.plan(1)
t.assert.throws(() => build({
title: 'check array coerce',
type: 'object',
properties: {},
patternProperties: {
'foo/\\': {
type: 'array',
items: {
type: 'string'
}
}
}
}), new Error('schema is invalid: data/patternProperties must match format "regex"'))
})

245
node_modules/fast-json-stringify/test/recursion.test.js generated vendored Normal file
View File

@@ -0,0 +1,245 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('can stringify recursive directory tree (issue #181)', (t) => {
t.plan(1)
const schema = {
definitions: {
directory: {
type: 'object',
properties: {
name: { type: 'string' },
subDirectories: {
type: 'array',
items: { $ref: '#/definitions/directory' },
default: []
}
}
}
},
type: 'array',
items: { $ref: '#/definitions/directory' }
}
const stringify = build(schema)
t.assert.equal(stringify([
{ name: 'directory 1', subDirectories: [] },
{
name: 'directory 2',
subDirectories: [
{ name: 'directory 2.1', subDirectories: [] },
{ name: 'directory 2.2', subDirectories: [] }
]
}
]), '[{"name":"directory 1","subDirectories":[]},{"name":"directory 2","subDirectories":[{"name":"directory 2.1","subDirectories":[]},{"name":"directory 2.2","subDirectories":[]}]}]')
})
test('can stringify when recursion in external schema', t => {
t.plan(1)
const referenceSchema = {
$id: 'person',
type: 'object',
properties: {
name: { type: 'string' },
children: {
type: 'array',
items: { $ref: '#' }
}
}
}
const schema = {
$id: 'mainSchema',
type: 'object',
properties: {
people: {
$ref: 'person'
}
}
}
const stringify = build(schema, {
schema: {
[referenceSchema.$id]: referenceSchema
}
})
const value = stringify({ people: { name: 'Elizabeth', children: [{ name: 'Charles' }] } })
t.assert.equal(value, '{"people":{"name":"Elizabeth","children":[{"name":"Charles"}]}}')
})
test('use proper serialize function', t => {
t.plan(1)
const personSchema = {
$id: 'person',
type: 'object',
properties: {
name: { type: 'string' },
children: {
type: 'array',
items: { $ref: '#' }
}
}
}
const directorySchema = {
$id: 'directory',
type: 'object',
properties: {
name: { type: 'string' },
subDirectories: {
type: 'array',
items: { $ref: '#' },
default: []
}
}
}
const schema = {
$id: 'mainSchema',
type: 'object',
properties: {
people: { $ref: 'person' },
directory: { $ref: 'directory' }
}
}
const stringify = build(schema, {
schema: {
[personSchema.$id]: personSchema,
[directorySchema.$id]: directorySchema
}
})
const value = stringify({
people: {
name: 'Elizabeth',
children: [{
name: 'Charles',
children: [{ name: 'William', children: [{ name: 'George' }, { name: 'Charlotte' }] }, { name: 'Harry' }]
}]
},
directory: {
name: 'directory 1',
subDirectories: [
{ name: 'directory 1.1', subDirectories: [] },
{
name: 'directory 1.2',
subDirectories: [{ name: 'directory 1.2.1' }, { name: 'directory 1.2.2' }]
}
]
}
})
t.assert.equal(value, '{"people":{"name":"Elizabeth","children":[{"name":"Charles","children":[{"name":"William","children":[{"name":"George"},{"name":"Charlotte"}]},{"name":"Harry"}]}]},"directory":{"name":"directory 1","subDirectories":[{"name":"directory 1.1","subDirectories":[]},{"name":"directory 1.2","subDirectories":[{"name":"directory 1.2.1","subDirectories":[]},{"name":"directory 1.2.2","subDirectories":[]}]}]}}')
})
test('can stringify recursive references in object types (issue #365)', t => {
t.plan(1)
const schema = {
type: 'object',
definitions: {
parentCategory: {
type: 'object',
properties: {
parent: {
$ref: '#/definitions/parentCategory'
}
}
}
},
properties: {
category: {
type: 'object',
properties: {
parent: {
$ref: '#/definitions/parentCategory'
}
}
}
}
}
const stringify = build(schema)
const data = {
category: {
parent: {
parent: {
parent: {
parent: {}
}
}
}
}
}
const value = stringify(data)
t.assert.equal(value, '{"category":{"parent":{"parent":{"parent":{"parent":{}}}}}}')
})
test('can stringify recursive inline $id references (issue #410)', t => {
t.plan(1)
const schema = {
$id: 'Node',
type: 'object',
properties: {
id: {
type: 'string'
},
nodes: {
type: 'array',
items: {
$ref: 'Node'
}
}
},
required: [
'id',
'nodes'
]
}
const stringify = build(schema)
const data = {
id: '0',
nodes: [
{
id: '1',
nodes: [{
id: '2',
nodes: [
{ id: '3', nodes: [] },
{ id: '4', nodes: [] },
{ id: '5', nodes: [] }
]
}]
},
{
id: '6',
nodes: [{
id: '7',
nodes: [
{ id: '8', nodes: [] },
{ id: '9', nodes: [] },
{ id: '10', nodes: [] }
]
}]
},
{
id: '11',
nodes: [{
id: '12',
nodes: [
{ id: '13', nodes: [] },
{ id: '14', nodes: [] },
{ id: '15', nodes: [] }
]
}]
}
]
}
const value = stringify(data)
t.assert.equal(value, '{"id":"0","nodes":[{"id":"1","nodes":[{"id":"2","nodes":[{"id":"3","nodes":[]},{"id":"4","nodes":[]},{"id":"5","nodes":[]}]}]},{"id":"6","nodes":[{"id":"7","nodes":[{"id":"8","nodes":[]},{"id":"9","nodes":[]},{"id":"10","nodes":[]}]}]},{"id":"11","nodes":[{"id":"12","nodes":[{"id":"13","nodes":[]},{"id":"14","nodes":[]},{"id":"15","nodes":[]}]}]}]}')
})

12
node_modules/fast-json-stringify/test/ref.json generated vendored Normal file
View File

@@ -0,0 +1,12 @@
{
"definitions": {
"def": {
"type": "object",
"properties": {
"str": {
"type": "string"
}
}
}
}
}

2046
node_modules/fast-json-stringify/test/ref.test.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

32
node_modules/fast-json-stringify/test/regex.test.js generated vendored Normal file
View File

@@ -0,0 +1,32 @@
'use strict'
const { test } = require('node:test')
const validator = require('is-my-json-valid')
const build = require('..')
test('object with RexExp', (t) => {
t.plan(3)
const schema = {
title: 'object with RegExp',
type: 'object',
properties: {
reg: {
type: 'string'
}
}
}
const obj = {
reg: /"([^"]|\\")*"/
}
const stringify = build(schema)
const validate = validator(schema)
const output = stringify(obj)
t.assert.doesNotThrow(() => JSON.parse(output))
t.assert.equal(obj.reg.source, new RegExp(JSON.parse(output).reg).source)
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})

204
node_modules/fast-json-stringify/test/required.test.js generated vendored Normal file
View File

@@ -0,0 +1,204 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('object with required field', (t) => {
t.plan(2)
const schema = {
title: 'object with required field',
type: 'object',
properties: {
str: {
type: 'string'
},
num: {
type: 'integer'
}
},
required: ['str']
}
const stringify = build(schema)
t.assert.doesNotThrow(() => {
stringify({
str: 'string'
})
})
t.assert.throws(() => {
stringify({
num: 42
})
}, { message: '"str" is required!' })
})
test('object with required field not in properties schema', (t) => {
t.plan(2)
const schema = {
title: 'object with required field',
type: 'object',
properties: {
num: {
type: 'integer'
}
},
required: ['str']
}
const stringify = build(schema)
t.assert.throws(() => {
stringify({})
}, { message: '"str" is required!' })
t.assert.throws(() => {
stringify({
num: 42
})
}, { message: '"str" is required!' })
})
test('object with required field not in properties schema with additional properties true', (t) => {
t.plan(2)
const schema = {
title: 'object with required field',
type: 'object',
properties: {
num: {
type: 'integer'
}
},
additionalProperties: true,
required: ['str']
}
const stringify = build(schema)
t.assert.throws(() => {
stringify({})
}, { message: '"str" is required!' })
t.assert.throws(() => {
stringify({
num: 42
})
}, { message: '"str" is required!' })
})
test('object with multiple required field not in properties schema', (t) => {
t.plan(3)
const schema = {
title: 'object with required field',
type: 'object',
properties: {
num: {
type: 'integer'
}
},
additionalProperties: true,
required: ['num', 'key1', 'key2']
}
const stringify = build(schema)
t.assert.throws(() => {
stringify({})
}, { message: '"key1" is required!' })
t.assert.throws(() => {
stringify({
key1: 42,
key2: 42
})
}, { message: '"num" is required!' })
t.assert.throws(() => {
stringify({
num: 42,
key1: 'some'
})
}, { message: '"key2" is required!' })
})
test('object with required bool', (t) => {
t.plan(2)
const schema = {
title: 'object with required field',
type: 'object',
properties: {
num: {
type: 'integer'
}
},
additionalProperties: true,
required: ['bool']
}
const stringify = build(schema)
t.assert.throws(() => {
stringify({})
}, { message: '"bool" is required!' })
t.assert.doesNotThrow(() => {
stringify({
bool: false
})
})
})
test('required nullable', (t) => {
t.plan(1)
const schema = {
title: 'object with required field',
type: 'object',
properties: {
num: {
type: ['integer']
}
},
additionalProperties: true,
required: ['null']
}
const stringify = build(schema)
t.assert.doesNotThrow(() => {
stringify({
null: null
})
})
})
test('required numbers', (t) => {
t.plan(2)
const schema = {
title: 'object with required field',
type: 'object',
properties: {
str: {
type: 'string'
},
num: {
type: 'integer'
}
},
required: ['num']
}
const stringify = build(schema)
t.assert.doesNotThrow(() => {
stringify({
num: 42
})
})
t.assert.throws(() => {
stringify({
num: 'aaa'
})
}, { message: 'The value "aaa" cannot be converted to an integer.' })
})

View File

@@ -0,0 +1,50 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('nested ref requires ajv', async t => {
t.test('nested ref requires ajv', async t => {
const schemaA = {
$id: 'urn:schema:a',
definitions: {
foo: { anyOf: [{ type: 'string' }, { type: 'null' }] }
}
}
const schemaB = {
$id: 'urn:schema:b',
type: 'object',
properties: {
results: {
type: 'object',
properties: {
items: {
type: 'object',
properties: {
bar: {
type: 'array',
items: { $ref: 'urn:schema:a#/definitions/foo' }
}
}
}
}
}
}
}
const stringify = build(schemaB, {
schema: {
[schemaA.$id]: schemaA
}
})
const result = stringify({
results: {
items: {
bar: ['baz']
}
}
})
t.assert.equal(result, '{"results":{"items":{"bar":["baz"]}}}')
})
})

141
node_modules/fast-json-stringify/test/sanitize.test.js generated vendored Normal file
View File

@@ -0,0 +1,141 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
const stringify = build({
title: 'Example Schema',
type: 'object',
properties: {
firstName: {
type: 'string'
},
lastName: {
type: 'string'
},
age: {
description: 'Age in years"',
type: 'integer'
},
[(() => "phra'&& process.exit(1) ||'phra")()]: {},
now: {
type: 'string'
},
reg: {
type: 'string',
default: 'a\'&& process.exit(1) ||\''
},
obj: {
type: 'object',
properties: {
bool: {
type: 'boolean'
}
}
},
'"\'w00t': {
type: 'string',
default: '"\'w00t'
},
arr: {
type: 'array',
items: {
type: 'object',
properties: {
'phra\' && process.exit(1)//': {
type: 'number'
},
str: {
type: 'string'
}
}
}
}
},
required: ['now'],
patternProperties: {
'.*foo$': {
type: 'string'
},
test: {
type: 'number'
},
'phra\'/ && process.exit(1) && /\'': {
type: 'number'
},
'"\'w00t.*////': {
type: 'number'
}
},
additionalProperties: {
type: 'string'
}
})
const obj = {
firstName: 'Matteo',
lastName: 'Collina',
age: 32,
now: new Date(),
foo: 'hello"',
bar: "world'",
'fuzz"': 42,
"me'": 42,
numfoo: 42,
test: 42,
strtest: '23',
arr: [{ 'phra\' && process.exit(1)//': 42 }],
obj: { bool: true },
notmatch: 'valar morghulis',
notmatchobj: { a: true },
notmatchnum: 42
}
test('sanitize', t => {
const json = stringify(obj)
t.assert.doesNotThrow(() => JSON.parse(json))
const stringify2 = build({
title: 'Example Schema',
type: 'object',
patternProperties: {
'"\'w00t.*////': {
type: 'number'
}
}
})
t.assert.deepStrictEqual(JSON.parse(stringify2({
'"\'phra////': 42,
asd: 42
})), {
})
const stringify3 = build({
title: 'Example Schema',
type: 'object',
properties: {
"\"phra\\'&&(console.log(42))//||'phra": {}
}
})
// this verifies the escaping
JSON.parse(stringify3({
'"phra\'&&(console.log(42))//||\'phra': 42
}))
const stringify4 = build({
title: 'Example Schema',
type: 'object',
properties: {
'"\\\\\\\\\'w00t': {
type: 'string',
default: '"\'w00t'
}
}
})
t.assert.deepStrictEqual(JSON.parse(stringify4({})), {
'"\\\\\\\\\'w00t': '"\'w00t'
})
})

View File

@@ -0,0 +1,18 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('sanitize 2', t => {
const payload = '(throw "pwoned")'
const stringify = build({
properties: {
[`*///\\\\\\']);${payload};{/*`]: {
type: 'number'
}
}
})
t.assert.doesNotThrow(() => stringify({}))
})

View File

@@ -0,0 +1,17 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('sanitize 3', t => {
t.assert.throws(() => {
build({
$defs: {
type: 'foooo"bar'
},
patternProperties: {
x: { $ref: '#/$defs' }
}
})
}, { message: 'foooo"bar unsupported' })
})

View File

@@ -0,0 +1,16 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('sanitize 4', t => {
const payload = '(throw "pwoned")'
const stringify = build({
required: [`"];${payload}//`]
})
t.assert.throws(() => {
stringify({})
}, { message: '""];(throw "pwoned")//" is required!' })
})

View File

@@ -0,0 +1,16 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('sanitize 5', t => {
const payload = '(throw "pwoned")'
t.assert.throws(() => {
build({
patternProperties: {
'*': { type: `*/${payload}){//` }
}
})
}, { message: 'schema is invalid: data/patternProperties must match format "regex"' })
})

View File

@@ -0,0 +1,22 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('sanitize 6', t => {
const payload = '(throw "pwoned")'
const stringify = build({
type: 'object',
properties: {
'/*': { type: 'object' },
x: {
type: 'object',
properties: {
a: { type: 'string', default: `*/}${payload};{//` }
}
}
}
})
t.assert.doesNotThrow(() => { stringify({}) })
})

View File

@@ -0,0 +1,68 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('required property containing single quote, contains property', (t) => {
t.plan(1)
const stringify = build({
type: 'object',
properties: {
'\'': { type: 'string' }
},
required: [
'\''
]
})
t.assert.throws(() => stringify({}), new Error('"\'" is required!'))
})
test('required property containing double quote, contains property', (t) => {
t.plan(1)
const stringify = build({
type: 'object',
properties: {
'"': { type: 'string' }
},
required: [
'"'
]
})
t.assert.throws(() => stringify({}), new Error('""" is required!'))
})
test('required property containing single quote, does not contain property', (t) => {
t.plan(1)
const stringify = build({
type: 'object',
properties: {
a: { type: 'string' }
},
required: [
'\''
]
})
t.assert.throws(() => stringify({}), new Error('"\'" is required!'))
})
test('required property containing double quote, does not contain property', (t) => {
t.plan(1)
const stringify = build({
type: 'object',
properties: {
a: { type: 'string' }
},
required: [
'"'
]
})
t.assert.throws(() => stringify({}), new Error('""" is required!'))
})

View File

@@ -0,0 +1,196 @@
'use strict'
const { test } = require('node:test')
const clone = require('rfdc/default')
const build = require('..')
test('oneOf with $ref should not change the input schema', t => {
t.plan(2)
const referenceSchema = {
$id: 'externalId',
type: 'object',
properties: {
name: { type: 'string' }
}
}
const schema = {
$id: 'mainSchema',
type: 'object',
properties: {
people: {
oneOf: [{ $ref: 'externalId' }]
}
}
}
const clonedSchema = clone(schema)
const stringify = build(schema, {
schema: {
[referenceSchema.$id]: referenceSchema
}
})
const value = stringify({ people: { name: 'hello', foo: 'bar' } })
t.assert.equal(value, '{"people":{"name":"hello"}}')
t.assert.deepStrictEqual(schema, clonedSchema)
})
test('oneOf and anyOf with $ref should not change the input schema', t => {
t.plan(3)
const referenceSchema = {
$id: 'externalSchema',
type: 'object',
properties: {
name: { type: 'string' }
}
}
const schema = {
$id: 'rootSchema',
type: 'object',
properties: {
people: {
oneOf: [{ $ref: 'externalSchema' }]
},
love: {
anyOf: [
{ $ref: '#/definitions/foo' },
{ type: 'boolean' }
]
}
},
definitions: {
foo: { type: 'string' }
}
}
const clonedSchema = clone(schema)
const stringify = build(schema, {
schema: {
[referenceSchema.$id]: referenceSchema
}
})
const valueAny1 = stringify({ people: { name: 'hello', foo: 'bar' }, love: 'music' })
const valueAny2 = stringify({ people: { name: 'hello', foo: 'bar' }, love: true })
t.assert.equal(valueAny1, '{"people":{"name":"hello"},"love":"music"}')
t.assert.equal(valueAny2, '{"people":{"name":"hello"},"love":true}')
t.assert.deepStrictEqual(schema, clonedSchema)
})
test('multiple $ref tree', t => {
t.plan(2)
const referenceDeepSchema = {
$id: 'deepId',
type: 'number'
}
const referenceSchema = {
$id: 'externalId',
type: 'object',
properties: {
name: { $ref: '#/definitions/foo' },
age: { $ref: 'deepId' }
},
definitions: {
foo: { type: 'string' }
}
}
const schema = {
$id: 'mainSchema',
type: 'object',
properties: {
people: {
oneOf: [{ $ref: 'externalId' }]
}
}
}
const clonedSchema = clone(schema)
const stringify = build(schema, {
schema: {
[referenceDeepSchema.$id]: referenceDeepSchema,
[referenceSchema.$id]: referenceSchema
}
})
const value = stringify({ people: { name: 'hello', foo: 'bar', age: 42 } })
t.assert.equal(value, '{"people":{"name":"hello","age":42}}')
t.assert.deepStrictEqual(schema, clonedSchema)
})
test('must not mutate items $ref', t => {
t.plan(2)
const referenceSchema = {
$id: 'ShowSchema',
$schema: 'http://json-schema.org/draft-07/schema#',
type: 'object',
properties: {
name: {
type: 'string'
}
}
}
const schema = {
$id: 'ListSchema',
$schema: 'http://json-schema.org/draft-07/schema#',
type: 'array',
items: {
$ref: 'ShowSchema#'
}
}
const clonedSchema = clone(schema)
const stringify = build(schema, {
schema: {
[referenceSchema.$id]: referenceSchema
}
})
const value = stringify([{ name: 'foo' }])
t.assert.equal(value, '[{"name":"foo"}]')
t.assert.deepStrictEqual(schema, clonedSchema)
})
test('must not mutate items referred by $ref', t => {
t.plan(2)
const firstSchema = {
$id: 'example1',
type: 'object',
properties: {
name: {
type: 'string'
}
}
}
const reusedSchema = {
$id: 'example2',
type: 'object',
properties: {
name: {
oneOf: [
{
$ref: 'example1'
}
]
}
}
}
const clonedSchema = clone(firstSchema)
const stringify = build(reusedSchema, {
schema: {
[firstSchema.$id]: firstSchema
}
})
const value = stringify({ name: { name: 'foo' } })
t.assert.equal(value, '{"name":{"name":"foo"}}')
t.assert.deepStrictEqual(firstSchema, clonedSchema)
})

View File

@@ -0,0 +1,219 @@
'use strict'
const { test, after } = require('node:test')
const fjs = require('..')
const fs = require('fs')
const path = require('path')
function build (opts, schema) {
return fjs(schema || {
title: 'default string',
type: 'object',
properties: {
firstName: {
type: 'string'
}
},
required: ['firstName']
}, opts)
}
const tmpDir = 'test/fixtures'
test('activate standalone mode', async (t) => {
t.plan(3)
after(async () => {
await fs.promises.rm(destination, { force: true })
})
const code = build({ mode: 'standalone' })
t.assert.ok(typeof code === 'string')
t.assert.equal(code.indexOf('ajv'), -1)
const destination = path.resolve(tmpDir, 'standalone.js')
await fs.promises.writeFile(destination, code)
const standalone = require(destination)
t.assert.equal(standalone({ firstName: 'Foo', surname: 'bar' }), JSON.stringify({ firstName: 'Foo' }), 'surname evicted')
})
test('test ajv schema', async (t) => {
t.plan(3)
after(async () => {
await fs.promises.rm(destination, { force: true })
})
const code = build({ mode: 'standalone' }, {
type: 'object',
properties: {
},
if: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['foobar'] }
}
},
then: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['foobar'] },
foo: { type: 'string' },
bar: { type: 'number' },
list: {
type: 'array',
items: {
type: 'object',
properties: {
name: { type: 'string' },
value: { type: 'string' }
}
}
}
}
},
else: {
type: 'object',
properties: {
kind: { type: 'string', enum: ['greeting'] },
hi: { type: 'string' },
hello: { type: 'number' },
list: {
type: 'array',
items: {
type: 'object',
properties: {
name: { type: 'string' },
value: { type: 'string' }
}
}
}
}
}
})
t.assert.ok(typeof code === 'string')
t.assert.equal(code.indexOf('ajv') > 0, true)
const destination = path.resolve(tmpDir, 'standalone2.js')
await fs.promises.writeFile(destination, code)
const standalone = require(destination)
t.assert.equal(standalone({
kind: 'foobar',
foo: 'FOO',
list: [{
name: 'name',
value: 'foo'
}],
bar: 42,
hi: 'HI',
hello: 45,
a: 'A',
b: 35
}), JSON.stringify({
kind: 'foobar',
foo: 'FOO',
bar: 42,
list: [{
name: 'name',
value: 'foo'
}]
}))
})
test('no need to keep external schemas once compiled', async (t) => {
t.plan(1)
after(async () => {
await fs.promises.rm(destination, { force: true })
})
const externalSchema = {
first: {
definitions: {
id1: {
type: 'object',
properties: {
id1: {
type: 'integer'
}
}
}
}
}
}
const code = fjs({
$ref: 'first#/definitions/id1'
}, {
mode: 'standalone',
schema: externalSchema
})
const destination = path.resolve(tmpDir, 'standalone3.js')
await fs.promises.writeFile(destination, code)
const standalone = require(destination)
t.assert.equal(standalone({ id1: 5 }), JSON.stringify({ id1: 5 }), 'serialization works with external schemas')
})
test('no need to keep external schemas once compiled - with oneOf validator', async (t) => {
t.plan(2)
after(async () => {
await fs.promises.rm(destination, { force: true })
})
const externalSchema = {
ext: {
definitions: {
oBaz: {
type: 'object',
properties: {
baz: { type: 'number' }
},
required: ['baz']
},
oBar: {
type: 'object',
properties: {
bar: { type: 'string' }
},
required: ['bar']
},
other: {
type: 'string',
const: 'other'
}
}
}
}
const schema = {
title: 'object with oneOf property value containing refs to external schema',
type: 'object',
properties: {
oneOfSchema: {
oneOf: [
{ $ref: 'ext#/definitions/oBaz' },
{ $ref: 'ext#/definitions/oBar' }
]
}
},
required: ['oneOfSchema']
}
const code = fjs(schema, {
mode: 'standalone',
schema: externalSchema
})
const destination = path.resolve(tmpDir, 'standalone-oneOf-ref.js')
await fs.promises.writeFile(destination, code)
const stringify = require(destination)
t.assert.equal(stringify({ oneOfSchema: { baz: 5 } }), '{"oneOfSchema":{"baz":5}}')
t.assert.equal(stringify({ oneOfSchema: { bar: 'foo' } }), '{"oneOfSchema":{"bar":"foo"}}')
})

84
node_modules/fast-json-stringify/test/string.test.js generated vendored Normal file
View File

@@ -0,0 +1,84 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('serialize short string', (t) => {
t.plan(2)
const schema = {
type: 'string'
}
const input = 'abcd'
const stringify = build(schema)
const output = stringify(input)
t.assert.equal(output, '"abcd"')
t.assert.equal(JSON.parse(output), input)
})
test('serialize short string', (t) => {
t.plan(2)
const schema = {
type: 'string'
}
const input = '\x00'
const stringify = build(schema)
const output = stringify(input)
t.assert.equal(output, '"\\u0000"')
t.assert.equal(JSON.parse(output), input)
})
test('serialize long string', (t) => {
t.plan(2)
const schema = {
type: 'string'
}
const input = new Array(2e4).fill('\x00').join('')
const stringify = build(schema)
const output = stringify(input)
t.assert.equal(output, `"${new Array(2e4).fill('\\u0000').join('')}"`)
t.assert.equal(JSON.parse(output), input)
})
test('unsafe string', (t) => {
t.plan(2)
const schema = {
type: 'string',
format: 'unsafe'
}
const input = 'abcd'
const stringify = build(schema)
const output = stringify(input)
t.assert.equal(output, `"${input}"`)
t.assert.equal(JSON.parse(output), input)
})
test('unsafe unescaped string', (t) => {
t.plan(2)
const schema = {
type: 'string',
format: 'unsafe'
}
const input = 'abcd "abcd"'
const stringify = build(schema)
const output = stringify(input)
t.assert.equal(output, `"${input}"`)
t.assert.throws(function () {
JSON.parse(output)
})
})

View File

@@ -0,0 +1,67 @@
'use strict'
const { test } = require('node:test')
const validator = require('is-my-json-valid')
const build = require('..')
test('render a string with surrogate pairs as JSON:test 1', (t) => {
t.plan(2)
const schema = {
title: 'surrogate',
type: 'string'
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify('𝌆')
t.assert.equal(output, '"𝌆"')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a string with surrogate pairs as JSON: test 2', (t) => {
t.plan(2)
const schema = {
title: 'long',
type: 'string'
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify('\uD834\uDF06')
t.assert.equal(output, '"𝌆"')
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a string with Unpaired surrogate code as JSON', (t) => {
t.plan(2)
const schema = {
title: 'surrogate',
type: 'string'
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify('\uDF06\uD834')
t.assert.equal(output, JSON.stringify('\uDF06\uD834'))
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})
test('render a string with lone surrogate code as JSON', (t) => {
t.plan(2)
const schema = {
title: 'surrogate',
type: 'string'
}
const validate = validator(schema)
const stringify = build(schema)
const output = stringify('\uDEAD')
t.assert.equal(output, JSON.stringify('\uDEAD'))
t.assert.ok(validate(JSON.parse(output)), 'valid schema')
})

203
node_modules/fast-json-stringify/test/toJSON.test.js generated vendored Normal file
View File

@@ -0,0 +1,203 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('use toJSON method on object types', (t) => {
t.plan(1)
const stringify = build({
title: 'simple object',
type: 'object',
properties: {
productName: {
type: 'string'
}
}
})
const object = {
product: { name: 'cola' },
toJSON: function () {
return { productName: this.product.name }
}
}
t.assert.equal('{"productName":"cola"}', stringify(object))
})
test('use toJSON method on nested object types', (t) => {
t.plan(1)
const stringify = build({
title: 'simple array',
type: 'array',
items: {
type: 'object',
properties: {
productName: {
type: 'string'
}
}
}
})
const array = [
{
product: { name: 'cola' },
toJSON: function () {
return { productName: this.product.name }
}
},
{
product: { name: 'sprite' },
toJSON: function () {
return { productName: this.product.name }
}
}
]
t.assert.equal('[{"productName":"cola"},{"productName":"sprite"}]', stringify(array))
})
test('not use toJSON if does not exist', (t) => {
t.plan(1)
const stringify = build({
title: 'simple object',
type: 'object',
properties: {
product: {
type: 'object',
properties: {
name: {
type: 'string'
}
}
}
}
})
const object = {
product: { name: 'cola' }
}
t.assert.equal('{"product":{"name":"cola"}}', stringify(object))
})
test('not fail on null object declared nullable', (t) => {
t.plan(1)
const stringify = build({
title: 'simple object',
type: 'object',
nullable: true,
properties: {
product: {
type: 'object',
properties: {
name: {
type: 'string'
}
}
}
}
})
t.assert.equal('null', stringify(null))
})
test('not fail on null sub-object declared nullable', (t) => {
t.plan(1)
const stringify = build({
title: 'simple object',
type: 'object',
properties: {
product: {
nullable: true,
type: 'object',
properties: {
name: {
type: 'string'
}
}
}
}
})
const object = {
product: null
}
t.assert.equal('{"product":null}', stringify(object))
})
test('on non nullable null sub-object it should coerce to {}', (t) => {
t.plan(1)
const stringify = build({
title: 'simple object',
type: 'object',
properties: {
product: {
nullable: false,
type: 'object',
properties: {
name: {
type: 'string'
}
}
}
}
})
const object = {
product: null
}
const result = stringify(object)
t.assert.equal(result, JSON.stringify({ product: {} }))
})
test('on non nullable null object it should coerce to {}', (t) => {
t.plan(1)
const stringify = build({
title: 'simple object',
nullable: false,
type: 'object',
properties: {
product: {
nullable: false,
type: 'object',
properties: {
name: {
type: 'string'
}
}
}
}
})
const result = stringify(null)
t.assert.equal(result, '{}')
})
test('on non-nullable null object it should skip rendering, skipping required fields checks', (t) => {
t.plan(1)
const stringify = build({
title: 'simple object',
nullable: false,
type: 'object',
properties: {
product: {
nullable: false,
type: 'object',
properties: {
name: {
type: 'string'
}
}
}
},
required: ['product']
})
const result = stringify(null)
t.assert.equal(result, '{}')
})

36
node_modules/fast-json-stringify/test/typebox.test.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('nested object in pattern properties for typebox', (t) => {
const { Type } = require('@sinclair/typebox')
t.plan(1)
const nestedSchema = Type.Object({
nestedKey1: Type.String()
})
const RootSchema = Type.Object({
key1: Type.Record(Type.String(), nestedSchema),
key2: Type.Record(Type.String(), nestedSchema)
})
const schema = RootSchema
const stringify = build(schema)
const value = stringify({
key1: {
nestedKey: {
nestedKey1: 'value1'
}
},
key2: {
nestedKey: {
nestedKey1: 'value2'
}
}
})
t.assert.equal(value, '{"key1":{"nestedKey":{"nestedKey1":"value1"}},"key2":{"nestedKey":{"nestedKey1":"value2"}}}')
})

View File

@@ -0,0 +1,550 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('possibly nullable integer primitive alternative', (t) => {
t.plan(1)
const schema = {
title: 'simple object with multi-type nullable primitive',
type: 'object',
properties: {
data: {
type: ['integer']
}
}
}
const stringify = build(schema, { ajv: { allowUnionTypes: true } })
const value = stringify({
data: 4
})
t.assert.equal(value, '{"data":4}')
})
test('possibly nullable number primitive alternative', (t) => {
t.plan(1)
const schema = {
title: 'simple object with multi-type nullable primitive',
type: 'object',
properties: {
data: {
type: ['number']
}
}
}
const stringify = build(schema)
const value = stringify({
data: 4
})
t.assert.equal(value, '{"data":4}')
})
test('possibly nullable integer primitive alternative with null value', (t) => {
t.plan(1)
const schema = {
title: 'simple object with multi-type nullable primitive',
type: 'object',
properties: {
data: {
type: ['integer']
}
}
}
const stringify = build(schema)
const value = stringify({
data: null
})
t.assert.equal(value, '{"data":0}')
})
test('possibly nullable number primitive alternative with null value', (t) => {
t.plan(1)
const schema = {
title: 'simple object with multi-type nullable primitive',
type: 'object',
properties: {
data: {
type: ['number']
}
}
}
const stringify = build(schema)
const value = stringify({
data: null
})
t.assert.equal(value, '{"data":0}')
})
test('possibly nullable number primitive alternative with null value', (t) => {
t.plan(1)
const schema = {
title: 'simple object with multi-type nullable primitive',
type: 'object',
properties: {
data: {
type: ['boolean']
}
}
}
const stringify = build(schema)
const value = stringify({
data: null
})
t.assert.equal(value, '{"data":false}')
})
test('nullable integer primitive', (t) => {
t.plan(1)
const schema = {
title: 'simple object with nullable primitive',
type: 'object',
properties: {
data: {
type: ['integer', 'null']
}
}
}
const stringify = build(schema)
const value = stringify({
data: 4
})
t.assert.equal(value, '{"data":4}')
})
test('nullable number primitive', (t) => {
t.plan(1)
const schema = {
title: 'simple object with nullable primitive',
type: 'object',
properties: {
data: {
type: ['number', 'null']
}
}
}
const stringify = build(schema)
const value = stringify({
data: 4
})
t.assert.equal(value, '{"data":4}')
})
test('nullable primitive with null value', (t) => {
t.plan(1)
const schema = {
title: 'simple object with nullable primitive',
type: 'object',
properties: {
data: {
type: ['integer', 'null']
}
}
}
const stringify = build(schema)
const value = stringify({
data: null
})
t.assert.equal(value, '{"data":null}')
})
test('nullable number primitive with null value', (t) => {
t.plan(1)
const schema = {
title: 'simple object with nullable primitive',
type: 'object',
properties: {
data: {
type: ['number', 'null']
}
}
}
const stringify = build(schema)
const value = stringify({
data: null
})
t.assert.equal(value, '{"data":null}')
})
test('possibly null object with multi-type property', (t) => {
t.plan(3)
const schema = {
title: 'simple object with multi-type property',
type: 'object',
properties: {
objectOrNull: {
type: ['object', 'null'],
properties: {
stringOrNumber: {
type: ['string', 'number']
}
}
}
}
}
const stringify = build(schema)
t.assert.equal(stringify({
objectOrNull: {
stringOrNumber: 'string'
}
}), '{"objectOrNull":{"stringOrNumber":"string"}}')
t.assert.equal(stringify({
objectOrNull: {
stringOrNumber: 42
}
}), '{"objectOrNull":{"stringOrNumber":42}}')
t.assert.equal(stringify({
objectOrNull: null
}), '{"objectOrNull":null}')
})
test('object with possibly null array of multiple types', (t) => {
t.plan(5)
const schema = {
title: 'object with array of multiple types',
type: 'object',
properties: {
arrayOfStringsAndNumbers: {
type: ['array', 'null'],
items: {
type: ['string', 'number', 'null']
}
}
}
}
const stringify = build(schema)
try {
const value = stringify({
arrayOfStringsAndNumbers: null
})
t.assert.equal(value, '{"arrayOfStringsAndNumbers":null}')
} catch (e) {
console.log(e)
t.fail()
}
try {
const value = stringify({
arrayOfStringsAndNumbers: ['string1', 'string2']
})
t.assert.equal(value, '{"arrayOfStringsAndNumbers":["string1","string2"]}')
} catch (e) {
console.log(e)
t.fail()
}
t.assert.equal(stringify({
arrayOfStringsAndNumbers: [42, 7]
}), '{"arrayOfStringsAndNumbers":[42,7]}')
t.assert.equal(stringify({
arrayOfStringsAndNumbers: ['string1', 42, 7, 'string2']
}), '{"arrayOfStringsAndNumbers":["string1",42,7,"string2"]}')
t.assert.equal(stringify({
arrayOfStringsAndNumbers: ['string1', null, 42, 7, 'string2', null]
}), '{"arrayOfStringsAndNumbers":["string1",null,42,7,"string2",null]}')
})
test('object with tuple of multiple types', (t) => {
t.plan(2)
const schema = {
title: 'object with array of multiple types',
type: 'object',
properties: {
fixedTupleOfStringsAndNumbers: {
type: 'array',
items: [
{
type: 'string'
},
{
type: 'number'
},
{
type: ['string', 'number']
}
]
}
}
}
const stringify = build(schema)
try {
const value = stringify({
fixedTupleOfStringsAndNumbers: ['string1', 42, 7]
})
t.assert.equal(value, '{"fixedTupleOfStringsAndNumbers":["string1",42,7]}')
} catch (e) {
console.log(e)
t.fail()
}
try {
const value = stringify({
fixedTupleOfStringsAndNumbers: ['string1', 42, 'string2']
})
t.assert.equal(value, '{"fixedTupleOfStringsAndNumbers":["string1",42,"string2"]}')
} catch (e) {
console.log(e)
t.fail()
}
})
test('object with anyOf and multiple types', (t) => {
t.plan(3)
const schema = {
title: 'object with anyOf and multiple types',
type: 'object',
properties: {
objectOrBoolean: {
anyOf: [
{
type: 'object',
properties: {
stringOrNumber: {
type: ['string', 'number']
}
}
},
{
type: 'boolean'
}
]
}
}
}
const stringify = build(schema, { ajv: { allowUnionTypes: true } })
try {
const value = stringify({
objectOrBoolean: { stringOrNumber: 'string' }
})
t.assert.equal(value, '{"objectOrBoolean":{"stringOrNumber":"string"}}')
} catch (e) {
console.log(e)
t.fail()
}
t.assert.equal(stringify({
objectOrBoolean: { stringOrNumber: 42 }
}), '{"objectOrBoolean":{"stringOrNumber":42}}')
t.assert.equal(stringify({
objectOrBoolean: true
}), '{"objectOrBoolean":true}')
})
test('string type array can handle dates', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
date: { type: ['string'] },
dateObject: { type: ['string'], format: 'date-time' }
}
}
const stringify = build(schema)
const value = stringify({
date: new Date('2018-04-20T07:52:31.017Z'),
dateObject: new Date('2018-04-21T07:52:31.017Z')
})
t.assert.equal(value, '{"date":"2018-04-20T07:52:31.017Z","dateObject":"2018-04-21T07:52:31.017Z"}')
})
test('object that is simultaneously a string and a json', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
simultaneously: {
type: ['string', 'object'],
properties: {
foo: { type: 'string' }
}
}
}
}
const likeObjectId = {
toString () { return 'hello' }
}
const stringify = build(schema)
const valueStr = stringify({ simultaneously: likeObjectId })
t.assert.equal(valueStr, '{"simultaneously":"hello"}')
const valueObj = stringify({ simultaneously: { foo: likeObjectId } })
t.assert.equal(valueObj, '{"simultaneously":{"foo":"hello"}}')
})
test('object that is simultaneously a string and a json switched', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
simultaneously: {
type: ['object', 'string'],
properties: {
foo: { type: 'string' }
}
}
}
}
const likeObjectId = {
toString () { return 'hello' }
}
const stringify = build(schema)
const valueStr = stringify({ simultaneously: likeObjectId })
t.assert.equal(valueStr, '{"simultaneously":{}}')
const valueObj = stringify({ simultaneously: { foo: likeObjectId } })
t.assert.equal(valueObj, '{"simultaneously":{"foo":"hello"}}')
})
test('class instance that is simultaneously a string and a json', (t) => {
t.plan(2)
const schema = {
type: 'object',
properties: {
simultaneously: {
type: ['string', 'object'],
properties: {
foo: { type: 'string' }
}
}
}
}
class Test {
toString () { return 'hello' }
}
const likeObjectId = new Test()
const stringify = build(schema)
const valueStr = stringify({ simultaneously: likeObjectId })
t.assert.equal(valueStr, '{"simultaneously":"hello"}')
const valueObj = stringify({ simultaneously: { foo: likeObjectId } })
t.assert.equal(valueObj, '{"simultaneously":{"foo":"hello"}}')
})
test('should not throw an error when type is array and object is null, it should instead coerce to []', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
arr: {
type: 'array',
items: {
type: 'number'
}
}
}
}
const stringify = build(schema)
const result = stringify({ arr: null })
t.assert.equal(result, JSON.stringify({ arr: [] }))
})
test('should throw an error when type is array and object is not an array', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
arr: {
type: 'array',
items: {
type: 'number'
}
}
}
}
const stringify = build(schema)
t.assert.throws(() => stringify({ arr: { foo: 'hello' } }), new TypeError('The value of \'#/properties/arr\' does not match schema definition.'))
})
test('should throw an error when type is array and object is not an array with external schema', (t) => {
t.plan(1)
const schema = {
type: 'object',
properties: {
arr: {
$ref: 'arrayOfNumbers#/definitions/arr'
}
}
}
const externalSchema = {
arrayOfNumbers: {
definitions: {
arr: {
type: 'array',
items: {
type: 'number'
}
}
}
}
}
const stringify = build(schema, { schema: externalSchema })
t.assert.throws(() => stringify({ arr: { foo: 'hello' } }), new TypeError('The value of \'arrayOfNumbers#/definitions/arr\' does not match schema definition.'))
})
test('throw an error if none of types matches', (t) => {
t.plan(1)
const schema = {
title: 'simple object with multi-type nullable primitive',
type: 'object',
properties: {
data: {
type: ['number', 'boolean']
}
}
}
const stringify = build(schema)
t.assert.throws(() => stringify({ data: 'string' }), 'The value "string" does not match schema definition.')
})

View File

@@ -0,0 +1,27 @@
'use strict'
const { test } = require('node:test')
const build = require('..')
test('object with custom format field', (t) => {
t.plan(1)
const schema = {
title: 'object with custom format field',
type: 'object',
properties: {
str: {
type: 'string',
format: 'test-format'
}
}
}
const stringify = build(schema)
t.assert.doesNotThrow(() => {
stringify({
str: 'string'
})
})
})

50
node_modules/fast-json-stringify/test/webpack.test.js generated vendored Normal file
View File

@@ -0,0 +1,50 @@
'use strict'
const { test } = require('node:test')
const webpack = require('webpack')
const path = require('path')
test('the library should work with webpack', async (t) => {
t.plan(1)
const targetdir = path.resolve(__dirname, '..', '.cache')
const targetname = path.join(targetdir, 'webpacktest.js')
const wopts = {
entry: path.resolve(__dirname, '..', 'index.js'),
mode: 'production',
target: 'node',
output: {
path: targetdir,
filename: 'webpacktest.js',
library: {
name: 'fastJsonStringify',
type: 'umd'
}
}
}
await new Promise((resolve, reject) => {
webpack(wopts, (err, stats) => {
if (err) { reject(err) } else { resolve(stats) };
})
})
const build = require(targetname)
const stringify = build({
title: 'webpack should not rename code to be executed',
type: 'object',
properties: {
foo: {
type: 'string'
},
bar: {
type: 'boolean'
}
},
patternProperties: {
foo: {
type: 'number'
}
}
})
const obj = { foo: '42', bar: true }
t.assert.equal(stringify(obj), '{"foo":"42","bar":true}')
})