From 282dcaa4054297da58fbcff4d5fb77f166ddce7a Mon Sep 17 00:00:00 2001 From: Juneidy Date: Thu, 14 Dec 2023 13:15:06 +0800 Subject: [PATCH] Fix self-ref within schema inheritance (`allOf`) --- lib/model.ts | 2 +- test/self-ref-allof.config.json | 6 ++ test/self-ref-allof.json | 57 ++++++++++++++++++ test/self-ref.spec.ts | 101 +++++++++++++++++++++----------- 4 files changed, 130 insertions(+), 36 deletions(-) create mode 100644 test/self-ref-allof.config.json create mode 100644 test/self-ref-allof.json diff --git a/lib/model.ts b/lib/model.ts index f8a236a..e0d1dfa 100644 --- a/lib/model.ts +++ b/lib/model.ts @@ -70,7 +70,7 @@ export class Model extends GenType { this.properties = sortedNames.map(propName => propertiesByName.get(propName) as Property); } else { // Simple / array / enum / union / intersection - this.simpleType = tsType(schema, options, openApi); + this.simpleType = tsType(schema, options, openApi, this); } this.collectImports(schema); this.updateImports(); diff --git a/test/self-ref-allof.config.json b/test/self-ref-allof.config.json new file mode 100644 index 0000000..d7ddde2 --- /dev/null +++ b/test/self-ref-allof.config.json @@ -0,0 +1,6 @@ +{ + "$schema": "../ng-openapi-gen-schema.json", + "input": "self-ref-allof.json", + "output": "out/self-ref-allof", + "ignoreUnusedModels": false +} diff --git a/test/self-ref-allof.json b/test/self-ref-allof.json new file mode 100644 index 0000000..96edeb3 --- /dev/null +++ b/test/self-ref-allof.json @@ -0,0 +1,57 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Blah", + "version": "1" + }, + "paths": {}, + "components": { + "schemas": { + "Parent.Class": { + "type": "object", + "properties": { + "parentProps": { + "type": "string" + } + } + }, + "Foo.Bar.Baz": { + "allOf": [{ "$ref": "#/components/schemas/Parent.Class" }, { + "type": "object", + "required": [ + "arrayProperty" + ], + "properties": { + "refProperty": { + "$ref": "#/components/schemas/Foo.Bar.Baz" + }, + "arrayProperty": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Foo.Bar.Baz" + } + }, + "objectProperty": { + "type": "object", + "required": [ + "nestedArray", + "nestedRef" + ], + "properties": { + "nestedArray": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Foo.Bar.Baz" + } + }, + "nestedRef": { + "$ref": "#/components/schemas/Foo.Bar.Baz" + } + } + } + } + }] + } + } + } +} diff --git a/test/self-ref.spec.ts b/test/self-ref.spec.ts index 5ad12c8..12a5fbd 100644 --- a/test/self-ref.spec.ts +++ b/test/self-ref.spec.ts @@ -1,47 +1,78 @@ import { InterfaceDeclaration, + TypeAliasDeclaration, TypescriptParser } from 'typescript-parser'; import { NgOpenApiGen } from '../lib/ng-openapi-gen'; import options from './self-ref.config.json'; import selfRef from './self-ref.json'; -const gen = new NgOpenApiGen(selfRef, options); -gen.generate(); - -describe('Generation tests using self-ref.json', () => { - it('Baz model', done => { - const baz = gen.models.get('Foo.Bar.Baz'); - const ts = gen.templates.apply('model', baz); - - const parser = new TypescriptParser(); - parser.parseSource(ts).then(ast => { - expect(ast.declarations.length).toBe(1); - expect(ast.declarations[0]).toEqual(jasmine.any(InterfaceDeclaration)); - const decl = ast.declarations[0] as InterfaceDeclaration; - expect(decl.name).toBe('Baz'); - expect(decl.properties.length).toBe(3); - - const ref = decl.properties.find(p => p.name === 'refProperty'); - expect(ref).withContext('refProperty property').toBeDefined(); - if (ref) { - expect(ref.type).toBe('Baz'); - } - - const array = decl.properties.find(p => p.name === 'arrayProperty'); - expect(array).withContext('arrayProperty property').toBeDefined(); - if (array) { - expect(array.type).toBe('Array'); - } - - const object = decl.properties.find(p => p.name === 'objectProperty'); - expect(object).withContext('objectProperty property').toBeDefined(); - if (object) { - expect(object.type).toBe('{\n\'nestedArray\': Array;\n\'nestedRef\': Baz;\n}'); - } - - done(); +import optionsAllof from './self-ref-allof.config.json'; +import selfRefAllof from './self-ref-allof.json'; + +describe('Test self referencing', () => { + describe('Generation tests using self-ref.json', () => { + const gen = new NgOpenApiGen(selfRef, options); + gen.generate(); + it('Baz model', done => { + const baz = gen.models.get('Foo.Bar.Baz'); + const ts = gen.templates.apply('model', baz); + + const parser = new TypescriptParser(); + parser.parseSource(ts).then(ast => { + expect(ast.declarations.length).toBe(1); + expect(ast.declarations[0]).toEqual(jasmine.any(InterfaceDeclaration)); + const decl = ast.declarations[0] as InterfaceDeclaration; + expect(decl.name).toBe('Baz'); + expect(decl.properties.length).toBe(3); + + const ref = decl.properties.find(p => p.name === 'refProperty'); + expect(ref).withContext('refProperty property').toBeDefined(); + if (ref) { + expect(ref.type).toBe('Baz'); + } + + const array = decl.properties.find(p => p.name === 'arrayProperty'); + expect(array).withContext('arrayProperty property').toBeDefined(); + if (array) { + expect(array.type).toBe('Array'); + } + + const object = decl.properties.find(p => p.name === 'objectProperty'); + expect(object).withContext('objectProperty property').toBeDefined(); + if (object) { + expect(object.type).toBe('{\n\'nestedArray\': Array;\n\'nestedRef\': Baz;\n}'); + } + + done(); + }); }); + }); + describe('Generation tests using self-ref-allof.json', () => { + const gen = new NgOpenApiGen(selfRefAllof, optionsAllof); + gen.generate(); + it('Baz model', done => { + const baz = gen.models.get('Foo.Bar.Baz'); + const ts = gen.templates.apply('model', baz); + + const parser = new TypescriptParser(); + parser.parseSource(ts).then(ast => { + expect(ast.declarations.length).toBe(1); + expect(ast.declarations[0]).toEqual(jasmine.any(TypeAliasDeclaration)); + const decl = ast.declarations[0] as TypeAliasDeclaration; + expect(decl.name).toBe('Baz'); + + const text = ts.substring(decl.start || 0, decl.end || ts.length); + + expect(text).toContain('\'refProperty\'?: Baz;'); + expect(text).toContain('\'arrayProperty\': Array;'); + expect(text).toContain('\'nestedArray\': Array;'); + expect(text).toContain('\'nestedRef\': Baz;'); + + done(); + }); + }); + }); });