Skip to content

Commit a8b0161

Browse files
committed
feat: enhance EnumTransformer and SpecGenerator to support title property, with corresponding tests
1 parent 8b770c6 commit a8b0161

8 files changed

Lines changed: 90 additions & 0 deletions

File tree

packages/cli/src/metadataGeneration/transformer/enumTransformer.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export class EnumTransformer extends Transformer {
2828
const enumVarnames = first.enumVarnames ? (second.enumVarnames ? [...first.enumVarnames, ...second.enumVarnames] : first.enumVarnames) : second.enumVarnames;
2929

3030
const example = first.example || second.example;
31+
const title = first.title || second.title;
3132

3233
return {
3334
dataType: 'refEnum',
@@ -37,6 +38,7 @@ export class EnumTransformer extends Transformer {
3738
refName: first.refName,
3839
deprecated,
3940
example,
41+
...(title && { title }),
4042
};
4143
}
4244

@@ -57,6 +59,7 @@ export class EnumTransformer extends Transformer {
5759
};
5860
const enums = declaration.members.map(e => resolver.current.typeChecker.getConstantValue(e)).filter(isNotUndefined);
5961
const enumVarnames = declaration.members.map(e => e.name.getText()).filter(isNotUndefined);
62+
const title = resolver.getNodeTitle(declaration);
6063

6164
return {
6265
dataType: 'refEnum',
@@ -66,6 +69,7 @@ export class EnumTransformer extends Transformer {
6669
enumVarnames,
6770
refName: enumName,
6871
deprecated: isExistJSDocTag(declaration, tag => tag.tagName.text === 'deprecated'),
72+
...(title && { title }),
6973
};
7074
}
7175

packages/cli/src/swagger/specGenerator2.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,10 @@ export class SpecGenerator2 extends SpecGenerator {
424424
swaggerType['x-deprecated'] = true;
425425
}
426426

427+
if (property.title) {
428+
swaggerType.title = property.title;
429+
}
430+
427431
if (property.extensions) {
428432
property.extensions.forEach(property => {
429433
swaggerType[property.key] = property.value;

packages/cli/src/swagger/specGenerator3.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,10 @@ export class SpecGenerator3 extends SpecGenerator {
588588
swaggerType.deprecated = true;
589589
}
590590

591+
if (property.title) {
592+
swaggerType.title = property.title;
593+
}
594+
591595
if (property.extensions) {
592596
property.extensions.forEach(property => {
593597
swaggerType[property.key] = property.value;

tests/fixtures/testModel.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ export interface TestModel extends Model {
182182
// prettier-ignore
183183
stringAndBoolArray?: Array<(string | boolean)>;
184184
testModelWithAnnotations?: TestModelWithAnnotations;
185+
enumWithTitle?: EnumWithTitle;
185186

186187
/**
187188
* @example {
@@ -1306,3 +1307,11 @@ interface TestModelWithAnnotations {
13061307
*/
13071308
param: string;
13081309
}
1310+
1311+
/**
1312+
* @title Title annotation for enum
1313+
*/
1314+
export enum EnumWithTitle {
1315+
Value1 = 'value1',
1316+
Value2 = 'value2',
1317+
}

tests/unit/metadataGeneration/transformer/enumTransformer.spec.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,57 @@ describe('EnumTransformer - Null Safety', () => {
207207
example: 'example1', // First example should be used
208208
});
209209
});
210+
211+
it('should merge title property correctly', () => {
212+
const first: Tsoa.RefEnumType = {
213+
dataType: 'refEnum',
214+
refName: 'TestEnum',
215+
enums: ['value1'],
216+
enumVarnames: ['VALUE1'],
217+
description: 'First enum',
218+
deprecated: false,
219+
title: 'First Title',
220+
};
221+
222+
const second: Tsoa.RefEnumType = {
223+
dataType: 'refEnum',
224+
refName: 'TestEnum',
225+
enums: ['value2'],
226+
enumVarnames: ['VALUE2'],
227+
description: 'Second enum',
228+
deprecated: false,
229+
title: 'Second Title',
230+
};
231+
232+
const result = EnumTransformer.merge(first, second);
233+
234+
expect(result.title).to.equal('First Title'); // First title should be used
235+
});
236+
237+
it('should use second title if first is undefined', () => {
238+
const first: Tsoa.RefEnumType = {
239+
dataType: 'refEnum',
240+
refName: 'TestEnum',
241+
enums: ['value1'],
242+
enumVarnames: ['VALUE1'],
243+
description: 'First enum',
244+
deprecated: false,
245+
};
246+
247+
const second: Tsoa.RefEnumType = {
248+
dataType: 'refEnum',
249+
refName: 'TestEnum',
250+
enums: ['value2'],
251+
enumVarnames: ['VALUE2'],
252+
description: 'Second enum',
253+
deprecated: false,
254+
title: 'Second Title',
255+
};
256+
257+
const result = EnumTransformer.merge(first, second);
258+
259+
expect(result.title).to.equal('Second Title');
260+
});
210261
});
211262

212263
describe('mergeMany method', () => {

tests/unit/swagger/definitionsGeneration/definitions.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1632,6 +1632,12 @@ describe('Definition generation', () => {
16321632
testModelWithAnnotations: () => {
16331633
// schema is validated in OpenAPI 3 specific tests
16341634
},
1635+
enumWithTitle: (propertyName, propertySchema) => {
1636+
expect(propertySchema.$ref).to.eq('#/definitions/EnumWithTitle', `for property ${propertyName}.$ref`);
1637+
1638+
const schema = getValidatedDefinition('EnumWithTitle', currentSpec);
1639+
expect(schema.title).to.eq('Title annotation for enum');
1640+
},
16351641
extensionComment: (propertyName, propertySchema) => {
16361642
expect(propertySchema).to.deep.eq(
16371643
{

tests/unit/swagger/schemaDetails3.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,6 +2000,12 @@ describe('Definition generation for OpenAPI 3.0.0', () => {
20002000

20012001
expect(paramSchema.title).to.eq('Title annotation for property');
20022002
},
2003+
enumWithTitle: (propertyName, propertySchema) => {
2004+
expect(propertySchema.$ref).to.eq('#/components/schemas/EnumWithTitle', `for property ${propertyName}.$ref`);
2005+
2006+
const schema = getComponentSchema('EnumWithTitle', currentSpec);
2007+
expect(schema.title).to.eq('Title annotation for enum');
2008+
},
20032009
advancedTypeAliases: (propertyName, propertySchema) => {
20042010
expect(propertySchema).to.deep.eq(
20052011
{

tests/unit/swagger/schemaDetails31.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4500,6 +4500,12 @@ describe('Definition generation for OpenAPI 3.1.0', () => {
45004500

45014501
expect(paramSchema.title).to.eq('Title annotation for property');
45024502
},
4503+
enumWithTitle: (propertyName, propertySchema) => {
4504+
expect(propertySchema.$ref).to.eq('#/components/schemas/EnumWithTitle', `for property ${propertyName}.$ref`);
4505+
4506+
const schema = getComponentSchema('EnumWithTitle', currentSpec);
4507+
expect(schema.title).to.eq('Title annotation for enum');
4508+
},
45034509
};
45044510

45054511
const testModel = currentSpec.spec.components.schemas[interfaceModelName];

0 commit comments

Comments
 (0)