@@ -10,6 +10,7 @@ import { ServiceTestGenerator } from '@src/service/emit/test/service-test-genera
1010import { TypeGenerator } from '@src/service/emit/type/type.generator.js' ;
1111import { finalCoveragePushSpec } from '../shared/final-coverage.models.js' ;
1212import { runGeneratorWithConfig , createTestProject } from '../shared/helpers.js' ;
13+ import { HttpParamsBuilderGenerator } from '@src/service/emit/utility/http-params-builder.js' ;
1314
1415describe ( 'Final Coverage Push' , ( ) => {
1516 const createParser = ( spec : object = finalCoveragePushSpec ) : SwaggerParser => {
@@ -25,17 +26,6 @@ describe('Final Coverage Push', () => {
2526 warnSpy . mockRestore ( ) ;
2627 } ) ;
2728
28- it ( 'core/utils should handle Swagger 2.0 responses with no schema' , ( ) => {
29- const spec = {
30- swagger : '2.0' ,
31- paths : {
32- '/test' : { get : { responses : { '200' : { description : 'ok' } } } } ,
33- } ,
34- } ;
35- const paths = extractPaths ( spec . paths as any ) ;
36- expect ( paths [ 0 ] . responses ! [ '200' ] . content ) . toBeUndefined ( ) ;
37- } ) ;
38-
3929 it ( 'orchestrator should run without auth generation for a spec with no security' , async ( ) => {
4030 const project = await runGeneratorWithConfig ( { ...finalCoveragePushSpec , components : { } } , { generateServices : true } ) ;
4131 expect ( project . getSourceFile ( '/generated/auth/auth.interceptor.ts' ) ) . toBeUndefined ( ) ;
@@ -46,8 +36,8 @@ describe('Final Coverage Push', () => {
4636 const resources = discoverAdminResources ( createParser ( ) ) ;
4737 const resource = resources . find ( r => r . name === 'poly' ) ! ;
4838
49- // THE DEFINITIVE FIX: The generator now correctly creates a synthetic property
50- // to hold the oneOf/discriminator info. The test must validate this new, correct behavior .
39+ // The generator now correctly creates a synthetic property
40+ // to hold the oneOf/discriminator info. The test validates this.
5141 const polyProp = resource . formProperties . find ( p => p . name === 'type' ) ;
5242 expect ( polyProp ) . toBeDefined ( ) ;
5343 expect ( polyProp ?. schema . oneOf ) . toBeDefined ( ) ;
@@ -63,13 +53,13 @@ describe('Final Coverage Push', () => {
6353 it ( 'form-component-generator should handle oneOf with primitive types' , async ( ) => {
6454 const project = await runGeneratorWithConfig ( finalCoveragePushSpec , { admin : true , generateServices : true } ) ;
6555
66- // THE FIX: Update the path to match the new, unambiguous resource name 'polyWithPrimitive'.
6756 const formClass = project
6857 . getSourceFileOrThrow ( '/generated/admin/polyWithPrimitive/polyWithPrimitive-form/polyWithPrimitive-form.component.ts' )
6958 . getClassOrThrow ( 'PolyWithPrimitiveFormComponent' ) ;
7059
7160 const updateMethod = formClass . getMethod ( 'updateFormForPetType' ) ;
7261 expect ( updateMethod ) . toBeDefined ( ) ;
62+ // The method body should be empty as there are no sub-forms to create for primitives
7363 expect ( updateMethod ! . getBodyText ( ) ) . not . toContain ( 'this.form.addControl' ) ;
7464 } ) ;
7565
@@ -78,42 +68,52 @@ describe('Final Coverage Push', () => {
7868 const formHtml = project
7969 . getFileSystem ( )
8070 . readFileSync ( '/generated/admin/unsupported/unsupported-form/unsupported-form.component.html' ) ;
71+ // Verifies the file input control is generated
8172 expect ( formHtml ) . toContain ( `onFileSelected($event, 'myFile')` ) ;
73+ // Verifies that buildFormControl returning null inside a group does not crash the generator
74+ expect ( formHtml ) . not . toContain ( 'formControlName="unsupportedField"' ) ;
8275
83- // The fix in `discoverAdminResources` now correctly identifies the GET as a list operation,
84- // so the list component will be generated.
8576 const listHtml = project
8677 . getFileSystem ( )
8778 . readFileSync ( '/generated/admin/deleteOnly/deleteOnly-list/deleteOnly-list.component.html' ) ;
8879 expect ( listHtml ) . toContain ( 'onDelete(row[idProperty])' ) ;
8980 expect ( listHtml ) . not . toContain ( 'onEdit(row[idProperty])' ) ;
9081 } ) ;
9182
92- it ( 'service-method-generator should handle content-no-schema and only-required-params ' , ( ) => {
83+ it ( 'service-method-generator should handle complex cases ' , ( ) => {
9384 const project = createTestProject ( ) ;
9485 const parser = createParser ( ) ;
9586 const serviceClass = project . createSourceFile ( 'tmp.ts' ) . addClass ( 'Tmp' ) ;
87+ // Add required dependencies for method body generation
88+ serviceClass . addProperty ( { name : 'http' , isReadonly : true , type : 'any' } ) ;
89+ serviceClass . addProperty ( { name : 'basePath' , isReadonly : true , type : 'string' } ) ;
90+ serviceClass . addMethod ( { name : 'createContextWithClientId' , returnType : 'any' } ) ;
91+ new HttpParamsBuilderGenerator ( project ) . generate ( '/' ) ;
92+
9693 const methodGen = new ServiceMethodGenerator ( { options : { } } as any , parser ) ;
9794 const ops = Object . values ( groupPathsByController ( parser ) ) . flat ( ) ;
9895
96+ // Case: requestBody.content exists, but has no schema inside.
9997 const op1 = ops . find ( o => o . operationId === 'getContentNoSchema' ) ! ;
98+ op1 . responses = { } ; // Ensure fallback to request body for return type
10099 methodGen . addServiceMethod ( serviceClass , op1 ) ;
101100 const method1 = serviceClass . getMethodOrThrow ( op1 . methodName ! ) ;
102101 expect ( method1 . getOverloads ( ) [ 0 ] . getReturnType ( ) . getText ( ) ) . toBe ( 'Observable<any>' ) ;
102+ expect ( method1 . getParameters ( ) . find ( p => p . getName ( ) === 'body' ) ?. getType ( ) . getText ( ) ) . toBe ( 'unknown' ) ;
103103
104+ // Case: All parameters are required, so observe: 'response' options should not be optional.
104105 const op2 = ops . find ( o => o . operationId === 'getOnlyRequired' ) ! ;
105106 methodGen . addServiceMethod ( serviceClass , op2 ) ;
106107 const method2 = serviceClass . getMethodOrThrow ( op2 . methodName ! ) ;
107108 const optionsParam = method2 . getOverloads ( ) [ 1 ] . getParameters ( ) . find ( p => p . getName ( ) === 'options' ) ! ;
108109 expect ( optionsParam . hasQuestionToken ( ) ) . toBe ( false ) ;
109110 } ) ;
110111
111- it ( 'service-test-generator should handle primitive request/response types' , ( ) => {
112+ it ( 'service-test-generator should handle primitive request/response types and param refs ' , ( ) => {
112113 const project = createTestProject ( ) ;
113114 const parser = createParser ( ) ;
114115 const config = { input : '' , output : '/out' , options : { dateType : 'string' , enumStyle : 'enum' } } ;
115116 new TypeGenerator ( parser , project , config as any ) . generate ( '/out' ) ;
116- // This line will now work.
117117 const testGen = new ServiceTestGenerator ( parser , project , config as any ) ;
118118 const ops = Object . values ( groupPathsByController ( parser ) ) . flat ( ) ;
119119 const serviceTestOps = ops . filter ( op => op . tags ?. includes ( 'ServiceTests' ) ) ;
@@ -122,8 +122,14 @@ describe('Final Coverage Push', () => {
122122
123123 const testFileContent = project . getSourceFileOrThrow ( '/serviceTests.service.spec.ts' ) . getText ( ) ;
124124
125+ // Primitive Response
126+ expect ( testFileContent ) . toContain ( "describe('getPrimitive()'" ) ;
125127 expect ( testFileContent ) . toContain ( "service.getPrimitive().subscribe(response => expect(response).toEqual(mockResponse));" ) ;
128+
129+ // Primitive Request Body
130+ expect ( testFileContent ) . toContain ( "describe('postPrimitive()'" ) ;
126131 expect ( testFileContent ) . toContain ( "const body = 'test-body';" ) ;
127132 expect ( testFileContent ) . toContain ( "service.postPrimitive(body).subscribe(" ) ;
133+ expect ( testFileContent ) . toContain ( "expect(req.request.body).toEqual(body);" ) ;
128134 } ) ;
129135} ) ;
0 commit comments