UNPKG

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
"use strict"; 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