@@ -6,6 +6,8 @@ import io.swagger.v3.oas.models.Operation
66import io.swagger.v3.oas.models.media.ComposedSchema
77import io.swagger.v3.oas.models.media.Schema
88import io.swagger.v3.oas.models.parameters.RequestBody
9+ import spock.lang.IgnoreIf
10+ import spock.lang.Issue
911
1012class OpenApiSchemaInheritanceSpec extends AbstractOpenApiTypeElementSpec {
1113
@@ -264,8 +266,9 @@ class MyBean {}
264266 expect :
265267 Schema owner = schemas[" Owner" ]
266268 Schema vehicleRef = owner. getProperties()[" vehicle" ]
267- ! (vehicleRef instanceof ComposedSchema )
268- vehicleRef. $ref == " #/components/schemas/Vehicle"
269+ vehicleRef instanceof ComposedSchema
270+ ((ComposedSchema ) vehicleRef). allOf[0 ]. $ref == " #/components/schemas/Vehicle"
271+ ((ComposedSchema ) vehicleRef). allOf[1 ]. description == " Vehicle of the owner. Here a car or bike with a name"
269272 Schema vehicle = schemas[" Vehicle" ]
270273 vehicle instanceof ComposedSchema
271274 ((ComposedSchema ) vehicle). oneOf[0 ]. $ref == ' #/components/schemas/Car'
@@ -341,8 +344,9 @@ class MyBean {}
341344 expect :
342345 Schema owner = schemas[" Owner" ]
343346 Schema vehicleRef = owner. getProperties()[" vehicle" ]
344- ! (vehicleRef instanceof ComposedSchema )
345- vehicleRef. $ref == " #/components/schemas/Owner.Vehicle"
347+ vehicleRef instanceof ComposedSchema
348+ ((ComposedSchema ) vehicleRef). allOf[0 ]. $ref == " #/components/schemas/Owner.Vehicle"
349+ ((ComposedSchema ) vehicleRef). allOf[1 ]. description == " Vehicle of the owner. Here a car or bike with a name"
346350 Schema ownerVehicle = schemas[" Owner.Vehicle" ]
347351 ((ComposedSchema ) ownerVehicle). oneOf[0 ]. $ref == ' #/components/schemas/Car'
348352 ((ComposedSchema ) ownerVehicle). oneOf[1 ]. $ref == ' #/components/schemas/Bike'
@@ -432,4 +436,127 @@ class MyBean {}
432436 ((ComposedSchema ) vehicle). oneOf[1 ]. $ref == ' #/components/schemas/Bike'
433437 }
434438
439+ @IgnoreIf ({ !jvm.isJava16Compatible() })
440+ @Issue (" https://github.com/micronaut-projects/micronaut-openapi/issues/659" )
441+ void " test OpenAPI proper inheritance of nullable, description and required attributes" () {
442+ given :
443+ buildBeanDefinition(' test.MyBean' , '''
444+
445+ package test;
446+
447+ import io.swagger.v3.oas.annotations.*;
448+ import io.swagger.v3.oas.annotations.parameters.*;
449+ import io.swagger.v3.oas.annotations.responses.*;
450+ import io.swagger.v3.oas.annotations.security.*;
451+ import io.swagger.v3.oas.annotations.media.*;
452+ import io.swagger.v3.oas.annotations.enums.*;
453+ import io.swagger.v3.oas.annotations.links.*;
454+ import io.micronaut.http.annotation.*;
455+ import io.micronaut.core.annotation.*;
456+ import io.swagger.v3.oas.annotations.tags.Tag;
457+ import java.util.List;
458+
459+ @Introspected
460+ @Schema(description = "Schema that represents the possible email protocols for sending emails")
461+ enum EmailSendProtocolDto {
462+ SMTP,
463+ SMTP_SSL,
464+ SMTP_STARTTLS
465+ }
466+
467+ @Introspected
468+ @Schema(description = "Schema that represents the current email settings")
469+ record ReadEmailSettingsDto(
470+
471+ @Schema(description = "Flag that indicates whether the email sending is active or not. If set to false, all other values are null", required = true)
472+ Boolean active,
473+
474+ @Schema(description = "Hostname or IP of the email server or null if email sending is disabled", required = true, nullable = true)
475+ String hostname,
476+
477+ @Schema(description = "Port of the email server or null if email sending is disabled", required = true, nullable = true)
478+ Integer port,
479+
480+ @Schema(description = "Protocol used for the connection or null if email sending is disabled", required = true, nullable = true)
481+ EmailSendProtocolDto protocol,
482+
483+ @Schema(description = "Email username to login or null if email sending is disabled", required = true, nullable = true)
484+ String username,
485+
486+ @Schema(description = "Plaintext password for the email user to login in or null if email sending is disabled", required = true, nullable = true)
487+ String plaintextPassword,
488+
489+ @Schema(description = "Sender email address that is used to send emails or null if email sending is disabled", required = true, nullable = true)
490+ String senderEmail
491+ ) {
492+ }
493+
494+ @Introspected
495+ @Schema(description = "Schema that represents an existing email output location")
496+ record ReadEmailOutputLocationDto(
497+
498+ // Snipped a lot of attributes. Class doesn't make any sense for outstanders
499+
500+ @Schema(description = "Protocol used for the connection", required = true)
501+ EmailSendProtocolDto protocol
502+ ) {
503+ }
504+
505+ @Controller("/api")
506+ class EmailController {
507+
508+ /**
509+ * Get the email settings.
510+ *
511+ * @return Email settings
512+ * @throws Exception Exception in case of invalid data or an issue with reading the settings
513+ */
514+ @Get("/email/settings")
515+ public ReadEmailSettingsDto getEmailSettings(){
516+ return null;
517+ }
518+
519+ /**
520+ * Get the email output location.
521+ *
522+ * @return Email output location
523+ * @throws Exception Exception in case of invalid data or an issue with reading the settings
524+ */
525+ @Get("/email/output")
526+ public ReadEmailOutputLocationDto getEmailOutputLocation() {
527+ return null;
528+ }
529+ }
530+
531+ @jakarta.inject.Singleton
532+ class MyBean {}
533+ ''' )
534+
535+ OpenAPI openAPI = AbstractOpenApiVisitor . testReference
536+ Map<String , Schema > schemas = openAPI. getComponents(). getSchemas()
537+
538+ expect :
539+ Schema EmailSendProtocolDtoSchema = schemas[" EmailSendProtocolDto" ]
540+
541+ EmailSendProtocolDtoSchema . description == " Schema that represents the possible email protocols for sending emails"
542+ ! EmailSendProtocolDtoSchema . nullable
543+ ! EmailSendProtocolDtoSchema . required
544+
545+ schemas[" ReadEmailOutputLocationDto" ]. required. containsAll([" protocol" ])
546+ Schema emailSendProtocolDtoSchemaFromReadEmailOutputLocationDto = schemas[" ReadEmailOutputLocationDto" ]. getProperties()[" protocol" ]
547+ emailSendProtocolDtoSchemaFromReadEmailOutputLocationDto instanceof ComposedSchema
548+ ((ComposedSchema ) emailSendProtocolDtoSchemaFromReadEmailOutputLocationDto). allOf[0 ]. $ref == " #/components/schemas/EmailSendProtocolDto"
549+ ((ComposedSchema ) emailSendProtocolDtoSchemaFromReadEmailOutputLocationDto). allOf[1 ]. description == " Protocol used for the connection"
550+ ! ((ComposedSchema ) emailSendProtocolDtoSchemaFromReadEmailOutputLocationDto). allOf[1 ]. nullable
551+ ! ((ComposedSchema ) emailSendProtocolDtoSchemaFromReadEmailOutputLocationDto). allOf[1 ]. required
552+
553+ schemas[" ReadEmailSettingsDto" ]. required. containsAll([" protocol" , " active" , " hostname" , " port" , " senderEmail" , " username" , " plaintextPassword" ])
554+ Schema emailSendProtocolDtoSchemaFromReadEmailSettingsDto = schemas[" ReadEmailSettingsDto" ]. getProperties()[" protocol" ]
555+ emailSendProtocolDtoSchemaFromReadEmailSettingsDto instanceof ComposedSchema
556+ ((ComposedSchema ) emailSendProtocolDtoSchemaFromReadEmailSettingsDto). allOf[0 ]. $ref == " #/components/schemas/EmailSendProtocolDto"
557+ ((ComposedSchema ) emailSendProtocolDtoSchemaFromReadEmailSettingsDto). allOf[1 ]. description == " Protocol used for the connection or null if email sending is disabled"
558+ ((ComposedSchema ) emailSendProtocolDtoSchemaFromReadEmailSettingsDto). allOf[1 ]. nullable
559+ ! ((ComposedSchema ) emailSendProtocolDtoSchemaFromReadEmailSettingsDto). allOf[1 ]. required
560+ }
561+
435562}
0 commit comments