@@ -393,4 +393,140 @@ await VerifyOpenApiDocument(builder, document =>
393
393
} ) ;
394
394
} ) ;
395
395
}
396
+
397
+ [ Fact ]
398
+ public async Task GetOpenApiResponse_HandlesGenericType ( )
399
+ {
400
+ // Arrange
401
+ var builder = CreateBuilder ( ) ;
402
+
403
+ // Act
404
+ builder . MapGet ( "/" , ( ) => TypedResults . Ok < PaginatedItems < Todo > > ( new ( 0 , 1 , 5 , 50 , [ new Todo ( 1 , "Test Title" , true , DateTime . Now ) , new Todo ( 2 , "Test Title 2" , false , DateTime . Now ) ] ) ) ) ;
405
+
406
+ // Assert that the response schema is correctly generated. For now, generics are inlined
407
+ // in the generated OpenAPI schema since OpenAPI supports generics via dynamic references as of
408
+ // OpenAPI 3.1.0.
409
+ await VerifyOpenApiDocument ( builder , document =>
410
+ {
411
+ var operation = document . Paths [ "/" ] . Operations [ OperationType . Get ] ;
412
+ var responses = Assert . Single ( operation . Responses ) ;
413
+ var response = responses . Value ;
414
+ Assert . True ( response . Content . TryGetValue ( "application/json" , out var mediaType ) ) ;
415
+ Assert . Equal ( "object" , mediaType . Schema . Type ) ;
416
+ Assert . Collection ( mediaType . Schema . Properties ,
417
+ property =>
418
+ {
419
+ Assert . Equal ( "pageIndex" , property . Key ) ;
420
+ Assert . Equal ( "integer" , property . Value . Type ) ;
421
+ Assert . Equal ( "int32" , property . Value . Format ) ;
422
+ } ,
423
+ property =>
424
+ {
425
+ Assert . Equal ( "pageSize" , property . Key ) ;
426
+ Assert . Equal ( "integer" , property . Value . Type ) ;
427
+ Assert . Equal ( "int32" , property . Value . Format ) ;
428
+ } ,
429
+ property =>
430
+ {
431
+ Assert . Equal ( "totalItems" , property . Key ) ;
432
+ Assert . Equal ( "integer" , property . Value . Type ) ;
433
+ Assert . Equal ( "int64" , property . Value . Format ) ;
434
+ } ,
435
+ property =>
436
+ {
437
+ Assert . Equal ( "totalPages" , property . Key ) ;
438
+ Assert . Equal ( "integer" , property . Value . Type ) ;
439
+ Assert . Equal ( "int32" , property . Value . Format ) ;
440
+ } ,
441
+ property =>
442
+ {
443
+ Assert . Equal ( "items" , property . Key ) ;
444
+ Assert . Equal ( "array" , property . Value . Type ) ;
445
+ Assert . NotNull ( property . Value . Items ) ;
446
+ Assert . Equal ( "object" , property . Value . Items . Type ) ;
447
+ Assert . Collection ( property . Value . Items . Properties ,
448
+ property =>
449
+ {
450
+ Assert . Equal ( "id" , property . Key ) ;
451
+ Assert . Equal ( "integer" , property . Value . Type ) ;
452
+ Assert . Equal ( "int32" , property . Value . Format ) ;
453
+ } ,
454
+ property =>
455
+ {
456
+ Assert . Equal ( "title" , property . Key ) ;
457
+ Assert . Equal ( "string" , property . Value . Type ) ;
458
+ } ,
459
+ property =>
460
+ {
461
+ Assert . Equal ( "completed" , property . Key ) ;
462
+ Assert . Equal ( "boolean" , property . Value . Type ) ;
463
+ } ,
464
+ property =>
465
+ {
466
+ Assert . Equal ( "createdAt" , property . Key ) ;
467
+ Assert . Equal ( "string" , property . Value . Type ) ;
468
+ Assert . Equal ( "date-time" , property . Value . Format ) ;
469
+ } ) ;
470
+ } ) ;
471
+ } ) ;
472
+ }
473
+
474
+ [ Fact ]
475
+ public async Task GetOpenApiResponse_HandlesValidationProblem ( )
476
+ {
477
+ // Arrange
478
+ var builder = CreateBuilder ( ) ;
479
+
480
+ // Act
481
+ builder . MapGet ( "/" , ( ) => TypedResults . ValidationProblem ( new Dictionary < string , string [ ] >
482
+ {
483
+ [ "Name" ] = [ "Name is required" ]
484
+ } ) ) ;
485
+
486
+ // Assert
487
+ await VerifyOpenApiDocument ( builder , document =>
488
+ {
489
+ var operation = document . Paths [ "/" ] . Operations [ OperationType . Get ] ;
490
+ var responses = Assert . Single ( operation . Responses ) ;
491
+ var response = responses . Value ;
492
+ Assert . True ( response . Content . TryGetValue ( "application/problem+json" , out var mediaType ) ) ;
493
+ Assert . Equal ( "object" , mediaType . Schema . Type ) ;
494
+ Assert . Collection ( mediaType . Schema . Properties ,
495
+ property =>
496
+ {
497
+ Assert . Equal ( "type" , property . Key ) ;
498
+ Assert . Equal ( "string" , property . Value . Type ) ;
499
+ } ,
500
+ property =>
501
+ {
502
+ Assert . Equal ( "title" , property . Key ) ;
503
+ Assert . Equal ( "string" , property . Value . Type ) ;
504
+ } ,
505
+ property =>
506
+ {
507
+ Assert . Equal ( "status" , property . Key ) ;
508
+ Assert . Equal ( "integer" , property . Value . Type ) ;
509
+ Assert . Equal ( "int32" , property . Value . Format ) ;
510
+ } ,
511
+ property =>
512
+ {
513
+ Assert . Equal ( "detail" , property . Key ) ;
514
+ Assert . Equal ( "string" , property . Value . Type ) ;
515
+ } ,
516
+ property =>
517
+ {
518
+ Assert . Equal ( "instance" , property . Key ) ;
519
+ Assert . Equal ( "string" , property . Value . Type ) ;
520
+ } ,
521
+ property =>
522
+ {
523
+ Assert . Equal ( "errors" , property . Key ) ;
524
+ Assert . Equal ( "object" , property . Value . Type ) ;
525
+ // The errors object is a dictionary of string[]. Use `additionalProperties`
526
+ // to indicate that the payload can be arbitrary keys with string[] values.
527
+ Assert . Equal ( "array" , property . Value . AdditionalProperties . Type ) ;
528
+ Assert . Equal ( "string" , property . Value . AdditionalProperties . Items . Type ) ;
529
+ } ) ;
530
+ } ) ;
531
+ }
396
532
}
0 commit comments