diff --git a/src/generators/csharp/CSharpGenerator.ts b/src/generators/csharp/CSharpGenerator.ts index 26a3a94b40..69d66168ab 100644 --- a/src/generators/csharp/CSharpGenerator.ts +++ b/src/generators/csharp/CSharpGenerator.ts @@ -54,7 +54,7 @@ export class CSharpGenerator extends AbstractGenerator( this.options.typeMapping, this.options.constraints, { diff --git a/src/generators/dart/DartGenerator.ts b/src/generators/dart/DartGenerator.ts index 98fde73749..9e945f6a23 100644 --- a/src/generators/dart/DartGenerator.ts +++ b/src/generators/dart/DartGenerator.ts @@ -49,7 +49,7 @@ export class DartGenerator extends AbstractGenerator( this.options.typeMapping, this.options.constraints, { diff --git a/src/generators/go/GoGenerator.ts b/src/generators/go/GoGenerator.ts index b8209b724c..780c4fbcf9 100644 --- a/src/generators/go/GoGenerator.ts +++ b/src/generators/go/GoGenerator.ts @@ -48,7 +48,7 @@ export class GoGenerator extends AbstractGenerator( this.options.typeMapping, this.options.constraints, { diff --git a/src/generators/java/JavaGenerator.ts b/src/generators/java/JavaGenerator.ts index 034da7fc7f..806247863c 100644 --- a/src/generators/java/JavaGenerator.ts +++ b/src/generators/java/JavaGenerator.ts @@ -48,7 +48,7 @@ export class JavaGenerator extends AbstractGenerator( this.options.typeMapping, this.options.constraints, { diff --git a/src/generators/javascript/JavaScriptGenerator.ts b/src/generators/javascript/JavaScriptGenerator.ts index fbd8c7d845..899aaac5bf 100644 --- a/src/generators/javascript/JavaScriptGenerator.ts +++ b/src/generators/javascript/JavaScriptGenerator.ts @@ -86,7 +86,7 @@ ${modelCode}`; } constrainToMetaModel(model: MetaModel): ConstrainedMetaModel { - return constrainMetaModel( + return constrainMetaModel( this.options.typeMapping, this.options.constraints, { diff --git a/src/generators/typescript/TypeScriptGenerator.ts b/src/generators/typescript/TypeScriptGenerator.ts index e3eae34f40..a3b63082cc 100644 --- a/src/generators/typescript/TypeScriptGenerator.ts +++ b/src/generators/typescript/TypeScriptGenerator.ts @@ -55,7 +55,7 @@ export class TypeScriptGenerator extends AbstractGenerator( this.options.typeMapping, this.options.constraints, { diff --git a/src/helpers/ConstrainHelpers.ts b/src/helpers/ConstrainHelpers.ts index bcb11a9510..d6729b17ac 100644 --- a/src/helpers/ConstrainHelpers.ts +++ b/src/helpers/ConstrainHelpers.ts @@ -152,7 +152,7 @@ function constrainObjectModel(typeMapping: TypeMapping, constr const constrainedPropertyModel = new ConstrainedObjectPropertyModel('', propertyMetaModel.required, constrainedModel); const constrainedPropertyName = constrainRules.propertyKey({objectPropertyModel: propertyMetaModel, constrainedObjectPropertyModel: constrainedPropertyModel, constrainedObjectModel: constrainedModel, objectModel: context.metaModel}); constrainedPropertyModel.propertyName = constrainedPropertyName; - const constrainedProperty = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: context.metaModel, propertyKey: constrainedPropertyName}); + const constrainedProperty = constrainMetaModel(typeMapping, constrainRules, {...context, metaModel: propertyMetaModel.property, propertyKey: constrainedPropertyName}); constrainedPropertyModel.property = constrainedProperty; constrainedModel.properties[String(constrainedPropertyName)] = constrainedPropertyModel; } @@ -178,7 +178,7 @@ function ConstrainEnumModel(typeMapping: TypeMapping, constrai return constrainedModel; } -export function constrainMetaModel(typeMapping: TypeMapping, constrainRules: Constraints, context: ConstrainContext): ConstrainedMetaModel { +export function constrainMetaModel(typeMapping: TypeMapping, constrainRules: Constraints, context: ConstrainContext): ConstrainedMetaModel { const constrainedName = constrainRules.modelName({modelName: context.metaModel.name}); const newContext = {...context, constrainedName}; if (newContext.metaModel instanceof ObjectModel) { diff --git a/test/helpers/ConstrainHelpers.spec.ts b/test/helpers/ConstrainHelpers.spec.ts new file mode 100644 index 0000000000..8a6e2a92f2 --- /dev/null +++ b/test/helpers/ConstrainHelpers.spec.ts @@ -0,0 +1,207 @@ +import { NO_NUMBER_START_CHAR, NO_EMPTY_VALUE, NO_DUPLICATE_PROPERTIES, FormatHelpers, NO_DUPLICATE_ENUM_KEYS, constrainMetaModel, TypeMapping, Constraints } from '../../src/helpers'; +import { AnyModel, ArrayModel, BooleanModel, ConstrainedAnyModel, ConstrainedArrayModel, ConstrainedBooleanModel, ConstrainedDictionaryModel, ConstrainedEnumModel, ConstrainedEnumValueModel, ConstrainedFloatModel, ConstrainedIntegerModel, ConstrainedObjectModel, ConstrainedObjectPropertyModel, ConstrainedReferenceModel, ConstrainedStringModel, ConstrainedTupleModel, ConstrainedTupleValueModel, ConstrainedUnionModel, DictionaryModel, EnumModel, EnumValueModel, FloatModel, IntegerModel, ObjectModel, ObjectPropertyModel, ReferenceModel, StringModel, TupleModel, TupleValueModel, UnionModel } from '../../src/models'; +const mockedTypeMapping: TypeMapping = { + Any: jest.fn(), + Array: jest.fn(), + Boolean: jest.fn(), + Dictionary: jest.fn(), + Enum: jest.fn(), + Float: jest.fn(), + Integer: jest.fn(), + Object: jest.fn(), + Reference: jest.fn(), + String: jest.fn(), + Tuple: jest.fn(), + Union: jest.fn() +}; +const mockedConstraints: Constraints = { + enumKey: jest.fn().mockImplementation(({enumKey}) => enumKey), + enumValue: jest.fn().mockImplementation(({enumValue}) => enumValue), + modelName: jest.fn().mockImplementation(({modelName}) => modelName), + propertyKey: jest.fn().mockImplementation(({objectPropertyModel}) => objectPropertyModel.propertyName) +}; +describe('ConstrainHelpers', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + describe('constrain ObjectModel', () => { + test('should constrain correctly', () => { + const testProperty = new StringModel('', undefined); + const metaModel = new ObjectModel('test', undefined, { + testProperty: new ObjectPropertyModel('testProperty', false, testProperty) + }); + const constrainedModel = constrainMetaModel(mockedTypeMapping, mockedConstraints, { + metaModel, + options: {}, + constrainedName: '' + }); + expect(constrainedModel instanceof ConstrainedObjectModel).toEqual(true); + expect((constrainedModel as ConstrainedObjectModel).properties['testProperty'].property instanceof ConstrainedStringModel).toEqual(true); + expect(mockedConstraints.modelName).toHaveBeenCalledTimes(2); + expect(mockedConstraints.propertyKey).toHaveBeenCalledTimes(1); + expect(mockedTypeMapping.Object).toHaveBeenCalledTimes(1); + expect(mockedTypeMapping.String).toHaveBeenCalledTimes(1); + }); + }); + describe('constrain ReferenceModel', () => { + test('should constrain correctly', () => { + const stringModel = new StringModel('', undefined); + const metaModel = new ReferenceModel('', undefined, stringModel); + const constrainedModel = constrainMetaModel(mockedTypeMapping, mockedConstraints, { + metaModel, + options: {}, + constrainedName: '' + }); + expect(constrainedModel instanceof ConstrainedReferenceModel).toEqual(true); + expect((constrainedModel as ConstrainedReferenceModel).ref instanceof ConstrainedStringModel).toEqual(true); + expect(mockedConstraints.modelName).toHaveBeenCalledTimes(2); + expect(mockedTypeMapping.String).toHaveBeenCalledTimes(1); + expect(mockedTypeMapping.Reference).toHaveBeenCalledTimes(1); + }); + }); + describe('constrain AnyModel', () => { + test('should constrain correctly', () => { + const metaModel = new AnyModel('', undefined); + const constrainedModel = constrainMetaModel(mockedTypeMapping, mockedConstraints, { + metaModel, + options: {}, + constrainedName: '' + }); + expect(constrainedModel instanceof ConstrainedAnyModel).toEqual(true); + expect(mockedConstraints.modelName).toHaveBeenCalledTimes(1); + expect(mockedTypeMapping.Any).toHaveBeenCalledTimes(1); + }); + }); + describe('constrain FloatModel', () => { + test('should constrain correctly', () => { + const metaModel = new FloatModel('', undefined); + const constrainedModel = constrainMetaModel(mockedTypeMapping, mockedConstraints, { + metaModel, + options: {}, + constrainedName: '' + }); + expect(constrainedModel instanceof ConstrainedFloatModel).toEqual(true); + expect(mockedConstraints.modelName).toHaveBeenCalledTimes(1); + expect(mockedTypeMapping.Float).toHaveBeenCalledTimes(1); + }); + }); + describe('constrain IntegerModel', () => { + test('should constrain correctly', () => { + const metaModel = new IntegerModel('', undefined); + const constrainedModel = constrainMetaModel(mockedTypeMapping, mockedConstraints, { + metaModel, + options: {}, + constrainedName: '' + }); + expect(constrainedModel instanceof ConstrainedIntegerModel).toEqual(true); + expect(mockedConstraints.modelName).toHaveBeenCalledTimes(1); + expect(mockedTypeMapping.Integer).toHaveBeenCalledTimes(1); + }); + }); + describe('constrain StringModel', () => { + test('should constrain correctly', () => { + const metaModel = new StringModel('', undefined); + const constrainedModel = constrainMetaModel(mockedTypeMapping, mockedConstraints, { + metaModel, + options: {}, + constrainedName: '' + }); + expect(constrainedModel instanceof ConstrainedStringModel).toEqual(true); + expect(mockedConstraints.modelName).toHaveBeenCalledTimes(1); + expect(mockedTypeMapping.String).toHaveBeenCalledTimes(1); + }); + }); + describe('constrain BooleanModel', () => { + test('should constrain correctly', () => { + const metaModel = new BooleanModel('', undefined); + const constrainedModel = constrainMetaModel(mockedTypeMapping, mockedConstraints, { + metaModel, + options: {}, + constrainedName: '' + }); + expect(constrainedModel instanceof ConstrainedBooleanModel).toEqual(true); + expect(mockedConstraints.modelName).toHaveBeenCalledTimes(1); + expect(mockedTypeMapping.Boolean).toHaveBeenCalledTimes(1); + }); + }); + + describe('constrain TupleModel', () => { + test('should constrain correctly', () => { + const stringModel = new StringModel('', undefined); + const metaModel = new TupleModel('test', undefined, [new TupleValueModel(0, stringModel)]); + const constrainedModel = constrainMetaModel(mockedTypeMapping, mockedConstraints, { + metaModel, + options: {}, + constrainedName: '' + }); + expect(constrainedModel instanceof ConstrainedTupleModel).toEqual(true); + expect((constrainedModel as ConstrainedTupleModel).tuple[0].value instanceof ConstrainedStringModel).toEqual(true); + expect(mockedConstraints.modelName).toHaveBeenCalledTimes(2); + expect(mockedTypeMapping.Tuple).toHaveBeenCalledTimes(1); + expect(mockedTypeMapping.String).toHaveBeenCalledTimes(1); + }); + }); + describe('constrain ArrayModel', () => { + test('should constrain correctly', () => { + const stringModel = new StringModel('', undefined); + const metaModel = new ArrayModel('test', undefined, stringModel); + const constrainedModel = constrainMetaModel(mockedTypeMapping, mockedConstraints, { + metaModel, + options: {}, + constrainedName: '' + }); + expect(constrainedModel instanceof ConstrainedArrayModel).toEqual(true); + expect((constrainedModel as ConstrainedArrayModel).valueModel instanceof ConstrainedStringModel).toEqual(true); + expect(mockedConstraints.modelName).toHaveBeenCalledTimes(2); + expect(mockedTypeMapping.Array).toHaveBeenCalledTimes(1); + expect(mockedTypeMapping.String).toHaveBeenCalledTimes(1); + }); + }); + describe('constrain UnionModel', () => { + test('should constrain correctly', () => { + const stringModel = new StringModel('', undefined); + const metaModel = new UnionModel('test', undefined, [stringModel]); + const constrainedModel = constrainMetaModel(mockedTypeMapping, mockedConstraints, { + metaModel, + options: {}, + constrainedName: '' + }); + expect(constrainedModel instanceof ConstrainedUnionModel).toEqual(true); + expect((constrainedModel as ConstrainedUnionModel).union[0] instanceof ConstrainedStringModel).toEqual(true); + expect(mockedConstraints.modelName).toHaveBeenCalledTimes(2); + expect(mockedTypeMapping.Union).toHaveBeenCalledTimes(1); + expect(mockedTypeMapping.String).toHaveBeenCalledTimes(1); + }); + }); + describe('constrain EnumModel', () => { + test('should constrain correctly', () => { + const metaModel = new EnumModel('test', undefined, [new EnumValueModel('test', 123)]); + const constrainedModel = constrainMetaModel(mockedTypeMapping, mockedConstraints, { + metaModel, + options: {}, + constrainedName: '' + }); + expect(constrainedModel instanceof ConstrainedEnumModel).toEqual(true); + expect((constrainedModel as ConstrainedEnumModel).values[0] instanceof ConstrainedEnumValueModel).toEqual(true); + expect(mockedConstraints.modelName).toHaveBeenCalledTimes(1); + expect(mockedTypeMapping.Enum).toHaveBeenCalledTimes(1); + }); + }); + describe('constrain DictionaryModel', () => { + test('should constrain correctly', () => { + const stringModel = new StringModel('', undefined); + const metaModel = new DictionaryModel('test', undefined, stringModel, stringModel); + const constrainedModel = constrainMetaModel(mockedTypeMapping, mockedConstraints, { + metaModel, + options: {}, + constrainedName: '' + }); + expect(constrainedModel instanceof ConstrainedDictionaryModel).toEqual(true); + expect((constrainedModel as ConstrainedDictionaryModel).key instanceof ConstrainedStringModel).toEqual(true); + expect((constrainedModel as ConstrainedDictionaryModel).value instanceof ConstrainedStringModel).toEqual(true); + expect(mockedConstraints.modelName).toHaveBeenCalledTimes(3); + expect(mockedTypeMapping.Dictionary).toHaveBeenCalledTimes(1); + expect(mockedTypeMapping.String).toHaveBeenCalledTimes(2); + }); + }); +});