@@ -180,6 +180,13 @@ object OpenAPIGenSpec extends ZIOSpecDefault {
180180 .out[SimpleOutputBody ]
181181 .outError[NotFoundError ](Status .NotFound )
182182
183+ private val queryParamOptEndpoint =
184+ Endpoint (GET / " withQuery" )
185+ .in[SimpleInputBody ]
186+ .query(HttpCodec .query[String ](" query" ).optional)
187+ .out[SimpleOutputBody ]
188+ .outError[NotFoundError ](Status .NotFound )
189+
183190 private val queryParamCollectionEndpoint =
184191 Endpoint (GET / " withQuery" )
185192 .in[SimpleInputBody ]
@@ -194,6 +201,19 @@ object OpenAPIGenSpec extends ZIOSpecDefault {
194201 .out[SimpleOutputBody ]
195202 .outError[NotFoundError ](Status .NotFound )
196203
204+ private val optionalHeaderEndpoint =
205+ Endpoint (GET / " withHeader" )
206+ .in[SimpleInputBody ]
207+ .header(HttpCodec .contentType.optional)
208+ .out[SimpleOutputBody ]
209+ .outError[NotFoundError ](Status .NotFound )
210+
211+ private val optionalPayloadEndpoint =
212+ Endpoint (GET / " withPayload" )
213+ .inCodec(HttpCodec .content[Payload ].optional)
214+ .out[SimpleOutputBody ]
215+ .outError[NotFoundError ](Status .NotFound )
216+
197217 private val alternativeInputEndpoint =
198218 Endpoint (GET / " inputAlternative" )
199219 .inCodec(
@@ -493,6 +513,134 @@ object OpenAPIGenSpec extends ZIOSpecDefault {
493513 |}""" .stripMargin
494514 assertTrue(json == toJsonAst(expectedJson))
495515 },
516+ test(" with optional query parameter" ) {
517+ val generated = OpenAPIGen .fromEndpoints(" Simple Endpoint" , " 1.0" , queryParamOptEndpoint)
518+ val json = toJsonAst(generated)
519+ val expectedJson = """ {
520+ | "openapi" : "3.1.0",
521+ | "info" : {
522+ | "title" : "Simple Endpoint",
523+ | "version" : "1.0"
524+ | },
525+ | "paths" : {
526+ | "/withQuery" : {
527+ | "get" : {
528+ | "parameters" : [
529+ |
530+ | {
531+ | "name" : "query",
532+ | "in" : "query",
533+ | "schema" :
534+ | {
535+ | "type" :[
536+ | "string",
537+ | "null"
538+ | ]
539+ | },
540+ | "allowReserved" : false,
541+ | "style" : "form"
542+ | }
543+ | ],
544+ | "requestBody" :
545+ | {
546+ | "content" : {
547+ | "application/json" : {
548+ | "schema" :
549+ | {
550+ | "$ref" : "#/components/schemas/SimpleInputBody"
551+ | }
552+ | }
553+ | },
554+ | "required" : true
555+ | },
556+ | "responses" : {
557+ | "200" :
558+ | {
559+ | "content" : {
560+ | "application/json" : {
561+ | "schema" :
562+ | {
563+ | "$ref" : "#/components/schemas/SimpleOutputBody"
564+ | }
565+ | }
566+ | }
567+ | },
568+ | "404" :
569+ | {
570+ | "content" : {
571+ | "application/json" : {
572+ | "schema" :
573+ | {
574+ | "$ref" : "#/components/schemas/NotFoundError"
575+ | }
576+ | }
577+ | }
578+ | }
579+ | }
580+ | }
581+ | }
582+ | },
583+ | "components" : {
584+ | "schemas" : {
585+ | "NotFoundError" :
586+ | {
587+ | "type" :
588+ | "object",
589+ | "properties" : {
590+ | "message" : {
591+ | "type" :
592+ | "string"
593+ | }
594+ | },
595+ | "required" : [
596+ | "message"
597+ | ]
598+ | },
599+ | "SimpleInputBody" :
600+ | {
601+ | "type" :
602+ | "object",
603+ | "properties" : {
604+ | "name" : {
605+ | "type" :
606+ | "string"
607+ | },
608+ | "age" : {
609+ | "type" :
610+ | "integer",
611+ | "format" : "int32"
612+ | }
613+ | },
614+ | "required" : [
615+ | "name",
616+ | "age"
617+ | ]
618+ | },
619+ | "SimpleOutputBody" :
620+ | {
621+ | "type" :
622+ | "object",
623+ | "properties" : {
624+ | "userName" : {
625+ | "type" :
626+ | "string"
627+ | },
628+ | "score" : {
629+ | "type" :
630+ | "integer",
631+ | "format" : "int32"
632+ | }
633+ | },
634+ | "required" : [
635+ | "userName",
636+ | "score"
637+ | ]
638+ | }
639+ | }
640+ | }
641+ |}""" .stripMargin
642+ assertTrue(json == toJsonAst(expectedJson))
643+ },
496644 test(" with query parameter with multiple values" ) {
497645 val generated = OpenAPIGen .fromEndpoints(" Simple Endpoint" , " 1.0" , queryParamCollectionEndpoint)
498646 val json = toJsonAst(generated)
@@ -749,6 +897,214 @@ object OpenAPIGenSpec extends ZIOSpecDefault {
749897 |}""" .stripMargin
750898 assertTrue(json == toJsonAst(expectedJson))
751899 },
900+ test(" optional header" ) {
901+ val generated = OpenAPIGen .fromEndpoints(" Simple Endpoint" , " 1.0" , optionalHeaderEndpoint)
902+ val json = toJsonAst(generated)
903+ val expectedJson = """ {
904+ | "openapi" : "3.1.0",
905+ | "info" : {
906+ | "title" : "Simple Endpoint",
907+ | "version" : "1.0"
908+ | },
909+ | "paths" : {
910+ | "/withHeader" : {
911+ | "get" : {
912+ | "parameters" : [
913+ | {
914+ | "name" : "content-type",
915+ | "in" : "header",
916+ | "schema" : {
917+ | "type" : [
918+ | "string",
919+ | "null"
920+ | ]
921+ | },
922+ | "style" : "simple"
923+ | }
924+ | ],
925+ | "requestBody" : {
926+ | "content" : {
927+ | "application/json" : {
928+ | "schema" : {
929+ | "$ref" : "#/components/schemas/SimpleInputBody",
930+ | "description" : ""
931+ | }
932+ | }
933+ | },
934+ | "required" : true
935+ | },
936+ | "responses" : {
937+ | "200" : {
938+ | "content" : {
939+ | "application/json" : {
940+ | "schema" : {
941+ | "$ref" : "#/components/schemas/SimpleOutputBody"
942+ | }
943+ | }
944+ | }
945+ | },
946+ | "404" : {
947+ | "content" : {
948+ | "application/json" : {
949+ | "schema" : {
950+ | "$ref" : "#/components/schemas/NotFoundError"
951+ | }
952+ | }
953+ | }
954+ | }
955+ | }
956+ | }
957+ | }
958+ | },
959+ | "components" : {
960+ | "schemas" : {
961+ | "NotFoundError" : {
962+ | "type" : "object",
963+ | "properties" : {
964+ | "message" : {
965+ | "type" : "string"
966+ | }
967+ | },
968+ | "required" : [
969+ | "message"
970+ | ]
971+ | },
972+ | "SimpleInputBody" : {
973+ | "type" : "object",
974+ | "properties" : {
975+ | "name" : {
976+ | "type" : "string"
977+ | },
978+ | "age" : {
979+ | "type" : "integer",
980+ | "format" : "int32"
981+ | }
982+ | },
983+ | "required" : [
984+ | "name",
985+ | "age"
986+ | ]
987+ | },
988+ | "SimpleOutputBody" : {
989+ | "type" : "object",
990+ | "properties" : {
991+ | "userName" : {
992+ | "type" : "string"
993+ | },
994+ | "score" : {
995+ | "type" : "integer",
996+ | "format" : "int32"
997+ | }
998+ | },
999+ | "required" : [
1000+ | "userName",
1001+ | "score"
1002+ | ]
1003+ | }
1004+ | }
1005+ | }
1006+ |}""" .stripMargin
1007+ assertTrue(json == toJsonAst(expectedJson))
1008+ },
1009+ test(" optional payload" ) {
1010+ val generated = OpenAPIGen .fromEndpoints(" Simple Endpoint" , " 1.0" , optionalPayloadEndpoint)
1011+ val json = toJsonAst(generated)
1012+ val expected = """ {
1013+ | "openapi" : "3.1.0",
1014+ | "info" : {
1015+ | "title" : "Simple Endpoint",
1016+ | "version" : "1.0"
1017+ | },
1018+ | "paths" : {
1019+ | "/withPayload" : {
1020+ | "get" : {
1021+ | "requestBody" : {
1022+ | "content" : {
1023+ | "application/json" : {
1024+ | "schema" : {
1025+ | "anyOf" : [
1026+ | {
1027+ | "type" : "null"
1028+ | },
1029+ | {
1030+ | "$ref" : "#/components/schemas/Payload"
1031+ | }
1032+ | ],
1033+ | "description" : ""
1034+ | }
1035+ | }
1036+ | },
1037+ | "required" : false
1038+ | },
1039+ | "responses" : {
1040+ | "200" : {
1041+ | "content" : {
1042+ | "application/json" : {
1043+ | "schema" : {
1044+ | "$ref" : "#/components/schemas/SimpleOutputBody"
1045+ | }
1046+ | }
1047+ | }
1048+ | },
1049+ | "404" : {
1050+ | "content" : {
1051+ | "application/json" : {
1052+ | "schema" : {
1053+ | "$ref" : "#/components/schemas/NotFoundError"
1054+ | }
1055+ | }
1056+ | }
1057+ | }
1058+ | }
1059+ | }
1060+ | }
1061+ | },
1062+ | "components" : {
1063+ | "schemas" : {
1064+ | "NotFoundError" : {
1065+ | "type" : "object",
1066+ | "properties" : {
1067+ | "message" : {
1068+ | "type" : "string"
1069+ | }
1070+ | },
1071+ | "required" : [
1072+ | "message"
1073+ | ]
1074+ | },
1075+ | "Payload" : {
1076+ | "type" : "object",
1077+ | "properties" : {
1078+ | "content" : {
1079+ | "type" : "string"
1080+ | }
1081+ | },
1082+ | "required" : [
1083+ | "content"
1084+ | ],
1085+ | "description" : "A simple payload"
1086+ | },
1087+ | "SimpleOutputBody" : {
1088+ | "type" : "object",
1089+ | "properties" : {
1090+ | "userName" : {
1091+ | "type" : "string"
1092+ | },
1093+ | "score" : {
1094+ | "type" : "integer",
1095+ | "format" : "int32"
1096+ | }
1097+ | },
1098+ | "required" : [
1099+ | "userName",
1100+ | "score"
1101+ | ]
1102+ | }
1103+ | }
1104+ | }
1105+ |}""" .stripMargin
1106+ assertTrue(json == toJsonAst(expected))
1107+ },
7521108 test(" alternative input" ) {
7531109 val generated = OpenAPIGen .fromEndpoints(" Simple Endpoint" , " 1.0" , alternativeInputEndpoint)
7541110 val json = toJsonAst(generated)
0 commit comments