├── .git-blame-ignore-revs ├── .github ├── release-drafter.yml └── workflows │ ├── ci.yml │ └── scala-steward.yml ├── .gitignore ├── .mergify.yml ├── .scala-steward.conf ├── .scalafmt.conf ├── LICENSE ├── README.md ├── apispec-model └── src │ ├── main │ └── scala │ │ └── sttp │ │ └── apispec │ │ ├── Schema.scala │ │ ├── SecurityScheme.scala │ │ ├── model.scala │ │ ├── package.scala │ │ └── validation │ │ ├── SchemaComparator.scala │ │ ├── SchemaCompatibilityIssue.scala │ │ ├── SchemaResolver.scala │ │ └── util.scala │ └── test │ └── scala │ └── sttp │ └── apispec │ ├── SchemaTest.scala │ └── validation │ ├── BoundsTest.scala │ ├── ComponentsSchemaComparatorTest.scala │ ├── DefsSchemaComparatorTest.scala │ └── SchemaComparatorTest.scala ├── asyncapi-circe-yaml └── src │ └── main │ └── scala │ └── sttp │ └── apispec │ └── asyncapi │ └── circe │ └── yaml │ ├── SttpAsyncAPICirceYaml.scala │ └── package.scala ├── asyncapi-circe └── src │ ├── main │ └── scala │ │ └── sttp │ │ └── apispec │ │ └── asyncapi │ │ └── circe │ │ └── package.scala │ └── test │ └── scala │ └── sttp │ └── apispec │ └── asyncapi │ └── circe │ └── EncoderTest.scala ├── asyncapi-model └── src │ └── main │ └── scala │ └── sttp │ └── apispec │ └── asyncapi │ ├── AsyncAPI.scala │ └── package.scala ├── banner.png ├── build.sbt ├── circe-testutils └── src │ └── main │ ├── scalajs │ └── sttp │ │ └── apispec │ │ └── test │ │ └── ResourcePlatform.scala │ ├── scalajvm │ └── sttp │ │ └── apispec │ │ └── test │ │ └── ResourcePlatform.scala │ └── scalanative │ └── sttp │ └── apispec │ └── test │ └── ResourcePlatform.scala ├── jsonschema-circe └── src │ ├── main │ └── scala │ │ └── sttp │ │ └── apispec │ │ ├── circe.scala │ │ └── internal │ │ ├── JsonSchemaCirceDecoders.scala │ │ └── JsonSchemaCirceEncoders.scala │ └── test │ ├── resources │ ├── extending-recursive.json │ └── self-describing-schema.json │ └── scala │ └── sttp │ └── apispec │ ├── DecoderTest.scala │ └── RoundTripTest.scala ├── openapi-circe-yaml └── src │ └── main │ └── scala │ └── sttp │ └── apispec │ └── openapi │ └── circe │ └── yaml │ ├── SttpOpenAPICirceYaml.scala │ └── package.scala ├── openapi-circe └── src │ ├── main │ └── scala │ │ └── sttp │ │ └── apispec │ │ └── openapi │ │ ├── circe │ │ └── package.scala │ │ └── internal │ │ ├── InternalSttpOpenAPICirceDecoders.scala │ │ └── InternalSttpOpenAPICirceEncoders.scala │ └── test │ ├── resources │ ├── callbacks │ │ └── callbacks.json │ ├── petstore │ │ ├── basic-petstore.json │ │ └── header-petstore.json │ ├── securityScheme │ │ ├── security-scheme-with-empty-scopes.json │ │ └── security-scheme-with-scopes.json │ └── spec │ │ ├── 3.0 │ │ └── schema.json │ │ └── 3.1 │ │ ├── any_and_nothing1.json │ │ ├── any_and_nothing2.json │ │ └── schema.json │ └── scala │ └── sttp │ └── apispec │ └── openapi │ └── circe │ ├── DecoderTest.scala │ ├── overridden │ └── EncoderTest.scala │ └── threeone │ └── EncoderTest.scala ├── openapi-comparator-tests └── src │ └── test │ ├── resources │ └── petstore │ │ ├── added-operation-callback │ │ ├── petstore-added-operation-callback.json │ │ └── petstore.json │ │ ├── added-operation │ │ ├── petstore-added-operation.json │ │ └── petstore.json │ │ ├── added-parameter-content-mediatype-schema │ │ ├── petstore-added-parameter-content-mediatype-schema.json │ │ └── petstore.json │ │ ├── added-parameter-content-mediatype │ │ ├── petstore-added-parameter-content-mediatype.json │ │ └── petstore.json │ │ ├── added-parameter-schema │ │ ├── petstore-added-parameter-schema.json │ │ └── petstore.json │ │ ├── added-parameter │ │ ├── petstore-added-parameter.json │ │ └── petstore.json │ │ ├── added-path │ │ ├── petstore-added-path.json │ │ └── petstore.json │ │ ├── added-requestbody-content-mediatype-encoding │ │ ├── petstore-added-requestbody-content-mediatype-encoding.json │ │ └── petstore.json │ │ ├── added-requestbody-content-mediatype-schema │ │ ├── petstore-added-requestbody-content-mediatype-schema.json │ │ └── petstore.json │ │ ├── added-requestbody-content-mediatype │ │ ├── petstore-added-requestbody-content-mediatype.json │ │ └── petstore.json │ │ ├── added-requestbody │ │ ├── petstore-added-requestbody.json │ │ └── petstore.json │ │ ├── added-response-content-mediatype-schema │ │ ├── petstore-added-response-content-mediatype-schema.json │ │ └── petstore.json │ │ ├── added-response-content-mediatype │ │ ├── petstore-added-response-content-mediatype.json │ │ └── petstore.json │ │ ├── added-response-header-content-mediatype-schema │ │ ├── petstore-added-response-header-content-mediatype-schema.json │ │ └── petstore.json │ │ ├── added-response-header-content-mediatype │ │ ├── petstore-added-response-header-content-mediatype.json │ │ └── petstore.json │ │ ├── added-response-header-schema │ │ ├── petstore-added-response-header-schema.json │ │ └── petstore.json │ │ ├── added-response-header │ │ ├── petstore-added-response-header.json │ │ └── petstore.json │ │ ├── added-response │ │ ├── petstore-added-response.json │ │ └── petstore.json │ │ ├── changed-metadata │ │ ├── petstore-changed-metadata.json │ │ └── petstore.json │ │ ├── identical │ │ ├── petstore-identical.json │ │ └── petstore.json │ │ ├── required-parameter │ │ ├── petstore-required-parameter.json │ │ └── petstore.json │ │ ├── required-request-body │ │ ├── petstore-required-request-body.json │ │ └── petstore.json │ │ ├── required-response-header │ │ ├── petstore-required-response-header.json │ │ └── petstore.json │ │ ├── updated-operation-callback │ │ ├── petstore-updated-operation-callback.json │ │ └── petstore.json │ │ ├── updated-operation-security │ │ ├── petstore-updated-operation-security.json │ │ └── petstore.json │ │ ├── updated-parameter-allow_empty_value │ │ ├── petstore-updated-parameter-allow_empty_value.json │ │ └── petstore.json │ │ ├── updated-parameter-allow_reserved │ │ ├── petstore-updated-parameter-allow_reserved.json │ │ └── petstore.json │ │ ├── updated-parameter-content-mediatype-encoding │ │ ├── petstore-updated-parameter-content-mediatype-encoding.json │ │ └── petstore.json │ │ ├── updated-parameter-content-mediatype-schema │ │ ├── petstore-updated-parameter-content-mediatype-schema.json │ │ └── petstore.json │ │ ├── updated-parameter-explode │ │ ├── petstore-updated-parameter-explode.json │ │ └── petstore.json │ │ ├── updated-parameter-name │ │ ├── petstore-updated-parameter-name.json │ │ └── petstore.json │ │ ├── updated-parameter-schema │ │ ├── petstore-updated-parameter-schema.json │ │ └── petstore.json │ │ ├── updated-parameter-style │ │ ├── petstore-updated-parameter-style.json │ │ └── petstore.json │ │ ├── updated-requestbody-content-mediatype-encoding │ │ ├── petstore-updated-requestbody-content-mediatype-encoding.json │ │ └── petstore.json │ │ ├── updated-requestbody-content-mediatype-schema │ │ ├── petstore-updated-requestbody-content-mediatype-schema.json │ │ └── petstore.json │ │ ├── updated-response-content-mediatype-schema │ │ ├── petstore-updated-response-content-mediatype-schema.json │ │ └── petstore.json │ │ ├── updated-response-header-allow_empty_value │ │ ├── petstore-updated-response-header-allow_empty_value.json │ │ └── petstore.json │ │ ├── updated-response-header-allow_reserved │ │ ├── petstore-updated-response-header-allow_reserved.json │ │ └── petstore.json │ │ ├── updated-response-header-content-mediatype-schema │ │ ├── petstore-updated-response-header-content-mediatype-schema.json │ │ └── petstore.json │ │ ├── updated-response-header-explode │ │ ├── petstore-updated-response-header-explode.json │ │ └── petstore.json │ │ ├── updated-response-header-schema │ │ ├── petstore-updated-response-header-schema.json │ │ └── petstore.json │ │ └── updated-response-header-style │ │ ├── petstore-updated-response-header-style.json │ │ └── petstore.json │ └── scala │ └── sttp │ └── apispec │ └── openapi │ └── validation │ └── OpenAPIComparatorTest.scala ├── openapi-model └── src │ ├── main │ └── scala │ │ └── sttp │ │ └── apispec │ │ └── openapi │ │ ├── OpenAPI.scala │ │ ├── package.scala │ │ └── validation │ │ ├── OpenAPIComparator.scala │ │ └── OpenAPICompatibilityIssue.scala │ └── test │ └── scala │ └── sttp │ └── apispec │ └── openapi │ └── OpenAPITest.scala └── project ├── build.properties └── plugins.sbt /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Scala Steward: Reformat with scalafmt 3.7.4 2 | 224364f653f2a4732889835913898d6e29e15418 3 | 4 | # Scala Steward: Reformat with scalafmt 3.7.6 5 | 2e4921cf83a3b1128da7d27660a713e50465edc0 6 | 7 | # Scala Steward: Reformat with scalafmt 3.7.14 8 | ece31cc91dfbb7f55e1dd9080ef914e3a00ce20a 9 | 10 | # Scala Steward: Reformat with scalafmt 3.9.2 11 | 01e4ad0b91afd01bff3e74cd1594b6f2e590aad2 12 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | template: | 2 | ## What’s Changed 3 | 4 | $CHANGES -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: 4 | branches: ['**'] 5 | push: 6 | branches: ['**'] 7 | tags: [v*] 8 | jobs: 9 | build: 10 | uses: softwaremill/github-actions-workflows/.github/workflows/build-scala.yml@main 11 | # run on external PRs, but not on internal PRs since those will be run by push to branch 12 | if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository 13 | with: 14 | java-opts: '-Xmx6G -Xss4M' 15 | sttp-native: 1 16 | install-libidn2: true 17 | 18 | mima: 19 | uses: softwaremill/github-actions-workflows/.github/workflows/mima.yml@main 20 | # run on external PRs, but not on internal PRs since those will be run by push to branch 21 | if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository 22 | 23 | publish: 24 | uses: softwaremill/github-actions-workflows/.github/workflows/publish-release.yml@main 25 | needs: [build] 26 | if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v')) 27 | secrets: inherit 28 | with: 29 | java-opts: "-Xmx4G -Xss4M" 30 | sttp-native: 1 -------------------------------------------------------------------------------- /.github/workflows/scala-steward.yml: -------------------------------------------------------------------------------- 1 | name: Scala Steward 2 | 3 | # This workflow will launch at 00:00 every day 4 | on: 5 | schedule: 6 | - cron: '0 0 * * *' 7 | workflow_dispatch: 8 | 9 | jobs: 10 | scala-steward: 11 | uses: softwaremill/github-actions-workflows/.github/workflows/scala-steward.yml@main 12 | secrets: 13 | repo-github-token: ${{secrets.REPO_GITHUB_TOKEN}} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.log 3 | 4 | # sbt specific 5 | .cache 6 | .history 7 | .lib/ 8 | dist/* 9 | target/ 10 | lib_managed/ 11 | src_managed/ 12 | project/boot/ 13 | project/plugins/project/ 14 | 15 | # Scala-IDE specific 16 | .scala_dependencies 17 | .worksheet 18 | 19 | .idea* 20 | 21 | .keys* 22 | 23 | core/native/local.sbt 24 | 25 | # Scala Native 26 | lowered.hnir 27 | 28 | # Bloop / Metals 29 | .bloop/ 30 | .metals/ 31 | metals.sbt 32 | .vscode 33 | 34 | .bsp -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | pull_request_rules: 2 | - name: delete head branch after merge 3 | conditions: [] 4 | actions: 5 | delete_head_branch: {} 6 | - name: automatic merge for softwaremill-ci pull requests affecting build.sbt 7 | conditions: 8 | - author=softwaremill-ci 9 | - check-success=ci 10 | - check-success=mima 11 | - "#files=1" 12 | - files=build.sbt 13 | actions: 14 | merge: 15 | method: merge 16 | - name: automatic merge for softwaremill-ci pull requests affecting project plugins.sbt 17 | conditions: 18 | - author=softwaremill-ci 19 | - check-success=ci 20 | - check-success=mima 21 | - "#files=1" 22 | - files=project/plugins.sbt 23 | actions: 24 | merge: 25 | method: merge 26 | - name: semi-automatic merge for softwaremill-ci pull requests 27 | conditions: 28 | - author=softwaremill-ci 29 | - check-success=ci 30 | - check-success=mima 31 | - "#approved-reviews-by>=1" 32 | actions: 33 | merge: 34 | method: merge 35 | - name: automatic merge for softwaremill-ci pull requests affecting project build.properties 36 | conditions: 37 | - author=softwaremill-ci 38 | - check-success=ci 39 | - check-success=mima 40 | - "#files=1" 41 | - files=project/build.properties 42 | actions: 43 | merge: 44 | method: merge 45 | - name: automatic merge for softwaremill-ci pull requests affecting .scalafmt.conf 46 | conditions: 47 | - author=softwaremill-ci 48 | - check-success=ci 49 | - check-success=mima 50 | - "#files=1" 51 | - files=.scalafmt.conf 52 | actions: 53 | merge: 54 | method: merge 55 | -------------------------------------------------------------------------------- /.scala-steward.conf: -------------------------------------------------------------------------------- 1 | updates.ignore = [ 2 | {groupId = "org.scala-lang", artifactId = "scala-compiler", version = "2.12."}, 3 | {groupId = "org.scala-lang", artifactId = "scala-compiler", version = "2.13."}, 4 | {groupId = "org.scala-lang", artifactId = "scala-compiler", version = "3."}, 5 | {groupId = "io.circe", artifactId = "circe-yaml", version = "1."} 6 | ] 7 | updates.pin = [ 8 | {groupId = "org.scala-lang", artifactId = "scala3-library", version = "3.3."}, 9 | {groupId = "org.scala-lang", artifactId = "scala3-library_sjs1", version = "3.3."} 10 | ] 11 | -------------------------------------------------------------------------------- /.scalafmt.conf: -------------------------------------------------------------------------------- 1 | runner.dialect = scala3 2 | version = 3.9.4 3 | maxColumn = 120 -------------------------------------------------------------------------------- /apispec-model/src/main/scala/sttp/apispec/SecurityScheme.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec 2 | 3 | import scala.collection.immutable.ListMap 4 | 5 | case class SecurityScheme( 6 | `type`: String, 7 | description: Option[String] = None, 8 | name: Option[String] = None, 9 | in: Option[String] = None, 10 | scheme: Option[String] = None, 11 | bearerFormat: Option[String] = None, 12 | flows: Option[OAuthFlows] = None, 13 | openIdConnectUrl: Option[String] = None, 14 | extensions: ListMap[String, ExtensionValue] = ListMap.empty 15 | ) 16 | 17 | case class OAuthFlows( 18 | `implicit`: Option[OAuthFlow] = None, 19 | password: Option[OAuthFlow] = None, 20 | clientCredentials: Option[OAuthFlow] = None, 21 | authorizationCode: Option[OAuthFlow] = None, 22 | extensions: ListMap[String, ExtensionValue] = ListMap.empty 23 | ) 24 | 25 | case class OAuthFlow( 26 | authorizationUrl: Option[String] = None, 27 | tokenUrl: Option[String] = None, 28 | refreshUrl: Option[String] = None, 29 | scopes: ListMap[String, String] = ListMap.empty, 30 | extensions: ListMap[String, ExtensionValue] = ListMap.empty 31 | ) 32 | -------------------------------------------------------------------------------- /apispec-model/src/main/scala/sttp/apispec/model.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec 2 | 3 | import scala.collection.immutable.ListMap 4 | 5 | sealed trait ExampleValue 6 | case class ExampleSingleValue(value: Any) extends ExampleValue 7 | case class ExampleMultipleValue(values: List[Any]) extends ExampleValue 8 | 9 | case class Tag( 10 | name: String, 11 | description: Option[String] = None, 12 | externalDocs: Option[ExternalDocumentation] = None, 13 | extensions: ListMap[String, ExtensionValue] = ListMap.empty 14 | ) 15 | 16 | case class ExternalDocumentation( 17 | url: String, 18 | description: Option[String] = None, 19 | extensions: ListMap[String, ExtensionValue] = ListMap.empty 20 | ) 21 | 22 | case class ExtensionValue(value: String) 23 | 24 | /** @see https://json-schema.org/understanding-json-schema/reference/regular_expressions.html */ 25 | final case class Pattern(value: String) 26 | -------------------------------------------------------------------------------- /apispec-model/src/main/scala/sttp/apispec/package.scala: -------------------------------------------------------------------------------- 1 | package sttp 2 | 3 | import scala.collection.immutable.ListMap 4 | 5 | package object apispec { 6 | // using a Vector instead of a List, as empty Lists are always encoded as nulls 7 | // here, we need them encoded as an empty array 8 | type SecurityRequirement = ListMap[String, Vector[String]] 9 | } 10 | -------------------------------------------------------------------------------- /apispec-model/src/main/scala/sttp/apispec/validation/SchemaResolver.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.validation 2 | 3 | import sttp.apispec.{AnySchema, Schema, SchemaLike} 4 | 5 | import scala.annotation.tailrec 6 | import scala.collection.immutable.ListMap 7 | 8 | class SchemaResolver(schemas: Map[String, Schema]) { 9 | 10 | def discriminatorMapping(schema: Schema): ListMap[String, Schema] = { 11 | // schema reference -> overridden discriminator value 12 | val explicitDiscValueByRef = schema.discriminator.flatMap(_.mapping).getOrElse(ListMap.empty).map(_.swap) 13 | // assuming that schema is valid and every reference in disc.mapping is also an element of oneOf/anyOf 14 | ListMap.empty ++ (schema.oneOf ++ schema.anyOf).collect { case s @ ReferenceSchema(ref) => 15 | val discValue = explicitDiscValueByRef.getOrElse( 16 | ref, 17 | ref match { 18 | case SchemaResolver.Reference(name) => name 19 | case _ => throw new NoSuchElementException(s"no discriminator value specified for non-local reference $ref") 20 | } 21 | ) 22 | discValue -> s 23 | } 24 | } 25 | 26 | @tailrec final def resolveAndNormalize(schema: SchemaLike): Schema = schema match { 27 | case AnySchema.Anything => Schema.Empty 28 | case AnySchema.Nothing => Schema.Nothing 29 | case s @ ReferenceSchema(SchemaResolver.Reference(name)) => 30 | resolveAndNormalize( 31 | schemas.getOrElse(name, throw new NoSuchElementException(s"could not resolve schema reference ${s.$ref.get}")) 32 | ) 33 | case s: Schema => normalize(s) 34 | } 35 | 36 | private object ReferenceSchema { 37 | def unapply(schema: Schema): Option[String] = 38 | schema.$ref.filter(ref => schema == Schema($ref = Some(ref))) 39 | } 40 | 41 | private def normalize(schema: Schema): Schema = 42 | schema.copy( 43 | $comment = None, 44 | $defs = None, 45 | $schema = None, 46 | title = None, 47 | description = None, 48 | default = None, 49 | deprecated = None, 50 | readOnly = None, 51 | writeOnly = None, 52 | examples = None, 53 | externalDocs = None, 54 | extensions = ListMap.empty 55 | ) 56 | } 57 | 58 | object SchemaResolver { 59 | val ComponentsRefPrefix = "#/components/schemas/" 60 | 61 | val DefsRefPrefix = "#/$defs/" 62 | 63 | private val Reference = new References(ComponentsRefPrefix, DefsRefPrefix) 64 | 65 | private class References(prefix: String*) { 66 | def unapply(ref: String): Option[String] = prefix.flatMap { p => 67 | Option(ref).filter(_.startsWith(p)).map(_.stripPrefix(p)) 68 | }.headOption 69 | } 70 | 71 | def apply(schemas: Map[String, Schema]): SchemaResolver = new SchemaResolver(schemas) 72 | 73 | def apply(schema: Schema): SchemaResolver = new SchemaResolver( 74 | schema.$defs.getOrElse(Map.empty).collect { case (name, s: Schema) => name -> s } 75 | ) 76 | } 77 | -------------------------------------------------------------------------------- /apispec-model/src/main/scala/sttp/apispec/validation/util.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.validation 2 | 3 | case class Bound[T](value: T, inclusive: Boolean) 4 | object Bound { 5 | def inclusive[T](value: T): Bound[T] = Bound(value, inclusive = true) 6 | def exclusive[T](value: T): Bound[T] = Bound(value, inclusive = false) 7 | } 8 | 9 | case class Bounds[T](min: Option[Bound[T]], max: Option[Bound[T]]) { 10 | override def toString: String = { 11 | val minRepr = min.fold("(-inf") { 12 | case Bound(value, false) => s"($value" 13 | case Bound(value, true) => s"[$value" 14 | } 15 | val maxRepr = max.fold("inf)") { 16 | case Bound(value, false) => s"$value)" 17 | case Bound(value, true) => s"$value]" 18 | } 19 | s"$minRepr,$maxRepr" 20 | } 21 | 22 | def contains(other: Bounds[T])(implicit ord: Ordering[T]): Boolean = { 23 | val minOk = (min, other.min) match { 24 | case (Some(Bound(tm, false)), Some(Bound(om, true))) => ord.lt(tm, om) 25 | case (Some(Bound(tm, _)), Some(Bound(om, _))) => ord.lteq(tm, om) 26 | case (Some(_), None) => false 27 | case (None, _) => true 28 | } 29 | val maxOk = (max, other.max) match { 30 | case (Some(Bound(tm, false)), Some(Bound(om, true))) => ord.gt(tm, om) 31 | case (Some(Bound(tm, _)), Some(Bound(om, _))) => ord.gteq(tm, om) 32 | case (Some(_), None) => false 33 | case (None, _) => true 34 | } 35 | minOk && maxOk 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /apispec-model/src/test/scala/sttp/apispec/SchemaTest.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | 5 | class SchemaTest extends AnyFunSuite { 6 | test("nullable with type") { 7 | val schema = Schema(SchemaType.String) 8 | assert(schema.nullable == Schema(SchemaType.String, SchemaType.Null)) 9 | assert(schema.nullable.nullable == schema.nullable) // idempotency 10 | } 11 | 12 | test("nullable without type") { 13 | val schema = Schema() 14 | assert(schema.nullable == Schema(anyOf = List(schema, Schema.Null))) 15 | assert(schema.nullable.nullable == schema.nullable) // idempotency 16 | } 17 | 18 | test("nullable with anyOf") { 19 | val schema = Schema(anyOf = List(Schema(SchemaType.String), Schema(SchemaType.Number))) 20 | assert(schema.nullable == Schema(anyOf = List(Schema(SchemaType.String), Schema(SchemaType.Number), Schema.Null))) 21 | assert(schema.nullable.nullable == schema.nullable) // idempotency 22 | } 23 | 24 | test("nullable enum") { 25 | val schema = 26 | Schema(`type` = Some(List(SchemaType.String)), `enum` = Some(List("a", "b").map(ExampleSingleValue(_)))) 27 | assert( 28 | schema.nullable == Schema( 29 | `type` = Some(List(SchemaType.String, SchemaType.Null)), 30 | `enum` = Some(List("a", "b", "null").map(ExampleSingleValue(_))) 31 | ) 32 | ) 33 | assert(schema.nullable.nullable == schema.nullable) // idempotency 34 | } 35 | 36 | test("nullable const") { 37 | val schema = Schema(`type` = Some(List(SchemaType.String)), `const` = Some(ExampleSingleValue("a"))) 38 | assert( 39 | schema.nullable == Schema( 40 | `type` = Some(List(SchemaType.String, SchemaType.Null)), 41 | `enum` = Some(List("a", "null").map(ExampleSingleValue(_))) 42 | ) 43 | ) 44 | assert(schema.nullable.nullable == schema.nullable) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /apispec-model/src/test/scala/sttp/apispec/validation/BoundsTest.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.validation 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | 5 | class BoundsTest extends AnyFunSuite { 6 | test("unbounded") { 7 | val b = Bounds[Int](None, None) 8 | assert(b.toString == "(-inf,inf)") 9 | assert(b.contains(b)) 10 | assert(b.contains(Bounds(None, Some(Bound.inclusive(1))))) 11 | assert(b.contains(Bounds(None, Some(Bound.exclusive(1))))) 12 | assert(b.contains(Bounds(Some(Bound.inclusive(1)), None))) 13 | assert(b.contains(Bounds(Some(Bound.exclusive(1)), None))) 14 | assert(b.contains(Bounds(Some(Bound.inclusive(1)), Some(Bound.inclusive(2))))) 15 | } 16 | 17 | test("right bounded") { 18 | val b = Bounds(None, Some(Bound.inclusive(10))) 19 | assert(b.toString == "(-inf,10]") 20 | assert(b.contains(b)) 21 | assert(!b.contains(Bounds(None, None))) 22 | assert(b.contains(Bounds(None, Some(Bound.exclusive(10))))) 23 | assert(b.contains(Bounds(None, Some(Bound.inclusive(9))))) 24 | assert(!b.contains(Bounds(None, Some(Bound.inclusive(11))))) 25 | assert(b.contains(Bounds(Some(Bound.inclusive(0)), Some(Bound.inclusive(10))))) 26 | assert(!b.contains(Bounds(Some(Bound.inclusive(0)), Some(Bound.inclusive(11))))) 27 | } 28 | 29 | test("right bounded open") { 30 | val b = Bounds(None, Some(Bound.exclusive(10))) 31 | assert(b.toString == "(-inf,10)") 32 | assert(b.contains(b)) 33 | assert(!b.contains(Bounds(None, None))) 34 | assert(b.contains(Bounds(None, Some(Bound.exclusive(9))))) 35 | assert(b.contains(Bounds(None, Some(Bound.inclusive(9))))) 36 | assert(!b.contains(Bounds(None, Some(Bound.inclusive(10))))) 37 | assert(!b.contains(Bounds(None, Some(Bound.inclusive(11))))) 38 | assert(b.contains(Bounds(Some(Bound.inclusive(0)), Some(Bound.exclusive(10))))) 39 | assert(!b.contains(Bounds(Some(Bound.inclusive(0)), Some(Bound.inclusive(10))))) 40 | assert(!b.contains(Bounds(Some(Bound.inclusive(0)), Some(Bound.inclusive(11))))) 41 | } 42 | 43 | test("left bounded") { 44 | val b = Bounds(Some(Bound.inclusive(10)), None) 45 | assert(b.toString == "[10,inf)") 46 | assert(b.contains(b)) 47 | assert(!b.contains(Bounds(None, None))) 48 | assert(b.contains(Bounds(Some(Bound.exclusive(10)), None))) 49 | assert(!b.contains(Bounds(Some(Bound.inclusive(9)), None))) 50 | assert(b.contains(Bounds(Some(Bound.inclusive(11)), None))) 51 | assert(b.contains(Bounds(Some(Bound.inclusive(10)), Some(Bound.inclusive(15))))) 52 | assert(!b.contains(Bounds(Some(Bound.inclusive(9)), Some(Bound.inclusive(15))))) 53 | } 54 | 55 | test("left bounded open") { 56 | val b = Bounds(Some(Bound.exclusive(10)), None) 57 | assert(b.toString == "(10,inf)") 58 | assert(b.contains(b)) 59 | assert(!b.contains(Bounds(None, None))) 60 | assert(b.contains(Bounds(Some(Bound.inclusive(11)), None))) 61 | assert(b.contains(Bounds(Some(Bound.exclusive(10)), None))) 62 | assert(!b.contains(Bounds(Some(Bound.inclusive(10)), None))) 63 | assert(!b.contains(Bounds(Some(Bound.inclusive(9)), None))) 64 | assert(!b.contains(Bounds(Some(Bound.inclusive(10)), Some(Bound.inclusive(15))))) 65 | assert(b.contains(Bounds(Some(Bound.exclusive(10)), Some(Bound.inclusive(15))))) 66 | assert(!b.contains(Bounds(Some(Bound.inclusive(9)), Some(Bound.inclusive(15))))) 67 | } 68 | 69 | test("bounded") { 70 | val b = Bounds(Some(Bound.inclusive(0)), Some(Bound.inclusive(10))) 71 | assert(b.toString == "[0,10]") 72 | assert(b.contains(b)) 73 | assert(!b.contains(Bounds(None, None))) 74 | assert(b.contains(Bounds(Some(Bound.exclusive(0)), Some(Bound.inclusive(10))))) 75 | assert(b.contains(Bounds(Some(Bound.exclusive(0)), Some(Bound.exclusive(10))))) 76 | assert(b.contains(Bounds(Some(Bound.inclusive(1)), Some(Bound.inclusive(9))))) 77 | assert(!b.contains(Bounds(Some(Bound.inclusive(1)), Some(Bound.inclusive(11))))) 78 | assert(!b.contains(Bounds(Some(Bound.inclusive(-1)), Some(Bound.inclusive(9))))) 79 | } 80 | 81 | test("bounded open") { 82 | val b = Bounds(Some(Bound.exclusive(0)), Some(Bound.exclusive(10))) 83 | assert(b.toString == "(0,10)") 84 | assert(b.contains(b)) 85 | assert(!b.contains(Bounds(None, None))) 86 | assert(!b.contains(Bounds(Some(Bound.inclusive(0)), Some(Bound.inclusive(10))))) 87 | assert(!b.contains(Bounds(Some(Bound.exclusive(0)), Some(Bound.inclusive(10))))) 88 | assert(!b.contains(Bounds(Some(Bound.inclusive(0)), Some(Bound.exclusive(10))))) 89 | assert(b.contains(Bounds(Some(Bound.exclusive(0)), Some(Bound.exclusive(10))))) 90 | assert(b.contains(Bounds(Some(Bound.exclusive(1)), Some(Bound.exclusive(9))))) 91 | assert(!b.contains(Bounds(Some(Bound.inclusive(1)), Some(Bound.inclusive(11))))) 92 | assert(!b.contains(Bounds(Some(Bound.inclusive(-1)), Some(Bound.inclusive(9))))) 93 | assert(!b.contains(Bounds(Some(Bound.inclusive(-1)), Some(Bound.inclusive(11))))) 94 | assert(!b.contains(Bounds(Some(Bound.exclusive(-1)), Some(Bound.exclusive(11))))) 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /apispec-model/src/test/scala/sttp/apispec/validation/ComponentsSchemaComparatorTest.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.validation 2 | 3 | class ComponentsSchemaComparatorTest extends SchemaComparatorTest(SchemaResolver.ComponentsRefPrefix) 4 | -------------------------------------------------------------------------------- /apispec-model/src/test/scala/sttp/apispec/validation/DefsSchemaComparatorTest.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.validation 2 | 3 | class DefsSchemaComparatorTest extends SchemaComparatorTest(SchemaResolver.DefsRefPrefix) 4 | -------------------------------------------------------------------------------- /asyncapi-circe-yaml/src/main/scala/sttp/apispec/asyncapi/circe/yaml/SttpAsyncAPICirceYaml.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.asyncapi.circe.yaml 2 | 3 | import io.circe.syntax._ 4 | import io.circe.yaml.Printer 5 | import io.circe.yaml.Printer.StringStyle 6 | import sttp.apispec.asyncapi.AsyncAPI 7 | import sttp.apispec.asyncapi.circe._ 8 | 9 | trait SttpAsyncAPICirceYaml { 10 | implicit class RichAsyncAPI(asyncAPI: AsyncAPI) { 11 | def toYaml: String = Printer(dropNullKeys = true, preserveOrder = true).pretty(asyncAPI.asJson) 12 | def toYaml(stringStyle: StringStyle): String = 13 | Printer(dropNullKeys = true, preserveOrder = true, stringStyle = stringStyle).pretty(asyncAPI.asJson) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /asyncapi-circe-yaml/src/main/scala/sttp/apispec/asyncapi/circe/yaml/package.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.asyncapi.circe 2 | 3 | package object yaml extends SttpAsyncAPICirceYaml 4 | -------------------------------------------------------------------------------- /asyncapi-model/src/main/scala/sttp/apispec/asyncapi/package.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec 2 | 3 | package object asyncapi { 4 | type ReferenceOr[T] = Either[Reference, T] 5 | } 6 | -------------------------------------------------------------------------------- /banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/softwaremill/sttp-apispec/aa17d05b85985af0160a2574ad9963a716c57767/banner.png -------------------------------------------------------------------------------- /circe-testutils/src/main/scalajs/sttp/apispec/test/ResourcePlatform.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.test 2 | 3 | import io.circe.{Json, Error} 4 | import io.circe.parser.decode 5 | 6 | trait ResourcePlatform { 7 | 8 | /** @return 9 | * Base directory of sbt project we should read resources from 10 | */ 11 | def basedir: String 12 | def resourcesPath(path: String): String = s"$basedir/src/test/resources$path" 13 | 14 | def resourceAsString(path: String): String = { 15 | import scalajs.js.Dynamic.{global => g} 16 | val fs = g.require("fs") 17 | 18 | def readFile(name: String): String = { 19 | fs.readFileSync(name).toString 20 | } 21 | 22 | readFile(resourcesPath(path)) 23 | } 24 | 25 | def readJson(path: String): Either[Error, Json] = { 26 | val string = resourceAsString(path) 27 | decode[Json](string) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /circe-testutils/src/main/scalajvm/sttp/apispec/test/ResourcePlatform.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.test 2 | 3 | import io.circe._ 4 | import io.circe.parser.decode 5 | import java.io.{BufferedReader, InputStreamReader, StringWriter} 6 | import java.nio.charset.StandardCharsets 7 | 8 | trait ResourcePlatform { 9 | 10 | /** @return 11 | * Base directory of sbt project we should read resources from. Not used from JVM 12 | */ 13 | def basedir: String 14 | def readJson(path: String): Either[Error, Json] = { 15 | 16 | val is = getClass.getResourceAsStream(path) 17 | val reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)) 18 | val writer = new StringWriter() 19 | reader.transferTo(writer) 20 | decode[Json](writer.toString) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /circe-testutils/src/main/scalanative/sttp/apispec/test/ResourcePlatform.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.test 2 | 3 | import io.circe._ 4 | import io.circe.parser.decode 5 | 6 | trait ResourcePlatform { 7 | 8 | /** @return 9 | * Base directory of sbt project we should read resources from 10 | */ 11 | def basedir: String 12 | def resourcesPath(path: String): String = s"$basedir/src/test/resources/$path" 13 | 14 | def readJson(path: String): Either[Error, Json] = { 15 | val string = scala.io.Source.fromFile(resourcesPath(path), "UTF-8").mkString 16 | decode[Json](string) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /jsonschema-circe/src/main/scala/sttp/apispec/circe.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec 2 | 3 | import sttp.apispec.AnySchema.Encoding.Boolean 4 | import sttp.apispec.internal.{JsonSchemaCirceDecoders, JsonSchemaCirceEncoders} 5 | 6 | object circe extends JsonSchemaCirceEncoders with JsonSchemaCirceDecoders { 7 | override def anyObjectEncoding: AnySchema.Encoding = Boolean 8 | } 9 | -------------------------------------------------------------------------------- /jsonschema-circe/src/test/resources/extending-recursive.json: -------------------------------------------------------------------------------- 1 | { 2 | "$id": "https://example.com/schemas/customer", 3 | "$schema": "https://json-schema.org/draft/2020-12/schema", 4 | 5 | "type": "object", 6 | "properties": { 7 | "first_name": { "type": "string" }, 8 | "last_name": { "type": "string" }, 9 | "shipping_address": { "$ref": "/schemas/address" }, 10 | "billing_address": { "$ref": "/schemas/address" } 11 | }, 12 | "required": ["first_name", "last_name", "shipping_address", "billing_address"], 13 | 14 | "$defs": { 15 | "address": { 16 | "$id": "/schemas/address", 17 | "$schema": "http://json-schema.org/draft-07/schema#", 18 | 19 | "type": "object", 20 | "properties": { 21 | "street_address": { "type": "string" }, 22 | "city": { "type": "string" }, 23 | "state": { "$ref": "#/definitions/state" } 24 | }, 25 | "required": ["street_address", "city", "state"], 26 | 27 | "definitions": { 28 | "state": { "enum": ["CA", "NY", "... etc ..."] } 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /jsonschema-circe/src/test/resources/self-describing-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema" : "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#", 3 | "description": "Meta-schema for self-describing JSON schema", 4 | "self": { 5 | "vendor": "com.snowplowanalytics.self-desc", 6 | "name": "schema", 7 | "format": "jsonschema", 8 | "version": "1-0-0" 9 | }, 10 | 11 | "allOf": [ 12 | { 13 | "properties": { 14 | "self": { 15 | "type": "object", 16 | "properties": { 17 | "vendor": { 18 | "type": "string", 19 | "pattern": "^[a-zA-Z0-9-_.]+$" 20 | }, 21 | "name": { 22 | "type": "string", 23 | "pattern": "^[a-zA-Z0-9-_]+$" 24 | }, 25 | "format": { 26 | "type": "string", 27 | "pattern": "^[a-zA-Z0-9-_]+$" 28 | }, 29 | "version": { 30 | "type": "string", 31 | "pattern": "^[0-9]+-[0-9]+-[0-9]+$" 32 | } 33 | }, 34 | "required": ["vendor", "name", "format", "version"], 35 | "additionalProperties": false 36 | } 37 | }, 38 | "required": ["self"] 39 | }, 40 | 41 | { 42 | "$ref": "http://json-schema.org/draft-04/schema#" 43 | } 44 | ] 45 | 46 | } 47 | -------------------------------------------------------------------------------- /jsonschema-circe/src/test/scala/sttp/apispec/DecoderTest.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import sttp.apispec.circe._ 5 | import sttp.apispec.test._ 6 | 7 | import scala.collection.immutable.ListMap 8 | 9 | class DecoderTest extends AnyFunSuite with ResourcePlatform { 10 | override val basedir = "jsonschema-circe" 11 | 12 | test("extending rescursive") { 13 | val Right(json) = readJson("/extending-recursive.json") 14 | val schema = json.as[Schema] 15 | assert(schema.isRight) 16 | val unsafeSchema = schema.right.get 17 | val adrEither = unsafeSchema.$defs.getOrElse(ListMap.empty)("address") 18 | 19 | adrEither match { 20 | case s: Schema => assert(s.$schema == Some("http://json-schema.org/draft-07/schema#") && s.$defs.isDefined) 21 | case _ => fail("Nope") 22 | } 23 | } 24 | 25 | test("self-decribing-schema") { 26 | val Right(json) = readJson("/self-describing-schema.json") 27 | val schema = json.as[Schema] 28 | assert(schema.isRight) 29 | 30 | val unsafeSchema = schema.right.get 31 | assert(unsafeSchema.description === Some("Meta-schema for self-describing JSON schema")) 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /jsonschema-circe/src/test/scala/sttp/apispec/RoundTripTest.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import sttp.apispec.circe._ 5 | import sttp.apispec.test._ 6 | import io.circe.syntax._ 7 | import io.circe.Decoder 8 | 9 | class RoundTripTest extends AnyFunSuite with ResourcePlatform { 10 | override val basedir = "jsonschema-circe" 11 | 12 | test("Can parse self-encoded schema") { 13 | val simple = Schema( 14 | $schema = Some("https://json-schema.org/draft/2020-12/schema"), 15 | $id = Some("http://yourdomain.com/schemas/myschema.json") 16 | ) 17 | val decoded = Decoder[Schema].decodeJson(simple.asJson) 18 | assert(decoded.isRight, decoded.fold(_.toString, _ => "")) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /openapi-circe-yaml/src/main/scala/sttp/apispec/openapi/circe/yaml/SttpOpenAPICirceYaml.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.openapi.circe.yaml 2 | 3 | import io.circe.syntax._ 4 | import io.circe.yaml.Printer 5 | import io.circe.yaml.Printer.StringStyle 6 | import sttp.apispec.openapi.OpenAPI 7 | 8 | trait SttpOpenAPICirceYaml { 9 | 10 | implicit class RichOpenAPI(openAPI: OpenAPI) { 11 | 12 | /** Converts `OpenAPI` to Open Api 3.0.3 YAML string */ 13 | def toYaml3_0_3: String = { 14 | import sttp.apispec.openapi.circe_openapi_3_0_3._ 15 | Printer(dropNullKeys = true, preserveOrder = true).pretty(openAPI.asJson) 16 | } 17 | 18 | /** Converts `OpenAPI` to Open Api 3.0.3 YAML string */ 19 | def toYaml3_0_3(stringStyle: StringStyle): String = { 20 | import sttp.apispec.openapi.circe_openapi_3_0_3._ 21 | Printer(dropNullKeys = true, preserveOrder = true, stringStyle = stringStyle).pretty(openAPI.asJson) 22 | } 23 | 24 | /** Converts `OpenAPI` to Open Api 3.1.0 YAML string */ 25 | def toYaml: String = { 26 | import sttp.apispec.openapi.circe._ 27 | Printer(dropNullKeys = true, preserveOrder = true).pretty(openAPI.asJson) 28 | } 29 | 30 | /** Converts `OpenAPI` to Open Api 3.1.0 YAML string */ 31 | def toYaml(stringStyle: StringStyle): String = { 32 | import sttp.apispec.openapi.circe._ 33 | Printer(dropNullKeys = true, preserveOrder = true, stringStyle = stringStyle).pretty(openAPI.asJson) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /openapi-circe-yaml/src/main/scala/sttp/apispec/openapi/circe/yaml/package.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.openapi.circe 2 | 3 | package object yaml extends SttpOpenAPICirceYaml 4 | -------------------------------------------------------------------------------- /openapi-circe/src/main/scala/sttp/apispec/openapi/circe/package.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.openapi 2 | 3 | import sttp.apispec.AnySchema 4 | import sttp.apispec.openapi.circe.{SttpOpenAPICirceDecoders, SttpOpenAPI3_0_3CirceEncoders} 5 | 6 | package object circe_openapi_3_0_3 extends SttpOpenAPI3_0_3CirceEncoders with SttpOpenAPICirceDecoders { 7 | override def anyObjectEncoding: AnySchema.Encoding = AnySchema.Encoding.Boolean 8 | } 9 | 10 | package object circe extends SttpOpenAPICirceEncoders with SttpOpenAPICirceDecoders { 11 | override def anyObjectEncoding: AnySchema.Encoding = AnySchema.Encoding.Boolean 12 | } 13 | 14 | package circe { 15 | trait SttpOpenAPI3_0_3CirceEncoders extends internal.InternalSttpOpenAPICirceEncoders { 16 | override def openApi30: Boolean = true 17 | } 18 | 19 | trait SttpOpenAPICirceEncoders extends internal.InternalSttpOpenAPICirceEncoders { 20 | override def openApi30: Boolean = false 21 | override def anyObjectEncoding: AnySchema.Encoding = AnySchema.Encoding.Boolean 22 | } 23 | 24 | trait SttpOpenAPICirceDecoders extends internal.InternalSttpOpenAPICirceDecoders 25 | } 26 | -------------------------------------------------------------------------------- /openapi-circe/src/main/scala/sttp/apispec/openapi/internal/InternalSttpOpenAPICirceEncoders.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec 2 | package openapi 3 | package internal 4 | 5 | import io.circe.generic.semiauto._ 6 | import io.circe.syntax._ 7 | import io.circe.{Encoder, Json} 8 | import sttp.apispec.internal.JsonSchemaCirceEncoders 9 | 10 | import scala.collection.immutable.ListMap 11 | 12 | trait InternalSttpOpenAPICirceEncoders extends JsonSchemaCirceEncoders { 13 | implicit val encoderReference: Encoder[Reference] = deriveEncoder[Reference].dropNulls 14 | implicit def encoderReferenceOr[T: Encoder]: Encoder[ReferenceOr[T]] = { 15 | case Left(Reference(ref, summary, description)) => 16 | Json 17 | .obj( 18 | s"$$ref" := ref, 19 | "summary" := summary, 20 | "description" := description 21 | ) 22 | .dropNullValues 23 | case Right(t) => implicitly[Encoder[T]].apply(t) 24 | } 25 | 26 | implicit val encoderOAuthFlow: Encoder[OAuthFlow] = { 27 | // #79: all OAuth flow object MUST include a scopes field, but it MAY be empty. 28 | implicit def encodeListMap: Encoder[ListMap[String, String]] = doEncodeListMap(nullWhenEmpty = false) 29 | 30 | deriveEncoder[OAuthFlow].dropNullsExpandExtensions 31 | } 32 | implicit val encoderOAuthFlows: Encoder[OAuthFlows] = deriveEncoder[OAuthFlows].dropNullsExpandExtensions 33 | implicit val encoderSecurityScheme: Encoder[SecurityScheme] = 34 | deriveEncoder[SecurityScheme].dropNullsExpandExtensions 35 | 36 | implicit val encoderHeader: Encoder[Header] = deriveEncoder[Header].dropNulls 37 | implicit val encoderExample: Encoder[Example] = deriveEncoder[Example].dropNullsExpandExtensions 38 | implicit val encoderResponse: Encoder[Response] = deriveEncoder[Response].dropNullsExpandExtensions 39 | implicit val encoderLink: Encoder[Link] = deriveEncoder[Link].dropNullsExpandExtensions 40 | implicit val encoderCallback: Encoder[Callback] = Encoder.instance { callback => 41 | Json.obj(callback.pathItems.map { case (path, pathItem) => path -> pathItem.asJson }.toList: _*) 42 | } 43 | implicit val encoderEncoding: Encoder[Encoding] = deriveEncoder[Encoding].dropNullsExpandExtensions 44 | implicit val encoderMediaType: Encoder[MediaType] = deriveEncoder[MediaType].dropNullsExpandExtensions 45 | implicit val encoderRequestBody: Encoder[RequestBody] = deriveEncoder[RequestBody].dropNullsExpandExtensions 46 | implicit val encoderParameterStyle: Encoder[ParameterStyle] = { e => Encoder.encodeString(e.value) } 47 | implicit val encoderParameterIn: Encoder[ParameterIn] = { e => Encoder.encodeString(e.value) } 48 | implicit val encoderParameter: Encoder[Parameter] = deriveEncoder[Parameter].dropNullsExpandExtensions 49 | implicit val encoderResponseMap: Encoder[ListMap[ResponsesKey, ReferenceOr[Response]]] = 50 | (responses: ListMap[ResponsesKey, ReferenceOr[Response]]) => { 51 | val fields = responses.map { 52 | case (ResponsesDefaultKey, r) => ("default", r.asJson) 53 | case (ResponsesCodeKey(code), r) => (code.toString, r.asJson) 54 | case (ResponsesRangeKey(range), r) => (s"${range}XX", r.asJson) 55 | } 56 | 57 | Json.obj(fields.toSeq: _*) 58 | } 59 | implicit val encoderResponses: Encoder[Responses] = Encoder.instance { resp => 60 | val extensions = resp.extensions.asJsonObject 61 | val respJson = resp.responses.asJson 62 | respJson.asObject.map(_.deepMerge(extensions).asJson).getOrElse(respJson) 63 | } 64 | 65 | implicit val encoderOperation: Encoder[Operation] = { 66 | // this is needed to override the encoding of `security: List[SecurityRequirement]`. An empty security requirement 67 | // should be represented as an empty object (`{}`), not `null`, which is the default encoding of `ListMap`s. 68 | implicit def encodeListMap[V: Encoder]: Encoder[ListMap[String, V]] = doEncodeListMap(nullWhenEmpty = false) 69 | 70 | implicit def encodeListMapForCallbacks: Encoder[ListMap[String, ReferenceOr[Callback]]] = 71 | doEncodeListMap(nullWhenEmpty = true) 72 | 73 | deriveEncoder[Operation].dropNullsExpandExtensions 74 | } 75 | implicit val encoderPathItem: Encoder[PathItem] = deriveEncoder[PathItem].dropNullsExpandExtensions 76 | implicit val encoderPaths: Encoder[Paths] = Encoder.instance { paths => 77 | val extensions = paths.extensions.asJsonObject 78 | val pathItems = paths.pathItems.asJson 79 | pathItems.asObject.map(_.deepMerge(extensions).asJson).getOrElse(pathItems) 80 | } 81 | implicit val encoderComponents: Encoder[Components] = deriveEncoder[Components].dropNullsExpandExtensions 82 | implicit val encoderServerVariable: Encoder[ServerVariable] = 83 | deriveEncoder[ServerVariable].dropNullsExpandExtensions 84 | implicit val encoderServer: Encoder[Server] = deriveEncoder[Server].dropNullsExpandExtensions 85 | implicit val encoderTag: Encoder[Tag] = deriveEncoder[Tag].dropNullsExpandExtensions 86 | implicit val encoderInfo: Encoder[Info] = deriveEncoder[Info].dropNullsExpandExtensions 87 | implicit val encoderContact: Encoder[Contact] = deriveEncoder[Contact].dropNullsExpandExtensions 88 | implicit val encoderLicense: Encoder[License] = deriveEncoder[License].dropNullsExpandExtensions 89 | implicit val encoderOpenAPI: Encoder[OpenAPI] = deriveEncoder[OpenAPI].dropNullsExpandExtensions 90 | } 91 | -------------------------------------------------------------------------------- /openapi-circe/src/test/resources/callbacks/callbacks.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.3", 3 | "info": { 4 | "title": "Simple Pet Store API", 5 | "version": "1.0.0" 6 | }, 7 | "paths": { 8 | "/pets": { 9 | "post": { 10 | "summary": "Add a new pet", 11 | "requestBody": { 12 | "required": true, 13 | "content": { 14 | "application/json": { 15 | "schema": { 16 | "type": "object", 17 | "properties": { 18 | "id": { 19 | "type": "integer" 20 | }, 21 | "name": { 22 | "type": "string" 23 | }, 24 | "tag": { 25 | "type": "string" 26 | } 27 | } 28 | } 29 | } 30 | } 31 | }, 32 | "responses": { 33 | "201": { 34 | "description": "Pet created successfully." 35 | } 36 | }, 37 | "callbacks": { 38 | "onPetStatusChange": { 39 | "{$request.body#/callbackUrl}": { 40 | "post": { 41 | "summary": "Notify about pet status change", 42 | "description": "This callback is triggered whenever the status of a pet changes.", 43 | "requestBody": { 44 | "required": true, 45 | "content": { 46 | "application/json": { 47 | "schema": { 48 | "type": "object", 49 | "properties": { 50 | "status": { 51 | "type": "string", 52 | "description": "The new status of the pet.", 53 | "enum": [ 54 | "available", 55 | "pending", 56 | "sold" 57 | ] 58 | }, 59 | "timestamp": { 60 | "type": "string", 61 | "format": "date-time", 62 | "description": "The time when the status change occurred." 63 | }, 64 | "petId": { 65 | "type": "integer", 66 | "description": "The unique ID of the pet whose status changed." 67 | } 68 | }, 69 | "required": [ 70 | "status", 71 | "timestamp", 72 | "petId" 73 | ] 74 | } 75 | } 76 | } 77 | }, 78 | "responses": { 79 | "200": { 80 | "description": "Callback successfully processed." 81 | }, 82 | "400": { 83 | "description": "Invalid payload provided.", 84 | "content": { 85 | "application/json": { 86 | "schema": { 87 | "type": "object", 88 | "properties": { 89 | "error": { 90 | "type": "string", 91 | "description": "Details about the error." 92 | } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | } 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /openapi-circe/src/test/resources/petstore/basic-petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.1" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "responses": { 30 | "200": { 31 | "description": "Success", 32 | "content": { 33 | "application/json": { 34 | "schema": { 35 | "type": "array", 36 | "items": { 37 | "$ref": "#/components/schemas/Pet" 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | }, 47 | "components": { 48 | "schemas": { 49 | "Pet": { 50 | "type": "object", 51 | "properties": { 52 | "id": { 53 | "type": "integer", 54 | "format": "int32" 55 | }, 56 | "name": { 57 | "type": "string" 58 | } 59 | } 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /openapi-circe/src/test/resources/petstore/header-petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.1" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "responses": { 30 | "200": { 31 | "description": "Success", 32 | "headers": { 33 | "Location": { 34 | "required": true, 35 | "schema": { 36 | "type": "string" 37 | } 38 | } 39 | }, 40 | "content": { 41 | "application/json": { 42 | "schema": { 43 | "type": "array", 44 | "items": { 45 | "$ref": "#/components/schemas/Pet" 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } 52 | } 53 | } 54 | }, 55 | "components": { 56 | "schemas": { 57 | "Pet": { 58 | "type": "object", 59 | "properties": { 60 | "id": { 61 | "type": "integer", 62 | "format": "int32" 63 | }, 64 | "name": { 65 | "type": "string" 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /openapi-circe/src/test/resources/securityScheme/security-scheme-with-empty-scopes.json: -------------------------------------------------------------------------------- 1 | { 2 | "type" : "oauth2", 3 | "flows" : { 4 | "clientCredentials" : { 5 | "tokenUrl" : "openapi-circe-token", 6 | "scopes" : { 7 | 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /openapi-circe/src/test/resources/securityScheme/security-scheme-with-scopes.json: -------------------------------------------------------------------------------- 1 | { 2 | "type" : "oauth2", 3 | "flows" : { 4 | "clientCredentials" : { 5 | "tokenUrl" : "openapi-circe-token", 6 | "scopes" : { 7 | "example" : "description" 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /openapi-circe/src/test/resources/spec/3.0/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.1", 3 | "info": { 4 | "title": "API", 5 | "version": "1.0.0" 6 | }, 7 | "components": { 8 | "schemas": { 9 | "type 'null'": { 10 | "type": "null", 11 | "description": "type 'null'" 12 | }, 13 | "nullable string": { 14 | "type": "string", 15 | "nullable": true, 16 | "description": "nullable string" 17 | }, 18 | "nullable enum" : { 19 | "description" : "nullable enum", 20 | "enum" : [ 21 | "a", 22 | "b", 23 | null 24 | ] 25 | }, 26 | "nullable reference": { 27 | "nullable": true, 28 | "allOf": [ 29 | { 30 | "$ref": "#/components/schemas/Foo" 31 | } 32 | ], 33 | "description": "nullable reference" 34 | }, 35 | "single example": { 36 | "type": "string", 37 | "description": "single example", 38 | "example": "exampleValue" 39 | }, 40 | "multi valued example" : { 41 | "type" : "array", 42 | "description" : "multi valued example", 43 | "example" : [ 44 | "ex1", 45 | "ex1" 46 | ] 47 | }, 48 | "object with example" : { 49 | "description" : "object with example", 50 | "example" : { 51 | "a" : 1, 52 | "b" : null 53 | }, 54 | "type" : "object" 55 | }, 56 | "min/max": { 57 | "minimum": 10, 58 | "maximum": 20, 59 | "description": "min/max" 60 | }, 61 | "exclusive min/max": { 62 | "minimum": 10, 63 | "exclusiveMinimum": true, 64 | "maximum": 20, 65 | "exclusiveMaximum": true, 66 | "description": "exclusive min/max" 67 | }, 68 | "exclusiveMinimum false": { 69 | "minimum": 10, 70 | "description": "exclusiveMinimum false" 71 | }, 72 | "array": { 73 | "type": "array", 74 | "items": { 75 | "type": "string" 76 | }, 77 | "description": "array" 78 | }, 79 | "array with unique items": { 80 | "type": "array", 81 | "uniqueItems": true, 82 | "description": "array with unique items" 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /openapi-circe/src/test/resources/spec/3.1/any_and_nothing1.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "API", 5 | "version": "1.0.0" 6 | }, 7 | "components": { 8 | "schemas": { 9 | "anything_boolean": true, 10 | "nothing_boolean": false 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /openapi-circe/src/test/resources/spec/3.1/any_and_nothing2.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "API", 5 | "version": "1.0.0" 6 | }, 7 | "components": { 8 | "schemas": { 9 | "anything_object": {}, 10 | "nothing_object": { 11 | "not": {} 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /openapi-circe/src/test/resources/spec/3.1/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "API", 5 | "version": "1.0.0" 6 | }, 7 | "components": { 8 | "schemas": { 9 | "type 'null'": { 10 | "type": "null", 11 | "description": "type 'null'" 12 | }, 13 | "nullable string": { 14 | "type": [ 15 | "string", 16 | "null" 17 | ], 18 | "description": "nullable string" 19 | }, 20 | "nullable enum" : { 21 | "description" : "nullable enum", 22 | "enum" : [ 23 | "a", 24 | "b", 25 | null 26 | ] 27 | }, 28 | "nullable reference": { 29 | "anyOf": [ 30 | { 31 | "$ref": "#/components/schemas/Foo" 32 | }, 33 | { 34 | "type": "null" 35 | } 36 | ], 37 | "description": "nullable reference" 38 | }, 39 | "single example": { 40 | "type": "string", 41 | "description": "single example", 42 | "examples": [ 43 | "exampleValue" 44 | ] 45 | }, 46 | "multi valued example" : { 47 | "type" : "array", 48 | "description" : "multi valued example", 49 | "examples" : [ 50 | [ 51 | "ex1", 52 | "ex1" 53 | ] 54 | ] 55 | }, 56 | "object with example" : { 57 | "description" : "object with example", 58 | "examples" : [ 59 | { 60 | "a" : 1, 61 | "b" : null 62 | } 63 | ], 64 | "type" : "object" 65 | }, 66 | "min/max": { 67 | "minimum": 10, 68 | "maximum": 20, 69 | "description": "min/max" 70 | }, 71 | "exclusive min/max": { 72 | "exclusiveMinimum": 10, 73 | "exclusiveMaximum": 20, 74 | "description": "exclusive min/max" 75 | }, 76 | "exclusiveMinimum false": { 77 | "minimum": 10, 78 | "description": "exclusiveMinimum false" 79 | }, 80 | "array": { 81 | "type": "array", 82 | "items": { 83 | "type": "string" 84 | }, 85 | "description": "array" 86 | }, 87 | "array with unique items": { 88 | "type": "array", 89 | "uniqueItems": true, 90 | "description": "array with unique items" 91 | }, 92 | "multiple examples": { 93 | "type": "string", 94 | "description": "multiple examples", 95 | "examples": [ 96 | "ex1", 97 | "ex2" 98 | ] 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /openapi-circe/src/test/scala/sttp/apispec/openapi/circe/DecoderTest.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec 2 | package openapi 3 | package circe 4 | 5 | import sttp.apispec.test._ 6 | import org.scalatest.funsuite.AnyFunSuite 7 | import scala.collection.immutable.ListMap 8 | 9 | class DecoderTest extends AnyFunSuite with ResourcePlatform { 10 | override val basedir = "openapi-circe" 11 | 12 | def extractOrThrow[T](option: Option[T], errorMessage: String): T = 13 | option.getOrElse(throw new IllegalArgumentException(errorMessage)) 14 | 15 | test("petstore deserialize") { 16 | val Right(openapi) = readJson("/petstore/basic-petstore.json").flatMap(_.as[OpenAPI]): @unchecked 17 | 18 | assert(openapi.info.description === Some("This is a sample server for a pet store.")) 19 | } 20 | 21 | test("spec any nothing schema boolean") { 22 | val Right(openapi) = readJson("/spec/3.1/any_and_nothing1.json").flatMap(_.as[OpenAPI]): @unchecked 23 | 24 | assert(openapi.info.title === "API") 25 | val schemas = openapi.components.getOrElse(Components.Empty).schemas 26 | assert(schemas.nonEmpty) 27 | assert(schemas("anything_boolean") === AnySchema.Anything) 28 | assert(schemas("nothing_boolean") === AnySchema.Nothing) 29 | } 30 | 31 | test("spec any nothing schema object") { 32 | val Right(openapi) = readJson("/spec/3.1/any_and_nothing2.json").flatMap(_.as[OpenAPI]): @unchecked 33 | 34 | assert(openapi.info.title === "API") 35 | val schemas = openapi.components.getOrElse(Components.Empty).schemas 36 | assert(schemas.nonEmpty) 37 | assert(schemas("anything_object") === AnySchema.Anything) 38 | assert(schemas("nothing_object") === AnySchema.Nothing) 39 | } 40 | 41 | test("all schemas types 3.1") { 42 | val Right(openapi) = readJson("/spec/3.1/schema.json").flatMap(_.as[OpenAPI]): @unchecked 43 | assert(openapi.info.title === "API") 44 | val schemas = openapi.components.getOrElse(Components.Empty).schemas 45 | assert(schemas.size === 13) 46 | } 47 | 48 | test("all schemas types 3.0") { 49 | val Right(openapi) = readJson("/spec/3.0/schema.json").flatMap(_.as[OpenAPI]): @unchecked 50 | assert(openapi.info.title === "API") 51 | val schemas = openapi.components.getOrElse(Components.Empty).schemas 52 | assert(schemas.size === 12) 53 | } 54 | 55 | test("decode security scheme with not empty scopes") { 56 | val expectedScopes = Some(Some(ListMap("example" -> "description"))) 57 | val expectedToken = Some(Some(Some("openapi-circe-token"))) 58 | 59 | val Right(securityScheme) = 60 | readJson("/securityScheme/security-scheme-with-scopes.json").flatMap(_.as[SecurityScheme]): @unchecked 61 | 62 | assert(securityScheme.flows.map(_.clientCredentials.map(_.tokenUrl)) === expectedToken) 63 | assert(securityScheme.flows.map(_.clientCredentials.map(_.scopes)) === expectedScopes) 64 | } 65 | 66 | test("decode security scheme with empty scopes") { 67 | val expectedScopes = Some(Some(ListMap.empty[String, String])) 68 | val expectedToken = Some(Some(Some("openapi-circe-token"))) 69 | 70 | val Right(securityScheme) = 71 | readJson("/securityScheme/security-scheme-with-empty-scopes.json").flatMap(_.as[SecurityScheme]): @unchecked 72 | 73 | assert(securityScheme.flows.map(_.clientCredentials.map(_.tokenUrl)) === expectedToken) 74 | assert(securityScheme.flows.map(_.clientCredentials.map(_.scopes)) === expectedScopes) 75 | } 76 | 77 | test("should decode callbacks pathitems successfully") { 78 | val Right(openapi) = readJson("/callbacks/callbacks.json").flatMap(_.as[OpenAPI]): @unchecked 79 | 80 | val pathItem = 81 | extractOrThrow(openapi.paths.pathItems.get("/pets"), "The specified path item '/pets' does not exist") 82 | val operation = extractOrThrow(pathItem.post, "The POST operation is not defined for the path '/pets'") 83 | val callback = extractOrThrow( 84 | operation.callbacks.get("onPetStatusChange"), 85 | "The callback 'onPetStatusChange' is not defined for the POST operation." 86 | ) 87 | 88 | val doesPathItemExist = callback.getOrElse(null).pathItems.contains("{$request.body#/callbackUrl}") 89 | 90 | assert(doesPathItemExist) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /openapi-circe/src/test/scala/sttp/apispec/openapi/circe/overridden/EncoderTest.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.openapi.circe.overridden 2 | 3 | import io.circe.syntax._ 4 | import sttp.apispec._ 5 | import sttp.apispec.openapi._ 6 | import org.scalatest.funsuite.AnyFunSuite 7 | import scala.collection.immutable.ListMap 8 | import sttp.apispec.test._ 9 | 10 | class EncoderTest extends AnyFunSuite with ResourcePlatform { 11 | override val basedir = "openapi-circe" 12 | def refOr[A](a: A): ReferenceOr[A] = Right(a) 13 | 14 | test("any boolean") { 15 | object obj extends sttp.apispec.openapi.circe.SttpOpenAPICirceEncoders 16 | import obj._ 17 | 18 | val components = Components( 19 | schemas = ListMap( 20 | "anything_boolean" -> AnySchema.Anything, 21 | "nothing_boolean" -> AnySchema.Nothing 22 | ) 23 | ) 24 | 25 | val openapi = OpenAPI( 26 | info = Info(title = "API", version = "1.0.0"), 27 | components = Some(components) 28 | ) 29 | 30 | val openApiJson = openapi.asJson 31 | val Right(json) = readJson("/spec/3.1/any_and_nothing1.json"): @unchecked 32 | 33 | assert(openApiJson.spaces2SortKeys == json.spaces2SortKeys) 34 | } 35 | 36 | test("any object") { 37 | object obj extends sttp.apispec.openapi.circe.SttpOpenAPICirceEncoders { 38 | override val anyObjectEncoding: AnySchema.Encoding = AnySchema.Encoding.Object 39 | } 40 | 41 | import obj._ 42 | 43 | val components = Components( 44 | schemas = ListMap( 45 | "anything_object" -> AnySchema.Anything, 46 | "nothing_object" -> AnySchema.Nothing 47 | ) 48 | ) 49 | 50 | val openapi = OpenAPI( 51 | info = Info(title = "API", version = "1.0.0"), 52 | components = Some(components) 53 | ) 54 | 55 | val openApiJson = openapi.asJson 56 | val Right(json) = readJson("/spec/3.1/any_and_nothing2.json"): @unchecked 57 | 58 | assert(openApiJson.spaces2SortKeys == json.spaces2SortKeys) 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-operation-callback/petstore-added-operation-callback.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.3", 3 | "info": { 4 | "title": "Simple Pet Store API", 5 | "version": "1.0.0" 6 | }, 7 | "paths": { 8 | "/pets": { 9 | "post": { 10 | "summary": "Add a new pet", 11 | "requestBody": { 12 | "required": true, 13 | "content": { 14 | "application/json": { 15 | "schema": { 16 | "type": "object", 17 | "properties": { 18 | "id": { 19 | "type": "integer" 20 | }, 21 | "name": { 22 | "type": "string" 23 | }, 24 | "tag": { 25 | "type": "string" 26 | } 27 | } 28 | } 29 | } 30 | } 31 | }, 32 | "responses": { 33 | "201": { 34 | "description": "Pet created successfully." 35 | } 36 | }, 37 | "callbacks": { 38 | "onPetStatusChange": { 39 | "{$request.body#/callbackUrl}": { 40 | "post": { 41 | "summary": "Notify about pet status change", 42 | "requestBody": { 43 | "required": true, 44 | "content": { 45 | "application/json": { 46 | "schema": { 47 | "type": "object", 48 | "properties": { 49 | "status": { 50 | "type": "string" 51 | }, 52 | "timestamp": { 53 | "type": "string", 54 | "format": "date-time" 55 | } 56 | } 57 | } 58 | } 59 | } 60 | }, 61 | "responses": { 62 | "200": { 63 | "description": "Callback successfully processed." 64 | } 65 | } 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-operation-callback/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.3", 3 | "info": { 4 | "title": "Simple Pet Store API", 5 | "version": "1.0.0" 6 | }, 7 | "paths": { 8 | "/pets": { 9 | "post": { 10 | "summary": "Add a new pet", 11 | "requestBody": { 12 | "required": true, 13 | "content": { 14 | "application/json": { 15 | "schema": { 16 | "type": "object", 17 | "properties": { 18 | "id": { 19 | "type": "integer" 20 | }, 21 | "name": { 22 | "type": "string" 23 | }, 24 | "tag": { 25 | "type": "string" 26 | } 27 | } 28 | } 29 | } 30 | } 31 | }, 32 | "responses": { 33 | "201": { 34 | "description": "Pet created successfully." 35 | } 36 | }, 37 | "callbacks": {} 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-operation/petstore-added-operation.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.3" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "responses": { 30 | "200": { 31 | "description": "Success", 32 | "content": { 33 | "application/json": { 34 | "schema": { 35 | "type": "array", 36 | "items": { 37 | "$ref": "#/components/schemas/Pet" 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | }, 45 | "post": { 46 | "operationId": "addPet", 47 | "description": "Add a new pet", 48 | "requestBody": { 49 | "required": true, 50 | "content": { 51 | "application/json": { 52 | "schema": { 53 | "$ref": "#/components/schemas/NewPet" 54 | } 55 | } 56 | } 57 | }, 58 | "responses": { 59 | "201": { 60 | "description": "Pet created", 61 | "content": { 62 | "application/json": { 63 | "schema": { 64 | "$ref": "#/components/schemas/Pet" 65 | } 66 | } 67 | } 68 | } 69 | } 70 | } 71 | }, 72 | "/pets/{petId}": { 73 | "get": { 74 | "operationId": "getPetById", 75 | "description": "Get a pet by its ID", 76 | "parameters": [ 77 | { 78 | "name": "petId", 79 | "in": "path", 80 | "required": true, 81 | "schema": { 82 | "type": "integer", 83 | "format": "int32" 84 | }, 85 | "description": "The ID of the pet to retrieve" 86 | } 87 | ], 88 | "responses": { 89 | "200": { 90 | "description": "Successful response", 91 | "content": { 92 | "application/json": { 93 | "schema": { 94 | "$ref": "#/components/schemas/Pet" 95 | } 96 | } 97 | } 98 | }, 99 | "404": { 100 | "description": "Pet not found" 101 | } 102 | } 103 | } 104 | } 105 | }, 106 | "components": { 107 | "schemas": { 108 | "Pet": { 109 | "type": "object", 110 | "properties": { 111 | "id": { 112 | "type": "integer", 113 | "format": "int32" 114 | }, 115 | "name": { 116 | "type": "string" 117 | } 118 | } 119 | }, 120 | "NewPet": { 121 | "type": "object", 122 | "properties": { 123 | "name": { 124 | "type": "string" 125 | } 126 | }, 127 | "required": [ 128 | "name" 129 | ] 130 | } 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-operation/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "responses": { 30 | "200": { 31 | "description": "Success", 32 | "content": { 33 | "application/json": { 34 | "schema": { 35 | "type": "array", 36 | "items": { 37 | "$ref": "#/components/schemas/Pet" 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | }, 46 | "/pets/{petId}": { 47 | "get": { 48 | "operationId": "getPetById", 49 | "description": "Get a pet by its ID", 50 | "parameters": [ 51 | { 52 | "name": "petId", 53 | "in": "path", 54 | "required": true, 55 | "schema": { 56 | "type": "integer", 57 | "format": "int32" 58 | }, 59 | "description": "The ID of the pet to retrieve" 60 | } 61 | ], 62 | "responses": { 63 | "200": { 64 | "description": "Successful response", 65 | "content": { 66 | "application/json": { 67 | "schema": { 68 | "$ref": "#/components/schemas/Pet" 69 | } 70 | } 71 | } 72 | }, 73 | "404": { 74 | "description": "Pet not found" 75 | } 76 | } 77 | } 78 | } 79 | }, 80 | "components": { 81 | "schemas": { 82 | "Pet": { 83 | "type": "object", 84 | "properties": { 85 | "id": { 86 | "type": "integer", 87 | "format": "int32" 88 | }, 89 | "name": { 90 | "type": "string" 91 | } 92 | } 93 | } 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype-schema/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.6" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "content": { 36 | "application/json": {} 37 | } 38 | } 39 | ], 40 | "responses": { 41 | "200": { 42 | "description": "Success", 43 | "content": { 44 | "application/json": { 45 | "schema": { 46 | "type": "array", 47 | "items": { 48 | "$ref": "#/components/schemas/Pet" 49 | } 50 | } 51 | } 52 | } 53 | } 54 | } 55 | }, 56 | "post": { 57 | "operationId": "addPet", 58 | "description": "Add a new pet", 59 | "requestBody": { 60 | "required": true, 61 | "content": { 62 | "application/json": { 63 | "schema": { 64 | "$ref": "#/components/schemas/NewPet" 65 | } 66 | } 67 | } 68 | }, 69 | "responses": { 70 | "201": { 71 | "description": "Pet created", 72 | "content": { 73 | "application/json": { 74 | "schema": { 75 | "$ref": "#/components/schemas/Pet" 76 | } 77 | } 78 | } 79 | } 80 | } 81 | } 82 | }, 83 | "/pets/{petId}": { 84 | "get": { 85 | "operationId": "getPetById", 86 | "description": "Get a pet by its ID", 87 | "parameters": [ 88 | { 89 | "name": "petId", 90 | "in": "path", 91 | "required": true, 92 | "schema": { 93 | "type": "integer", 94 | "format": "int32" 95 | }, 96 | "description": "The ID of the pet to retrieve" 97 | } 98 | ], 99 | "responses": { 100 | "200": { 101 | "description": "Successful response", 102 | "content": { 103 | "application/json": { 104 | "schema": { 105 | "$ref": "#/components/schemas/Pet" 106 | } 107 | } 108 | } 109 | }, 110 | "404": { 111 | "description": "Pet not found" 112 | } 113 | } 114 | } 115 | } 116 | }, 117 | "components": { 118 | "schemas": { 119 | "Pet": { 120 | "type": "object", 121 | "properties": { 122 | "id": { 123 | "type": "integer", 124 | "format": "int32" 125 | }, 126 | "name": { 127 | "type": "string" 128 | } 129 | } 130 | }, 131 | "NewPet": { 132 | "type": "object", 133 | "properties": { 134 | "name": { 135 | "type": "string" 136 | } 137 | }, 138 | "required": [ 139 | "name" 140 | ] 141 | } 142 | } 143 | } 144 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype/petstore-added-parameter-content-mediatype.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.6" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "content": { 36 | "application/json": { 37 | "schema": { 38 | "type": "array", 39 | "items": { 40 | "$ref": "#/components/schemas/Pet" 41 | } 42 | } 43 | } 44 | } 45 | } 46 | ], 47 | "responses": { 48 | "200": { 49 | "description": "Success", 50 | "content": { 51 | "application/json": { 52 | "schema": { 53 | "type": "array", 54 | "items": { 55 | "$ref": "#/components/schemas/Pet" 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | }, 63 | "post": { 64 | "operationId": "addPet", 65 | "description": "Add a new pet", 66 | "requestBody": { 67 | "required": true, 68 | "content": { 69 | "application/json": { 70 | "schema": { 71 | "$ref": "#/components/schemas/NewPet" 72 | } 73 | } 74 | } 75 | }, 76 | "responses": { 77 | "201": { 78 | "description": "Pet created", 79 | "content": { 80 | "application/json": { 81 | "schema": { 82 | "$ref": "#/components/schemas/Pet" 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } 89 | }, 90 | "/pets/{petId}": { 91 | "get": { 92 | "operationId": "getPetById", 93 | "description": "Get a pet by its ID", 94 | "parameters": [ 95 | { 96 | "name": "petId", 97 | "in": "path", 98 | "required": true, 99 | "schema": { 100 | "type": "integer", 101 | "format": "int32" 102 | }, 103 | "description": "The ID of the pet to retrieve" 104 | } 105 | ], 106 | "responses": { 107 | "200": { 108 | "description": "Successful response", 109 | "content": { 110 | "application/json": { 111 | "schema": { 112 | "$ref": "#/components/schemas/Pet" 113 | } 114 | } 115 | } 116 | }, 117 | "404": { 118 | "description": "Pet not found" 119 | } 120 | } 121 | } 122 | } 123 | }, 124 | "components": { 125 | "schemas": { 126 | "Pet": { 127 | "type": "object", 128 | "properties": { 129 | "id": { 130 | "type": "integer", 131 | "format": "int32" 132 | }, 133 | "name": { 134 | "type": "string" 135 | } 136 | } 137 | }, 138 | "NewPet": { 139 | "type": "object", 140 | "properties": { 141 | "name": { 142 | "type": "string" 143 | } 144 | }, 145 | "required": [ 146 | "name" 147 | ] 148 | } 149 | } 150 | } 151 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.5" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false 35 | } 36 | ], 37 | "responses": { 38 | "200": { 39 | "description": "Success", 40 | "content": { 41 | "application/json": { 42 | "schema": { 43 | "type": "array", 44 | "items": { 45 | "$ref": "#/components/schemas/Pet" 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } 52 | }, 53 | "post": { 54 | "operationId": "addPet", 55 | "description": "Add a new pet", 56 | "requestBody": { 57 | "required": true, 58 | "content": { 59 | "application/json": { 60 | "schema": { 61 | "$ref": "#/components/schemas/NewPet" 62 | } 63 | } 64 | } 65 | }, 66 | "responses": { 67 | "201": { 68 | "description": "Pet created", 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "$ref": "#/components/schemas/Pet" 73 | } 74 | } 75 | } 76 | } 77 | } 78 | } 79 | }, 80 | "/pets/{petId}": { 81 | "get": { 82 | "operationId": "getPetById", 83 | "description": "Get a pet by its ID", 84 | "parameters": [ 85 | { 86 | "name": "petId", 87 | "in": "path", 88 | "required": true, 89 | "schema": { 90 | "type": "integer", 91 | "format": "int32" 92 | }, 93 | "description": "The ID of the pet to retrieve" 94 | } 95 | ], 96 | "responses": { 97 | "200": { 98 | "description": "Successful response", 99 | "content": { 100 | "application/json": { 101 | "schema": { 102 | "$ref": "#/components/schemas/Pet" 103 | } 104 | } 105 | } 106 | }, 107 | "404": { 108 | "description": "Pet not found" 109 | } 110 | } 111 | } 112 | } 113 | }, 114 | "components": { 115 | "schemas": { 116 | "Pet": { 117 | "type": "object", 118 | "properties": { 119 | "id": { 120 | "type": "integer", 121 | "format": "int32" 122 | }, 123 | "name": { 124 | "type": "string" 125 | } 126 | } 127 | }, 128 | "NewPet": { 129 | "type": "object", 130 | "properties": { 131 | "name": { 132 | "type": "string" 133 | } 134 | }, 135 | "required": [ 136 | "name" 137 | ] 138 | } 139 | } 140 | } 141 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-parameter-schema/petstore-added-parameter-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.4" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "schema": { 36 | "type": "string", 37 | "enum": [ 38 | "available", 39 | "sold" 40 | ] 41 | } 42 | } 43 | ], 44 | "responses": { 45 | "200": { 46 | "description": "Success", 47 | "content": { 48 | "application/json": { 49 | "schema": { 50 | "type": "array", 51 | "items": { 52 | "$ref": "#/components/schemas/Pet" 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } 59 | }, 60 | "post": { 61 | "operationId": "addPet", 62 | "description": "Add a new pet", 63 | "requestBody": { 64 | "required": true, 65 | "content": { 66 | "application/json": { 67 | "schema": { 68 | "$ref": "#/components/schemas/NewPet" 69 | } 70 | } 71 | } 72 | }, 73 | "responses": { 74 | "201": { 75 | "description": "Pet created", 76 | "content": { 77 | "application/json": { 78 | "schema": { 79 | "$ref": "#/components/schemas/Pet" 80 | } 81 | } 82 | } 83 | } 84 | } 85 | } 86 | }, 87 | "/pets/{petId}": { 88 | "get": { 89 | "operationId": "getPetById", 90 | "description": "Get a pet by its ID", 91 | "parameters": [ 92 | { 93 | "name": "petId", 94 | "in": "path", 95 | "required": true, 96 | "schema": { 97 | "type": "integer", 98 | "format": "int32" 99 | }, 100 | "description": "The ID of the pet to retrieve" 101 | } 102 | ], 103 | "responses": { 104 | "200": { 105 | "description": "Successful response", 106 | "content": { 107 | "application/json": { 108 | "schema": { 109 | "$ref": "#/components/schemas/Pet" 110 | } 111 | } 112 | } 113 | }, 114 | "404": { 115 | "description": "Pet not found" 116 | } 117 | } 118 | } 119 | } 120 | }, 121 | "components": { 122 | "schemas": { 123 | "Pet": { 124 | "type": "object", 125 | "properties": { 126 | "id": { 127 | "type": "integer", 128 | "format": "int32" 129 | }, 130 | "name": { 131 | "type": "string" 132 | } 133 | } 134 | }, 135 | "NewPet": { 136 | "type": "object", 137 | "properties": { 138 | "name": { 139 | "type": "string" 140 | } 141 | }, 142 | "required": [ 143 | "name" 144 | ] 145 | } 146 | } 147 | } 148 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-parameter-schema/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.4" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false 35 | } 36 | ], 37 | "responses": { 38 | "200": { 39 | "description": "Success", 40 | "content": { 41 | "application/json": { 42 | "schema": { 43 | "type": "array", 44 | "items": { 45 | "$ref": "#/components/schemas/Pet" 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } 52 | }, 53 | "post": { 54 | "operationId": "addPet", 55 | "description": "Add a new pet", 56 | "requestBody": { 57 | "required": true, 58 | "content": { 59 | "application/json": { 60 | "schema": { 61 | "$ref": "#/components/schemas/NewPet" 62 | } 63 | } 64 | } 65 | }, 66 | "responses": { 67 | "201": { 68 | "description": "Pet created", 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "$ref": "#/components/schemas/Pet" 73 | } 74 | } 75 | } 76 | } 77 | } 78 | } 79 | }, 80 | "/pets/{petId}": { 81 | "get": { 82 | "operationId": "getPetById", 83 | "description": "Get a pet by its ID", 84 | "parameters": [ 85 | { 86 | "name": "petId", 87 | "in": "path", 88 | "required": true, 89 | "schema": { 90 | "type": "integer", 91 | "format": "int32" 92 | }, 93 | "description": "The ID of the pet to retrieve" 94 | } 95 | ], 96 | "responses": { 97 | "200": { 98 | "description": "Successful response", 99 | "content": { 100 | "application/json": { 101 | "schema": { 102 | "$ref": "#/components/schemas/Pet" 103 | } 104 | } 105 | } 106 | }, 107 | "404": { 108 | "description": "Pet not found" 109 | } 110 | } 111 | } 112 | } 113 | }, 114 | "components": { 115 | "schemas": { 116 | "Pet": { 117 | "type": "object", 118 | "properties": { 119 | "id": { 120 | "type": "integer", 121 | "format": "int32" 122 | }, 123 | "name": { 124 | "type": "string" 125 | } 126 | } 127 | }, 128 | "NewPet": { 129 | "type": "object", 130 | "properties": { 131 | "name": { 132 | "type": "string" 133 | } 134 | }, 135 | "required": [ 136 | "name" 137 | ] 138 | } 139 | } 140 | } 141 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-parameter/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.3" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "responses": { 30 | "200": { 31 | "description": "Success", 32 | "content": { 33 | "application/json": { 34 | "schema": { 35 | "type": "array", 36 | "items": { 37 | "$ref": "#/components/schemas/Pet" 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | }, 45 | "post": { 46 | "operationId": "addPet", 47 | "description": "Add a new pet", 48 | "requestBody": { 49 | "required": true, 50 | "content": { 51 | "application/json": { 52 | "schema": { 53 | "$ref": "#/components/schemas/NewPet" 54 | } 55 | } 56 | } 57 | }, 58 | "responses": { 59 | "201": { 60 | "description": "Pet created", 61 | "content": { 62 | "application/json": { 63 | "schema": { 64 | "$ref": "#/components/schemas/Pet" 65 | } 66 | } 67 | } 68 | } 69 | } 70 | } 71 | }, 72 | "/pets/{petId}": { 73 | "get": { 74 | "operationId": "getPetById", 75 | "description": "Get a pet by its ID", 76 | "parameters": [ 77 | { 78 | "name": "petId", 79 | "in": "path", 80 | "required": true, 81 | "schema": { 82 | "type": "integer", 83 | "format": "int32" 84 | }, 85 | "description": "The ID of the pet to retrieve" 86 | } 87 | ], 88 | "responses": { 89 | "200": { 90 | "description": "Successful response", 91 | "content": { 92 | "application/json": { 93 | "schema": { 94 | "$ref": "#/components/schemas/Pet" 95 | } 96 | } 97 | } 98 | }, 99 | "404": { 100 | "description": "Pet not found" 101 | } 102 | } 103 | } 104 | } 105 | }, 106 | "components": { 107 | "schemas": { 108 | "Pet": { 109 | "type": "object", 110 | "properties": { 111 | "id": { 112 | "type": "integer", 113 | "format": "int32" 114 | }, 115 | "name": { 116 | "type": "string" 117 | } 118 | } 119 | }, 120 | "NewPet": { 121 | "type": "object", 122 | "properties": { 123 | "name": { 124 | "type": "string" 125 | } 126 | }, 127 | "required": [ 128 | "name" 129 | ] 130 | } 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-path/petstore-added-path.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "responses": { 30 | "200": { 31 | "description": "Success", 32 | "content": { 33 | "application/json": { 34 | "schema": { 35 | "type": "array", 36 | "items": { 37 | "$ref": "#/components/schemas/Pet" 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | }, 46 | "/pets/{petId}": { 47 | "get": { 48 | "operationId": "getPetById", 49 | "description": "Get a pet by its ID", 50 | "parameters": [ 51 | { 52 | "name": "petId", 53 | "in": "path", 54 | "required": true, 55 | "schema": { 56 | "type": "integer", 57 | "format": "int32" 58 | }, 59 | "description": "The ID of the pet to retrieve" 60 | } 61 | ], 62 | "responses": { 63 | "200": { 64 | "description": "Successful response", 65 | "content": { 66 | "application/json": { 67 | "schema": { 68 | "$ref": "#/components/schemas/Pet" 69 | } 70 | } 71 | } 72 | }, 73 | "404": { 74 | "description": "Pet not found" 75 | } 76 | } 77 | } 78 | } 79 | }, 80 | "components": { 81 | "schemas": { 82 | "Pet": { 83 | "type": "object", 84 | "properties": { 85 | "id": { 86 | "type": "integer", 87 | "format": "int32" 88 | }, 89 | "name": { 90 | "type": "string" 91 | } 92 | } 93 | } 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-path/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.1" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "responses": { 30 | "200": { 31 | "description": "Success", 32 | "content": { 33 | "application/json": { 34 | "schema": { 35 | "type": "array", 36 | "items": { 37 | "$ref": "#/components/schemas/Pet" 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | }, 47 | "components": { 48 | "schemas": { 49 | "Pet": { 50 | "type": "object", 51 | "properties": { 52 | "id": { 53 | "type": "integer", 54 | "format": "int32" 55 | }, 56 | "name": { 57 | "type": "string" 58 | } 59 | } 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-encoding/petstore-added-requestbody-content-mediatype-encoding.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.3", 3 | "info": { 4 | "title": "Simple Pet Store API", 5 | "version": "1.0.0" 6 | }, 7 | "paths": { 8 | "/pets": { 9 | "post": { 10 | "summary": "Add a new pet", 11 | "requestBody": { 12 | "required": true, 13 | "content": { 14 | "multipart/form-data": { 15 | "schema": { 16 | "type": "object", 17 | "properties": { 18 | "id": { 19 | "type": "integer" 20 | }, 21 | "name": { 22 | "type": "string" 23 | }, 24 | "photo": { 25 | "type": "string", 26 | "format": "binary" 27 | } 28 | } 29 | }, 30 | "encoding": { 31 | "photo": { 32 | "contentType": "image/jpeg" 33 | } 34 | } 35 | } 36 | } 37 | }, 38 | "responses": { 39 | "201": { 40 | "description": "Pet created successfully.", 41 | "content": { 42 | "application/json": { 43 | "schema": { 44 | "type": "object", 45 | "properties": { 46 | "id": { 47 | "type": "integer" 48 | }, 49 | "name": { 50 | "type": "string" 51 | }, 52 | "tag": { 53 | "type": "string" 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-encoding/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.3", 3 | "info": { 4 | "title": "Simple Pet Store API", 5 | "version": "1.0.0" 6 | }, 7 | "paths": { 8 | "/pets": { 9 | "post": { 10 | "summary": "Add a new pet", 11 | "requestBody": { 12 | "required": true, 13 | "content": { 14 | "multipart/form-data": { 15 | "schema": { 16 | "type": "object", 17 | "properties": { 18 | "id": { 19 | "type": "integer" 20 | }, 21 | "name": { 22 | "type": "string" 23 | }, 24 | "photo": { 25 | "type": "string", 26 | "format": "binary" 27 | } 28 | } 29 | }, 30 | "encoding": {} 31 | } 32 | } 33 | }, 34 | "responses": { 35 | "201": { 36 | "description": "Pet created successfully.", 37 | "content": { 38 | "application/json": { 39 | "schema": { 40 | "type": "object", 41 | "properties": { 42 | "id": { 43 | "type": "integer" 44 | }, 45 | "name": { 46 | "type": "string" 47 | }, 48 | "tag": { 49 | "type": "string" 50 | } 51 | } 52 | } 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-schema/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "content": { 36 | "application/json": { 37 | "schema": { 38 | "type": "string" 39 | } 40 | } 41 | } 42 | } 43 | ], 44 | "responses": { 45 | "200": { 46 | "description": "Success", 47 | "content": { 48 | "application/json": { 49 | "schema": { 50 | "type": "array", 51 | "items": { 52 | "$ref": "#/components/schemas/Pet" 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } 59 | }, 60 | "post": { 61 | "operationId": "addPet", 62 | "description": "Add a new pet", 63 | "requestBody": { 64 | "required": true, 65 | "content": { 66 | "application/json": {} 67 | } 68 | }, 69 | "responses": { 70 | "201": { 71 | "description": "Pet created", 72 | "content": { 73 | "application/json": { 74 | "schema": { 75 | "$ref": "#/components/schemas/Pet" 76 | } 77 | } 78 | } 79 | } 80 | } 81 | } 82 | }, 83 | "/pets/{petId}": { 84 | "get": { 85 | "operationId": "getPetById", 86 | "description": "Get a pet by its ID", 87 | "parameters": [ 88 | { 89 | "name": "petId", 90 | "in": "path", 91 | "required": true, 92 | "schema": { 93 | "type": "integer", 94 | "format": "int32" 95 | }, 96 | "description": "The ID of the pet to retrieve" 97 | } 98 | ], 99 | "responses": { 100 | "200": { 101 | "description": "Successful response", 102 | "content": { 103 | "application/json": { 104 | "schema": { 105 | "$ref": "#/components/schemas/Pet" 106 | } 107 | } 108 | } 109 | }, 110 | "404": { 111 | "description": "Pet not found" 112 | } 113 | } 114 | } 115 | } 116 | }, 117 | "components": { 118 | "schemas": { 119 | "Pet": { 120 | "type": "object", 121 | "properties": { 122 | "id": { 123 | "type": "integer", 124 | "format": "int32" 125 | }, 126 | "name": { 127 | "type": "string" 128 | }, 129 | "breed": { 130 | "type": "string", 131 | "description": "The breed of the pet" 132 | } 133 | } 134 | }, 135 | "NewPet": { 136 | "type": "object", 137 | "properties": { 138 | "name": { 139 | "type": "string" 140 | } 141 | }, 142 | "required": [ 143 | "name" 144 | ] 145 | }, 146 | "UpdatedPet": { 147 | "type": "object", 148 | "properties": { 149 | "name": { 150 | "type": "string" 151 | }, 152 | "breed": { 153 | "type": "string" 154 | } 155 | }, 156 | "required": [ 157 | "name" 158 | ] 159 | } 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype/petstore-added-requestbody-content-mediatype.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "$ref": "#/components/schemas/NewPet" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | } 121 | } 122 | }, 123 | "404": { 124 | "description": "Pet not found" 125 | } 126 | } 127 | } 128 | } 129 | }, 130 | "components": { 131 | "schemas": { 132 | "Pet": { 133 | "type": "object", 134 | "properties": { 135 | "id": { 136 | "type": "integer", 137 | "format": "int32" 138 | }, 139 | "name": { 140 | "type": "string" 141 | }, 142 | "breed": { 143 | "type": "string", 144 | "description": "The breed of the pet" 145 | } 146 | } 147 | }, 148 | "NewPet": { 149 | "type": "object", 150 | "properties": { 151 | "name": { 152 | "type": "string" 153 | } 154 | }, 155 | "required": [ 156 | "name" 157 | ] 158 | }, 159 | "UpdatedPet": { 160 | "type": "object", 161 | "properties": { 162 | "name": { 163 | "type": "string" 164 | }, 165 | "breed": { 166 | "type": "string" 167 | } 168 | }, 169 | "required": [ 170 | "name" 171 | ] 172 | } 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-requestbody/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "responses": { 68 | "201": { 69 | "description": "Pet created", 70 | "content": { 71 | "application/json": { 72 | "schema": { 73 | "$ref": "#/components/schemas/Pet" 74 | } 75 | } 76 | } 77 | } 78 | } 79 | } 80 | }, 81 | "/pets/{petId}": { 82 | "get": { 83 | "operationId": "getPetById", 84 | "description": "Get a pet by its ID", 85 | "parameters": [ 86 | { 87 | "name": "petId", 88 | "in": "path", 89 | "required": true, 90 | "schema": { 91 | "type": "integer", 92 | "format": "int32" 93 | }, 94 | "description": "The ID of the pet to retrieve" 95 | } 96 | ], 97 | "responses": { 98 | "200": { 99 | "description": "Successful response", 100 | "content": { 101 | "application/json": { 102 | "schema": { 103 | "$ref": "#/components/schemas/Pet" 104 | } 105 | }, 106 | "application/xml": { 107 | "schema": { 108 | "type": "string" 109 | } 110 | } 111 | }, 112 | "headers": { 113 | "X-Rate-Limit": { 114 | "description": "The number of requests allowed per hour", 115 | "style": "form", 116 | "explode": true, 117 | "allowEmptyValue": true, 118 | "allowReserved": true, 119 | "content": { 120 | "application/json": { 121 | "schema": { 122 | "type": "integer" 123 | } 124 | } 125 | } 126 | } 127 | } 128 | }, 129 | "404": { 130 | "description": "Pet not found" 131 | }, 132 | "500": { 133 | "description": "Internal Error" 134 | } 135 | } 136 | } 137 | } 138 | }, 139 | "components": { 140 | "schemas": { 141 | "Pet": { 142 | "type": "object", 143 | "properties": { 144 | "id": { 145 | "type": "integer", 146 | "format": "int32" 147 | }, 148 | "name": { 149 | "type": "string" 150 | }, 151 | "breed": { 152 | "type": "string", 153 | "description": "The breed of the pet" 154 | } 155 | } 156 | }, 157 | "NewPet": { 158 | "type": "object", 159 | "properties": { 160 | "name": { 161 | "type": "string" 162 | } 163 | }, 164 | "required": [ 165 | "name" 166 | ] 167 | }, 168 | "UpdatedPet": { 169 | "type": "object", 170 | "properties": { 171 | "name": { 172 | "type": "string" 173 | }, 174 | "breed": { 175 | "type": "string" 176 | } 177 | }, 178 | "required": [ 179 | "name" 180 | ] 181 | } 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype-schema/petstore-added-response-content-mediatype-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "type": "string" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | } 121 | } 122 | }, 123 | "404": { 124 | "description": "Pet not found" 125 | }, 126 | "500": { 127 | "description": "Internal Error" 128 | } 129 | } 130 | } 131 | } 132 | }, 133 | "components": { 134 | "schemas": { 135 | "Pet": { 136 | "type": "object", 137 | "properties": { 138 | "id": { 139 | "type": "integer", 140 | "format": "int32" 141 | }, 142 | "name": { 143 | "type": "string" 144 | }, 145 | "breed": { 146 | "type": "string", 147 | "description": "The breed of the pet" 148 | } 149 | } 150 | }, 151 | "NewPet": { 152 | "type": "object", 153 | "properties": { 154 | "name": { 155 | "type": "string" 156 | } 157 | }, 158 | "required": [ 159 | "name" 160 | ] 161 | }, 162 | "UpdatedPet": { 163 | "type": "object", 164 | "properties": { 165 | "name": { 166 | "type": "string" 167 | }, 168 | "breed": { 169 | "type": "string" 170 | } 171 | }, 172 | "required": [ 173 | "name" 174 | ] 175 | } 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype-schema/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "type": "string" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": {} 117 | } 118 | }, 119 | "404": { 120 | "description": "Pet not found" 121 | }, 122 | "500": { 123 | "description": "Internal Error" 124 | } 125 | } 126 | } 127 | } 128 | }, 129 | "components": { 130 | "schemas": { 131 | "Pet": { 132 | "type": "object", 133 | "properties": { 134 | "id": { 135 | "type": "integer", 136 | "format": "int32" 137 | }, 138 | "name": { 139 | "type": "string" 140 | }, 141 | "breed": { 142 | "type": "string", 143 | "description": "The breed of the pet" 144 | } 145 | } 146 | }, 147 | "NewPet": { 148 | "type": "object", 149 | "properties": { 150 | "name": { 151 | "type": "string" 152 | } 153 | }, 154 | "required": [ 155 | "name" 156 | ] 157 | }, 158 | "UpdatedPet": { 159 | "type": "object", 160 | "properties": { 161 | "name": { 162 | "type": "string" 163 | }, 164 | "breed": { 165 | "type": "string" 166 | } 167 | }, 168 | "required": [ 169 | "name" 170 | ] 171 | } 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype/petstore-added-response-content-mediatype.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "type": "string" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | }, 121 | "application/xml": { 122 | "schema": { 123 | "$ref": "#/components/schemas/Pet" 124 | } 125 | } 126 | } 127 | }, 128 | "404": { 129 | "description": "Pet not found" 130 | }, 131 | "500": { 132 | "description": "Internal Error" 133 | } 134 | } 135 | } 136 | } 137 | }, 138 | "components": { 139 | "schemas": { 140 | "Pet": { 141 | "type": "object", 142 | "properties": { 143 | "id": { 144 | "type": "integer", 145 | "format": "int32" 146 | }, 147 | "name": { 148 | "type": "string" 149 | }, 150 | "breed": { 151 | "type": "string", 152 | "description": "The breed of the pet" 153 | } 154 | } 155 | }, 156 | "NewPet": { 157 | "type": "object", 158 | "properties": { 159 | "name": { 160 | "type": "string" 161 | } 162 | }, 163 | "required": [ 164 | "name" 165 | ] 166 | }, 167 | "UpdatedPet": { 168 | "type": "object", 169 | "properties": { 170 | "name": { 171 | "type": "string" 172 | }, 173 | "breed": { 174 | "type": "string" 175 | } 176 | }, 177 | "required": [ 178 | "name" 179 | ] 180 | } 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "type": "string" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | } 121 | } 122 | }, 123 | "404": { 124 | "description": "Pet not found" 125 | }, 126 | "500": { 127 | "description": "Internal Error" 128 | } 129 | } 130 | } 131 | } 132 | }, 133 | "components": { 134 | "schemas": { 135 | "Pet": { 136 | "type": "object", 137 | "properties": { 138 | "id": { 139 | "type": "integer", 140 | "format": "int32" 141 | }, 142 | "name": { 143 | "type": "string" 144 | }, 145 | "breed": { 146 | "type": "string", 147 | "description": "The breed of the pet" 148 | } 149 | } 150 | }, 151 | "NewPet": { 152 | "type": "object", 153 | "properties": { 154 | "name": { 155 | "type": "string" 156 | } 157 | }, 158 | "required": [ 159 | "name" 160 | ] 161 | }, 162 | "UpdatedPet": { 163 | "type": "object", 164 | "properties": { 165 | "name": { 166 | "type": "string" 167 | }, 168 | "breed": { 169 | "type": "string" 170 | } 171 | }, 172 | "required": [ 173 | "name" 174 | ] 175 | } 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-response-header-schema/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "type": "string" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | }, 121 | "application/xml": { 122 | "schema": { 123 | "type": "string" 124 | } 125 | } 126 | }, 127 | "headers": { 128 | "X-Rate-Limit": { 129 | "description": "The number of requests allowed per hour" 130 | } 131 | } 132 | }, 133 | "404": { 134 | "description": "Pet not found" 135 | }, 136 | "500": { 137 | "description": "Internal Error" 138 | } 139 | } 140 | } 141 | } 142 | }, 143 | "components": { 144 | "schemas": { 145 | "Pet": { 146 | "type": "object", 147 | "properties": { 148 | "id": { 149 | "type": "integer", 150 | "format": "int32" 151 | }, 152 | "name": { 153 | "type": "string" 154 | }, 155 | "breed": { 156 | "type": "string", 157 | "description": "The breed of the pet" 158 | } 159 | } 160 | }, 161 | "NewPet": { 162 | "type": "object", 163 | "properties": { 164 | "name": { 165 | "type": "string" 166 | } 167 | }, 168 | "required": [ 169 | "name" 170 | ] 171 | }, 172 | "UpdatedPet": { 173 | "type": "object", 174 | "properties": { 175 | "name": { 176 | "type": "string" 177 | }, 178 | "breed": { 179 | "type": "string" 180 | } 181 | }, 182 | "required": [ 183 | "name" 184 | ] 185 | } 186 | } 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-response-header/petstore-added-response-header.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "type": "string" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | }, 121 | "application/xml": { 122 | "schema": { 123 | "type": "string" 124 | } 125 | } 126 | }, 127 | "headers": { 128 | "X-Rate-Limit": { 129 | "description": "The number of requests allowed per hour", 130 | "schema": { 131 | "type": "integer" 132 | } 133 | } 134 | } 135 | }, 136 | "404": { 137 | "description": "Pet not found" 138 | }, 139 | "500": { 140 | "description": "Internal Error" 141 | } 142 | } 143 | } 144 | } 145 | }, 146 | "components": { 147 | "schemas": { 148 | "Pet": { 149 | "type": "object", 150 | "properties": { 151 | "id": { 152 | "type": "integer", 153 | "format": "int32" 154 | }, 155 | "name": { 156 | "type": "string" 157 | }, 158 | "breed": { 159 | "type": "string", 160 | "description": "The breed of the pet" 161 | } 162 | } 163 | }, 164 | "NewPet": { 165 | "type": "object", 166 | "properties": { 167 | "name": { 168 | "type": "string" 169 | } 170 | }, 171 | "required": [ 172 | "name" 173 | ] 174 | }, 175 | "UpdatedPet": { 176 | "type": "object", 177 | "properties": { 178 | "name": { 179 | "type": "string" 180 | }, 181 | "breed": { 182 | "type": "string" 183 | } 184 | }, 185 | "required": [ 186 | "name" 187 | ] 188 | } 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-response-header/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "type": "string" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | }, 121 | "application/xml": { 122 | "schema": { 123 | "type": "string" 124 | } 125 | } 126 | } 127 | }, 128 | "404": { 129 | "description": "Pet not found" 130 | }, 131 | "500": { 132 | "description": "Internal Error" 133 | } 134 | } 135 | } 136 | } 137 | }, 138 | "components": { 139 | "schemas": { 140 | "Pet": { 141 | "type": "object", 142 | "properties": { 143 | "id": { 144 | "type": "integer", 145 | "format": "int32" 146 | }, 147 | "name": { 148 | "type": "string" 149 | }, 150 | "breed": { 151 | "type": "string", 152 | "description": "The breed of the pet" 153 | } 154 | } 155 | }, 156 | "NewPet": { 157 | "type": "object", 158 | "properties": { 159 | "name": { 160 | "type": "string" 161 | } 162 | }, 163 | "required": [ 164 | "name" 165 | ] 166 | }, 167 | "UpdatedPet": { 168 | "type": "object", 169 | "properties": { 170 | "name": { 171 | "type": "string" 172 | }, 173 | "breed": { 174 | "type": "string" 175 | } 176 | }, 177 | "required": [ 178 | "name" 179 | ] 180 | } 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/added-response/petstore-added-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "type": "string" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | } 121 | } 122 | }, 123 | "404": { 124 | "description": "Pet not found" 125 | }, 126 | "500": { 127 | "description": "Internal Error" 128 | } 129 | } 130 | } 131 | } 132 | }, 133 | "components": { 134 | "schemas": { 135 | "Pet": { 136 | "type": "object", 137 | "properties": { 138 | "id": { 139 | "type": "integer", 140 | "format": "int32" 141 | }, 142 | "name": { 143 | "type": "string" 144 | }, 145 | "breed": { 146 | "type": "string", 147 | "description": "The breed of the pet" 148 | } 149 | } 150 | }, 151 | "NewPet": { 152 | "type": "object", 153 | "properties": { 154 | "name": { 155 | "type": "string" 156 | } 157 | }, 158 | "required": [ 159 | "name" 160 | ] 161 | }, 162 | "UpdatedPet": { 163 | "type": "object", 164 | "properties": { 165 | "name": { 166 | "type": "string" 167 | }, 168 | "breed": { 169 | "type": "string" 170 | } 171 | }, 172 | "required": [ 173 | "name" 174 | ] 175 | } 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/required-parameter/petstore-required-parameter.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "responses": { 30 | "200": { 31 | "description": "Success", 32 | "content": { 33 | "application/json": { 34 | "schema": { 35 | "type": "array", 36 | "items": { 37 | "$ref": "#/components/schemas/Pet" 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | }, 46 | "/pets/{petId}": { 47 | "get": { 48 | "operationId": "getPetById", 49 | "description": "Get a pet by its ID", 50 | "parameters": [ 51 | { 52 | "name": "petId", 53 | "in": "path", 54 | "required": true, 55 | "schema": { 56 | "type": "integer", 57 | "format": "int32" 58 | }, 59 | "description": "The ID of the pet to retrieve" 60 | } 61 | ], 62 | "responses": { 63 | "200": { 64 | "description": "Successful response", 65 | "content": { 66 | "application/json": { 67 | "schema": { 68 | "$ref": "#/components/schemas/Pet" 69 | } 70 | } 71 | } 72 | }, 73 | "404": { 74 | "description": "Pet not found" 75 | } 76 | } 77 | } 78 | } 79 | }, 80 | "components": { 81 | "schemas": { 82 | "Pet": { 83 | "type": "object", 84 | "properties": { 85 | "id": { 86 | "type": "integer", 87 | "format": "int32" 88 | }, 89 | "name": { 90 | "type": "string" 91 | } 92 | } 93 | } 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/required-parameter/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "responses": { 30 | "200": { 31 | "description": "Success", 32 | "content": { 33 | "application/json": { 34 | "schema": { 35 | "type": "array", 36 | "items": { 37 | "$ref": "#/components/schemas/Pet" 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | }, 46 | "/pets/{petId}": { 47 | "get": { 48 | "operationId": "getPetById", 49 | "description": "Get a pet by its ID", 50 | "parameters": [ 51 | { 52 | "name": "petId", 53 | "in": "path", 54 | "required": false, 55 | "schema": { 56 | "type": "integer", 57 | "format": "int32" 58 | }, 59 | "description": "The ID of the pet to retrieve" 60 | } 61 | ], 62 | "responses": { 63 | "200": { 64 | "description": "Successful response", 65 | "content": { 66 | "application/json": { 67 | "schema": { 68 | "$ref": "#/components/schemas/Pet" 69 | } 70 | } 71 | } 72 | }, 73 | "404": { 74 | "description": "Pet not found" 75 | } 76 | } 77 | } 78 | } 79 | }, 80 | "components": { 81 | "schemas": { 82 | "Pet": { 83 | "type": "object", 84 | "properties": { 85 | "id": { 86 | "type": "integer", 87 | "format": "int32" 88 | }, 89 | "name": { 90 | "type": "string" 91 | } 92 | } 93 | } 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/required-request-body/petstore-required-request-body.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "$ref": "#/components/schemas/NewPet" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | } 121 | } 122 | }, 123 | "404": { 124 | "description": "Pet not found" 125 | } 126 | } 127 | } 128 | } 129 | }, 130 | "components": { 131 | "schemas": { 132 | "Pet": { 133 | "type": "object", 134 | "properties": { 135 | "id": { 136 | "type": "integer", 137 | "format": "int32" 138 | }, 139 | "name": { 140 | "type": "string" 141 | }, 142 | "breed": { 143 | "type": "string", 144 | "description": "The breed of the pet" 145 | } 146 | } 147 | }, 148 | "NewPet": { 149 | "type": "object", 150 | "properties": { 151 | "name": { 152 | "type": "string" 153 | } 154 | }, 155 | "required": [ 156 | "name" 157 | ] 158 | }, 159 | "UpdatedPet": { 160 | "type": "object", 161 | "properties": { 162 | "name": { 163 | "type": "string" 164 | }, 165 | "breed": { 166 | "type": "string" 167 | } 168 | }, 169 | "required": [ 170 | "name" 171 | ] 172 | } 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/required-request-body/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": false, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "$ref": "#/components/schemas/NewPet" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | } 121 | } 122 | }, 123 | "404": { 124 | "description": "Pet not found" 125 | } 126 | } 127 | } 128 | } 129 | }, 130 | "components": { 131 | "schemas": { 132 | "Pet": { 133 | "type": "object", 134 | "properties": { 135 | "id": { 136 | "type": "integer", 137 | "format": "int32" 138 | }, 139 | "name": { 140 | "type": "string" 141 | }, 142 | "breed": { 143 | "type": "string", 144 | "description": "The breed of the pet" 145 | } 146 | } 147 | }, 148 | "NewPet": { 149 | "type": "object", 150 | "properties": { 151 | "name": { 152 | "type": "string" 153 | } 154 | }, 155 | "required": [ 156 | "name" 157 | ] 158 | }, 159 | "UpdatedPet": { 160 | "type": "object", 161 | "properties": { 162 | "name": { 163 | "type": "string" 164 | }, 165 | "breed": { 166 | "type": "string" 167 | } 168 | }, 169 | "required": [ 170 | "name" 171 | ] 172 | } 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/updated-operation-callback/petstore-updated-operation-callback.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.3", 3 | "info": { 4 | "title": "Simple Pet Store API", 5 | "version": "1.0.0" 6 | }, 7 | "paths": { 8 | "/pets": { 9 | "post": { 10 | "summary": "Add a new pet", 11 | "requestBody": { 12 | "required": true, 13 | "content": { 14 | "application/json": { 15 | "schema": { 16 | "type": "object", 17 | "properties": { 18 | "id": { 19 | "type": "integer" 20 | }, 21 | "name": { 22 | "type": "string" 23 | }, 24 | "tag": { 25 | "type": "string" 26 | } 27 | } 28 | } 29 | } 30 | } 31 | }, 32 | "responses": { 33 | "201": { 34 | "description": "Pet created successfully." 35 | } 36 | }, 37 | "callbacks": { 38 | "onPetStatusChange": { 39 | "{$request.body#/callbackUrl}": { 40 | "post": { 41 | "summary": "Notify about pet status change", 42 | "description": "This callback is triggered whenever the status of a pet changes.", 43 | "requestBody": { 44 | "required": true, 45 | "content": { 46 | "application/json": { 47 | "schema": { 48 | "type": "object", 49 | "properties": { 50 | "status": { 51 | "type": "string", 52 | "description": "The new status of the pet.", 53 | "enum": [ 54 | "available", 55 | "pending", 56 | "sold" 57 | ] 58 | }, 59 | "timestamp": { 60 | "type": "string", 61 | "format": "date-time", 62 | "description": "The time when the status change occurred." 63 | }, 64 | "petId": { 65 | "type": "integer", 66 | "description": "The unique ID of the pet whose status changed." 67 | } 68 | }, 69 | "required": [ 70 | "status", 71 | "timestamp", 72 | "petId" 73 | ] 74 | } 75 | } 76 | } 77 | }, 78 | "responses": { 79 | "200": { 80 | "description": "Callback successfully processed." 81 | }, 82 | "400": { 83 | "description": "Invalid payload provided.", 84 | "content": { 85 | "application/json": { 86 | "schema": { 87 | "type": "object", 88 | "properties": { 89 | "error": { 90 | "type": "string", 91 | "description": "Details about the error." 92 | } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/updated-operation-callback/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.3", 3 | "info": { 4 | "title": "Simple Pet Store API", 5 | "version": "1.0.0" 6 | }, 7 | "paths": { 8 | "/pets": { 9 | "post": { 10 | "summary": "Add a new pet", 11 | "requestBody": { 12 | "required": true, 13 | "content": { 14 | "application/json": { 15 | "schema": { 16 | "type": "object", 17 | "properties": { 18 | "id": { 19 | "type": "integer" 20 | }, 21 | "name": { 22 | "type": "string" 23 | }, 24 | "tag": { 25 | "type": "string" 26 | } 27 | } 28 | } 29 | } 30 | } 31 | }, 32 | "responses": { 33 | "201": { 34 | "description": "Pet created successfully." 35 | } 36 | }, 37 | "callbacks": { 38 | "onPetStatusChange": { 39 | "{$request.body#/callbackUrl}": { 40 | "post": { 41 | "summary": "Notify about pet status change", 42 | "description": "This callback is triggered whenever the status of a pet changes.", 43 | "requestBody": { 44 | "required": true, 45 | "content": { 46 | "application/json": { 47 | "schema": { 48 | "type": "object", 49 | "properties": { 50 | "status": { 51 | "type": "string", 52 | "description": "The new status of the pet.", 53 | "enum": [ 54 | "available", 55 | "pending", 56 | "sold" 57 | ] 58 | }, 59 | "timestamp": { 60 | "type": "string", 61 | "format": "date-time", 62 | "description": "The time when the status change occurred." 63 | }, 64 | "petId": { 65 | "type": "integer", 66 | "description": "The unique ID of the pet whose status changed." 67 | } 68 | }, 69 | "required": [ 70 | "status", 71 | "timestamp", 72 | "petId" 73 | ] 74 | } 75 | } 76 | } 77 | }, 78 | "responses": { 79 | "200": { 80 | "description": "Callback successfully processed." 81 | } 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/updated-operation-security/petstore-updated-operation-security.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.3", 3 | "info": { 4 | "title": "Simple Pet Store API", 5 | "version": "1.0.0" 6 | }, 7 | "paths": { 8 | "/pets": { 9 | "get": { 10 | "summary": "Get a list of pets", 11 | "security": [ 12 | { 13 | "OAuth2": [ 14 | "read:pets", 15 | "write:pets" 16 | ] 17 | } 18 | ], 19 | "responses": { 20 | "200": { 21 | "description": "A list of pets.", 22 | "content": { 23 | "application/json": { 24 | "schema": { 25 | "type": "array", 26 | "items": { 27 | "type": "object", 28 | "properties": { 29 | "id": { 30 | "type": "integer" 31 | }, 32 | "name": { 33 | "type": "string" 34 | }, 35 | "tag": { 36 | "type": "string" 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | }, 48 | "components": { 49 | "securitySchemes": { 50 | "OAuth2": { 51 | "type": "oauth2", 52 | "flows": { 53 | "authorizationCode": { 54 | "authorizationUrl": "https://example.com/oauth/authorize", 55 | "tokenUrl": "https://example.com/oauth/token", 56 | "scopes": { 57 | "read:pets": "Read pets information", 58 | "write:pets": "Add or modify pets" 59 | } 60 | } 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/updated-operation-security/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.3", 3 | "info": { 4 | "title": "Simple Pet Store API", 5 | "version": "1.0.0" 6 | }, 7 | "paths": { 8 | "/pets": { 9 | "get": { 10 | "summary": "Get a list of pets", 11 | "security": [ 12 | { 13 | "OAuth2": [ 14 | "read:pets" 15 | ] 16 | } 17 | ], 18 | "responses": { 19 | "200": { 20 | "description": "A list of pets.", 21 | "content": { 22 | "application/json": { 23 | "schema": { 24 | "type": "array", 25 | "items": { 26 | "type": "object", 27 | "properties": { 28 | "id": { 29 | "type": "integer" 30 | }, 31 | "name": { 32 | "type": "string" 33 | }, 34 | "tag": { 35 | "type": "string" 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | }, 47 | "components": { 48 | "securitySchemes": { 49 | "OAuth2": { 50 | "type": "oauth2", 51 | "flows": { 52 | "authorizationCode": { 53 | "authorizationUrl": "https://example.com/oauth/authorize", 54 | "tokenUrl": "https://example.com/oauth/token", 55 | "scopes": { 56 | "read:pets": "Read pets information", 57 | "write:pets": "Add or modify pets" 58 | } 59 | } 60 | } 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-encoding/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.6" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "content": { 36 | "application/json": { 37 | "schema": { 38 | "type": "array", 39 | "items": { 40 | "$ref": "#/components/schemas/Pet" 41 | } 42 | } 43 | } 44 | } 45 | } 46 | ], 47 | "responses": { 48 | "200": { 49 | "description": "Success", 50 | "content": { 51 | "application/json": { 52 | "schema": { 53 | "type": "array", 54 | "items": { 55 | "$ref": "#/components/schemas/Pet" 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | }, 63 | "post": { 64 | "operationId": "addPet", 65 | "description": "Add a new pet", 66 | "requestBody": { 67 | "required": true, 68 | "content": { 69 | "application/json": { 70 | "schema": { 71 | "$ref": "#/components/schemas/NewPet" 72 | } 73 | } 74 | } 75 | }, 76 | "responses": { 77 | "201": { 78 | "description": "Pet created", 79 | "content": { 80 | "application/json": { 81 | "schema": { 82 | "$ref": "#/components/schemas/Pet" 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } 89 | }, 90 | "/pets/{petId}": { 91 | "get": { 92 | "operationId": "getPetById", 93 | "description": "Get a pet by its ID", 94 | "parameters": [ 95 | { 96 | "name": "petId", 97 | "in": "path", 98 | "required": true, 99 | "schema": { 100 | "type": "integer", 101 | "format": "int32" 102 | }, 103 | "description": "The ID of the pet to retrieve" 104 | } 105 | ], 106 | "responses": { 107 | "200": { 108 | "description": "Successful response", 109 | "content": { 110 | "application/json": { 111 | "schema": { 112 | "$ref": "#/components/schemas/Pet" 113 | } 114 | } 115 | } 116 | }, 117 | "404": { 118 | "description": "Pet not found" 119 | } 120 | } 121 | } 122 | } 123 | }, 124 | "components": { 125 | "schemas": { 126 | "Pet": { 127 | "type": "object", 128 | "properties": { 129 | "id": { 130 | "type": "integer", 131 | "format": "int32" 132 | }, 133 | "name": { 134 | "type": "string" 135 | } 136 | } 137 | }, 138 | "NewPet": { 139 | "type": "object", 140 | "properties": { 141 | "name": { 142 | "type": "string" 143 | } 144 | }, 145 | "required": [ 146 | "name" 147 | ] 148 | } 149 | } 150 | } 151 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-schema/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.0.6" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "content": { 36 | "application/json": { 37 | "schema": { 38 | "type": "array", 39 | "items": { 40 | "$ref": "#/components/schemas/Pet" 41 | } 42 | } 43 | } 44 | } 45 | } 46 | ], 47 | "responses": { 48 | "200": { 49 | "description": "Success", 50 | "content": { 51 | "application/json": { 52 | "schema": { 53 | "type": "array", 54 | "items": { 55 | "$ref": "#/components/schemas/Pet" 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | }, 63 | "post": { 64 | "operationId": "addPet", 65 | "description": "Add a new pet", 66 | "requestBody": { 67 | "required": true, 68 | "content": { 69 | "application/json": { 70 | "schema": { 71 | "$ref": "#/components/schemas/NewPet" 72 | } 73 | } 74 | } 75 | }, 76 | "responses": { 77 | "201": { 78 | "description": "Pet created", 79 | "content": { 80 | "application/json": { 81 | "schema": { 82 | "$ref": "#/components/schemas/Pet" 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } 89 | }, 90 | "/pets/{petId}": { 91 | "get": { 92 | "operationId": "getPetById", 93 | "description": "Get a pet by its ID", 94 | "parameters": [ 95 | { 96 | "name": "petId", 97 | "in": "path", 98 | "required": true, 99 | "schema": { 100 | "type": "integer", 101 | "format": "int32" 102 | }, 103 | "description": "The ID of the pet to retrieve" 104 | } 105 | ], 106 | "responses": { 107 | "200": { 108 | "description": "Successful response", 109 | "content": { 110 | "application/json": { 111 | "schema": { 112 | "$ref": "#/components/schemas/Pet" 113 | } 114 | } 115 | } 116 | }, 117 | "404": { 118 | "description": "Pet not found" 119 | } 120 | } 121 | } 122 | } 123 | }, 124 | "components": { 125 | "schemas": { 126 | "Pet": { 127 | "type": "object", 128 | "properties": { 129 | "id": { 130 | "type": "integer", 131 | "format": "int32" 132 | }, 133 | "name": { 134 | "type": "string" 135 | } 136 | } 137 | }, 138 | "NewPet": { 139 | "type": "object", 140 | "properties": { 141 | "name": { 142 | "type": "string" 143 | } 144 | }, 145 | "required": [ 146 | "name" 147 | ] 148 | } 149 | } 150 | } 151 | } -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-encoding/petstore-updated-requestbody-content-mediatype-encoding.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.3", 3 | "info": { 4 | "title": "Simple Pet Store API", 5 | "version": "1.0.0" 6 | }, 7 | "paths": { 8 | "/pets": { 9 | "post": { 10 | "summary": "Add a new pet", 11 | "requestBody": { 12 | "required": true, 13 | "content": { 14 | "multipart/form-data": { 15 | "schema": { 16 | "type": "object", 17 | "properties": { 18 | "id": { 19 | "type": "integer" 20 | }, 21 | "name": { 22 | "type": "string" 23 | }, 24 | "photo": { 25 | "type": "string", 26 | "format": "binary" 27 | } 28 | } 29 | }, 30 | "encoding": { 31 | "photo": { 32 | "contentType": "image/jpeg", 33 | "style": "form", 34 | "explode": true, 35 | "allowReserved": false, 36 | "headers": { 37 | "X-Custom-Header": { 38 | "description": "Custom header for encoding", 39 | "schema": { 40 | "type": "string" 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | }, 49 | "responses": { 50 | "201": { 51 | "description": "Pet created successfully.", 52 | "content": { 53 | "application/json": { 54 | "schema": { 55 | "type": "object", 56 | "properties": { 57 | "id": { 58 | "type": "integer" 59 | }, 60 | "name": { 61 | "type": "string" 62 | }, 63 | "tag": { 64 | "type": "string" 65 | } 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-encoding/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.3", 3 | "info": { 4 | "title": "Simple Pet Store API", 5 | "version": "1.0.0" 6 | }, 7 | "paths": { 8 | "/pets": { 9 | "post": { 10 | "summary": "Add a new pet", 11 | "requestBody": { 12 | "required": true, 13 | "content": { 14 | "multipart/form-data": { 15 | "schema": { 16 | "type": "object", 17 | "properties": { 18 | "id": { 19 | "type": "integer" 20 | }, 21 | "name": { 22 | "type": "string" 23 | }, 24 | "photo": { 25 | "type": "string", 26 | "format": "binary" 27 | } 28 | } 29 | }, 30 | "encoding": { 31 | "photo": { 32 | "contentType": "image/jpeg" 33 | } 34 | } 35 | } 36 | } 37 | }, 38 | "responses": { 39 | "201": { 40 | "description": "Pet created successfully.", 41 | "content": { 42 | "application/json": { 43 | "schema": { 44 | "type": "object", 45 | "properties": { 46 | "id": { 47 | "type": "integer" 48 | }, 49 | "name": { 50 | "type": "string" 51 | }, 52 | "tag": { 53 | "type": "string" 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-schema/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "$ref": "#/components/schemas/NewPet" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | } 121 | } 122 | }, 123 | "404": { 124 | "description": "Pet not found" 125 | } 126 | } 127 | } 128 | } 129 | }, 130 | "components": { 131 | "schemas": { 132 | "Pet": { 133 | "type": "object", 134 | "properties": { 135 | "id": { 136 | "type": "integer", 137 | "format": "int32" 138 | }, 139 | "name": { 140 | "type": "string" 141 | }, 142 | "breed": { 143 | "type": "string", 144 | "description": "The breed of the pet" 145 | } 146 | } 147 | }, 148 | "NewPet": { 149 | "type": "object", 150 | "properties": { 151 | "name": { 152 | "type": "string" 153 | } 154 | }, 155 | "required": [ 156 | "name" 157 | ] 158 | }, 159 | "UpdatedPet": { 160 | "type": "object", 161 | "properties": { 162 | "name": { 163 | "type": "string" 164 | }, 165 | "breed": { 166 | "type": "string" 167 | } 168 | }, 169 | "required": [ 170 | "name" 171 | ] 172 | } 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/updated-response-content-mediatype-schema/petstore-updated-response-content-mediatype-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "type": "string" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | }, 121 | "application/xml": { 122 | "schema": { 123 | "type": "string" 124 | } 125 | } 126 | } 127 | }, 128 | "404": { 129 | "description": "Pet not found" 130 | }, 131 | "500": { 132 | "description": "Internal Error" 133 | } 134 | } 135 | } 136 | } 137 | }, 138 | "components": { 139 | "schemas": { 140 | "Pet": { 141 | "type": "object", 142 | "properties": { 143 | "id": { 144 | "type": "integer", 145 | "format": "int32" 146 | }, 147 | "name": { 148 | "type": "string" 149 | }, 150 | "breed": { 151 | "type": "string", 152 | "description": "The breed of the pet" 153 | } 154 | } 155 | }, 156 | "NewPet": { 157 | "type": "object", 158 | "properties": { 159 | "name": { 160 | "type": "string" 161 | } 162 | }, 163 | "required": [ 164 | "name" 165 | ] 166 | }, 167 | "UpdatedPet": { 168 | "type": "object", 169 | "properties": { 170 | "name": { 171 | "type": "string" 172 | }, 173 | "breed": { 174 | "type": "string" 175 | } 176 | }, 177 | "required": [ 178 | "name" 179 | ] 180 | } 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/updated-response-content-mediatype-schema/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "type": "string" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | }, 121 | "application/xml": { 122 | "schema": { 123 | "$ref": "#/components/schemas/Pet" 124 | } 125 | } 126 | } 127 | }, 128 | "404": { 129 | "description": "Pet not found" 130 | }, 131 | "500": { 132 | "description": "Internal Error" 133 | } 134 | } 135 | } 136 | } 137 | }, 138 | "components": { 139 | "schemas": { 140 | "Pet": { 141 | "type": "object", 142 | "properties": { 143 | "id": { 144 | "type": "integer", 145 | "format": "int32" 146 | }, 147 | "name": { 148 | "type": "string" 149 | }, 150 | "breed": { 151 | "type": "string", 152 | "description": "The breed of the pet" 153 | } 154 | } 155 | }, 156 | "NewPet": { 157 | "type": "object", 158 | "properties": { 159 | "name": { 160 | "type": "string" 161 | } 162 | }, 163 | "required": [ 164 | "name" 165 | ] 166 | }, 167 | "UpdatedPet": { 168 | "type": "object", 169 | "properties": { 170 | "name": { 171 | "type": "string" 172 | }, 173 | "breed": { 174 | "type": "string" 175 | } 176 | }, 177 | "required": [ 178 | "name" 179 | ] 180 | } 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /openapi-comparator-tests/src/test/resources/petstore/updated-response-header-schema/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.1.0", 3 | "info": { 4 | "title": "Sample Pet Store App", 5 | "summary": "A pet store manager.", 6 | "description": "This is a sample server for a pet store.", 7 | "termsOfService": "https://example.com/terms/", 8 | "contact": { 9 | "name": "API Support", 10 | "url": "https://www.example.com/support", 11 | "email": "support@example.com" 12 | }, 13 | "license": { 14 | "name": "Apache 2.0", 15 | "url": "https://www.apache.org/licenses/LICENSE-2.0.html" 16 | }, 17 | "version": "1.1.2" 18 | }, 19 | "servers": [ 20 | { 21 | "url": "http://petstore.swagger.io/v1" 22 | } 23 | ], 24 | "paths": { 25 | "/pets": { 26 | "get": { 27 | "operationId": "getPets", 28 | "description": "Gets all pets", 29 | "parameters": [ 30 | { 31 | "name": "status", 32 | "in": "query", 33 | "description": "Filter pets by status", 34 | "required": false, 35 | "style": "form", 36 | "explode": true, 37 | "allowEmptyValue": true, 38 | "allowReserved": true, 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "string" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "responses": { 49 | "200": { 50 | "description": "Success", 51 | "content": { 52 | "application/json": { 53 | "schema": { 54 | "type": "array", 55 | "items": { 56 | "$ref": "#/components/schemas/Pet" 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } 63 | }, 64 | "post": { 65 | "operationId": "addPet", 66 | "description": "Add a new pet", 67 | "requestBody": { 68 | "required": true, 69 | "content": { 70 | "application/json": { 71 | "schema": { 72 | "type": "string" 73 | } 74 | }, 75 | "application/xml": { 76 | "schema": { 77 | "$ref": "#/components/schemas/NewPet" 78 | } 79 | } 80 | } 81 | }, 82 | "responses": { 83 | "201": { 84 | "description": "Pet created", 85 | "content": { 86 | "application/json": { 87 | "schema": { 88 | "$ref": "#/components/schemas/Pet" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | }, 96 | "/pets/{petId}": { 97 | "get": { 98 | "operationId": "getPetById", 99 | "description": "Get a pet by its ID", 100 | "parameters": [ 101 | { 102 | "name": "petId", 103 | "in": "path", 104 | "required": true, 105 | "schema": { 106 | "type": "integer", 107 | "format": "int32" 108 | }, 109 | "description": "The ID of the pet to retrieve" 110 | } 111 | ], 112 | "responses": { 113 | "200": { 114 | "description": "Successful response", 115 | "content": { 116 | "application/json": { 117 | "schema": { 118 | "$ref": "#/components/schemas/Pet" 119 | } 120 | }, 121 | "application/xml": { 122 | "schema": { 123 | "type": "string" 124 | } 125 | } 126 | }, 127 | "headers": { 128 | "X-Rate-Limit": { 129 | "description": "The number of requests allowed per hour", 130 | "schema": { 131 | "type": "integer" 132 | } 133 | } 134 | } 135 | }, 136 | "404": { 137 | "description": "Pet not found" 138 | }, 139 | "500": { 140 | "description": "Internal Error" 141 | } 142 | } 143 | } 144 | } 145 | }, 146 | "components": { 147 | "schemas": { 148 | "Pet": { 149 | "type": "object", 150 | "properties": { 151 | "id": { 152 | "type": "integer", 153 | "format": "int32" 154 | }, 155 | "name": { 156 | "type": "string" 157 | }, 158 | "breed": { 159 | "type": "string", 160 | "description": "The breed of the pet" 161 | } 162 | } 163 | }, 164 | "NewPet": { 165 | "type": "object", 166 | "properties": { 167 | "name": { 168 | "type": "string" 169 | } 170 | }, 171 | "required": [ 172 | "name" 173 | ] 174 | }, 175 | "UpdatedPet": { 176 | "type": "object", 177 | "properties": { 178 | "name": { 179 | "type": "string" 180 | }, 181 | "breed": { 182 | "type": "string" 183 | } 184 | }, 185 | "required": [ 186 | "name" 187 | ] 188 | } 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /openapi-model/src/main/scala/sttp/apispec/openapi/package.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec 2 | 3 | package object openapi { 4 | type ReferenceOr[T] = Either[Reference, T] 5 | } 6 | -------------------------------------------------------------------------------- /openapi-model/src/test/scala/sttp/apispec/openapi/OpenAPITest.scala: -------------------------------------------------------------------------------- 1 | package sttp.apispec.openapi 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | import org.scalatest.matchers.should.Matchers 5 | 6 | class OpenAPITest extends AnyFunSuite with Matchers { 7 | test("'default' in ServerVariable should belong to 'enum'") { 8 | a[java.lang.IllegalArgumentException] shouldBe thrownBy { 9 | Server("https://{username}.example.com:{port}/{basePath}") 10 | .description("The production API server") 11 | .variables( 12 | "username" -> ServerVariable(None, "demo", Some("Username")), 13 | "port" -> ServerVariable(Some(List("8443", "443")), "80", None), 14 | "basePath" -> ServerVariable(None, "v2", None) 15 | ) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.10.11 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | libraryDependencies += "org.scala-js" %% "scalajs-env-selenium" % "1.1.1" 2 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.18.2") 3 | addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.7") 4 | addSbtPlugin("com.eed3si9n" % "sbt-projectmatrix" % "0.10.1") 5 | 6 | val sbtSoftwareMillVersion = "2.0.21" 7 | addSbtPlugin("com.softwaremill.sbt-softwaremill" % "sbt-softwaremill-common" % sbtSoftwareMillVersion) 8 | addSbtPlugin("com.softwaremill.sbt-softwaremill" % "sbt-softwaremill-publish" % sbtSoftwareMillVersion) 9 | addSbtPlugin("com.softwaremill.sbt-softwaremill" % "sbt-softwaremill-browser-test-js" % sbtSoftwareMillVersion) 10 | 11 | addSbtPlugin("org.jetbrains" % "sbt-ide-settings" % "1.1.0") 12 | addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "1.1.4") 13 | --------------------------------------------------------------------------------