MCP Terminal Server

/** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import * as assert from 'assert'; import { describe, it } from 'node:test'; import { ValidationError, parseSchema, toJsonSchema, validateSchema, z, } from '../src/schema.js'; describe('validate()', () => { const tests = [ { it: 'should return true for a valid json schema', jsonSchema: { type: 'object', properties: { foo: { type: 'boolean', }, }, }, data: { foo: true }, valid: true, }, { it: 'should return errors for an invalid json schema', jsonSchema: { type: 'object', properties: { foo: { type: 'boolean', }, }, }, data: { foo: 123 }, valid: false, errors: [{ path: 'foo', message: 'must be boolean' }], }, { it: 'should return true for a valid zod schema', schema: z.object({ foo: z.boolean() }), data: { foo: true }, valid: true, }, { it: 'should return errors for an invalid zod schema', schema: z.object({ foo: z.boolean() }), data: { foo: 123 }, valid: false, errors: [{ path: 'foo', message: 'must be boolean' }], }, { it: 'should allow for date types', schema: z.object({ date: z.string().datetime() }), data: { date: '2024-05-22T17:00:00Z' }, valid: true, }, { it: 'should return dotted path for errors', schema: z.object({ foo: z.array(z.object({ bar: z.boolean() })) }), data: { foo: [{ bar: 123 }] }, valid: false, errors: [{ path: 'foo.0.bar', message: 'must be boolean' }], }, { it: 'should be understandable for top-level errors', jsonSchema: { type: 'object', additionalProperties: false }, data: { foo: 'bar' }, valid: false, errors: [ { path: '(root)', message: 'must NOT have additional properties' }, ], }, { it: 'should be understandable for required fields', jsonSchema: { type: 'object', properties: { foo: { type: 'string' } }, required: ['foo'], }, data: {}, valid: false, errors: [ { path: '(root)', message: "must have required property 'foo'" }, ], }, ]; for (const test of tests) { it(test.it, () => { const { valid, errors } = validateSchema(test.data, { jsonSchema: test.jsonSchema, schema: test.schema, }); assert.strictEqual(valid, test.valid); assert.deepStrictEqual(errors, test.errors); }); } }); describe('parse()', () => { it('should throw a ValidationError for invalid schema', () => { assert.throws(() => { parseSchema( { foo: 123 }, { schema: z.object({ foo: z.boolean() }), } ); }, ValidationError); }); it('should return the data if valid', () => { assert.deepEqual( parseSchema( { foo: true }, { schema: z.object({ foo: z.boolean() }), } ), { foo: true } ); }); }); describe('toJsonSchema', () => { it('converts zod to JSON schema', async () => { assert.deepStrictEqual( toJsonSchema({ schema: z.object({ output: z.string(), }), }), { $schema: 'http://json-schema.org/draft-07/schema#', additionalProperties: true, properties: { output: { type: 'string', }, }, required: ['output'], type: 'object', } ); }); });