Skip to main content
Glama
anyof.test.js16.2 kB
'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"}') } })

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/krtw00/search-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server