Skip to content

Commit f2071dd

Browse files
author
Simon Tsvilik
committed
tests: add support for union/enum types for @formfield()
1 parent 07c67b5 commit f2071dd

File tree

3 files changed

+182
-26
lines changed

3 files changed

+182
-26
lines changed

tests/fixtures/controllers/parameterController.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Body, BodyProp, Get, Header, Path, Post, Query, Request, Route, Res, TsoaResponse, Deprecated, Queries, RequestProp, FormField } from '@tsoa/runtime';
2-
import { Gender, ParameterTestModel } from '../testModel';
2+
import { EnumNumberValue, FormTestModel, Gender, ParameterTestModel } from '../testModel';
33

44
@Route('ParameterTest')
55
export class ParameterController {
@@ -314,8 +314,13 @@ export class ParameterController {
314314
}
315315

316316
@Get('FormDataStringType')
317-
public async formData(@FormField() data: string): Promise<void> {
317+
public async formData(@FormField() data: string, @FormField() indexes: EnumNumberValue, @FormField() gender: Gender): Promise<FormTestModel> {
318318
//
319+
return Promise.resolve<FormTestModel>({
320+
data,
321+
indexes,
322+
gender,
323+
});
319324
}
320325

321326
@Get('Path/{test}')
@@ -399,7 +404,10 @@ export class ParameterController {
399404
}
400405

401406
@Post('Inline1')
402-
public async inline1(@Body() body: { requestString: string; requestNumber: number }): Promise<{ resultString: string; responseNumber: number }> {
407+
public async inline1(@Body() body: { requestString: string; requestNumber: number }): Promise<{
408+
resultString: string;
409+
responseNumber: number;
410+
}> {
403411
return { resultString: 'a', responseNumber: 1 };
404412
}
405413
}

tests/fixtures/testModel.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,12 @@ export class ParameterTestModel {
828828
public nicknames?: string[];
829829
}
830830

831+
export class FormTestModel {
832+
public data!: string;
833+
public indexes!: EnumNumberValue;
834+
public gender!: Gender;
835+
}
836+
831837
export class ValidateCustomErrorModel {}
832838

833839
export class ValidateModel {

tests/unit/swagger/schemaDetails.spec.ts

Lines changed: 165 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,16 @@ describe('Schema details generation', () => {
714714
expect(extensionPath['x-attKey3']).to.deep.equal(null);
715715
expect(extensionPath['x-attKey4']).to.deep.equal({ test: 'testVal' });
716716
expect(extensionPath['x-attKey5']).to.deep.equal(['y0', 'y1', 123, true, null]);
717-
expect(extensionPath['x-attKey6']).to.deep.equal([{ y0: 'yt0', y1: 'yt1', y2: 123, y3: true, y4: null }, { y2: 'yt2' }]);
717+
expect(extensionPath['x-attKey6']).to.deep.equal([
718+
{
719+
y0: 'yt0',
720+
y1: 'yt1',
721+
y2: 123,
722+
y3: true,
723+
y4: null,
724+
},
725+
{ y2: 'yt2' },
726+
]);
718727
expect(extensionPath['x-attKey7']).to.deep.equal({ test: ['testVal', 123, true, null] });
719728
expect(extensionPath['x-attKey8']).to.deep.equal({ test: { testArray: ['testVal1', true, null, ['testVal2', 'testVal3', 123, true, null]] } });
720729
expect(extensionPath['x-attKey10']).to.deep.equal(['testVal1', 'testVal2', 123, true, null]);
@@ -839,7 +848,13 @@ describe('Schema details generation', () => {
839848
expect(schema).to.deep.eq({
840849
properties: {
841850
account: { $ref: '#/definitions/Account', format: undefined, description: undefined, example: undefined },
842-
defaultValue2: { type: 'string', default: 'Default Value 2', description: undefined, format: undefined, example: undefined },
851+
defaultValue2: {
852+
type: 'string',
853+
default: 'Default Value 2',
854+
description: undefined,
855+
format: undefined,
856+
example: undefined,
857+
},
843858
enumKeys: {
844859
default: undefined,
845860
description: undefined,
@@ -849,11 +864,40 @@ describe('Schema details generation', () => {
849864
type: 'string',
850865
'x-nullable': false,
851866
},
852-
keyInterface: { type: 'string', default: undefined, description: undefined, format: undefined, example: undefined, enum: ['id'], 'x-nullable': false },
853-
indexedType: { type: 'string', default: undefined, description: undefined, format: undefined, example: undefined },
854-
indexedTypeToInterface: { $ref: '#/definitions/IndexedInterface', description: undefined, format: undefined, example: undefined },
855-
indexedTypeToClass: { $ref: '#/definitions/IndexedClass', description: undefined, format: undefined, example: undefined },
856-
indexedTypeToAlias: { $ref: '#/definitions/IndexedInterface', description: undefined, format: undefined, example: undefined },
867+
keyInterface: {
868+
type: 'string',
869+
default: undefined,
870+
description: undefined,
871+
format: undefined,
872+
example: undefined,
873+
enum: ['id'],
874+
'x-nullable': false,
875+
},
876+
indexedType: {
877+
type: 'string',
878+
default: undefined,
879+
description: undefined,
880+
format: undefined,
881+
example: undefined,
882+
},
883+
indexedTypeToInterface: {
884+
$ref: '#/definitions/IndexedInterface',
885+
description: undefined,
886+
format: undefined,
887+
example: undefined,
888+
},
889+
indexedTypeToClass: {
890+
$ref: '#/definitions/IndexedClass',
891+
description: undefined,
892+
format: undefined,
893+
example: undefined,
894+
},
895+
indexedTypeToAlias: {
896+
$ref: '#/definitions/IndexedInterface',
897+
description: undefined,
898+
format: undefined,
899+
example: undefined,
900+
},
857901
indexedResponse: {
858902
$ref: '#/definitions/Record_id.string_',
859903
description: undefined,
@@ -895,7 +939,15 @@ describe('Schema details generation', () => {
895939
example: 'classPropExample',
896940
title: 'Example title',
897941
},
898-
optionalPublicStringProperty: { type: 'string', minLength: 0, maxLength: 10, default: undefined, description: undefined, format: undefined, example: undefined },
942+
optionalPublicStringProperty: {
943+
type: 'string',
944+
minLength: 0,
945+
maxLength: 10,
946+
default: undefined,
947+
description: undefined,
948+
format: undefined,
949+
example: undefined,
950+
},
899951
emailPattern: {
900952
type: 'string',
901953
default: undefined,
@@ -904,12 +956,54 @@ describe('Schema details generation', () => {
904956
pattern: '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$',
905957
example: undefined,
906958
},
907-
stringProperty: { type: 'string', default: undefined, description: undefined, format: undefined, example: undefined },
908-
deprecated1: { type: 'boolean', default: undefined, description: undefined, format: undefined, example: undefined, 'x-deprecated': true },
909-
deprecated2: { type: 'boolean', default: undefined, description: undefined, format: undefined, example: undefined, 'x-deprecated': true },
910-
extensionTest: { type: 'boolean', default: undefined, description: undefined, format: undefined, example: undefined, 'x-key-1': 'value-1', 'x-key-2': 'value-2' },
911-
extensionComment: { type: 'boolean', default: undefined, description: undefined, format: undefined, example: undefined, 'x-key-1': 'value-1', 'x-key-2': 'value-2' },
912-
stringExample: { type: 'string', default: undefined, description: undefined, format: undefined, example: 'stringValue' },
959+
stringProperty: {
960+
type: 'string',
961+
default: undefined,
962+
description: undefined,
963+
format: undefined,
964+
example: undefined,
965+
},
966+
deprecated1: {
967+
type: 'boolean',
968+
default: undefined,
969+
description: undefined,
970+
format: undefined,
971+
example: undefined,
972+
'x-deprecated': true,
973+
},
974+
deprecated2: {
975+
type: 'boolean',
976+
default: undefined,
977+
description: undefined,
978+
format: undefined,
979+
example: undefined,
980+
'x-deprecated': true,
981+
},
982+
extensionTest: {
983+
type: 'boolean',
984+
default: undefined,
985+
description: undefined,
986+
format: undefined,
987+
example: undefined,
988+
'x-key-1': 'value-1',
989+
'x-key-2': 'value-2',
990+
},
991+
extensionComment: {
992+
type: 'boolean',
993+
default: undefined,
994+
description: undefined,
995+
format: undefined,
996+
example: undefined,
997+
'x-key-1': 'value-1',
998+
'x-key-2': 'value-2',
999+
},
1000+
stringExample: {
1001+
type: 'string',
1002+
default: undefined,
1003+
description: undefined,
1004+
format: undefined,
1005+
example: 'stringValue',
1006+
},
9131007
objectExample: {
9141008
type: 'object',
9151009
default: undefined,
@@ -937,13 +1031,51 @@ describe('Schema details generation', () => {
9371031
},
9381032
required: ['label', 'id'],
9391033
},
940-
publicConstructorVar: { type: 'string', default: undefined, description: 'This is a description for publicConstructorVar', format: undefined, example: undefined },
941-
readonlyConstructorArgument: { type: 'string', default: undefined, description: undefined, format: undefined, example: undefined },
942-
optionalPublicConstructorVar: { type: 'string', default: undefined, description: undefined, format: undefined, example: undefined },
943-
deprecatedPublicConstructorVar: { type: 'boolean', default: undefined, description: undefined, format: undefined, example: undefined, 'x-deprecated': true },
944-
deprecatedPublicConstructorVar2: { type: 'boolean', default: undefined, description: undefined, format: undefined, example: undefined, 'x-deprecated': true },
1034+
publicConstructorVar: {
1035+
type: 'string',
1036+
default: undefined,
1037+
description: 'This is a description for publicConstructorVar',
1038+
format: undefined,
1039+
example: undefined,
1040+
},
1041+
readonlyConstructorArgument: {
1042+
type: 'string',
1043+
default: undefined,
1044+
description: undefined,
1045+
format: undefined,
1046+
example: undefined,
1047+
},
1048+
optionalPublicConstructorVar: {
1049+
type: 'string',
1050+
default: undefined,
1051+
description: undefined,
1052+
format: undefined,
1053+
example: undefined,
1054+
},
1055+
deprecatedPublicConstructorVar: {
1056+
type: 'boolean',
1057+
default: undefined,
1058+
description: undefined,
1059+
format: undefined,
1060+
example: undefined,
1061+
'x-deprecated': true,
1062+
},
1063+
deprecatedPublicConstructorVar2: {
1064+
type: 'boolean',
1065+
default: undefined,
1066+
description: undefined,
1067+
format: undefined,
1068+
example: undefined,
1069+
'x-deprecated': true,
1070+
},
9451071
id: { type: 'number', format: 'double', default: undefined, description: undefined, example: undefined },
946-
defaultValue1: { type: 'string', default: 'Default Value 1', description: undefined, format: undefined, example: undefined },
1072+
defaultValue1: {
1073+
type: 'string',
1074+
default: 'Default Value 1',
1075+
description: undefined,
1076+
format: undefined,
1077+
example: undefined,
1078+
},
9471079
},
9481080
required: ['account', 'enumKeys', 'publicStringProperty', 'stringProperty', 'publicConstructorVar', 'readonlyConstructorArgument', 'id'],
9491081
type: 'object',
@@ -1006,9 +1138,19 @@ describe('Schema details generation', () => {
10061138

10071139
const method = spec.paths['/ParameterTest/FormDataStringType'].get?.parameters ?? [];
10081140

1009-
expect(method).to.have.lengthOf(1);
1010-
const queryParam = method[0];
1011-
expect(queryParam.in).to.equal('formData');
1141+
expect(method).to.have.lengthOf(3);
1142+
const [data, indexes, gender] = method;
1143+
1144+
expect(data.in).to.equal('formData');
1145+
expect(data.type).to.equal('string');
1146+
// Can process numeric enum
1147+
expect(indexes.in).to.equal('formData');
1148+
expect(indexes.type).to.equal('number');
1149+
expect(indexes.enum).to.deep.equal([0, 2, 5]);
1150+
// Can process string enum
1151+
expect(gender.in).to.equal('formData');
1152+
expect(gender.type).to.equal('string');
1153+
expect(gender.enum).to.deep.equal(['MALE', 'FEMALE']);
10121154
});
10131155
});
10141156

0 commit comments

Comments
 (0)