Skip to main content
Glama
schema.test.ts9.19 kB
/** * Tests for the schema module */ import { describe, it, expect } from 'vitest'; import { baseSchema, type BaseDocument } from '../schema/base-schema.js'; import { buildTypeDocument, buildMethodDocument, buildFunctionDocument, buildScriptDocument, } from '../schema/schema-builder.js'; import type { ExtractedType, ExtractedMethod, ExtractedFunction } from '../extractor/types.js'; import type { CachedScript } from '../script/types.js'; describe('Base Schema', () => { it('has required id field', () => { expect(baseSchema.id).toBe('string'); }); it('has documentType as enum', () => { expect(baseSchema.documentType).toBe('enum'); }); it('has name field for search', () => { expect(baseSchema.name).toBe('string'); }); it('has description field for search', () => { expect(baseSchema.description).toBe('string'); }); it('has searchTokens field for enhanced search', () => { expect(baseSchema.searchTokens).toBe('string'); }); it('has library and category as enum for filtering', () => { expect(baseSchema.library).toBe('enum'); expect(baseSchema.category).toBe('enum'); }); it('has type-specific fields', () => { expect(baseSchema.properties).toBe('string'); expect(baseSchema.typeDefinition).toBe('string'); expect(baseSchema.nestedTypes).toBe('string'); expect(baseSchema.typeKind).toBe('enum'); }); it('has method-specific fields', () => { expect(baseSchema.parameters).toBe('string'); expect(baseSchema.returnType).toBe('string'); expect(baseSchema.signature).toBe('string'); expect(baseSchema.className).toBe('string'); }); it('has script-specific fields', () => { expect(baseSchema.filePath).toBe('string'); expect(baseSchema.keywords).toBe('string'); }); }); describe('Schema Builder', () => { describe('buildTypeDocument', () => { it('builds a document from ExtractedType', () => { const extractedType: ExtractedType = { name: 'V1Pod', kind: 'class', description: 'A Pod resource.', library: '@kubernetes/client-node', sourceFile: '/path/to/file.d.ts', properties: [ { name: 'metadata', type: 'V1ObjectMeta', optional: true }, { name: 'spec', type: 'V1PodSpec', optional: true }, ], nestedTypes: ['V1ObjectMeta', 'V1PodSpec'], }; const doc = buildTypeDocument(extractedType); // ID includes library for uniqueness expect(doc.id).toBe('type:@kubernetes/client-node:V1Pod'); expect(doc.documentType).toBe('type'); expect(doc.name).toBe('V1Pod'); expect(doc.description).toBe('A Pod resource.'); expect(doc.library).toBe('@kubernetes/client-node'); expect(doc.category).toBe('class'); expect(doc.typeKind).toBe('class'); expect(doc.nestedTypes).toBe('V1ObjectMeta, V1PodSpec'); expect(doc.searchTokens).toContain('V1Pod'); }); it('includes properties as JSON', () => { const extractedType: ExtractedType = { name: 'TestType', kind: 'interface', description: 'Test type.', library: 'test-lib', sourceFile: '/path/to/file.d.ts', properties: [ { name: 'id', type: 'string', optional: false }, { name: 'value', type: 'number', optional: true }, ], nestedTypes: [], }; const doc = buildTypeDocument(extractedType); const properties = JSON.parse(doc.properties); expect(properties.length).toBe(2); expect(properties[0].name).toBe('id'); expect(properties[1].optional).toBe(true); }); }); describe('buildMethodDocument', () => { it('builds a document from ExtractedMethod', () => { const extractedMethod: ExtractedMethod = { name: 'listNamespacedPod', className: 'CoreV1Api', description: 'List pods in a namespace.', library: '@kubernetes/client-node', sourceFile: '/path/to/file.d.ts', parameters: [ { name: 'namespace', type: 'string', optional: false }, { name: 'pretty', type: 'string', optional: true }, ], returnType: 'Promise<V1PodList>', isAsync: true, isStatic: false, }; const doc = buildMethodDocument(extractedMethod); // ID includes library and className for uniqueness expect(doc.id).toBe('method:@kubernetes/client-node:CoreV1Api:listNamespacedPod'); expect(doc.documentType).toBe('method'); expect(doc.name).toBe('listNamespacedPod'); expect(doc.description).toBe('List pods in a namespace.'); expect(doc.library).toBe('@kubernetes/client-node'); expect(doc.className).toBe('CoreV1Api'); expect(doc.returnType).toBe('Promise<V1PodList>'); expect(doc.searchTokens).toContain('listNamespacedPod'); }); it('extracts action category from method name', () => { const extractedMethod: ExtractedMethod = { name: 'createDeployment', className: 'AppsV1Api', description: 'Create a deployment.', library: '@kubernetes/client-node', sourceFile: '/path/to/file.d.ts', parameters: [], returnType: 'Promise<V1Deployment>', isAsync: true, isStatic: false, }; const doc = buildMethodDocument(extractedMethod); expect(doc.category).toBe('create'); }); it('includes parameters as JSON', () => { const extractedMethod: ExtractedMethod = { name: 'getItem', className: 'Api', description: 'Get an item.', library: 'test-lib', sourceFile: '/path/to/file.d.ts', parameters: [ { name: 'id', type: 'string', optional: false }, { name: 'options', type: 'Options', optional: true }, ], returnType: 'Promise<Item>', isAsync: true, isStatic: false, }; const doc = buildMethodDocument(extractedMethod); const parameters = JSON.parse(doc.parameters); expect(parameters.length).toBe(2); expect(parameters[0].name).toBe('id'); expect(parameters[1].optional).toBe(true); }); it('builds signature from method info', () => { const extractedMethod: ExtractedMethod = { name: 'queryRange', className: 'LokiClient', description: 'Query logs over a time range.', library: '@prodisco/loki-client', sourceFile: '/path/to/file.d.ts', parameters: [ { name: 'logQL', type: 'string', optional: false }, { name: 'start', type: 'Date', optional: false }, { name: 'end', type: 'Date', optional: false }, ], returnType: 'Promise<QueryResult>', isAsync: true, isStatic: false, }; const doc = buildMethodDocument(extractedMethod); expect(doc.signature).toContain('queryRange'); expect(doc.signature).toContain('logQL'); }); }); describe('buildFunctionDocument', () => { it('builds a document from ExtractedFunction', () => { const extractedFunction: ExtractedFunction = { name: 'mean', description: 'Calculate the arithmetic mean.', library: 'simple-statistics', sourceFile: '/path/to/file.d.ts', parameters: [{ name: 'values', type: 'number[]', optional: false }], returnType: 'number', isAsync: false, signature: 'mean(values: number[]): number', }; const doc = buildFunctionDocument(extractedFunction); // ID includes library for uniqueness expect(doc.id).toBe('function:simple-statistics:mean'); expect(doc.documentType).toBe('function'); expect(doc.name).toBe('mean'); expect(doc.description).toBe('Calculate the arithmetic mean.'); expect(doc.library).toBe('simple-statistics'); expect(doc.category).toBe('descriptive'); expect(doc.returnType).toBe('number'); }); }); describe('buildScriptDocument', () => { it('builds a document from CachedScript', () => { const script: CachedScript = { filename: 'list-pods.ts', filePath: '/path/to/list-pods.ts', description: 'List all pods in the cluster.', resourceTypes: ['pod'], keywords: ['list', 'pods', 'kubernetes'], apiClasses: ['CoreV1Api'], }; const doc = buildScriptDocument(script); expect(doc.id).toBe('script:list-pods.ts'); expect(doc.documentType).toBe('script'); expect(doc.name).toBe('list-pods'); // Filename without .ts extension expect(doc.description).toBe('List all pods in the cluster.'); expect(doc.library).toBe('CoreV1Api'); // First API class expect(doc.filePath).toBe('/path/to/list-pods.ts'); expect(doc.keywords).toBe('list pods kubernetes'); }); it('handles empty keywords', () => { const script: CachedScript = { filename: 'empty-script.ts', filePath: '/path/to/empty-script.ts', description: 'A script with no keywords.', resourceTypes: [], keywords: [], apiClasses: [], }; const doc = buildScriptDocument(script); expect(doc.keywords).toBe(''); }); }); });

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/harche/ProDisco'

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