diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c47fc81..c02bfc9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 env: STTP_NATIVE: 1 - JAVA_OPTS: -Xmx4G -Xss4M # larger stack needed due to Circe generating large trees: https://github.com/lampepfl/dotty/issues/18669 + JAVA_OPTS: -Xmx6G -Xss4M # larger stack needed due to Circe generating large trees: https://github.com/lampepfl/dotty/issues/18669 steps: - name: Checkout uses: actions/checkout@v2 diff --git a/build.sbt b/build.sbt index bb76542..aea9e74 100644 --- a/build.sbt +++ b/build.sbt @@ -74,7 +74,8 @@ lazy val allProjectAggregates: Seq[ProjectReference] = openapiCirceYaml.projectRefs ++ asyncapiModel.projectRefs ++ asyncapiCirce.projectRefs ++ - asyncapiCirceYaml.projectRefs + asyncapiCirceYaml.projectRefs ++ + openapiComparatorTests.projectRefs lazy val projectAggregates: Seq[ProjectReference] = if (sys.env.isDefinedAt("STTP_NATIVE")) { println("[info] STTP_NATIVE defined, including native in the aggregate projects") @@ -262,3 +263,23 @@ lazy val asyncapiCirceYaml: ProjectMatrix = (projectMatrix in file("asyncapi-cir settings = commonJvmSettings ) .dependsOn(asyncapiCirce) + +lazy val openapiComparatorTests: ProjectMatrix = (projectMatrix in file("openapi-comparator-tests")) + .settings(commonSettings) + .settings( + name := "openapi-comparator-tests", + publish / skip := true + ) + .jvmPlatform( + scalaVersions = scalaJVMVersions, + settings = commonJvmSettings + ) + .jsPlatform( + scalaVersions = scalaJSVersions, + settings = commonJsSettings + ) + .nativePlatform( + scalaVersions = scalaNativeVersions, + settings = commonNativeSettings + ) + .dependsOn(openapiModel, openapiCirce, circeTestUtils % Test) \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-operation-callback/petstore-added-operation-callback.json b/openapi-comparator-tests/src/test/resources/petstore/added-operation-callback/petstore-added-operation-callback.json new file mode 100644 index 0000000..b997e73 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-operation-callback/petstore-added-operation-callback.json @@ -0,0 +1,73 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Simple Pet Store API", + "version": "1.0.0" + }, + "paths": { + "/pets": { + "post": { + "summary": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Pet created successfully." + } + }, + "callbacks": { + "onPetStatusChange": { + "{$request.body#/callbackUrl}": { + "post": { + "summary": "Notify about pet status change", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Callback successfully processed." + } + } + } + } + } + } + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-operation-callback/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-operation-callback/petstore.json new file mode 100644 index 0000000..6255aed --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-operation-callback/petstore.json @@ -0,0 +1,41 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Simple Pet Store API", + "version": "1.0.0" + }, + "paths": { + "/pets": { + "post": { + "summary": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Pet created successfully." + } + }, + "callbacks": {} + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-operation/petstore-added-operation.json b/openapi-comparator-tests/src/test/resources/petstore/added-operation/petstore-added-operation.json new file mode 100644 index 0000000..d840ecd --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-operation/petstore-added-operation.json @@ -0,0 +1,133 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.3" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-operation/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-operation/petstore.json new file mode 100644 index 0000000..b202960 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-operation/petstore.json @@ -0,0 +1,96 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype-schema/petstore-added-parameter-content-mediatype-schema.json b/openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype-schema/petstore-added-parameter-content-mediatype-schema.json new file mode 100644 index 0000000..319759b --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype-schema/petstore-added-parameter-content-mediatype-schema.json @@ -0,0 +1,148 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.7" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype-schema/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype-schema/petstore.json new file mode 100644 index 0000000..e8f17ca --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype-schema/petstore.json @@ -0,0 +1,144 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.6" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "content": { + "application/json": {} + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype/petstore-added-parameter-content-mediatype.json b/openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype/petstore-added-parameter-content-mediatype.json new file mode 100644 index 0000000..fc268bb --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype/petstore-added-parameter-content-mediatype.json @@ -0,0 +1,151 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.6" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype/petstore.json new file mode 100644 index 0000000..a45541f --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-parameter-content-mediatype/petstore.json @@ -0,0 +1,141 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.5" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-parameter-schema/petstore-added-parameter-schema.json b/openapi-comparator-tests/src/test/resources/petstore/added-parameter-schema/petstore-added-parameter-schema.json new file mode 100644 index 0000000..8c11826 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-parameter-schema/petstore-added-parameter-schema.json @@ -0,0 +1,148 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.4" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "schema": { + "type": "string", + "enum": [ + "available", + "sold" + ] + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-parameter-schema/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-parameter-schema/petstore.json new file mode 100644 index 0000000..235d7de --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-parameter-schema/petstore.json @@ -0,0 +1,141 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.4" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-parameter/petstore-added-parameter.json b/openapi-comparator-tests/src/test/resources/petstore/added-parameter/petstore-added-parameter.json new file mode 100644 index 0000000..ab2b215 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-parameter/petstore-added-parameter.json @@ -0,0 +1,148 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.4" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "schema": { + "type": "string", + "enum": [ + "available", + "sold" + ] + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-parameter/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-parameter/petstore.json new file mode 100644 index 0000000..d840ecd --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-parameter/petstore.json @@ -0,0 +1,133 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.3" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-path/petstore-added-path.json b/openapi-comparator-tests/src/test/resources/petstore/added-path/petstore-added-path.json new file mode 100644 index 0000000..b202960 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-path/petstore-added-path.json @@ -0,0 +1,96 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-path/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-path/petstore.json new file mode 100644 index 0000000..a7f22e5 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-path/petstore.json @@ -0,0 +1,63 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.1" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-encoding/petstore-added-requestbody-content-mediatype-encoding.json b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-encoding/petstore-added-requestbody-content-mediatype-encoding.json new file mode 100644 index 0000000..7056232 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-encoding/petstore-added-requestbody-content-mediatype-encoding.json @@ -0,0 +1,64 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Simple Pet Store API", + "version": "1.0.0" + }, + "paths": { + "/pets": { + "post": { + "summary": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "photo": { + "type": "string", + "format": "binary" + } + } + }, + "encoding": { + "photo": { + "contentType": "image/jpeg" + } + } + } + } + }, + "responses": { + "201": { + "description": "Pet created successfully.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + } + } + } + } + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-encoding/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-encoding/petstore.json new file mode 100644 index 0000000..9ac582f --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-encoding/petstore.json @@ -0,0 +1,60 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Simple Pet Store API", + "version": "1.0.0" + }, + "paths": { + "/pets": { + "post": { + "summary": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "photo": { + "type": "string", + "format": "binary" + } + } + }, + "encoding": {} + } + } + }, + "responses": { + "201": { + "description": "Pet created successfully.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + } + } + } + } + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-schema/petstore-added-requestbody-content-mediatype-schema.json b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-schema/petstore-added-requestbody-content-mediatype-schema.json new file mode 100644 index 0000000..d4cbd5d --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-schema/petstore-added-requestbody-content-mediatype-schema.json @@ -0,0 +1,166 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-schema/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-schema/petstore.json new file mode 100644 index 0000000..1fb418e --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype-schema/petstore.json @@ -0,0 +1,162 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": {} + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype/petstore-added-requestbody-content-mediatype.json b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype/petstore-added-requestbody-content-mediatype.json new file mode 100644 index 0000000..9749b19 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype/petstore-added-requestbody-content-mediatype.json @@ -0,0 +1,175 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype/petstore.json new file mode 100644 index 0000000..ed87cde --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody-content-mediatype/petstore.json @@ -0,0 +1,152 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.1" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-requestbody/petstore-added-requestbody.json b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody/petstore-added-requestbody.json new file mode 100644 index 0000000..11989e6 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody/petstore-added-requestbody.json @@ -0,0 +1,199 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-requestbody/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody/petstore.json new file mode 100644 index 0000000..da8239b --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-requestbody/petstore.json @@ -0,0 +1,184 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype-schema/petstore-added-response-content-mediatype-schema.json b/openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype-schema/petstore-added-response-content-mediatype-schema.json new file mode 100644 index 0000000..cff46ba --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype-schema/petstore-added-response-content-mediatype-schema.json @@ -0,0 +1,178 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype-schema/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype-schema/petstore.json new file mode 100644 index 0000000..373c358 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype-schema/petstore.json @@ -0,0 +1,174 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": {} + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype/petstore-added-response-content-mediatype.json b/openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype/petstore-added-response-content-mediatype.json new file mode 100644 index 0000000..4cd017f --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype/petstore-added-response-content-mediatype.json @@ -0,0 +1,183 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype/petstore.json new file mode 100644 index 0000000..cff46ba --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response-content-mediatype/petstore.json @@ -0,0 +1,178 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response-header-content-mediatype-schema/petstore-added-response-header-content-mediatype-schema.json b/openapi-comparator-tests/src/test/resources/petstore/added-response-header-content-mediatype-schema/petstore-added-response-header-content-mediatype-schema.json new file mode 100644 index 0000000..e571041 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response-header-content-mediatype-schema/petstore-added-response-header-content-mediatype-schema.json @@ -0,0 +1,195 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response-header-content-mediatype-schema/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-response-header-content-mediatype-schema/petstore.json new file mode 100644 index 0000000..2ae996f --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response-header-content-mediatype-schema/petstore.json @@ -0,0 +1,191 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "content": { + "application/json": {} + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response-header-content-mediatype/petstore-added-response-header-content-mediatype.json b/openapi-comparator-tests/src/test/resources/petstore/added-response-header-content-mediatype/petstore-added-response-header-content-mediatype.json new file mode 100644 index 0000000..38eaf60 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response-header-content-mediatype/petstore-added-response-header-content-mediatype.json @@ -0,0 +1,200 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "content": { + "application/xml": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response-header-content-mediatype/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-response-header-content-mediatype/petstore.json new file mode 100644 index 0000000..342ae8e --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response-header-content-mediatype/petstore.json @@ -0,0 +1,195 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "content": { + "application/xml": { + "schema": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response-header-schema/petstore-added-response-header-schema.json b/openapi-comparator-tests/src/test/resources/petstore/added-response-header-schema/petstore-added-response-header-schema.json new file mode 100644 index 0000000..0ff614e --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response-header-schema/petstore-added-response-header-schema.json @@ -0,0 +1,191 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "schema": { + "type": "integer" + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response-header-schema/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-response-header-schema/petstore.json new file mode 100644 index 0000000..7a62193 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response-header-schema/petstore.json @@ -0,0 +1,188 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour" + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response-header/petstore-added-response-header.json b/openapi-comparator-tests/src/test/resources/petstore/added-response-header/petstore-added-response-header.json new file mode 100644 index 0000000..0ff614e --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response-header/petstore-added-response-header.json @@ -0,0 +1,191 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "schema": { + "type": "integer" + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response-header/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-response-header/petstore.json new file mode 100644 index 0000000..f9fb574 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response-header/petstore.json @@ -0,0 +1,183 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response/petstore-added-response.json b/openapi-comparator-tests/src/test/resources/petstore/added-response/petstore-added-response.json new file mode 100644 index 0000000..cff46ba --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response/petstore-added-response.json @@ -0,0 +1,178 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/added-response/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/added-response/petstore.json new file mode 100644 index 0000000..a7eb4e6 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/added-response/petstore.json @@ -0,0 +1,175 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/changed-metadata/petstore-changed-metadata.json b/openapi-comparator-tests/src/test/resources/petstore/changed-metadata/petstore-changed-metadata.json new file mode 100644 index 0000000..aa2cfd6 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/changed-metadata/petstore-changed-metadata.json @@ -0,0 +1,199 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Example Pet Store API", + "summary": "Manages pet store operations.", + "description": "This is a sample API for managing a pet store.", + "termsOfService": "https://example.com/terms-of-service", + "contact": { + "name": "API Support Team", + "url": "https://www.example.com/help", + "email": "support@example.com" + }, + "license": { + "name": "Apache License 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Get pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status value", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "get pets successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "A new pet is created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get pet by ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet" + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The hourly limit for requests", + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The pet's breed" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/changed-metadata/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/changed-metadata/petstore.json new file mode 100644 index 0000000..11989e6 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/changed-metadata/petstore.json @@ -0,0 +1,199 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/identical/petstore-identical.json b/openapi-comparator-tests/src/test/resources/petstore/identical/petstore-identical.json new file mode 100644 index 0000000..d9e3872 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/identical/petstore-identical.json @@ -0,0 +1,199 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/identical/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/identical/petstore.json new file mode 100644 index 0000000..d9e3872 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/identical/petstore.json @@ -0,0 +1,199 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/required-parameter/petstore-required-parameter.json b/openapi-comparator-tests/src/test/resources/petstore/required-parameter/petstore-required-parameter.json new file mode 100644 index 0000000..80b4e6a --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/required-parameter/petstore-required-parameter.json @@ -0,0 +1,96 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/required-parameter/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/required-parameter/petstore.json new file mode 100644 index 0000000..59ea55a --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/required-parameter/petstore.json @@ -0,0 +1,96 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": false, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/required-request-body/petstore-required-request-body.json b/openapi-comparator-tests/src/test/resources/petstore/required-request-body/petstore-required-request-body.json new file mode 100644 index 0000000..9749b19 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/required-request-body/petstore-required-request-body.json @@ -0,0 +1,175 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/required-request-body/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/required-request-body/petstore.json new file mode 100644 index 0000000..a8bc71c --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/required-request-body/petstore.json @@ -0,0 +1,175 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/required-response-header/petstore-required-response-header.json b/openapi-comparator-tests/src/test/resources/petstore/required-response-header/petstore-required-response-header.json new file mode 100644 index 0000000..795fe1a --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/required-response-header/petstore-required-response-header.json @@ -0,0 +1,196 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/required-response-header/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/required-response-header/petstore.json new file mode 100644 index 0000000..059ae5d --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/required-response-header/petstore.json @@ -0,0 +1,196 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-operation-callback/petstore-updated-operation-callback.json b/openapi-comparator-tests/src/test/resources/petstore/updated-operation-callback/petstore-updated-operation-callback.json new file mode 100644 index 0000000..60a6f64 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-operation-callback/petstore-updated-operation-callback.json @@ -0,0 +1,106 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Simple Pet Store API", + "version": "1.0.0" + }, + "paths": { + "/pets": { + "post": { + "summary": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Pet created successfully." + } + }, + "callbacks": { + "onPetStatusChange": { + "{$request.body#/callbackUrl}": { + "post": { + "summary": "Notify about pet status change", + "description": "This callback is triggered whenever the status of a pet changes.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "The new status of the pet.", + "enum": [ + "available", + "pending", + "sold" + ] + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "The time when the status change occurred." + }, + "petId": { + "type": "integer", + "description": "The unique ID of the pet whose status changed." + } + }, + "required": [ + "status", + "timestamp", + "petId" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Callback successfully processed." + }, + "400": { + "description": "Invalid payload provided.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "error": { + "type": "string", + "description": "Details about the error." + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-operation-callback/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-operation-callback/petstore.json new file mode 100644 index 0000000..2a1d226 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-operation-callback/petstore.json @@ -0,0 +1,90 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Simple Pet Store API", + "version": "1.0.0" + }, + "paths": { + "/pets": { + "post": { + "summary": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Pet created successfully." + } + }, + "callbacks": { + "onPetStatusChange": { + "{$request.body#/callbackUrl}": { + "post": { + "summary": "Notify about pet status change", + "description": "This callback is triggered whenever the status of a pet changes.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "The new status of the pet.", + "enum": [ + "available", + "pending", + "sold" + ] + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "The time when the status change occurred." + }, + "petId": { + "type": "integer", + "description": "The unique ID of the pet whose status changed." + } + }, + "required": [ + "status", + "timestamp", + "petId" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Callback successfully processed." + } + } + } + } + } + } + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-operation-security/petstore-updated-operation-security.json b/openapi-comparator-tests/src/test/resources/petstore/updated-operation-security/petstore-updated-operation-security.json new file mode 100644 index 0000000..857f276 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-operation-security/petstore-updated-operation-security.json @@ -0,0 +1,65 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Simple Pet Store API", + "version": "1.0.0" + }, + "paths": { + "/pets": { + "get": { + "summary": "Get a list of pets", + "security": [ + { + "OAuth2": [ + "read:pets", + "write:pets" + ] + } + ], + "responses": { + "200": { + "description": "A list of pets.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "OAuth2": { + "type": "oauth2", + "flows": { + "authorizationCode": { + "authorizationUrl": "https://example.com/oauth/authorize", + "tokenUrl": "https://example.com/oauth/token", + "scopes": { + "read:pets": "Read pets information", + "write:pets": "Add or modify pets" + } + } + } + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-operation-security/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-operation-security/petstore.json new file mode 100644 index 0000000..eaec9c2 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-operation-security/petstore.json @@ -0,0 +1,64 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Simple Pet Store API", + "version": "1.0.0" + }, + "paths": { + "/pets": { + "get": { + "summary": "Get a list of pets", + "security": [ + { + "OAuth2": [ + "read:pets" + ] + } + ], + "responses": { + "200": { + "description": "A list of pets.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "OAuth2": { + "type": "oauth2", + "flows": { + "authorizationCode": { + "authorizationUrl": "https://example.com/oauth/authorize", + "tokenUrl": "https://example.com/oauth/token", + "scopes": { + "read:pets": "Read pets information", + "write:pets": "Add or modify pets" + } + } + } + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-allow_empty_value/petstore-updated-parameter-allow_empty_value.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-allow_empty_value/petstore-updated-parameter-allow_empty_value.json new file mode 100644 index 0000000..ec035d4 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-allow_empty_value/petstore-updated-parameter-allow_empty_value.json @@ -0,0 +1,151 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.0" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-allow_empty_value/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-allow_empty_value/petstore.json new file mode 100644 index 0000000..e616bc2 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-allow_empty_value/petstore.json @@ -0,0 +1,150 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.9" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-allow_reserved/petstore-updated-parameter-allow_reserved.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-allow_reserved/petstore-updated-parameter-allow_reserved.json new file mode 100644 index 0000000..ed87cde --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-allow_reserved/petstore-updated-parameter-allow_reserved.json @@ -0,0 +1,152 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.1" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-allow_reserved/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-allow_reserved/petstore.json new file mode 100644 index 0000000..ec035d4 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-allow_reserved/petstore.json @@ -0,0 +1,151 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.0" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-encoding/petstore-updated-parameter-content-mediatype-encoding.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-encoding/petstore-updated-parameter-content-mediatype-encoding.json new file mode 100644 index 0000000..c5c3cb0 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-encoding/petstore-updated-parameter-content-mediatype-encoding.json @@ -0,0 +1,151 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.6" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-encoding/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-encoding/petstore.json new file mode 100644 index 0000000..fc268bb --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-encoding/petstore.json @@ -0,0 +1,151 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.6" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-schema/petstore-updated-parameter-content-mediatype-schema.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-schema/petstore-updated-parameter-content-mediatype-schema.json new file mode 100644 index 0000000..319759b --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-schema/petstore-updated-parameter-content-mediatype-schema.json @@ -0,0 +1,148 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.7" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-schema/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-schema/petstore.json new file mode 100644 index 0000000..fc268bb --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-content-mediatype-schema/petstore.json @@ -0,0 +1,151 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.6" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-explode/petstore-updated-parameter-explode.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-explode/petstore-updated-parameter-explode.json new file mode 100644 index 0000000..e616bc2 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-explode/petstore-updated-parameter-explode.json @@ -0,0 +1,150 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.9" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-explode/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-explode/petstore.json new file mode 100644 index 0000000..df50c9f --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-explode/petstore.json @@ -0,0 +1,149 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.8" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-name/petstore-updated-parameter-name.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-name/petstore-updated-parameter-name.json new file mode 100644 index 0000000..4848c8f --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-name/petstore-updated-parameter-name.json @@ -0,0 +1,199 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{Id}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-name/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-name/petstore.json new file mode 100644 index 0000000..d9e3872 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-name/petstore.json @@ -0,0 +1,199 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-schema/petstore-updated-parameter-schema.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-schema/petstore-updated-parameter-schema.json new file mode 100644 index 0000000..b89c469 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-schema/petstore-updated-parameter-schema.json @@ -0,0 +1,151 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.5" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "available", + "sold" + ] + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-schema/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-schema/petstore.json new file mode 100644 index 0000000..ab2b215 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-schema/petstore.json @@ -0,0 +1,148 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.4" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "schema": { + "type": "string", + "enum": [ + "available", + "sold" + ] + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-style/petstore-updated-parameter-style.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-style/petstore-updated-parameter-style.json new file mode 100644 index 0000000..df50c9f --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-style/petstore-updated-parameter-style.json @@ -0,0 +1,149 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.8" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-style/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-style/petstore.json new file mode 100644 index 0000000..319759b --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-parameter-style/petstore.json @@ -0,0 +1,148 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0.7" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} \ No newline at end of file diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-encoding/petstore-updated-requestbody-content-mediatype-encoding.json b/openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-encoding/petstore-updated-requestbody-content-mediatype-encoding.json new file mode 100644 index 0000000..2584757 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-encoding/petstore-updated-requestbody-content-mediatype-encoding.json @@ -0,0 +1,75 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Simple Pet Store API", + "version": "1.0.0" + }, + "paths": { + "/pets": { + "post": { + "summary": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "photo": { + "type": "string", + "format": "binary" + } + } + }, + "encoding": { + "photo": { + "contentType": "image/jpeg", + "style": "form", + "explode": true, + "allowReserved": false, + "headers": { + "X-Custom-Header": { + "description": "Custom header for encoding", + "schema": { + "type": "string" + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Pet created successfully.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + } + } + } + } + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-encoding/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-encoding/petstore.json new file mode 100644 index 0000000..7056232 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-encoding/petstore.json @@ -0,0 +1,64 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Simple Pet Store API", + "version": "1.0.0" + }, + "paths": { + "/pets": { + "post": { + "summary": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "photo": { + "type": "string", + "format": "binary" + } + } + }, + "encoding": { + "photo": { + "contentType": "image/jpeg" + } + } + } + } + }, + "responses": { + "201": { + "description": "Pet created successfully.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + } + } + } + } + } + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-schema/petstore-updated-requestbody-content-mediatype-schema.json b/openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-schema/petstore-updated-requestbody-content-mediatype-schema.json new file mode 100644 index 0000000..a7eb4e6 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-schema/petstore-updated-requestbody-content-mediatype-schema.json @@ -0,0 +1,175 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-schema/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-schema/petstore.json new file mode 100644 index 0000000..9749b19 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-requestbody-content-mediatype-schema/petstore.json @@ -0,0 +1,175 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-content-mediatype-schema/petstore-updated-response-content-mediatype-schema.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-content-mediatype-schema/petstore-updated-response-content-mediatype-schema.json new file mode 100644 index 0000000..f9fb574 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-content-mediatype-schema/petstore-updated-response-content-mediatype-schema.json @@ -0,0 +1,183 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-content-mediatype-schema/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-content-mediatype-schema/petstore.json new file mode 100644 index 0000000..4cd017f --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-content-mediatype-schema/petstore.json @@ -0,0 +1,183 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-allow_empty_value/petstore-updated-response-header-allow_empty_value.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-allow_empty_value/petstore-updated-response-header-allow_empty_value.json new file mode 100644 index 0000000..76dfd15 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-allow_empty_value/petstore-updated-response-header-allow_empty_value.json @@ -0,0 +1,198 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "explode": true, + "allowEmptyValue": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-allow_empty_value/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-allow_empty_value/petstore.json new file mode 100644 index 0000000..1269aca --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-allow_empty_value/petstore.json @@ -0,0 +1,197 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "explode": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-allow_reserved/petstore-updated-response-header-allow_reserved.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-allow_reserved/petstore-updated-response-header-allow_reserved.json new file mode 100644 index 0000000..d9e3872 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-allow_reserved/petstore-updated-response-header-allow_reserved.json @@ -0,0 +1,199 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-allow_reserved/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-allow_reserved/petstore.json new file mode 100644 index 0000000..76dfd15 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-allow_reserved/petstore.json @@ -0,0 +1,198 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "explode": true, + "allowEmptyValue": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-content-mediatype-schema/petstore-updated-response-header-content-mediatype-schema.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-content-mediatype-schema/petstore-updated-response-header-content-mediatype-schema.json new file mode 100644 index 0000000..e571041 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-content-mediatype-schema/petstore-updated-response-header-content-mediatype-schema.json @@ -0,0 +1,195 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-content-mediatype-schema/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-content-mediatype-schema/petstore.json new file mode 100644 index 0000000..4a90228 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-content-mediatype-schema/petstore.json @@ -0,0 +1,195 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-explode/petstore-updated-response-header-explode.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-explode/petstore-updated-response-header-explode.json new file mode 100644 index 0000000..1269aca --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-explode/petstore-updated-response-header-explode.json @@ -0,0 +1,197 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "explode": true, + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-explode/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-explode/petstore.json new file mode 100644 index 0000000..b6e3332 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-explode/petstore.json @@ -0,0 +1,196 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-schema/petstore-updated-response-header-schema.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-schema/petstore-updated-response-header-schema.json new file mode 100644 index 0000000..0d458b4 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-schema/petstore-updated-response-header-schema.json @@ -0,0 +1,191 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-schema/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-schema/petstore.json new file mode 100644 index 0000000..0ff614e --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-schema/petstore.json @@ -0,0 +1,191 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "schema": { + "type": "integer" + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-style/petstore-updated-response-header-style.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-style/petstore-updated-response-header-style.json new file mode 100644 index 0000000..b6e3332 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-style/petstore-updated-response-header-style.json @@ -0,0 +1,196 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "style": "form", + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-style/petstore.json b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-style/petstore.json new file mode 100644 index 0000000..e571041 --- /dev/null +++ b/openapi-comparator-tests/src/test/resources/petstore/updated-response-header-style/petstore.json @@ -0,0 +1,195 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Sample Pet Store App", + "summary": "A pet store manager.", + "description": "This is a sample server for a pet store.", + "termsOfService": "https://example.com/terms/", + "contact": { + "name": "API Support", + "url": "https://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.1.2" + }, + "servers": [ + { + "url": "http://petstore.swagger.io/v1" + } + ], + "paths": { + "/pets": { + "get": { + "operationId": "getPets", + "description": "Gets all pets", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Filter pets by status", + "required": false, + "style": "form", + "explode": true, + "allowEmptyValue": true, + "allowReserved": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "post": { + "operationId": "addPet", + "description": "Add a new pet", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "string" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/NewPet" + } + } + } + }, + "responses": { + "201": { + "description": "Pet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + } + }, + "/pets/{petId}": { + "get": { + "operationId": "getPetById", + "description": "Get a pet by its ID", + "parameters": [ + { + "name": "petId", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + }, + "description": "The ID of the pet to retrieve" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "type": "string" + } + } + }, + "headers": { + "X-Rate-Limit": { + "description": "The number of requests allowed per hour", + "content": { + "application/json": { + "schema": { + "type": "integer" + } + } + } + } + } + }, + "404": { + "description": "Pet not found" + }, + "500": { + "description": "Internal Error" + } + } + } + } + }, + "components": { + "schemas": { + "Pet": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "breed": { + "type": "string", + "description": "The breed of the pet" + } + } + }, + "NewPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UpdatedPet": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "breed": { + "type": "string" + } + }, + "required": [ + "name" + ] + } + } + } +} diff --git a/openapi-comparator-tests/src/test/scala/sttp/apispec/openapi/validation/OpenAPIComparatorTest.scala b/openapi-comparator-tests/src/test/scala/sttp/apispec/openapi/validation/OpenAPIComparatorTest.scala new file mode 100644 index 0000000..445831e --- /dev/null +++ b/openapi-comparator-tests/src/test/scala/sttp/apispec/openapi/validation/OpenAPIComparatorTest.scala @@ -0,0 +1,772 @@ +package sttp.apispec.openapi.validation + +import org.scalatest.funsuite.AnyFunSuite +import sttp.apispec.SchemaType +import sttp.apispec.openapi.ParameterStyle +import sttp.apispec.openapi.{OpenAPI, ResponsesCodeKey} +import sttp.apispec.openapi.circe.openAPIDecoder +import sttp.apispec.test.ResourcePlatform +import sttp.apispec.validation.TypeMismatch + +import scala.collection.immutable.ListMap + +class OpenAPIComparatorTest extends AnyFunSuite with ResourcePlatform { + override val basedir = "openapi-comparator-tests" + + def readOpenAPI(path: String): OpenAPI = readJson(path).flatMap(_.as[OpenAPI]) match { + case Right(openapi) => openapi + case Left(error) => throw new RuntimeException(s"Failed to parse OpenAPI from $path: $error") + } + + private def compare(clientOpenapi: OpenAPI, serverOpenapi: OpenAPI): List[OpenAPICompatibilityIssue] = + OpenAPIComparator(clientOpenapi, serverOpenapi).compare() + + test("identical") { + val clientOpenapi = readOpenAPI("/petstore/identical/petstore-identical.json") + val serverOpenapi = readOpenAPI("/petstore/identical/petstore.json") + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("no errors when metadata is updated") { + val clientOpenapi = readOpenAPI("/petstore/changed-metadata/petstore-changed-metadata.json") + val serverOpenapi = readOpenAPI("/petstore/changed-metadata/petstore.json") + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server missing path when client has an extra one") { + val clientOpenapi = readOpenAPI("/petstore/added-path/petstore-added-path.json") + val serverOpenapi = readOpenAPI("/petstore/added-path/petstore.json") + + val expected = List(MissingPath("/pets/{petId}")) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has an additional path") { + val clientOpenapi = readOpenAPI("/petstore/added-path/petstore.json") + val serverOpenapi = readOpenAPI("/petstore/added-path/petstore-added-path.json") + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server missing operation when client has an extra one") { + val clientOpenapi = readOpenAPI("/petstore/added-operation/petstore-added-operation.json") + val serverOpenapi = readOpenAPI("/petstore/added-operation/petstore.json") + + val operationIssue = MissingOperation("post") + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has an additional operation") { + val clientOpenapi = readOpenAPI("/petstore/added-operation/petstore.json") + val serverOpenapi = readOpenAPI("/petstore/added-operation/petstore-added-operation.json") + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server missing parameter when client has an extra one") { + val clientOpenapi = readOpenAPI("/petstore/added-parameter/petstore-added-parameter.json") + val serverOpenapi = readOpenAPI("/petstore/added-parameter/petstore.json") + + val parameterIssue = MissingParameter("status") + val operationIssue = IncompatibleOperation("get", List(parameterIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has an additional parameter") { + val clientOpenapi = readOpenAPI("/petstore/added-parameter/petstore.json") + val serverOpenapi = readOpenAPI("/petstore/added-parameter/petstore-added-parameter.json") + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server parameter schema is incompatible with client schema") { + val clientOpenapi = readOpenAPI("/petstore/updated-parameter-schema/petstore-updated-parameter-schema.json") + val serverOpenapi = readOpenAPI("/petstore/updated-parameter-schema/petstore.json") + + val schemaTypeMismatch = TypeMismatch(List(SchemaType.Array), List(SchemaType.String)) + val schemaIssue = IncompatibleSchema(List(schemaTypeMismatch)) + val parameterIssue = IncompatibleParameter("status", List(schemaIssue)) + val operationIssue = IncompatibleOperation("get", List(parameterIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server missing parameter schema when client has one") { + val clientOpenapi = + readOpenAPI("/petstore/added-parameter-schema/petstore-added-parameter-schema.json") + val serverOpenapi = readOpenAPI("/petstore/added-parameter-schema/petstore.json") + + val schemaIssue = MissingSchema() + val parameterIssue = IncompatibleParameter("status", List(schemaIssue)) + val operationIssue = IncompatibleOperation("get", List(parameterIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has a parameter schema but client does not") { + val clientOpenapi = + readOpenAPI("/petstore/added-parameter-schema/petstore.json") + val serverOpenapi = readOpenAPI("/petstore/added-parameter-schema/petstore-added-parameter-schema.json") + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server missing parameter content media-type when client has an extra one") { + val clientOpenapi = + readOpenAPI("/petstore/added-parameter-content-mediatype/petstore-added-parameter-content-mediatype.json") + val serverOpenapi = readOpenAPI("/petstore/added-parameter-content-mediatype/petstore.json") + + val mediaTypeIssue = MissingMediaType("application/json") + val parameterContentIssue = IncompatibleContent(List(mediaTypeIssue)) + val parameterIssue = IncompatibleParameter("status", List(parameterContentIssue)) + val operationIssue = IncompatibleOperation("get", List(parameterIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has an additional parameter content media-type") { + val clientOpenapi = readOpenAPI("/petstore/added-parameter-content-mediatype/petstore.json") + val serverOpenapi = + readOpenAPI("/petstore/added-parameter-content-mediatype/petstore-added-parameter-content-mediatype.json") + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server parameter content media-type schema is incompatible with client schema") { + val clientOpenapi = readOpenAPI( + "/petstore/updated-parameter-content-mediatype-schema/petstore-updated-parameter-content-mediatype-schema.json" + ) + val serverOpenapi = readOpenAPI("/petstore/updated-parameter-content-mediatype-schema/petstore.json") + + val schemaMismatch = IncompatibleSchema(List(TypeMismatch(List(SchemaType.String), List(SchemaType.Array)))) + val mediaTypeIssue = IncompatibleMediaType("application/json", List(schemaMismatch)) + val parameterContentIssue = IncompatibleContent(List(mediaTypeIssue)) + val parameterIssue = IncompatibleParameter("status", List(parameterContentIssue)) + val operationIssue = IncompatibleOperation("get", List(parameterIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server missing parameter content media-type schema when client has one") { + val clientOpenapi = + readOpenAPI( + "/petstore/added-parameter-content-mediatype-schema/petstore-added-parameter-content-mediatype-schema.json" + ) + val serverOpenapi = readOpenAPI("/petstore/added-parameter-content-mediatype-schema/petstore.json") + + val schemaIssue = MissingSchema() + val mediaTypeIssue = IncompatibleMediaType("application/json", List(schemaIssue)) + val parameterContentIssue = IncompatibleContent(List(mediaTypeIssue)) + val parameterIssue = IncompatibleParameter("status", List(parameterContentIssue)) + val operationIssue = IncompatibleOperation("get", List(parameterIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has a parameter content media-type schema but client does not") { + val clientOpenapi = + readOpenAPI("/petstore/added-parameter-content-mediatype-schema/petstore.json") + val serverOpenapi = readOpenAPI( + "/petstore/added-parameter-content-mediatype-schema/petstore-added-parameter-content-mediatype-schema.json" + ) + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server parameter style is incompatible with client parameter style") { + val clientOpenapi = readOpenAPI("/petstore/updated-parameter-style/petstore-updated-parameter-style.json") + val serverOpenapi = readOpenAPI("/petstore/updated-parameter-style/petstore.json") + + val styleIssue = IncompatibleStyle(Some(ParameterStyle.Form), None) + val parameterIssue = IncompatibleParameter("status", List(styleIssue)) + val operationIssue = IncompatibleOperation("get", List(parameterIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server parameter explode is incompatible with client parameter explode") { + val clientOpenapi = + readOpenAPI("/petstore/updated-parameter-explode/petstore-updated-parameter-explode.json") + val serverOpenapi = readOpenAPI("/petstore/updated-parameter-explode/petstore.json") + + val explodeIssue = IncompatibleExplode(Some(true), None) + val parameterIssue = IncompatibleParameter("status", List(explodeIssue)) + val operationIssue = IncompatibleOperation("get", List(parameterIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server parameter allowEmptyValue is incompatible with client parameter allowEmptyValue") { + val clientOpenapi = + readOpenAPI("/petstore/updated-parameter-allow_empty_value/petstore-updated-parameter-allow_empty_value.json") + val serverOpenapi = readOpenAPI("/petstore/updated-parameter-allow_empty_value/petstore.json") + + val allowEmptyValueIssue = IncompatibleAllowEmptyValue(Some(true), None) + val parameterIssue = IncompatibleParameter("status", List(allowEmptyValueIssue)) + val operationIssue = IncompatibleOperation("get", List(parameterIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server parameter allowReserved is incompatible with client parameter allowReserved") { + val clientOpenapi = + readOpenAPI("/petstore/updated-parameter-allow_reserved/petstore-updated-parameter-allow_reserved.json") + val serverOpenapi = readOpenAPI("/petstore/updated-parameter-allow_reserved/petstore.json") + + val allowReservedIssue = IncompatibleAllowReserved(Some(true), None) + val parameterIssue = IncompatibleParameter("status", List(allowReservedIssue)) + val operationIssue = IncompatibleOperation("get", List(parameterIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server missing request-body when client has an extra one") { + val clientOpenapi = readOpenAPI("/petstore/added-requestbody/petstore-added-requestbody.json") + val serverOpenapi = readOpenAPI("/petstore/added-requestbody/petstore.json") + + val requestBodyIssue = MissingRequestBody() + val operationIssue = IncompatibleOperation("post", List(requestBodyIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has an additional request-body") { + val clientOpenapi = readOpenAPI("/petstore/added-requestbody/petstore.json") + val serverOpenapi = readOpenAPI("/petstore/added-requestbody/petstore-added-requestbody.json") + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server missing request-body content media-type when client has an extra one") { + val clientOpenapi = + readOpenAPI("/petstore/added-requestbody-content-mediatype/petstore-added-requestbody-content-mediatype.json") + val serverOpenapi = readOpenAPI("/petstore/added-requestbody-content-mediatype/petstore.json") + + val mediaTypeIssue = MissingMediaType("application/xml") + val requestBodyContentIssue = IncompatibleContent(List(mediaTypeIssue)) + val requestBodyIssue = IncompatibleRequestBody(List(requestBodyContentIssue)) + val operationIssue = IncompatibleOperation("post", List(requestBodyIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has an additional request-body content media-type") { + val clientOpenapi = readOpenAPI("/petstore/added-requestbody-content-mediatype/petstore.json") + val serverOpenapi = + readOpenAPI("/petstore/added-requestbody-content-mediatype/petstore-added-requestbody-content-mediatype.json") + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server request-body content media-type schema is incompatible with client schema") { + val clientOpenapi = readOpenAPI( + "/petstore/updated-requestbody-content-mediatype-schema/petstore-updated-requestbody-content-mediatype-schema.json" + ) + val serverOpenapi = readOpenAPI("/petstore/updated-requestbody-content-mediatype-schema/petstore.json") + + val schemaTypeMismatch = TypeMismatch(List(SchemaType.String), List(SchemaType.Object)) + val schemaIssue = IncompatibleSchema(List(schemaTypeMismatch)) + val mediaTypeIssue = IncompatibleMediaType("application/json", List(schemaIssue)) + val requestBodyContentIssue = IncompatibleContent(List(mediaTypeIssue)) + val requestBodyIssue = IncompatibleRequestBody(List(requestBodyContentIssue)) + val operationIssue = IncompatibleOperation("post", List(requestBodyIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server missing request-body content media-type schema when client has one") { + val clientOpenapi = + readOpenAPI( + "/petstore/added-requestbody-content-mediatype-schema/petstore-added-requestbody-content-mediatype-schema.json" + ) + val serverOpenapi = readOpenAPI("/petstore/added-requestbody-content-mediatype-schema/petstore.json") + + val schemaIssue = MissingSchema() + val mediaTypeIssue = IncompatibleMediaType("application/json", List(schemaIssue)) + val requestBodyContentIssue = IncompatibleContent(List(mediaTypeIssue)) + val requestBodyIssue = IncompatibleRequestBody(List(requestBodyContentIssue)) + val operationIssue = IncompatibleOperation("post", List(requestBodyIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has a request-body content media-type schema but client does not") { + val clientOpenapi = + readOpenAPI("/petstore/added-requestbody-content-mediatype-schema/petstore.json") + val serverOpenapi = readOpenAPI( + "/petstore/added-requestbody-content-mediatype-schema/petstore-added-requestbody-content-mediatype-schema.json" + ) + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server missing response when client has an extra one") { + val clientOpenapi = readOpenAPI("/petstore/added-response/petstore-added-response.json") + val serverOpenapi = readOpenAPI("/petstore/added-response/petstore.json") + + val responsesIssue = MissingResponse(ResponsesCodeKey(500)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has an additional response") { + val clientOpenapi = readOpenAPI("/petstore/added-response/petstore.json") + val serverOpenapi = readOpenAPI("/petstore/added-response/petstore-added-response.json") + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server missing response content media-type when client has an extra one") { + val clientOpenapi = + readOpenAPI("/petstore/added-response-content-mediatype/petstore-added-response-content-mediatype.json") + val serverOpenapi = readOpenAPI("/petstore/added-response-content-mediatype/petstore.json") + + val mediaTypeIssues = MissingMediaType("application/xml") + val responseContentIssues = IncompatibleContent(List(mediaTypeIssues)) + val responsesIssue = IncompatibleResponse(List(responseContentIssues)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has an additional response content media-type") { + val clientOpenapi = readOpenAPI("/petstore/added-response-content-mediatype/petstore.json") + val serverOpenapi = + readOpenAPI("/petstore/added-response-content-mediatype/petstore-added-response-content-mediatype.json") + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server response content media-type schema is incompatible with client schema") { + val clientOpenapi = readOpenAPI( + "/petstore/updated-response-content-mediatype-schema/petstore-updated-response-content-mediatype-schema.json" + ) + val serverOpenapi = readOpenAPI("/petstore/updated-response-content-mediatype-schema/petstore.json") + + val schemaTypeMismatch = TypeMismatch(List(SchemaType.String), List(SchemaType.Object)) + val schemaIssue = IncompatibleSchema(List(schemaTypeMismatch)) + val mediaTypeIssues = IncompatibleMediaType("application/xml", List(schemaIssue)) + val responseContentIssues = IncompatibleContent(List(mediaTypeIssues)) + val responsesIssue = IncompatibleResponse(List(responseContentIssues)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server missing response content media-type schema when client has one") { + val clientOpenapi = + readOpenAPI( + "/petstore/added-response-content-mediatype-schema/petstore-added-response-content-mediatype-schema.json" + ) + val serverOpenapi = readOpenAPI("/petstore/added-response-content-mediatype-schema/petstore.json") + + val schemaIssue = MissingSchema() + val mediaTypeIssues = IncompatibleMediaType("application/json", List(schemaIssue)) + val responseContentIssues = IncompatibleContent(List(mediaTypeIssues)) + val responsesIssue = IncompatibleResponse(List(responseContentIssues)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has a response content media-type schema but client does not") { + val clientOpenapi = + readOpenAPI("/petstore/added-response-content-mediatype-schema/petstore.json") + val serverOpenapi = readOpenAPI( + "/petstore/added-response-content-mediatype-schema/petstore-added-response-content-mediatype-schema.json" + ) + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server missing response header when client has an extra one") { + val clientOpenapi = readOpenAPI("/petstore/added-response-header/petstore-added-response-header.json") + val serverOpenapi = readOpenAPI("/petstore/added-response-header/petstore.json") + + val headerIssue = MissingHeader("X-Rate-Limit") + val responsesIssue = IncompatibleResponse(List(headerIssue)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has an additional response header") { + val clientOpenapi = readOpenAPI("/petstore/added-response-header/petstore.json") + val serverOpenapi = readOpenAPI("/petstore/added-response-header/petstore-added-response-header.json") + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server response header schema is incompatible with client schema") { + val clientOpenapi = + readOpenAPI("/petstore/updated-response-header-schema/petstore-updated-response-header-schema.json") + val serverOpenapi = readOpenAPI("/petstore/updated-response-header-schema/petstore.json") + + val schemaTypeMismatch = TypeMismatch(List(SchemaType.String), List(SchemaType.Integer)) + val schemaIssue = IncompatibleSchema(List(schemaTypeMismatch)) + val headerIssue = IncompatibleHeader("X-Rate-Limit", List(schemaIssue)) + val responsesIssue = IncompatibleResponse(List(headerIssue)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server missing response header schema when client has one") { + val clientOpenapi = + readOpenAPI("/petstore/added-response-header-schema/petstore-added-response-header-schema.json") + val serverOpenapi = readOpenAPI("/petstore/added-response-header-schema/petstore.json") + + val schemaIssue = MissingSchema() + val headerIssue = IncompatibleHeader("X-Rate-Limit", List(schemaIssue)) + val responsesIssue = IncompatibleResponse(List(headerIssue)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has a response header schema but client does not") { + val clientOpenapi = + readOpenAPI("/petstore/added-response-header-schema/petstore.json") + val serverOpenapi = readOpenAPI("/petstore/added-response-header-schema/petstore-added-response-header-schema.json") + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server missing response header content media-type when client has an extra one") { + val clientOpenapi = readOpenAPI( + "/petstore/added-response-header-content-mediatype/petstore-added-response-header-content-mediatype.json" + ) + val serverOpenapi = readOpenAPI("/petstore/added-response-header-content-mediatype/petstore.json") + + val mediaTypeIssues = MissingMediaType("application/json") + val contentIssues = IncompatibleContent(List(mediaTypeIssues)) + val headerIssue = IncompatibleHeader("X-Rate-Limit", List(contentIssues)) + val responsesIssue = IncompatibleResponse(List(headerIssue)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has an additional response header content media-type") { + val clientOpenapi = readOpenAPI("/petstore/added-response-header-content-mediatype/petstore.json") + val serverOpenapi = readOpenAPI( + "/petstore/added-response-header-content-mediatype/petstore-added-response-header-content-mediatype.json" + ) + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server response header content media-type schema is incompatible with client schema") { + val clientOpenapi = readOpenAPI( + "/petstore/updated-response-header-content-mediatype-schema/petstore-updated-response-header-content-mediatype-schema.json" + ) + val serverOpenapi = readOpenAPI("/petstore/updated-response-header-content-mediatype-schema/petstore.json") + + val schemaTypeMismatch = TypeMismatch(List(SchemaType.Integer), List(SchemaType.String)) + val schemaIssue = IncompatibleSchema(List(schemaTypeMismatch)) + val mediaTypeIssues = IncompatibleMediaType("application/json", List(schemaIssue)) + val contentIssues = IncompatibleContent(List(mediaTypeIssues)) + val headerIssue = IncompatibleHeader("X-Rate-Limit", List(contentIssues)) + val responsesIssue = IncompatibleResponse(List(headerIssue)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server missing response header content media-type schema when client has one") { + val clientOpenapi = + readOpenAPI( + "/petstore/added-response-header-content-mediatype-schema/petstore-added-response-header-content-mediatype-schema.json" + ) + val serverOpenapi = readOpenAPI("/petstore/added-response-header-content-mediatype-schema/petstore.json") + + val schemaIssue = MissingSchema() + val mediaTypeIssues = IncompatibleMediaType("application/json", List(schemaIssue)) + val contentIssues = IncompatibleContent(List(mediaTypeIssues)) + val headerIssue = IncompatibleHeader("X-Rate-Limit", List(contentIssues)) + val responsesIssue = IncompatibleResponse(List(headerIssue)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has a response header content media-type schema but client does not") { + val clientOpenapi = + readOpenAPI("/petstore/added-response-header-content-mediatype-schema/petstore.json") + val serverOpenapi = readOpenAPI( + "/petstore/added-response-header-content-mediatype-schema/petstore-added-response-header-content-mediatype-schema.json" + ) + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test("server response header style is incompatible with client response header style") { + val clientOpenapi = + readOpenAPI("/petstore/updated-response-header-style/petstore-updated-response-header-style.json") + val serverOpenapi = readOpenAPI("/petstore/updated-response-header-style/petstore.json") + + val styleIssue = IncompatibleStyle(Some(ParameterStyle.Form), None) + val headerIssue = IncompatibleHeader("X-Rate-Limit", List(styleIssue)) + val responsesIssue = IncompatibleResponse(List(headerIssue)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server response header explode is incompatible with client response header explode") { + val clientOpenapi = + readOpenAPI("/petstore/updated-response-header-explode/petstore-updated-response-header-explode.json") + val serverOpenapi = readOpenAPI("/petstore/updated-response-header-explode/petstore.json") + + val explodeIssue = IncompatibleExplode(Some(true), None) + val headerIssue = IncompatibleHeader("X-Rate-Limit", List(explodeIssue)) + val responsesIssue = IncompatibleResponse(List(headerIssue)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server response header allowEmptyValue is incompatible with client response header allowEmptyValue") { + val clientOpenapi = readOpenAPI( + "/petstore/updated-response-header-allow_empty_value/petstore-updated-response-header-allow_empty_value.json" + ) + val serverOpenapi = readOpenAPI("/petstore/updated-response-header-allow_empty_value/petstore.json") + + val allowEmptyValueIssue = IncompatibleAllowEmptyValue(Some(true), None) + val headerIssue = IncompatibleHeader("X-Rate-Limit", List(allowEmptyValueIssue)) + val responsesIssue = IncompatibleResponse(List(headerIssue)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server response header allowReserved is incompatible with client response header allowReserved") { + val clientOpenapi = readOpenAPI( + "/petstore/updated-response-header-allow_reserved/petstore-updated-response-header-allow_reserved.json" + ) + val serverOpenapi = readOpenAPI("/petstore/updated-response-header-allow_reserved/petstore.json") + + val allowReservedIssue = IncompatibleAllowReserved(Some(true), None) + val headerIssue = IncompatibleHeader("X-Rate-Limit", List(allowReservedIssue)) + val responsesIssue = IncompatibleResponse(List(headerIssue)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server parameter name is incompatible with client parameter name") { + val clientOpenapi = readOpenAPI("/petstore/updated-parameter-name/petstore-updated-parameter-name.json") + val serverOpenapi = readOpenAPI("/petstore/updated-parameter-name/petstore.json") + + val expected = List(MissingPath("/pets/{Id}")) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server parameter required value is incompatible with client parameter required value") { + val clientOpenapi = readOpenAPI("/petstore/required-parameter/petstore-required-parameter.json") + val serverOpenapi = readOpenAPI("/petstore/required-parameter/petstore.json") + + val requiredValueIssue = IncompatibleRequiredValue(Some(true), Some(false)) + val parameterIssue = IncompatibleParameter("petId", List(requiredValueIssue)) + val operationIssue = IncompatibleOperation("get", List(parameterIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server response header required value is incompatible with client response header required value") { + val clientOpenapi = readOpenAPI("/petstore/required-response-header/petstore-required-response-header.json") + val serverOpenapi = readOpenAPI("/petstore/required-response-header/petstore.json") + + val requiredValueIssue = IncompatibleRequiredValue(Some(true), Some(false)) + val headerIssue = IncompatibleHeader("X-Rate-Limit", List(requiredValueIssue)) + val responsesIssue = IncompatibleResponse(List(headerIssue)) + val operationIssue = IncompatibleOperation("get", List(responsesIssue)) + val pathIssue = IncompatiblePath("/pets/{petId}", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server request-body required value is incompatible with client request-body required value") { + val clientOpenapi = readOpenAPI("/petstore/required-request-body/petstore-required-request-body.json") + val serverOpenapi = readOpenAPI("/petstore/required-request-body/petstore.json") + + val requiredValueIssue = IncompatibleRequiredValue(Some(true), Some(false)) + val requestBodyIssue = IncompatibleRequestBody(List(requiredValueIssue)) + val operationIssue = IncompatibleOperation("post", List(requestBodyIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server missing request-body content media-type encoding when client has one") { + val clientOpenapi = readOpenAPI( + "/petstore/added-requestbody-content-mediatype-encoding/petstore-added-requestbody-content-mediatype-encoding.json" + ) + val serverOpenapi = readOpenAPI("/petstore/added-requestbody-content-mediatype-encoding/petstore.json") + + val encodingIssue = MissingEncoding("photo") + val mediaTypeIssues = IncompatibleMediaType("multipart/form-data", List(encodingIssue)) + val contentIssues = IncompatibleContent(List(mediaTypeIssues)) + val requestBodyIssue = IncompatibleRequestBody(List(contentIssues)) + val operationIssue = IncompatibleOperation("post", List(requestBodyIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("no errors when server has a request-body content media-type encoding but client does not") { + val clientOpenapi = readOpenAPI("/petstore/added-requestbody-content-mediatype-encoding/petstore.json") + val serverOpenapi = readOpenAPI( + "/petstore/added-requestbody-content-mediatype-encoding/petstore-added-requestbody-content-mediatype-encoding.json" + ) + + assert(compare(clientOpenapi, serverOpenapi).isEmpty) + } + + test( + "server request-body content media-type encoding is incompatible with client request-body content media-type encoding" + ) { + val clientOpenapi = + readOpenAPI( + "/petstore/updated-requestbody-content-mediatype-encoding/petstore-updated-requestbody-content-mediatype-encoding.json" + ) + val serverOpenapi = readOpenAPI("/petstore/updated-requestbody-content-mediatype-encoding/petstore.json") + + val missingHeaderIssue = MissingHeader("X-Custom-Header") + val allowReservedIssue = IncompatibleAllowReserved(Some(false), None) + val explodeIssue = IncompatibleExplode(Some(true), None) + val styleIssue = IncompatibleStyle(Some(ParameterStyle.Form), None) + val encodingIssue = IncompatibleEncoding( + "photo", + List( + missingHeaderIssue, + styleIssue, + explodeIssue, + allowReservedIssue + ) + ) + val mediaTypeIssue = IncompatibleMediaType("multipart/form-data", List(encodingIssue)) + val contentIssue = IncompatibleContent(List(mediaTypeIssue)) + val requestBodyIssue = IncompatibleRequestBody(List(contentIssue)) + val operationIssue = IncompatibleOperation("post", List(requestBodyIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("server operation security is incompatible with client operation security") { + val clientOpenapi = readOpenAPI("/petstore/updated-operation-security/petstore-updated-operation-security.json") + val serverOpenapi = readOpenAPI("/petstore/updated-operation-security/petstore.json") + + val securityRequirementIssue = + IncompatibleSecurityRequirement(ListMap("OAuth2" -> Vector("read:pets", "write:pets"))) + val operationIssue = IncompatibleOperation("get", List(securityRequirementIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + val expected = List(pathIssue) + + assert(compare(clientOpenapi, serverOpenapi) == expected) + } + + test("format single issue description correctly") { + val clientOpenapi = readOpenAPI("/petstore/added-path/petstore-added-path.json") + val serverOpenapi = readOpenAPI("/petstore/added-path/petstore.json") + + val expected = List(MissingPath("/pets/{petId}")) + val expectedDescription = "List(missing path: /pets/{petId})" + + val result = compare(clientOpenapi, serverOpenapi) + + assert(result == expected) + assert(result.toString() == expectedDescription) + } + + test("render list of issues with proper indentation") { + val clientOpenapi = readOpenAPI("/petstore/updated-parameter-style/petstore-updated-parameter-style.json") + val serverOpenapi = readOpenAPI("/petstore/updated-parameter-style/petstore.json") + + val styleIssue = IncompatibleStyle(Some(ParameterStyle.Form), None) + val parameterIssue = IncompatibleParameter("status", List(styleIssue)) + val operationIssue = IncompatibleOperation("get", List(parameterIssue)) + val pathIssue = IncompatiblePath("/pets", List(operationIssue)) + + val expected = List(pathIssue) + val expectedDescription = + "List(incompatible path /pets:\n- incompatible operation get:\n - incompatible parameter status:\n - incompatible style value: client=Some(Form), server=None)" + + val result = compare(clientOpenapi, serverOpenapi) + + assert(result == expected) + assert(result.toString() == expectedDescription) + } +} diff --git a/openapi-model/src/main/scala/sttp/apispec/openapi/validation/OpenAPIComparator.scala b/openapi-model/src/main/scala/sttp/apispec/openapi/validation/OpenAPIComparator.scala new file mode 100644 index 0000000..e30e7ee --- /dev/null +++ b/openapi-model/src/main/scala/sttp/apispec/openapi/validation/OpenAPIComparator.scala @@ -0,0 +1,376 @@ +package sttp.apispec.openapi.validation + +import sttp.apispec.{Schema, SchemaLike} +import sttp.apispec.openapi.{ + Encoding, + Header, + MediaType, + OpenAPI, + Operation, + Parameter, + PathItem, + RequestBody, + Response +} +import sttp.apispec.validation.SchemaComparator + +import scala.collection.immutable.ListMap + +object OpenAPIComparator { + def apply(clientOpenAPI: OpenAPI, serverOpenAPI: OpenAPI): OpenAPIComparator = + new OpenAPIComparator(clientOpenAPI, serverOpenAPI) +} + +/** A utility for comparing two OpenAPI specifications to validate their compatibility. + * + * The `OpenAPIComparator` class compares the client's OpenAPI specification with the server's specification to detect + * and highlight compatibility issues. It evaluates various components including paths, operations, parameters, request + * bodies, responses, headers, schemas, content, and media types. + * + * Note: This comparator does not compare meta-data, such as the info object, server lists, or descriptions in + * properties. + * + * @param clientOpenAPI + * the OpenAPI specification provided by the client. + * @param serverOpenAPI + * the OpenAPI specification provided by the server. + */ + +class OpenAPIComparator private ( + clientOpenAPI: OpenAPI, + serverOpenAPI: OpenAPI +) { + + private val httpMethods = List( + ("get", (_: PathItem).get), + ("post", (_: PathItem).post), + ("patch", (_: PathItem).patch), + ("delete", (_: PathItem).delete), + ("options", (_: PathItem).options), + ("trace", (_: PathItem).trace), + ("head", (_: PathItem).head), + ("put", (_: PathItem).put) + ) + + private val clientSchemas: Map[String, Schema] = clientOpenAPI.components match { + case Some(components) => + components.schemas.flatMap { + case (key, schema: Schema) => Some((key, schema)) + case _ => None + } + case _ => Map.empty[String, Schema] + } + + private val serverSchemas: Map[String, Schema] = serverOpenAPI.components match { + case Some(components) => + components.schemas.flatMap { + case (key, schema: Schema) => Some((key, schema)) + case _ => None + } + case _ => Map.empty[String, Schema] + } + + /** Compares the client and server OpenAPI specifications for compatibility. + * + * This method compares the paths in both specifications to identify compatibility issues. It detects + * incompatibilities such as missing paths, parameter mismatches, schema inconsistencies, and other discrepancies. It + * organizes the issues into a tree-like structure, with main issues and their sub-issues. + * + * @return + * a list of `OpenAPICompatibilityIssue` instances detailing the identified issues. + */ + + def compare(): List[OpenAPICompatibilityIssue] = { + clientOpenAPI.paths.pathItems.toList.flatMap { + case (pathName, clientPathItem) => + val serverPathItem = serverOpenAPI.paths.pathItems.get(pathName) + serverPathItem match { + case None => Some(MissingPath(pathName)) + case Some(serverPathItem) => + val pathIssues = checkPath(pathName, clientPathItem, serverPathItem) + if (pathIssues.isEmpty) + None + else + pathIssues + case _ => None + } + case _ => None + } + } + + private def checkPath( + pathName: String, + clientPathItem: PathItem, + serverPathItem: PathItem + ): Option[IncompatiblePath] = { + val issues = httpMethods.flatMap { case (httpMethod, getOperation) => + val clientOperation = getOperation(clientPathItem) + val serverOperation = getOperation(serverPathItem) + + (clientOperation, serverOperation) match { + case (Some(_), None) => Some(MissingOperation(httpMethod)) + case (Some(clientOp), Some(serverOp)) => checkOperation(httpMethod, clientOp, serverOp) + case _ => None + } + } + if (issues.isEmpty) + None + else + Some(IncompatiblePath(pathName, issues)) + } + + private def checkOperation( + httpMethod: String, + clientOperation: Operation, + serverOperation: Operation + ): Option[IncompatibleOperation] = { + val serverParameters = getOperationParameters(serverOperation) + val clientParameters = getOperationParameters(clientOperation) + + val parametersIssue = clientParameters.flatMap { clientParameter => + val serverParameter = serverParameters.find(_.name == clientParameter.name) + serverParameter match { + case None => Some(MissingParameter(clientParameter.name)) + case Some(serverParameter) => checkParameter(clientParameter, serverParameter) + } + } + + val requestBodyIssue = (clientOperation.requestBody, serverOperation.requestBody) match { + case (Some(Right(clientRequestBody)), Some(Right(serverRequestBody))) => + checkRequestBody(clientRequestBody, serverRequestBody) + case (Some(Right(_)), None) => Some(MissingRequestBody()) + case _ => None + } + + val responsesIssues = clientOperation.responses.responses.flatMap { + case (clientResponseKey, Right(clientResponse)) => + val serverResponse = serverOperation.responses.responses.get(clientResponseKey) + serverResponse match { + case Some(Right(serverResponse)) => checkResponse(clientResponse, serverResponse) + case None => Some(MissingResponse(clientResponseKey)) + case _ => None + } + case _ => None + } + + // TODO: callbacks + val incompatibleSecurityRequirements = clientOperation.security.filterNot(serverOperation.security.contains) + val securityIssues = incompatibleSecurityRequirements.map(IncompatibleSecurityRequirement(_)) + + val issues = parametersIssue ++ requestBodyIssue ++ responsesIssues ++ securityIssues + if (issues.isEmpty) + None + else + Some(IncompatibleOperation(httpMethod, issues)) + } + + private def checkParameter(clientParameter: Parameter, serverParameter: Parameter): Option[IncompatibleParameter] = { + val isCompatibleStyle = serverParameter.style == clientParameter.style + val isCompatibleExplode = serverParameter.explode == clientParameter.explode + val isCompatibleAllowEmptyValue = serverParameter.allowEmptyValue == clientParameter.allowEmptyValue + val isCompatibleAllowReserved = serverParameter.allowReserved == clientParameter.allowReserved + val isCompatibleRequiredValue = serverParameter.required == clientParameter.required + + val issues = + checkSchema(clientParameter.schema, serverParameter.schema).toList ++ + checkContent(clientParameter.content, serverParameter.content).toList ++ + (if (!isCompatibleStyle) Some(IncompatibleStyle(clientParameter.style, serverParameter.style)) + else None).toList ++ + (if (!isCompatibleExplode) Some(IncompatibleExplode(clientParameter.explode, serverParameter.explode)) + else None).toList ++ + (if (!isCompatibleAllowEmptyValue) + Some(IncompatibleAllowEmptyValue(clientParameter.allowEmptyValue, serverParameter.allowEmptyValue)) + else None).toList ++ + (if (!isCompatibleAllowReserved) + Some(IncompatibleAllowReserved(clientParameter.allowReserved, serverParameter.allowReserved)) + else None).toList ++ + (if (!isCompatibleRequiredValue) + Some(IncompatibleRequiredValue(clientParameter.required, serverParameter.required)) + else None).toList + + if (issues.isEmpty) + None + else + Some(IncompatibleParameter(clientParameter.name, issues)) + } + + private def checkContent( + clientContent: ListMap[String, MediaType], + serverContent: ListMap[String, MediaType] + ): Option[IncompatibleContent] = { + val issues = clientContent.flatMap { case (clientMediaType, clientMediaTypeDescription) => + val serverMediaTypeDescription = serverContent.get(clientMediaType) + serverMediaTypeDescription match { + case None => Some(MissingMediaType(clientMediaType)) + case Some(serverMediaTypeDescription) => + checkMediaType(clientMediaType, clientMediaTypeDescription, serverMediaTypeDescription) + } + } + + if (issues.isEmpty) + None + else + Some(IncompatibleContent(issues.toList)) + } + + private def checkEncoding( + encodingName: String, + clientEncoding: Encoding, + serverEncoding: Encoding + ): Option[IncompatibleEncoding] = { + val isCompatibleStyle = serverEncoding.style == clientEncoding.style + val isCompatibleExplode = serverEncoding.explode == clientEncoding.explode + val isCompatibleAllowReserved = serverEncoding.allowReserved == clientEncoding.allowReserved + val isCompatibleContentType = serverEncoding.contentType == clientEncoding.contentType + val headerIssues = clientEncoding.headers.flatMap { + case (clientHeaderName, Right(clientHeader)) => + val serverHeader = serverEncoding.headers.get(clientHeaderName) + serverHeader match { + case Some(Right(serverHeader)) => checkResponseHeader(clientHeaderName, clientHeader, serverHeader) + case None => Some(MissingHeader(clientHeaderName)) + case _ => None + } + case _ => None + } + + val issues = headerIssues ++ + (if (!isCompatibleStyle) Some(IncompatibleStyle(clientEncoding.style, serverEncoding.style)) else None).toList ++ + (if (!isCompatibleContentType) + Some(IncompatibleContentType(clientEncoding.contentType, serverEncoding.contentType)) + else None).toList ++ + (if (!isCompatibleExplode) Some(IncompatibleExplode(clientEncoding.explode, serverEncoding.explode)) + else None).toList ++ + (if (!isCompatibleAllowReserved) + Some(IncompatibleAllowReserved(clientEncoding.allowReserved, serverEncoding.allowReserved)) + else None).toList + + if (issues.nonEmpty) + Some(IncompatibleEncoding(encodingName, issues.toList)) + else + None + } + + private def checkMediaType( + mediaType: String, + clientMediaTypeDescription: MediaType, + serverMediaTypeDescription: MediaType + ): Option[IncompatibleMediaType] = { + val encodingIssues = clientMediaTypeDescription.encoding.flatMap { case (clientEncodingName, clientEncoding) => + val serverEncoding = serverMediaTypeDescription.encoding.get(clientEncodingName) + serverEncoding match { + case None => Some(MissingEncoding(clientEncodingName)) + case Some(serverEncoding) => checkEncoding(clientEncodingName, clientEncoding, serverEncoding) + } + } + + val issues = checkSchema(clientMediaTypeDescription.schema, serverMediaTypeDescription.schema) ++ encodingIssues + if (issues.nonEmpty) + Some(IncompatibleMediaType(mediaType, issues.toList)) + else + None + } + + private def checkSchema( + clientSchema: Option[SchemaLike], + serverSchema: Option[SchemaLike] + ): Option[OpenAPICompatibilityIssue] = { + (clientSchema, serverSchema) match { + case (Some(clientSchema), Some(serverSchema)) => + val schemaComparator = new SchemaComparator(clientSchemas, serverSchemas) + val schemaIssues = schemaComparator.compare(clientSchema, serverSchema) + if (schemaIssues.nonEmpty) + Some(IncompatibleSchema(schemaIssues)) + else + None + case (Some(_), None) => Some(MissingSchema()) + case _ => None + } + } + + private def getOperationParameters(operation: Operation): List[Parameter] = { + operation.parameters.flatMap { + case Right(parameter) => Some(parameter) + case Left(reference) => resolveParameterReference(serverOpenAPI, reference.$ref) + } + } + + private def resolveParameterReference(openAPI: OpenAPI, ref: String): Option[Parameter] = { + openAPI.components match { + case Some(component) => component.getLocalParameter(ref) + case None => None + } + } + + private def checkRequestBody( + clientRequestBody: RequestBody, + serverRequestBody: RequestBody + ): Option[IncompatibleRequestBody] = { + val isCompatibleRequiredValue = serverRequestBody.required == clientRequestBody.required + val contentIssues = checkContent(clientRequestBody.content, serverRequestBody.content).toList + + val issues = contentIssues ++ + (if (!isCompatibleRequiredValue) + Some(IncompatibleRequiredValue(clientRequestBody.required, serverRequestBody.required)) + else None).toList + + if (issues.nonEmpty) + Some(IncompatibleRequestBody(issues)) + else + None + } + + private def checkResponse(clientResponse: Response, serverResponse: Response): Option[IncompatibleResponse] = { + val contentIssue = checkContent(clientResponse.content, serverResponse.content) + val headerIssues = clientResponse.headers.flatMap { + case (clientHeaderName, Right(clientHeader)) => + val serverHeader = serverResponse.headers.get(clientHeaderName) + serverHeader match { + case Some(Right(serverHeader)) => checkResponseHeader(clientHeaderName, clientHeader, serverHeader) + case None => Some(MissingHeader(clientHeaderName)) + case _ => None + } + case _ => None + } + + val issues = contentIssue.toList ++ headerIssues + if (issues.nonEmpty) + Some(IncompatibleResponse(issues)) + else + None + } + + private def checkResponseHeader( + headerName: String, + clientHeader: Header, + serverHeader: Header + ): Option[IncompatibleHeader] = { + val schemaIssues = checkSchema(clientHeader.schema, serverHeader.schema) + val contentIssue = checkContent(clientHeader.content, serverHeader.content) + val isCompatibleStyle = serverHeader.style == clientHeader.style + val isCompatibleExplode = serverHeader.explode == clientHeader.explode + val isCompatibleAllowEmptyValue = serverHeader.allowEmptyValue == clientHeader.allowEmptyValue + val isCompatibleAllowReserved = serverHeader.allowReserved == clientHeader.allowReserved + val isCompatibleRequiredValue = serverHeader.required == clientHeader.required + + val issues = + schemaIssues.toList ++ + contentIssue.toList ++ + (if (!isCompatibleStyle) Some(IncompatibleStyle(clientHeader.style, serverHeader.style)) else None).toList ++ + (if (!isCompatibleExplode) Some(IncompatibleExplode(clientHeader.explode, serverHeader.explode)) + else None).toList ++ + (if (!isCompatibleAllowEmptyValue) + Some(IncompatibleAllowEmptyValue(clientHeader.allowEmptyValue, serverHeader.allowEmptyValue)) + else None).toList ++ + (if (!isCompatibleAllowReserved) + Some(IncompatibleAllowReserved(clientHeader.allowReserved, serverHeader.allowReserved)) + else None).toList ++ + (if (!isCompatibleRequiredValue) + Some(IncompatibleRequiredValue(clientHeader.required, serverHeader.required)) + else None).toList + + if (issues.nonEmpty) + Some(IncompatibleHeader(headerName, issues)) + else + None + } +} diff --git a/openapi-model/src/main/scala/sttp/apispec/openapi/validation/OpenAPICompatibilityIssue.scala b/openapi-model/src/main/scala/sttp/apispec/openapi/validation/OpenAPICompatibilityIssue.scala new file mode 100644 index 0000000..12f625d --- /dev/null +++ b/openapi-model/src/main/scala/sttp/apispec/openapi/validation/OpenAPICompatibilityIssue.scala @@ -0,0 +1,175 @@ +package sttp.apispec.openapi.validation + +import sttp.apispec.SecurityRequirement +import sttp.apispec.openapi.{ParameterStyle, ResponsesKey} +import sttp.apispec.validation.SchemaCompatibilityIssue + +sealed abstract class OpenAPICompatibilityIssue { + def description: String + + override def toString: String = description + protected def issuesRepr(issues: List[OpenAPICompatibilityIssue]): String = + issues.iterator + .map(i => s"- ${i.description.replace("\n", "\n ")}") // indent + .mkString("\n") +} + +sealed abstract class OpenAPICompatibilitySubIssues extends OpenAPICompatibilityIssue { + def subIssues: List[OpenAPICompatibilityIssue] +} + +case class MissingPath(pathName: String) extends OpenAPICompatibilityIssue { + def description: String = + s"missing path: $pathName" +} + +case class IncompatiblePath( + pathName: String, + subIssues: List[OpenAPICompatibilityIssue] +) extends OpenAPICompatibilitySubIssues { + def description: String = + s"incompatible path $pathName:\n${issuesRepr(subIssues)}" +} + +case class MissingOperation(httpMethod: String) extends OpenAPICompatibilityIssue { + def description: String = + s"missing operation for $httpMethod method" +} + +case class IncompatibleOperation( + httpMethod: String, + subIssues: List[OpenAPICompatibilityIssue] +) extends OpenAPICompatibilitySubIssues { + def description: String = + s"incompatible operation $httpMethod:\n${issuesRepr(subIssues)}" +} + +case class MissingParameter( + name: String +) extends OpenAPICompatibilityIssue { + def description: String = + s"missing parameter $name" +} + +case class IncompatibleRequiredValue( + clientValue: Option[Boolean], + serverValue: Option[Boolean] +) extends OpenAPICompatibilityIssue { + def description: String = + s"required value mismatch: client has $clientValue, but server has $serverValue" +} + +case class IncompatibleParameter( + name: String, + subIssues: List[OpenAPICompatibilityIssue] +) extends OpenAPICompatibilitySubIssues { + def description: String = + s"incompatible parameter $name:\n${issuesRepr(subIssues)}" +} + +case class IncompatibleSchema( + schemaIssues: List[SchemaCompatibilityIssue] +) extends OpenAPICompatibilityIssue { + def description: String = + s"incompatible schema:\n${schemaIssues}" +} + +case class IncompatibleContent( + subIssues: List[OpenAPICompatibilityIssue] +) extends OpenAPICompatibilitySubIssues { + def description: String = + s"incompatible content:\n${issuesRepr(subIssues)}" +} + +case class MissingMediaType(mediaType: String) extends OpenAPICompatibilityIssue { + def description: String = + s"missing media type $mediaType" +} + +case class IncompatibleMediaType(mediaType: String, subIssues: List[OpenAPICompatibilityIssue]) + extends OpenAPICompatibilitySubIssues { + def description: String = + s"incompatible media type $mediaType:\n${issuesRepr(subIssues)}" +} + +case class IncompatibleStyle(clientValue: Option[ParameterStyle], serverValue: Option[ParameterStyle]) + extends OpenAPICompatibilityIssue { + def description: String = + s"incompatible style value: client=$clientValue, server=$serverValue" +} + +case class IncompatibleExplode(clientValue: Option[Boolean], serverValue: Option[Boolean]) + extends OpenAPICompatibilityIssue { + def description: String = + s"incompatible explode value: client=$clientValue, server=$serverValue" +} + +case class IncompatibleAllowEmptyValue(clientValue: Option[Boolean], serverValue: Option[Boolean]) + extends OpenAPICompatibilityIssue { + def description: String = + s"incompatible allowEmptyValue value: client=$clientValue, server=$serverValue" +} + +case class IncompatibleAllowReserved(clientValue: Option[Boolean], serverValue: Option[Boolean]) + extends OpenAPICompatibilityIssue { + def description: String = + s"incompatible allowReserved value: client=$clientValue, server=$serverValue" +} + +case class MissingRequestBody() extends OpenAPICompatibilityIssue { + def description: String = + s"missing request body" +} + +case class IncompatibleRequestBody(subIssues: List[OpenAPICompatibilityIssue]) extends OpenAPICompatibilitySubIssues { + def description: String = + s"incompatible request body:\n${issuesRepr(subIssues)}" +} + +case class MissingResponse(responsesKey: ResponsesKey) extends OpenAPICompatibilityIssue { + def description: String = + s"missing response for $responsesKey" +} + +case class IncompatibleResponse(subIssues: List[OpenAPICompatibilityIssue]) extends OpenAPICompatibilitySubIssues { + def description: String = + s"incompatible response:\n${issuesRepr(subIssues)}" +} + +case class MissingHeader(headerName: String) extends OpenAPICompatibilityIssue { + def description: String = + s"missing header $headerName" +} + +case class IncompatibleHeader(headerName: String, subIssues: List[OpenAPICompatibilityIssue]) + extends OpenAPICompatibilitySubIssues { + def description: String = + s"incompatible header $headerName:\n${issuesRepr(subIssues)}" +} + +case class MissingSchema() extends OpenAPICompatibilityIssue { + def description: String = + s"missing schema" +} + +case class MissingEncoding(encodingName: String) extends OpenAPICompatibilityIssue { + def description: String = + s"missing encoding $encodingName" +} + +case class IncompatibleEncoding(encodingName: String, subIssues: List[OpenAPICompatibilityIssue]) + extends OpenAPICompatibilityIssue { + def description: String = + s"incompatible encoding $encodingName:\n${issuesRepr(subIssues)}" +} + +case class IncompatibleContentType(clientValue: Option[String], serverValue: Option[String]) + extends OpenAPICompatibilityIssue { + def description: String = + s"incompatible contentType: client=$clientValue, server=$serverValue" +} + +case class IncompatibleSecurityRequirement(securityRequirement: SecurityRequirement) extends OpenAPICompatibilityIssue { + def description: String = + s"incompatible security requirement $securityRequirement" +}