hey-api-builders
Version:
A custom plugin for @hey-api/openapi-ts that generates mock data builders with a lightweight custom runtime, Zod integration, or static mock generation.
510 lines (444 loc) • 13.8 kB
text/typescript
import { describe, it, expect } from 'vitest';
import { generateMock } from './mock-runtime';
describe('Custom Mock Runtime', () => {
describe('generateMock', () => {
it('generates mock from simple string schema', () => {
const schema = { type: 'string' };
const result = generateMock(schema);
expect(typeof result).toBe('string');
});
it('generates mock from number schema', () => {
const schema = { type: 'number' };
const result = generateMock(schema);
expect(typeof result).toBe('number');
});
it('generates mock from boolean schema', () => {
const schema = { type: 'boolean' };
const result = generateMock(schema);
expect(typeof result).toBe('boolean');
});
it('generates mock from object schema', () => {
const schema = {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'number' },
},
required: ['name'],
};
const result = generateMock<{ name: string; age?: number }>(schema);
expect(result).toHaveProperty('name');
expect(typeof result.name).toBe('string');
});
it('generates mock from array schema', () => {
const schema = {
type: 'array',
items: { type: 'string' },
};
const result = generateMock<string[]>(schema);
expect(Array.isArray(result)).toBe(true);
});
it('respects enum values', () => {
const schema = {
type: 'string',
enum: ['active', 'inactive'],
};
const result = generateMock<string>(schema);
expect(['active', 'inactive']).toContain(result);
});
it('uses default value when useDefault is true', () => {
const schema = {
type: 'string',
default: 'default-value',
};
const result = generateMock<string>(schema, { useDefault: true });
expect(result).toBe('default-value');
});
it('uses example value when useExamples is true', () => {
const schema = {
type: 'string',
examples: ['example-value'],
};
const result = generateMock<string>(schema, { useExamples: true });
expect(result).toBe('example-value');
});
it('respects minLength for strings', () => {
const schema = {
type: 'string',
minLength: 10,
};
const result = generateMock<string>(schema);
expect(result.length).toBeGreaterThanOrEqual(10);
});
it('respects maxLength for strings', () => {
const schema = {
type: 'string',
maxLength: 5,
};
const result = generateMock<string>(schema);
expect(result.length).toBeLessThanOrEqual(5);
});
it('respects minimum for numbers', () => {
const schema = {
type: 'number',
minimum: 10,
};
const result = generateMock<number>(schema);
expect(result).toBeGreaterThanOrEqual(10);
});
it('respects maximum for numbers', () => {
const schema = {
type: 'number',
maximum: 100,
};
const result = generateMock<number>(schema);
expect(result).toBeLessThanOrEqual(100);
});
it('handles requiredOnly option', () => {
const schema = {
type: 'object',
properties: {
required1: { type: 'string' },
optional1: { type: 'string' },
},
required: ['required1'],
};
const result = generateMock<Record<string, unknown>>(schema, { requiredOnly: true });
expect(result).toHaveProperty('required1');
});
it('generates consistent types for schemas', () => {
const schema = {
type: 'object',
properties: {
id: { type: 'string', format: 'uuid' },
email: { type: 'string', format: 'email' },
count: { type: 'integer' },
},
required: ['id', 'email', 'count'],
};
const result = generateMock<{ id: string; email: string; count: number }>(schema);
expect(typeof result.id).toBe('string');
expect(typeof result.email).toBe('string');
expect(typeof result.count).toBe('number');
});
it('handles nested objects', () => {
const schema = {
type: 'object',
properties: {
user: {
type: 'object',
properties: {
name: { type: 'string' },
},
required: ['name'],
},
},
required: ['user'],
};
const result = generateMock<{ user: { name: string } }>(schema);
expect(result).toHaveProperty('user');
expect(result.user).toHaveProperty('name');
});
it('handles arrays of objects', () => {
const schema = {
type: 'array',
items: {
type: 'object',
properties: {
name: { type: 'string' },
},
required: ['name'],
},
minItems: 1,
};
const result = generateMock<Array<{ name: string }>>(schema);
expect(Array.isArray(result)).toBe(true);
expect(result.length).toBeGreaterThanOrEqual(1);
expect(result[0]).toHaveProperty('name');
});
it('handles null type', () => {
const schema = { type: 'null' };
const result = generateMock(schema);
expect(result).toBe(null);
});
it('handles oneOf schemas', () => {
const schema = {
oneOf: [{ type: 'string' }, { type: 'number' }],
};
const result = generateMock(schema);
expect(['string', 'number']).toContain(typeof result);
});
it('handles anyOf schemas', () => {
const schema = {
anyOf: [{ type: 'string' }, { type: 'number' }],
};
const result = generateMock(schema);
expect(['string', 'number']).toContain(typeof result);
});
it('handles allOf schemas with merging', () => {
const schema = {
allOf: [
{
type: 'object',
properties: {
name: { type: 'string' },
},
required: ['name'],
},
{
type: 'object',
properties: {
age: { type: 'number' },
},
},
],
};
const result = generateMock<{ name: string; age?: number }>(schema);
expect(result).toHaveProperty('name');
expect(typeof result.name).toBe('string');
});
it('respects minItems for arrays', () => {
const schema = {
type: 'array',
items: { type: 'string' },
minItems: 5,
};
const result = generateMock<string[]>(schema);
expect(Array.isArray(result)).toBe(true);
expect(result.length).toBeGreaterThanOrEqual(5);
});
it('respects maxItems for arrays', () => {
const schema = {
type: 'array',
items: { type: 'string' },
maxItems: 2,
};
const result = generateMock<string[]>(schema);
expect(Array.isArray(result)).toBe(true);
expect(result.length).toBeLessThanOrEqual(2);
});
it('handles integer type specifically', () => {
const schema = {
type: 'integer',
};
const result = generateMock(schema);
expect(typeof result).toBe('number');
expect(Number.isInteger(result)).toBe(true);
});
it('respects minimum for numbers', () => {
const schema = {
type: 'number',
minimum: 100,
};
const result = generateMock(schema);
expect(result).toBeGreaterThanOrEqual(100);
});
it('respects maximum for numbers', () => {
const schema = {
type: 'number',
maximum: 10,
};
const result = generateMock(schema);
expect(result).toBeLessThanOrEqual(10);
});
it('respects minLength for strings', () => {
const schema = {
type: 'string',
minLength: 20,
};
const result = generateMock(schema);
expect(typeof result).toBe('string');
expect((result as string).length).toBeGreaterThanOrEqual(20);
});
it('respects maxLength for strings', () => {
const schema = {
type: 'string',
maxLength: 5,
};
const result = generateMock(schema);
expect(typeof result).toBe('string');
expect((result as string).length).toBeLessThanOrEqual(5);
});
it('handles pattern for strings with placeholder', () => {
const schema = {
type: 'string',
pattern: '^[0-9]{3}$',
};
const result = generateMock(schema);
expect(typeof result).toBe('string');
expect(result).toMatch(/^x+$/);
});
it('handles uuid format with placeholder', () => {
const schema = {
type: 'string',
format: 'uuid',
};
const result = generateMock(schema);
expect(typeof result).toBe('string');
expect(result).toBe('00000000-0000-0000-0000-000000000000');
});
it('handles email format', () => {
const schema = {
type: 'string',
format: 'email',
};
const result = generateMock(schema);
expect(typeof result).toBe('string');
expect(result).toMatch(/@/);
});
it('handles uri format', () => {
const schema = {
type: 'string',
format: 'uri',
};
const result = generateMock(schema);
expect(typeof result).toBe('string');
expect(result).toMatch(/^https?:\/\//);
});
it('handles date-time format', () => {
const schema = {
type: 'string',
format: 'date-time',
};
const result = generateMock(schema);
expect(typeof result).toBe('string');
expect(!isNaN(Date.parse(result as string))).toBe(true);
});
it('handles date format', () => {
const schema = {
type: 'string',
format: 'date',
};
const result = generateMock(schema);
expect(typeof result).toBe('string');
expect(/^\d{4}-\d{2}-\d{2}$/.test(result as string)).toBe(true);
});
it('handles time format', () => {
const schema = {
type: 'string',
format: 'time',
};
const result = generateMock(schema);
expect(typeof result).toBe('string');
expect(/^\d{2}:\d{2}:\d{2}/.test(result as string)).toBe(true);
});
it('applies overrides to nested properties', () => {});
it('handles schemas with const value', () => {
const schema = {
type: 'string',
const: 'fixed-value',
};
const result = generateMock(schema);
expect(result).toBe('fixed-value');
});
it('handles schemas with default value', () => {
const schema = {
type: 'string',
default: 'default-value',
};
const result = generateMock(schema);
expect(typeof result).toBe('string');
});
it('handles schemas with examples', () => {
const schema = {
type: 'string',
examples: ['example1', 'example2'],
};
const result = generateMock(schema);
expect(typeof result).toBe('string');
});
it('handles deeply nested structures', () => {
const schema = {
type: 'object',
properties: {
level1: {
type: 'object',
properties: {
level2: {
type: 'object',
properties: {
level3: {
type: 'string',
},
},
required: ['level3'],
},
},
required: ['level2'],
},
},
required: ['level1'],
} as const;
const result = generateMock<{ level1: { level2: { level3: string } } }>(schema);
expect(result.level1.level2.level3).toBeDefined();
expect(typeof result.level1.level2.level3).toBe('string');
});
it('handles array within object within array', () => {
const schema = {
type: 'array',
items: {
type: 'object',
properties: {
tags: {
type: 'array',
items: { type: 'string' },
},
},
required: ['tags'],
},
};
const result = generateMock<Array<{ tags: string[] }>>(schema);
expect(Array.isArray(result)).toBe(true);
expect(result.length).toBeGreaterThan(0);
expect(Array.isArray(result[0].tags)).toBe(true);
});
it('returns null for unknown schema type', () => {
const schema = {
type: 'unknown-type' as unknown as 'string',
};
const result = generateMock(schema);
expect(result).toBeNull();
});
it('handles exclusiveMinimum', () => {
const schema = {
type: 'number',
exclusiveMinimum: 10,
};
const result = generateMock(schema);
expect(result).toBeGreaterThan(10);
});
it('handles exclusiveMaximum', () => {
const schema = {
type: 'number',
exclusiveMaximum: 10,
};
const result = generateMock(schema);
expect(result).toBeLessThan(10);
});
it('handles multipleOf constraint', () => {
const schema = {
type: 'number',
multipleOf: 5,
};
const result = generateMock(schema);
expect((result as number) % 5).toBe(0);
});
it('handles empty object schema', () => {
const schema = {
type: 'object',
properties: {},
};
const result = generateMock(schema);
expect(typeof result).toBe('object');
expect(result).toEqual({});
});
it('handles empty array items', () => {
const schema = {
type: 'array',
items: {},
};
const result = generateMock(schema);
expect(Array.isArray(result)).toBe(true);
});
});
});