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.
319 lines • 16.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const code_generator_1 = require("./code-generator");
(0, vitest_1.describe)('Code Generator', () => {
(0, vitest_1.describe)('generateWithMethods', () => {
(0, vitest_1.it)('generates with methods for object with properties', () => {
const schema = {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'number' },
email: { type: 'string', format: 'email' },
},
};
const result = (0, code_generator_1.generateWithMethods)(schema, 'User');
(0, vitest_1.expect)(result).toContain('withName');
(0, vitest_1.expect)(result).toContain('withAge');
(0, vitest_1.expect)(result).toContain('withEmail');
(0, vitest_1.expect)(result).toContain('types.User["name"]');
(0, vitest_1.expect)(result).toContain('types.User["age"]');
(0, vitest_1.expect)(result).toContain('types.User["email"]');
});
(0, vitest_1.it)('returns empty string for non-object schema', () => {
const schema = {
type: 'string',
};
const result = (0, code_generator_1.generateWithMethods)(schema, 'StringType');
(0, vitest_1.expect)(result).toBe('');
});
(0, vitest_1.it)('returns empty string for object without properties', () => {
const schema = {
type: 'object',
};
const result = (0, code_generator_1.generateWithMethods)(schema, 'EmptyObject');
(0, vitest_1.expect)(result).toBe('');
});
(0, vitest_1.it)('handles properties with special characters in names', () => {
const schema = {
type: 'object',
properties: {
'user-name': { type: 'string' },
user_email: { type: 'string' },
},
};
const result = (0, code_generator_1.generateWithMethods)(schema, 'User');
(0, vitest_1.expect)(result).toContain('withUserName');
(0, vitest_1.expect)(result).toContain('withUserEmail');
});
(0, vitest_1.it)('generates methods for all properties', () => {
const schema = {
type: 'object',
properties: {
id: { type: 'string' },
isActive: { type: 'boolean' },
count: { type: 'integer' },
},
};
const result = (0, code_generator_1.generateWithMethods)(schema, 'Entity');
const lines = result.split('\n').filter((l) => l.trim());
(0, vitest_1.expect)(lines.length).toBe(3);
});
});
(0, vitest_1.describe)('generateImports', () => {
(0, vitest_1.it)('generates runtime imports when mockStrategy is runtime', () => {
const result = (0, code_generator_1.generateImports)({
mockStrategy: 'runtime',
generateZod: false,
});
(0, vitest_1.expect)(result).toContain('import { generateMock }');
(0, vitest_1.expect)(result).toContain('import type { BuilderSchema }');
(0, vitest_1.expect)(result).toContain('import type * as types from "./types.gen"');
(0, vitest_1.expect)(result).not.toContain('import { z }');
});
(0, vitest_1.it)('generates Zod imports when mockStrategy is zod', () => {
const result = (0, code_generator_1.generateImports)({
mockStrategy: 'zod',
generateZod: false,
});
(0, vitest_1.expect)(result).toContain('import { generateMockFromZodSchema }');
(0, vitest_1.expect)(result).toContain('import { z }');
(0, vitest_1.expect)(result).not.toContain('import { generateMock }');
});
(0, vitest_1.it)('generates no library imports when mockStrategy is static', () => {
const result = (0, code_generator_1.generateImports)({
mockStrategy: 'static',
generateZod: false,
});
(0, vitest_1.expect)(result).not.toContain('import { generateMock }');
(0, vitest_1.expect)(result).not.toContain('import { generateMockFromZodSchema }');
(0, vitest_1.expect)(result).toContain('import type * as types from "./types.gen"');
});
(0, vitest_1.it)('includes Zod import when generateZod is true', () => {
const result = (0, code_generator_1.generateImports)({
mockStrategy: 'runtime',
generateZod: true,
});
(0, vitest_1.expect)(result).toContain('import { z }');
});
(0, vitest_1.it)('includes Zod import only once when both options use it', () => {
const result = (0, code_generator_1.generateImports)({
mockStrategy: 'zod',
generateZod: true,
});
const zodImports = result.match(/import \{ z \}/g);
(0, vitest_1.expect)(zodImports).toHaveLength(1);
});
});
(0, vitest_1.describe)('generateBuilderOptionsType', () => {
(0, vitest_1.it)('generates BuilderOptions type definition', () => {
const result = (0, code_generator_1.generateBuilderOptionsType)();
(0, vitest_1.expect)(result).toContain('type BuilderOptions');
(0, vitest_1.expect)(result).toContain('useDefault?: boolean');
(0, vitest_1.expect)(result).toContain('useExamples?: boolean');
(0, vitest_1.expect)(result).toContain('alwaysIncludeOptionals?: boolean');
(0, vitest_1.expect)(result).toContain('optionalsProbability?: number | false');
(0, vitest_1.expect)(result).toContain('omitNulls?: boolean');
});
(0, vitest_1.it)('returns consistent output', () => {
const result1 = (0, code_generator_1.generateBuilderOptionsType)();
const result2 = (0, code_generator_1.generateBuilderOptionsType)();
(0, vitest_1.expect)(result1).toBe(result2);
});
});
(0, vitest_1.describe)('generateSchemaConstants', () => {
(0, vitest_1.it)('generates schema constants object', () => {
const metas = [
{ constName: 'UserSchema', schema: { type: 'object' } },
{ constName: 'ProductSchema', schema: { type: 'object' } },
];
const result = (0, code_generator_1.generateSchemaConstants)(metas);
(0, vitest_1.expect)(result).toContain('const schemas = {');
(0, vitest_1.expect)(result).toContain('UserSchema:');
(0, vitest_1.expect)(result).toContain('ProductSchema:');
(0, vitest_1.expect)(result).toContain('satisfies Record<string, BuilderSchema>');
});
(0, vitest_1.it)('handles single schema', () => {
const metas = [{ constName: 'SingleSchema', schema: { type: 'string' } }];
const result = (0, code_generator_1.generateSchemaConstants)(metas);
(0, vitest_1.expect)(result).toContain('SingleSchema:');
(0, vitest_1.expect)(result).toContain('"type":"string"');
});
(0, vitest_1.it)('handles empty array', () => {
const result = (0, code_generator_1.generateSchemaConstants)([]);
(0, vitest_1.expect)(result).toContain('const schemas = {');
(0, vitest_1.expect)(result).toContain('}');
});
(0, vitest_1.it)('properly serializes schema objects', () => {
const metas = [
{
constName: 'ComplexSchema',
schema: {
type: 'object',
properties: {
name: { type: 'string' },
},
required: ['name'],
},
},
];
const result = (0, code_generator_1.generateSchemaConstants)(metas);
(0, vitest_1.expect)(result).toContain('"properties"');
(0, vitest_1.expect)(result).toContain('"required"');
});
});
(0, vitest_1.describe)('generateImports edge cases', () => {
(0, vitest_1.it)('includes all imports when all options are enabled', () => {
const result = (0, code_generator_1.generateImports)({
mockStrategy: 'zod',
generateZod: true,
});
(0, vitest_1.expect)(result).toContain('import type * as types from "./types.gen"');
(0, vitest_1.expect)(result).toContain('generateMockFromZodSchema');
(0, vitest_1.expect)(result).toContain('import { z } from "zod"');
});
(0, vitest_1.it)('includes only base imports when no options are enabled', () => {
const result = (0, code_generator_1.generateImports)({
mockStrategy: 'runtime',
generateZod: false,
});
(0, vitest_1.expect)(result).toContain('import type * as types from "./types.gen"');
(0, vitest_1.expect)(result).toContain('generateMock');
});
(0, vitest_1.it)('handles static mocks correctly', () => {
const result = (0, code_generator_1.generateImports)({
mockStrategy: 'static',
generateZod: false,
});
(0, vitest_1.expect)(result).toContain('import type * as types from "./types.gen"');
});
});
(0, vitest_1.describe)('generateBuilderOptionsType edge cases', () => {
(0, vitest_1.it)('generates the correct type definition', () => {
const result = (0, code_generator_1.generateBuilderOptionsType)();
(0, vitest_1.expect)(result).toContain('type BuilderOptions');
(0, vitest_1.expect)(result).toContain('useDefault');
(0, vitest_1.expect)(result).toContain('boolean');
});
(0, vitest_1.it)('includes proper formatting', () => {
const result = (0, code_generator_1.generateBuilderOptionsType)();
(0, vitest_1.expect)(result).toMatch(/\n/);
(0, vitest_1.expect)(result.includes('{')).toBe(true);
(0, vitest_1.expect)(result.includes('}')).toBe(true);
});
});
(0, vitest_1.describe)('generateWithMethods advanced cases', () => {
(0, vitest_1.it)('handles property names with special characters', () => {
const schema = {
type: 'object',
properties: {
'nested-property': { type: 'string' },
another_nested: { type: 'number' },
},
};
const result = (0, code_generator_1.generateWithMethods)(schema, 'Complex');
(0, vitest_1.expect)(result).toContain('withNestedProperty');
(0, vitest_1.expect)(result).toContain('withAnotherNested');
});
(0, vitest_1.it)('generates correct method signatures', () => {
const schema = {
type: 'object',
properties: {
id: { type: 'number' },
},
};
const result = (0, code_generator_1.generateWithMethods)(schema, 'Entity');
(0, vitest_1.expect)(result).toContain('withId(');
(0, vitest_1.expect)(result).toContain('value: types.Entity["id"]');
(0, vitest_1.expect)(result).toContain('return this');
});
});
(0, vitest_1.describe)('generateSchemaConstants advanced cases', () => {
(0, vitest_1.it)('handles schemas with multiple complex properties', () => {
const metas = [
{
constName: 'MultiPropertySchema',
schema: {
type: 'object',
properties: {
name: { type: 'string', minLength: 5 },
age: { type: 'number', minimum: 0, maximum: 120 },
email: { type: 'string', format: 'email' },
tags: { type: 'array', items: { type: 'string' } },
},
required: ['name', 'email'],
},
},
];
const result = (0, code_generator_1.generateSchemaConstants)(metas);
(0, vitest_1.expect)(result).toContain('MultiPropertySchema');
(0, vitest_1.expect)(result).toContain('minLength');
(0, vitest_1.expect)(result).toContain('minimum');
(0, vitest_1.expect)(result).toContain('format');
});
(0, vitest_1.it)('escapes special characters in schema values', () => {
const metas = [
{
constName: 'SpecialCharsSchema',
schema: {
type: 'string',
pattern: '^[a-z]+"test"\\s*$',
},
},
];
const result = (0, code_generator_1.generateSchemaConstants)(metas);
(0, vitest_1.expect)(result).toContain('pattern');
});
});
(0, vitest_1.describe)('generateProperty', () => {
(0, vitest_1.it)('generates a private property declaration', () => {
const result = (0, code_generator_1.generateProperty)('overrides', 'Partial<User>', '{}');
(0, vitest_1.expect)(result).toBe(' private overrides: Partial<User> = {}\n');
});
(0, vitest_1.it)('generates property with different types', () => {
const result = (0, code_generator_1.generateProperty)('options', 'BuilderOptions', '{}');
(0, vitest_1.expect)(result).toContain('private options');
(0, vitest_1.expect)(result).toContain('BuilderOptions');
});
});
(0, vitest_1.describe)('generateMethod', () => {
(0, vitest_1.it)('generates a method declaration', () => {
const body = ' return this.value;\n';
const result = (0, code_generator_1.generateMethod)('getValue', 'string', body);
(0, vitest_1.expect)(result).toContain('getValue()');
(0, vitest_1.expect)(result).toContain(': string {');
(0, vitest_1.expect)(result).toContain('return this.value');
});
(0, vitest_1.it)('generates method with complex body', () => {
const body = ' const result = doSomething();\n return result;\n';
const result = (0, code_generator_1.generateMethod)('build', 'User', body);
(0, vitest_1.expect)(result).toContain('build()');
(0, vitest_1.expect)(result).toContain(': User {');
});
});
(0, vitest_1.describe)('indent', () => {
(0, vitest_1.it)('indents single line code', () => {
const code = 'const x = 1;';
const result = (0, code_generator_1.indent)(code, 2);
(0, vitest_1.expect)(result).toBe(' const x = 1;');
});
(0, vitest_1.it)('indents multi-line code', () => {
const code = 'const x = 1;\nconst y = 2;';
const result = (0, code_generator_1.indent)(code, 4);
(0, vitest_1.expect)(result).toBe(' const x = 1;\n const y = 2;');
});
(0, vitest_1.it)('preserves empty lines', () => {
const code = 'const x = 1;\n\nconst y = 2;';
const result = (0, code_generator_1.indent)(code, 2);
(0, vitest_1.expect)(result).toBe(' const x = 1;\n\n const y = 2;');
});
(0, vitest_1.it)('handles code with existing indentation', () => {
const code = ' const x = 1;\n const y = 2;';
const result = (0, code_generator_1.indent)(code, 2);
(0, vitest_1.expect)(result).toContain(' const x = 1;');
(0, vitest_1.expect)(result).toContain(' const y = 2;');
});
});
});
//# sourceMappingURL=code-generator.test.js.map