diff --git a/package.json b/package.json index faf55e4ac4..78b55a102b 100644 --- a/package.json +++ b/package.json @@ -94,22 +94,22 @@ "test:runtime:python": "cross-env CI=true jest ./test/runtime/runtime-python.spec.ts", "generate:runtime:python": "cross-env CI=true ts-node ./test/runtime/runtime-python.ts", "generate:runtime:java": "cross-env CI=true ts-node ./test/runtime/runtime-java.ts", - "test:runtime:go": "cross-env CI=true jest ./test/runtime/runtime-go.spec.ts", "generate:runtime:go": "cross-env CI=true ts-node ./test/runtime/runtime-go.ts", - "test:runtime:cplusplus": "cross-env CI=true jest ./test/runtime/runtime-cplusplus.spec.ts", "generate:runtime:cplusplus": "cross-env CI=true ts-node ./test/runtime/runtime-cplusplus.ts", - "test:runtime:kotlin": "cross-env CI=true jest ./test/runtime/runtime-kotlin.spec.ts", "generate:runtime:kotlin": "cross-env CI=true ts-node ./test/runtime/runtime-kotlin.ts", - "test:runtime:rust": "cross-env CI=true jest ./test/runtime/runtime-rust.spec.ts", "generate:runtime:rust": "cross-env CI=true ts-node ./test/runtime/runtime-rust.ts", - "test:runtime:php": "cross-env CI=true jest ./test/runtime/runtime-php.spec.ts", "generate:runtime:php": "cross-env CI=true ts-node ./test/runtime/runtime-php.ts", - "test:runtime:typescript": "cd ./test/runtime/runtime-typescript && npm i && npm run test", "generate:runtime:typescript": "cross-env CI=true ts-node ./test/runtime/runtime-typescript.ts", - "test:runtime:csharp": "cross-env CI=true jest ./test/runtime/runtime-csharp.spec.ts", "generate:runtime:csharp": "cross-env CI=true ts-node ./test/runtime/runtime-csharp.ts", - "test:runtime:scala": "cross-env CI=true jest ./test/runtime/runtime-scala.spec.ts", "generate:runtime:scala": "cross-env CI=true ts-node ./test/runtime/runtime-scala.ts", + "test:runtime:go": "cross-env CI=true jest ./test/runtime/runtime-go.spec.ts", + "test:runtime:cplusplus": "cross-env CI=true jest ./test/runtime/runtime-cplusplus.spec.ts", + "test:runtime:kotlin": "cross-env CI=true jest ./test/runtime/runtime-kotlin.spec.ts", + "test:runtime:rust": "cross-env CI=true jest ./test/runtime/runtime-rust.spec.ts", + "test:runtime:php": "cross-env CI=true jest ./test/runtime/runtime-php.spec.ts", + "test:runtime:typescript": "cd ./test/runtime/runtime-typescript && npm i && npm run test", + "test:runtime:csharp": "cross-env CI=true jest ./test/runtime/runtime-csharp.spec.ts", + "test:runtime:scala": "cross-env CI=true jest ./test/runtime/runtime-scala.spec.ts", "test:watch": "jest --watch", "docs": "npm run docs:api", "docs:api": "typedoc --sourceLinkExternal src/index.ts --out ./modelina-website/public/apidocs/generated --name Modelina", diff --git a/src/generators/typescript/presets/utils/MarshalFunction.ts b/src/generators/typescript/presets/utils/MarshalFunction.ts index a2b080a154..55e928a7d7 100644 --- a/src/generators/typescript/presets/utils/MarshalFunction.ts +++ b/src/generators/typescript/presets/utils/MarshalFunction.ts @@ -33,6 +33,7 @@ function renderMarshalProperty( return realizePropertyFactory(modelInstanceVariable); } + /** * Render marshalling logic for tuples */ @@ -47,12 +48,12 @@ function renderTupleSerialization( tupleEntry.value ); return `if(${modelInstanceVariable}[${tupleEntry.index}]) { - serializedTuple[${tupleEntry.index}] = ${temp} + serializedTuple[${tupleEntry.index}] = \`${temp}\` } else { serializedTuple[${tupleEntry.index}] = null; }`; }); - return `const serializedTuple = []; + return `const serializedTuple: any[] = []; ${t.join('\n')} json += \`"${unconstrainedProperty}": [\${serializedTuple.join(',')}],\`;`; } diff --git a/test/generators/typescript/preset/__snapshots__/MarshallingPreset.spec.ts.snap b/test/generators/typescript/preset/__snapshots__/MarshallingPreset.spec.ts.snap index 6e075e4fb0..80f8ce2c3c 100644 --- a/test/generators/typescript/preset/__snapshots__/MarshallingPreset.spec.ts.snap +++ b/test/generators/typescript/preset/__snapshots__/MarshallingPreset.spec.ts.snap @@ -104,14 +104,14 @@ exports[`Marshalling preset should render un/marshal code 1`] = ` json += \`\\"arrayTest\\": [\${arrayTestJsonValues.join(',')}],\`; } if(this.tupleTest !== undefined) { - const serializedTuple = []; + const serializedTuple: any[] = []; if(this.tupleTest[0]) { - serializedTuple[0] = \${this.tupleTest[0].marshal()} + serializedTuple[0] = \`\${this.tupleTest[0].marshal()}\` } else { serializedTuple[0] = null; } if(this.tupleTest[1]) { - serializedTuple[1] = \${typeof this.tupleTest[1] === 'number' || typeof this.tupleTest[1] === 'boolean' ? this.tupleTest[1] : JSON.stringify(this.tupleTest[1])} + serializedTuple[1] = \`\${typeof this.tupleTest[1] === 'number' || typeof this.tupleTest[1] === 'boolean' ? this.tupleTest[1] : JSON.stringify(this.tupleTest[1])}\` } else { serializedTuple[1] = null; } diff --git a/test/runtime/generic-input-all.json b/test/runtime/generic-input-all.json new file mode 100644 index 0000000000..1c2147a92a --- /dev/null +++ b/test/runtime/generic-input-all.json @@ -0,0 +1,78 @@ +{ + "$id": "TestObject", + "description": "This object contains all types of MetaModel generations", + "type": "object", + "properties": { + "string_type": { + "type": "string" + }, + "number_type": { + "type": "number" + }, + "boolean_type": { + "type": "boolean", + "description": "Status if marriage live in given house" + }, + "union_type": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + } + ] + }, + "array_type": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + } + }, + "tuple_type": { + "type": "array", + "items": [ + { + "type": "string" + }, + { + "type": "number" + } + ], + "additionalItems": false + }, + "object_type": { + "type": "object", + "properties": { + "test": { + "type": "string" + } + } + }, + "dictionary_type": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "enum_type": { + "enum": ["test", 1, true, {"test": 2}] + } + }, + "patternProperties": { + "^S(.?*)test&": { + "type": "string" + } + }, + "required": ["string_type", "boolean_type"] +} diff --git a/test/runtime/generic-input-simple.json b/test/runtime/generic-input-simple.json new file mode 100644 index 0000000000..ac630ebabf --- /dev/null +++ b/test/runtime/generic-input-simple.json @@ -0,0 +1,49 @@ +{ + "$id": "TestObject", + "description": "This object contains simple types of MetaModel generations. Object, enum, number, boolean array, tuple.", + "type": "object", + "properties": { + "string_type": { + "type": "string" + }, + "number_type": { + "type": "number" + }, + "boolean_type": { + "type": "boolean", + "description": "Status if marriage live in given house" + }, + "array_type": { + "type": "array", + "items": { + "type": "string" + } + }, + "tuple_type": { + "type": "array", + "items": [ + { + "type": "string" + }, + { + "type": "number" + } + ], + "additionalItems": false + }, + "object_type": { + "type": "object", + "properties": { + "test": { + "type": "string" + } + }, + "additionalProperties": false + }, + "enum_type": { + "enum": ["test", 1, true, {"test": 2}] + } + }, + "additionalProperties": false, + "required": ["string_type", "boolean_type"] +} diff --git a/test/runtime/runtime-typescript.ts b/test/runtime/runtime-typescript.ts index d262987ba6..4b46a3a71b 100644 --- a/test/runtime/runtime-typescript.ts +++ b/test/runtime/runtime-typescript.ts @@ -1,6 +1,7 @@ import { TS_COMMON_PRESET, TS_JSONBINPACK_PRESET, TypeScriptFileGenerator } from '../../'; import path from 'path'; -import input from './generic-input.json'; +import input from './generic-input-all.json'; +import simpleInput from './generic-input-simple.json'; async function generateNamedExport() { const generator = new TypeScriptFileGenerator({}); @@ -52,6 +53,7 @@ async function generateMarshalling() { { exportType: 'named' } ); } + async function generateJsonBinPack() { const generator = new TypeScriptFileGenerator({ presets: [ @@ -64,29 +66,8 @@ async function generateJsonBinPack() { TS_JSONBINPACK_PRESET ] }); - const simplifiedInput = { - "$id": "Address", - "description": "This object contains all types of MetaModel generations", - "type": "object", - "properties": { - "street_name": { - "type": "string" - }, - "house_number": { - "type": "number" - }, - "marriage": { - "type": "boolean", - "description": "Status if marriage live in given house" - }, - }, - "required": [ - "street_name", - "house_number", - ] - } await generator.generateToFiles( - simplifiedInput, + simpleInput, path.resolve( // eslint-disable-next-line no-undef __dirname, @@ -96,14 +77,11 @@ async function generateJsonBinPack() { ); } -async function generateEverything() { - await Promise.all( - [ - generateNamedExport(), - generateDefaultExport(), - generateMarshalling(), - generateJsonBinPack() - ] - ) -} -generateEverything(); \ No newline at end of file +Promise.all( + [ + generateNamedExport(), + generateDefaultExport(), + generateMarshalling(), + generateJsonBinPack() + ] +) \ No newline at end of file diff --git a/test/runtime/runtime-typescript/test/DefaultAddressTest.spec.ts b/test/runtime/runtime-typescript/test/DefaultAddressTest.spec.ts index cb54e268f3..02f5060fce 100644 --- a/test/runtime/runtime-typescript/test/DefaultAddressTest.spec.ts +++ b/test/runtime/runtime-typescript/test/DefaultAddressTest.spec.ts @@ -1,24 +1,33 @@ -import Address from '../src/defaultExport/Address'; -import NestedObject from '../src/defaultExport/NestedObject'; +import TestObject from '../src/defaultExport/TestObject'; +import ObjectType from '../src/defaultExport/ObjectType'; +import EnumType from '../src/defaultExport/EnumType'; -describe('Address', () => { +describe('Default exports', () => { test('should be able to instantiate default export model', () => { - const nestedObj = new NestedObject({ + const objectType = new ObjectType({ test: 'test' }); - const address = new Address({ - streetName: 'test', - houseNumber: 1, - marriage: true, - members: 2, + const testObject = new TestObject({ + stringType: 'test', + numberType: 1, + booleanType: true, arrayType: [1, 'test'], - nestedObject: nestedObj + objectType: objectType, + dictionaryType: new Map(Object.entries({"test": "test"})), + additionalProperties: new Map(Object.entries({"test": "test"})), + enumType: EnumType.CURLYLEFT_QUOTATION_TEST_QUOTATION_COLON_2_CURLYRIGHT, + tupleType: ['test', 1], + unionType: 'test' }); - expect(address.streetName).toEqual('test'); - expect(address.houseNumber).toEqual(1); - expect(address.marriage).toEqual(true); - expect(address.members).toEqual(2); - expect(address.arrayType).toEqual([1, 'test']); - expect(address.nestedObject?.test).toEqual('test'); + expect(testObject.stringType).toEqual('test'); + expect(testObject.numberType).toEqual(1); + expect(testObject.booleanType).toEqual(true); + expect(testObject.arrayType).toEqual([1, 'test']); + expect(testObject.objectType).toEqual(objectType); + expect(Object.fromEntries(testObject.dictionaryType!)).toEqual({"test": "test"}); + expect(Object.fromEntries(testObject.additionalProperties!)).toEqual({"test": "test"}); + expect(testObject.enumType).toEqual(EnumType.CURLYLEFT_QUOTATION_TEST_QUOTATION_COLON_2_CURLYRIGHT); + expect(testObject.tupleType).toEqual(['test', 1]); + expect(testObject.unionType).toEqual('test'); }); }); diff --git a/test/runtime/runtime-typescript/test/JsonBinPackPreset.spec.ts b/test/runtime/runtime-typescript/test/JsonBinPackPreset.spec.ts index b01f1b9ca3..7855931846 100644 --- a/test/runtime/runtime-typescript/test/JsonBinPackPreset.spec.ts +++ b/test/runtime/runtime-typescript/test/JsonBinPackPreset.spec.ts @@ -1,14 +1,23 @@ -import { Address } from '../src/jsonbinpack/Address'; +import { ObjectType } from '../src/jsonbinpack/ObjectType'; +import { TestObject } from '../src/jsonbinpack/TestObject'; +import { EnumType } from '../src/jsonbinpack/EnumType'; -describe('Address', () => { - const address = new Address({ - streetName: 'test', - houseNumber: 1, - marriage: true +describe('JSON binpack', () => { + const objectType = new ObjectType({ + test: 'test' }); - test('be able to serialize model and turning it back to a model with the same values', async () => { - const serialized = await address.jsonbinSerialize(); - const newAddress = await Address.jsonbinDeserialize(serialized); - expect(address.marshal()).toEqual(newAddress.marshal()); + const testObject = new TestObject({ + stringType: 'test', + numberType: 1, + booleanType: true, + arrayType: ['test'], + objectType: objectType, + enumType: EnumType.CURLYLEFT_QUOTATION_TEST_QUOTATION_COLON_2_CURLYRIGHT, + tupleType: ['test', 1] + }); + test.skip('should be able to serialize model and turning it back to a model with the same values', async () => { + const serialized = await testObject.jsonbinSerialize(); + const newTestObject = await TestObject.jsonbinDeserialize(serialized); + expect(testObject.marshal()).toEqual(newTestObject.marshal()); }); }); diff --git a/test/runtime/runtime-typescript/test/Marshalling.spec.ts b/test/runtime/runtime-typescript/test/Marshalling.spec.ts index 969b90aed8..036b213779 100644 --- a/test/runtime/runtime-typescript/test/Marshalling.spec.ts +++ b/test/runtime/runtime-typescript/test/Marshalling.spec.ts @@ -1,100 +1,32 @@ -import { Address } from '../src/marshalling/Address'; -import { NestedObject } from '../src/marshalling/NestedObject'; +import {TestObject} from '../src/marshalling/TestObject'; +import {ObjectType} from '../src/marshalling/ObjectType'; +import {EnumType} from '../src/marshalling/EnumType'; -describe('Address', () => { - describe('marshalling', () => { - describe('required properties', () => { - const address = new Address({ - streetName: 'test', - houseNumber: 1, - arrayType: [1, 'test'] - }); - test('should contain correctly marshalled JSON', () => { - const serialized = address.marshal(); - expect(serialized).toEqual("{\"street_name\": \"test\",\"house_number\": 1,\"array_type\": [1,\"test\"]}"); - }); - test('be able to serialize model and turning it back to a model with the same values', () => { - const serialized = address.marshal(); - const newAddress = Address.unmarshal(serialized); - expect(serialized).toEqual(newAddress.marshal()); - }); - }); - - describe('marriage', () => { - const address = new Address({ - streetName: 'test', - houseNumber: 1, - arrayType: [1, 'test'], - marriage: true, - }); - test('should contain correctly marshalled JSON', () => { - const serialized = address.marshal(); - expect(serialized).toEqual("{\"street_name\": \"test\",\"house_number\": 1,\"marriage\": true,\"array_type\": [1,\"test\"]}"); - }); - test('be able to serialize model and turning it back to a model with the same values', () => { - const serialized = address.marshal(); - const newAddress = Address.unmarshal(serialized); - expect(serialized).toEqual(newAddress.marshal()); - }); - }); - - describe('members', () => { - const address = new Address({ - streetName: 'test', - houseNumber: 1, - arrayType: [1, 'test'], - members: 2, - }); - test('should contain correctly marshalled JSON', () => { - const serialized = address.marshal(); - expect(serialized).toEqual("{\"street_name\": \"test\",\"house_number\": 1,\"members\": 2,\"array_type\": [1,\"test\"]}"); - }); - test('be able to serialize model and turning it back to a model with the same values', () => { - const serialized = address.marshal(); - const newAddress = Address.unmarshal(serialized); - expect(serialized).toEqual(newAddress.marshal()); - }); - }); - - describe('nestedObject', () => { - const nestedObj = new NestedObject({ - test: 'test' - }); - const address = new Address({ - streetName: 'test', - houseNumber: 1, - arrayType: [1, 'test'], - nestedObject: nestedObj - }); - test('should contain correctly marshalled JSON', () => { - const serialized = address.marshal(); - expect(serialized).toEqual("{\"street_name\": \"test\",\"house_number\": 1,\"array_type\": [1,\"test\"],\"nestedObject\": {\"test\": \"test\"}}"); - }); - test('be able to serialize model and turning it back to a model with the same values', () => { - const serialized = address.marshal(); - const newAddress = Address.unmarshal(serialized); - expect(serialized).toEqual(newAddress.marshal()); - }); - }); +describe('Marshalling', () => { + describe('should be able to serialize and deserialize the model', () => { describe('full model', () => { - const nestedObj = new NestedObject({ + const objectType = new ObjectType({ test: 'test' }); - const address = new Address({ - streetName: 'test', - houseNumber: 1, - marriage: true, - members: 2, + const testObject = new TestObject({ + stringType: 'test', + numberType: 1, + booleanType: true, arrayType: [1, 'test'], - nestedObject: nestedObj + objectType: objectType, + dictionaryType: new Map(Object.entries({"test": "test"})), + additionalProperties: new Map(Object.entries({"test": "test"})), + enumType: EnumType.CURLYLEFT_QUOTATION_TEST_QUOTATION_COLON_2_CURLYRIGHT, + tupleType: ['test', 1], + unionType: 'test' }); test('be able to serialize model', () => { - const serialized = address.marshal(); - expect(serialized).toEqual("{\"street_name\": \"test\",\"house_number\": 1,\"marriage\": true,\"members\": 2,\"array_type\": [1,\"test\"],\"nestedObject\": {\"test\": \"test\"}}"); + const serialized = testObject.marshal(); + expect(serialized).toEqual("{\"string_type\": \"test\",\"number_type\": 1,\"boolean_type\": true,\"union_type\": \"test\",\"array_type\": [1,\"test\"],\"tuple_type\": [\"test\",1],\"object_type\": {\"test\": \"test\"},\"dictionary_type\": {},\"enum_type\": \"{\\\"test\\\":2}\",\"test\": \"test\"}"); }); test('be able to serialize model and turning it back to a model with the same values', () => { - const serialized = address.marshal(); - const newAddress = Address.unmarshal(serialized); + const serialized = testObject.marshal(); + const newAddress = TestObject.unmarshal(serialized); expect(serialized).toEqual(newAddress.marshal()); }); }) diff --git a/test/runtime/runtime-typescript/test/NamedAddressTest.spec.ts b/test/runtime/runtime-typescript/test/NamedAddressTest.spec.ts index 12f62f0443..e2607238b2 100644 --- a/test/runtime/runtime-typescript/test/NamedAddressTest.spec.ts +++ b/test/runtime/runtime-typescript/test/NamedAddressTest.spec.ts @@ -1,24 +1,33 @@ -import { Address } from '../src/namedExport/Address'; -import { NestedObject } from '../src/namedExport/NestedObject'; +import {TestObject} from '../src/namedExport/TestObject'; +import {ObjectType} from '../src/namedExport/ObjectType'; +import {EnumType} from '../src/namedExport/EnumType'; -describe('Address', () => { +describe('Named exports', () => { test('should be able to instantiate named export model', () => { - const nestedObj = new NestedObject({ + const objectType = new ObjectType({ test: 'test' }); - const address = new Address({ - streetName: 'test', - houseNumber: 1, - marriage: true, - members: 2, + const testObject = new TestObject({ + stringType: 'test', + numberType: 1, + booleanType: true, arrayType: [1, 'test'], - nestedObject: nestedObj + objectType: objectType, + dictionaryType: new Map(Object.entries({"test": "test"})), + additionalProperties: new Map(Object.entries({"test": "test"})), + enumType: EnumType.CURLYLEFT_QUOTATION_TEST_QUOTATION_COLON_2_CURLYRIGHT, + tupleType: ['test', 1], + unionType: 'test' }); - expect(address.streetName).toEqual('test'); - expect(address.houseNumber).toEqual(1); - expect(address.marriage).toEqual(true); - expect(address.members).toEqual(2); - expect(address.arrayType).toEqual([1, 'test']); - expect(address.nestedObject?.test).toEqual('test'); + expect(testObject.stringType).toEqual('test'); + expect(testObject.numberType).toEqual(1); + expect(testObject.booleanType).toEqual(true); + expect(testObject.arrayType).toEqual([1, 'test']); + expect(testObject.objectType).toEqual(objectType); + expect(Object.fromEntries(testObject.dictionaryType!)).toEqual({"test": "test"}); + expect(Object.fromEntries(testObject.additionalProperties!)).toEqual({"test": "test"}); + expect(testObject.enumType).toEqual(EnumType.CURLYLEFT_QUOTATION_TEST_QUOTATION_COLON_2_CURLYRIGHT); + expect(testObject.tupleType).toEqual(['test', 1]); + expect(testObject.unionType).toEqual('test'); }); });