@lobehub/chat
Version:
Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.
215 lines (177 loc) • 6.77 kB
text/typescript
import { describe, expect, it } from 'vitest';
import {
ModelParamsMetaSchema,
ModelParamsSchema,
type RuntimeImageGenParams,
extractDefaultValues,
validateModelParamsSchema,
} from './meta-schema';
describe('meta-schema', () => {
describe('ModelParamsMetaSchema', () => {
it('should validate a complete parameter schema', () => {
const validSchema: ModelParamsSchema = {
prompt: { default: 'test prompt' },
width: { default: 1024, min: 512, max: 2048, step: 64 },
height: { default: 1024, min: 512, max: 2048, step: 64 },
steps: { default: 20, min: 1, max: 50 },
seed: { default: null, min: 0 },
cfg: { default: 7.5, min: 1, max: 20, step: 0.5 },
aspectRatio: { default: '1:1', enum: ['1:1', '16:9', '4:3'] },
size: { default: '1024x1024', enum: ['512x512', '1024x1024', '1536x1536'] },
imageUrl: { default: null },
imageUrls: { default: [] },
};
expect(() => ModelParamsMetaSchema.parse(validSchema)).not.toThrow();
});
it('should validate minimal parameter schema with only prompt', () => {
const minimalSchema: ModelParamsSchema = {
prompt: { default: '' },
};
expect(() => ModelParamsMetaSchema.parse(minimalSchema)).not.toThrow();
});
it('should apply default values for optional properties', () => {
const schema: ModelParamsSchema = {
prompt: {},
width: { default: 1024, min: 512, max: 2048 },
seed: {},
};
const result = ModelParamsMetaSchema.parse(schema);
expect(result.prompt.default).toBe('');
expect(result.width?.step).toBe(1);
expect(result.seed?.default).toBeNull();
expect(result.seed?.min).toBe(0);
});
it('should reject invalid parameter schemas', () => {
const invalidSchema = {
prompt: { default: 123 }, // Should be string
width: { min: 'invalid' }, // Should be number
};
expect(() => ModelParamsMetaSchema.parse(invalidSchema)).toThrow();
});
it('should handle optional parameters correctly', () => {
const partialSchema: ModelParamsSchema = {
prompt: { default: 'test' },
width: { default: 512, min: 256, max: 1024 },
};
const result = ModelParamsMetaSchema.parse(partialSchema);
expect(result.prompt.default).toBe('test');
expect(result.width?.default).toBe(512);
expect(result.height).toBeUndefined();
});
});
describe('validateModelParamsSchema', () => {
it('should validate correct parameter schema', () => {
const schema = {
prompt: { default: 'test' },
width: { default: 1024, min: 512, max: 2048 },
};
expect(() => validateModelParamsSchema(schema)).not.toThrow();
});
it('should throw error for invalid parameter schema', () => {
const invalidSchema = {
prompt: { default: 123 }, // Invalid type
};
expect(() => validateModelParamsSchema(invalidSchema)).toThrow();
});
it('should handle unknown properties gracefully', () => {
const schemaWithExtra = {
prompt: { default: 'test' },
unknownParam: { default: 'value' },
};
// Should not throw since schema uses passthrough
expect(() => validateModelParamsSchema(schemaWithExtra)).not.toThrow();
});
});
describe('extractDefaultValues', () => {
it('should extract default values from parameter schema', () => {
const schema: ModelParamsSchema = {
prompt: { default: 'test prompt' },
width: { default: 1024, min: 512, max: 2048 },
height: { default: 768, min: 512, max: 2048 },
steps: { default: 20, min: 1, max: 50 },
seed: { default: null },
};
const result = extractDefaultValues(schema);
expect(result).toEqual({
prompt: 'test prompt',
width: 1024,
height: 768,
steps: 20,
seed: null,
});
});
it('should apply schema defaults for missing properties', () => {
const schema: ModelParamsSchema = {
prompt: {},
width: { default: 1024, min: 512, max: 2048 },
seed: {},
};
const result = extractDefaultValues(schema);
expect(result.prompt).toBe(''); // Schema default
expect(result.width).toBe(1024);
expect(result.seed).toBeNull(); // Schema default
});
it('should handle empty schema gracefully', () => {
const schema: ModelParamsSchema = {
prompt: { default: '' },
};
const result = extractDefaultValues(schema);
expect(result).toEqual({
prompt: '',
});
});
it('should preserve all parameter types correctly', () => {
const schema: ModelParamsSchema = {
prompt: { default: 'test' },
width: { default: 1024, min: 512, max: 2048 },
seed: { default: 12345 },
cfg: { default: 7.5, min: 1, max: 20, step: 0.5 },
aspectRatio: { default: '16:9', enum: ['1:1', '16:9', '4:3'] },
imageUrls: { default: ['test.jpg'] },
imageUrl: { default: 'test.jpg' },
};
const result = extractDefaultValues(schema);
expect(typeof result.prompt).toBe('string');
expect(typeof result.width).toBe('number');
expect(typeof result.seed).toBe('number');
expect(typeof result.cfg).toBe('number');
expect(typeof result.aspectRatio).toBe('string');
expect(Array.isArray(result.imageUrls)).toBe(true);
expect(typeof result.imageUrl).toBe('string');
});
it('should handle null values properly', () => {
const schema: ModelParamsSchema = {
prompt: { default: 'test' },
seed: { default: null },
imageUrl: { default: null },
};
const result = extractDefaultValues(schema);
expect(result.seed).toBeNull();
expect(result.imageUrl).toBeNull();
});
});
describe('Type inference', () => {
it('should infer correct RuntimeImageGenParams type', () => {
// This is a compile-time test to ensure types are correctly inferred
const params: RuntimeImageGenParams = {
prompt: 'test',
width: 1024,
height: 768,
steps: 20,
seed: null,
cfg: 7.5,
};
expect(params.prompt).toBe('test');
expect(params.width).toBe(1024);
expect(params.seed).toBeNull();
});
it('should require prompt but make other parameters optional', () => {
// This test ensures prompt is required while others are optional
const minimalParams: RuntimeImageGenParams = {
prompt: 'required prompt',
};
expect(minimalParams.prompt).toBe('required prompt');
expect(minimalParams.width).toBeUndefined();
});
});
});