@@ -13,6 +13,7 @@ import {
13
13
import { ApplicationModule } from './src/app.module' ;
14
14
import { Cat } from './src/cats/classes/cat.class' ;
15
15
import { TagDto } from './src/cats/dto/tag.dto' ;
16
+ import { DogsModule } from './src/dogs/dogs.module' ;
16
17
17
18
describe ( 'Validate OpenAPI schema' , ( ) => {
18
19
let app : INestApplication ;
@@ -215,3 +216,115 @@ describe('Validate OpenAPI schema', () => {
215
216
} ) ;
216
217
} ) ;
217
218
} ) ;
219
+
220
+ describe ( 'Nested module scanning' , ( ) => {
221
+ let app : INestApplication ;
222
+ let options : Omit < OpenAPIObject , 'paths' > ;
223
+
224
+ beforeEach ( async ( ) => {
225
+ app = await NestFactory . create ( DogsModule , {
226
+ logger : false
227
+ } ) ;
228
+ app . setGlobalPrefix ( 'api/' ) ;
229
+
230
+ options = new DocumentBuilder ( )
231
+ . setTitle ( 'Cats example' )
232
+ . setDescription ( 'The cats API description' )
233
+ . setVersion ( '1.0' )
234
+ . build ( ) ;
235
+ } ) ;
236
+
237
+ describe ( 'deepScanRoutes' , ( ) => {
238
+ it ( 'should include only 1-depth nested routes when deepScanRoutes is true' , async ( ) => {
239
+ const document = SwaggerModule . createDocument ( app , options , {
240
+ deepScanRoutes : true ,
241
+ include : [ DogsModule ]
242
+ } ) ;
243
+
244
+ // Root module routes should be included
245
+ expect ( document . paths [ '/api/dogs' ] ) . toBeDefined ( ) ;
246
+ expect ( document . paths [ '/api/dogs/puppies' ] ) . toBeDefined ( ) ;
247
+
248
+ // First depth routes should be included
249
+ expect ( document . paths [ '/api/depth1-dogs' ] ) . toBeDefined ( ) ;
250
+
251
+ // Deeper routes should NOT be included
252
+ expect ( document . paths [ '/api/depth2-dogs' ] ) . toBeUndefined ( ) ;
253
+ expect ( document . paths [ '/api/depth3-dogs' ] ) . toBeUndefined ( ) ;
254
+
255
+ // Verify controller tags are correct
256
+ expect ( document . paths [ '/api/dogs' ] . get . tags ) . toContain ( 'dogs' ) ;
257
+ expect ( document . paths [ '/api/depth1-dogs' ] . get . tags ) . toContain ( 'depth1-dogs' ) ;
258
+ } ) ;
259
+ } ) ;
260
+
261
+ describe ( 'recursiveModuleScan' , ( ) => {
262
+ it ( 'should include all nested routes when recursiveModuleScan is enabled' , async ( ) => {
263
+ const document = SwaggerModule . createDocument ( app , options , {
264
+ include : [ DogsModule ] ,
265
+ deepScanRoutes : true ,
266
+ recursiveModuleScan : true
267
+ } ) ;
268
+
269
+ // All routes at every depth should be included
270
+ expect ( document . paths [ '/api/dogs' ] ) . toBeDefined ( ) ;
271
+ expect ( document . paths [ '/api/dogs/puppies' ] ) . toBeDefined ( ) ;
272
+ expect ( document . paths [ '/api/depth1-dogs' ] ) . toBeDefined ( ) ;
273
+ expect ( document . paths [ '/api/depth2-dogs' ] ) . toBeDefined ( ) ;
274
+ expect ( document . paths [ '/api/depth3-dogs' ] ) . toBeDefined ( ) ;
275
+
276
+ // Verify all controller tags are correct
277
+ expect ( document . paths [ '/api/dogs' ] . get . tags ) . toContain ( 'dogs' ) ;
278
+ expect ( document . paths [ '/api/depth1-dogs' ] . get . tags ) . toContain ( 'depth1-dogs' ) ;
279
+ expect ( document . paths [ '/api/depth2-dogs' ] . get . tags ) . toContain ( 'depth2-dogs' ) ;
280
+ expect ( document . paths [ '/api/depth3-dogs' ] . get . tags ) . toContain ( 'depth3-dogs' ) ;
281
+ } ) ;
282
+ } ) ;
283
+
284
+ describe ( 'maxScanDepth' , ( ) => {
285
+ it ( 'should limit scanning depth when maxScanDepth is set' , async ( ) => {
286
+ const document = SwaggerModule . createDocument ( app , options , {
287
+ include : [ DogsModule ] ,
288
+ deepScanRoutes : true ,
289
+ recursiveModuleScan : true ,
290
+ maxScanDepth : 1
291
+ } ) ;
292
+
293
+ // Routes up to depth 1 should be included
294
+ expect ( document . paths [ '/api/dogs' ] ) . toBeDefined ( ) ;
295
+ expect ( document . paths [ '/api/dogs/puppies' ] ) . toBeDefined ( ) ;
296
+ expect ( document . paths [ '/api/depth1-dogs' ] ) . toBeDefined ( ) ;
297
+
298
+ // Routes beyond depth 1 should NOT be included
299
+ expect ( document . paths [ '/api/depth2-dogs' ] ) . toBeUndefined ( ) ;
300
+ expect ( document . paths [ '/api/depth3-dogs' ] ) . toBeUndefined ( ) ;
301
+
302
+ // Verify included controller tags are correct
303
+ expect ( document . paths [ '/api/dogs' ] . get . tags ) . toContain ( 'dogs' ) ;
304
+ expect ( document . paths [ '/api/depth1-dogs' ] . get . tags ) . toContain ( 'depth1-dogs' ) ;
305
+ } ) ;
306
+
307
+ it ( 'should include routes up to specified maxScanDepth' , async ( ) => {
308
+ const document = SwaggerModule . createDocument ( app , options , {
309
+ include : [ DogsModule ] ,
310
+ deepScanRoutes : true ,
311
+ recursiveModuleScan : true ,
312
+ maxScanDepth : 2
313
+ } ) ;
314
+
315
+ // Routes up to depth 2 should be included
316
+ expect ( document . paths [ '/api/dogs' ] ) . toBeDefined ( ) ;
317
+ expect ( document . paths [ '/api/dogs/puppies' ] ) . toBeDefined ( ) ;
318
+ expect ( document . paths [ '/api/depth1-dogs' ] ) . toBeDefined ( ) ;
319
+ expect ( document . paths [ '/api/depth2-dogs' ] ) . toBeDefined ( ) ;
320
+
321
+ // Routes beyond depth 2 should NOT be included
322
+ expect ( document . paths [ '/api/depth3-dogs' ] ) . toBeUndefined ( ) ;
323
+
324
+ // Verify included controller tags are correct
325
+ expect ( document . paths [ '/api/dogs' ] . get . tags ) . toContain ( 'dogs' ) ;
326
+ expect ( document . paths [ '/api/depth1-dogs' ] . get . tags ) . toContain ( 'depth1-dogs' ) ;
327
+ expect ( document . paths [ '/api/depth2-dogs' ] . get . tags ) . toContain ( 'depth2-dogs' ) ;
328
+ } ) ;
329
+ } ) ;
330
+ } ) ;
0 commit comments