diff --git a/src/schema.rs b/src/schema.rs index 8dc849d..133c978 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -435,7 +435,7 @@ impl Compare { if old_boolean != new_boolean { self.schema_push_change( dry_run, - "integer schema changed", + "boolean schema changed", &old_schema_type, &new_schema_type, comparison, @@ -733,6 +733,9 @@ impl Compare { Ok(ret) } + // NOTE: Single-element allOf schemas are flattened by `try_compare_flattened` + // before reaching this function. Multi-element allOf would require semantic + // merging for proper comparison, so we just do an equality check. fn compare_schema_type_all_of( &mut self, comparison: SchemaComparison, @@ -740,37 +743,19 @@ impl Compare { old_all_of: Contextual<'_, &Vec>>, new_all_of: Contextual<'_, &Vec>>, ) -> anyhow::Result { - let old_schemas = old_all_of.as_ref(); - let new_schemas = new_all_of.as_ref(); - - if old_schemas.len() != new_schemas.len() { - return self.schema_push_change( - dry_run, - "allOf schema count changed", - &old_all_of, - &new_all_of, - comparison, - ChangeClass::Unhandled, - ChangeDetails::UnknownDifference, - ); - } - - if old_schemas.len() != 1 { - return self.schema_push_change( + if old_all_of.as_ref() != new_all_of.as_ref() { + self.schema_push_change( dry_run, - "allOf with multiple schemas is unhandled", + "unhandled, 'allOf' schema", &old_all_of, &new_all_of, comparison, ChangeClass::Unhandled, ChangeDetails::UnknownDifference, - ); + ) + } else { + Ok(true) } - - let old_single_schema = old_all_of.append_deref(old_all_of.first().unwrap(), "0"); - let new_single_schema = new_all_of.append_deref(new_all_of.first().unwrap(), "0"); - - self.compare_schema_ref_helper(dry_run, comparison, old_single_schema, new_single_schema) } #[allow(clippy::too_many_arguments)] diff --git a/tests/cases/simple/base.json b/tests/cases/simple/base.json index 208443e..9b0c33a 100644 --- a/tests/cases/simple/base.json +++ b/tests/cases/simple/base.json @@ -253,6 +253,60 @@ } } } + }, + "/oneof": { + "get": { + "operationId": "get_oneof", + "summary": "Get oneOf schema", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MultiOneOf" + } + } + } + } + } + } + }, + "/anyof": { + "get": { + "operationId": "get_anyof", + "summary": "Get anyOf schema", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AnyOfExample" + } + } + } + } + } + } + }, + "/allof": { + "get": { + "operationId": "get_allof", + "summary": "Get allOf schema", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MultiAllOf" + } + } + } + } + } + } } }, "components": { diff --git a/tests/cases/simple/output/add-cookie-parameter.out b/tests/cases/simple/output/add-cookie-parameter.out index fe0f605..805b882 100644 --- a/tests/cases/simple/output/add-cookie-parameter.out +++ b/tests/cases/simple/output/add-cookie-parameter.out @@ -1,6 +1,6 @@ --- add-cookie-parameter.json +++ patched -@@ -311,6 +311,16 @@ +@@ -365,6 +365,16 @@ "get": { "description": "A simple ping endpoint that does nothing.", "operationId": "ping", diff --git a/tests/cases/simple/output/add-default-response.out b/tests/cases/simple/output/add-default-response.out index c1b92d0..712492a 100644 --- a/tests/cases/simple/output/add-default-response.out +++ b/tests/cases/simple/output/add-default-response.out @@ -1,6 +1,6 @@ --- add-default-response.json +++ patched -@@ -314,6 +314,16 @@ +@@ -368,6 +368,16 @@ "responses": { "200": { "description": "Ping successful" diff --git a/tests/cases/simple/output/add-header-parameter.out b/tests/cases/simple/output/add-header-parameter.out index c904528..006a63b 100644 --- a/tests/cases/simple/output/add-header-parameter.out +++ b/tests/cases/simple/output/add-header-parameter.out @@ -1,6 +1,6 @@ --- add-header-parameter.json +++ patched -@@ -311,6 +311,16 @@ +@@ -365,6 +365,16 @@ "get": { "description": "A simple ping endpoint that does nothing.", "operationId": "ping", diff --git a/tests/cases/simple/output/add-operation-with-id.out b/tests/cases/simple/output/add-operation-with-id.out index d9c8000..7b51342 100644 --- a/tests/cases/simple/output/add-operation-with-id.out +++ b/tests/cases/simple/output/add-operation-with-id.out @@ -1,6 +1,6 @@ --- add-operation-with-id.json +++ patched -@@ -278,6 +278,17 @@ +@@ -314,6 +314,17 @@ "summary": "Update an item" } }, diff --git a/tests/cases/simple/output/add-operation.out b/tests/cases/simple/output/add-operation.out index f811442..f938e86 100644 --- a/tests/cases/simple/output/add-operation.out +++ b/tests/cases/simple/output/add-operation.out @@ -1,6 +1,6 @@ --- add-operation.json +++ patched -@@ -202,6 +202,16 @@ +@@ -238,6 +238,16 @@ "summary": "Get arrays" } }, diff --git a/tests/cases/simple/output/add-optional-body.out b/tests/cases/simple/output/add-optional-body.out index fed8126..75fe676 100644 --- a/tests/cases/simple/output/add-optional-body.out +++ b/tests/cases/simple/output/add-optional-body.out @@ -1,6 +1,6 @@ --- add-optional-body.json +++ patched -@@ -281,6 +281,21 @@ +@@ -317,6 +317,21 @@ "/no-body": { "post": { "operationId": "no_body", diff --git a/tests/cases/simple/output/add-optional-parameter.out b/tests/cases/simple/output/add-optional-parameter.out index c312850..34b0217 100644 --- a/tests/cases/simple/output/add-optional-parameter.out +++ b/tests/cases/simple/output/add-optional-parameter.out @@ -1,6 +1,6 @@ --- add-optional-parameter.json +++ patched -@@ -221,6 +221,15 @@ +@@ -257,6 +257,15 @@ "schema": { "type": "string" } diff --git a/tests/cases/simple/output/add-required-body.out b/tests/cases/simple/output/add-required-body.out index 249a23c..47d7d4e 100644 --- a/tests/cases/simple/output/add-required-body.out +++ b/tests/cases/simple/output/add-required-body.out @@ -1,6 +1,6 @@ --- add-required-body.json +++ patched -@@ -281,6 +281,21 @@ +@@ -317,6 +317,21 @@ "/no-body": { "post": { "operationId": "no_body", diff --git a/tests/cases/simple/output/add-required-parameter.out b/tests/cases/simple/output/add-required-parameter.out index f081446..b2e82b0 100644 --- a/tests/cases/simple/output/add-required-parameter.out +++ b/tests/cases/simple/output/add-required-parameter.out @@ -1,6 +1,6 @@ --- add-required-parameter.json +++ patched -@@ -221,6 +221,15 @@ +@@ -257,6 +257,15 @@ "schema": { "type": "string" } diff --git a/tests/cases/simple/output/add-response-code.out b/tests/cases/simple/output/add-response-code.out index 8e51f43..4d98490 100644 --- a/tests/cases/simple/output/add-response-code.out +++ b/tests/cases/simple/output/add-response-code.out @@ -1,6 +1,6 @@ --- add-response-code.json +++ patched -@@ -314,6 +314,9 @@ +@@ -368,6 +368,9 @@ "responses": { "200": { "description": "Ping successful" diff --git a/tests/cases/simple/output/body-description-change.out b/tests/cases/simple/output/body-description-change.out index 81ebede..3e2eb01 100644 --- a/tests/cases/simple/output/body-description-change.out +++ b/tests/cases/simple/output/body-description-change.out @@ -1,6 +1,6 @@ --- body-description-change.json +++ patched -@@ -249,6 +249,7 @@ +@@ -285,6 +285,7 @@ } } }, diff --git a/tests/cases/simple/output/body-extension-change.out b/tests/cases/simple/output/body-extension-change.out index a6abf4a..06cbc81 100644 --- a/tests/cases/simple/output/body-extension-change.out +++ b/tests/cases/simple/output/body-extension-change.out @@ -1,6 +1,6 @@ --- body-extension-change.json +++ patched -@@ -249,7 +249,8 @@ +@@ -285,7 +285,8 @@ } } }, diff --git a/tests/cases/simple/output/body-optional-to-required.out b/tests/cases/simple/output/body-optional-to-required.out index defb6c9..b09a68f 100644 --- a/tests/cases/simple/output/body-optional-to-required.out +++ b/tests/cases/simple/output/body-optional-to-required.out @@ -1,6 +1,6 @@ --- body-optional-to-required.json +++ patched -@@ -268,7 +268,7 @@ +@@ -304,7 +304,7 @@ } } }, diff --git a/tests/cases/simple/output/body-required-to-optional.out b/tests/cases/simple/output/body-required-to-optional.out index e7d6e37..a41b06d 100644 --- a/tests/cases/simple/output/body-required-to-optional.out +++ b/tests/cases/simple/output/body-required-to-optional.out @@ -1,6 +1,6 @@ --- body-required-to-optional.json +++ patched -@@ -249,7 +249,7 @@ +@@ -285,7 +285,7 @@ } } }, diff --git a/tests/cases/simple/output/boolean-enum-change.out b/tests/cases/simple/output/boolean-enum-change.out new file mode 100644 index 0000000..670c172 --- /dev/null +++ b/tests/cases/simple/output/boolean-enum-change.out @@ -0,0 +1,31 @@ +--- boolean-enum-change.json ++++ patched +@@ -159,6 +159,9 @@ + "type": "integer" + }, + "enabled": { ++ "enum": [ ++ true ++ ], + "type": "boolean" + }, + "ratio": { + + +Result for patch: +[ + Change { + message: "boolean schema changed", + old_path: [ + "#/components/schemas/TypedProperties/properties/enabled", + "#/paths/~1typed/get/responses/200/content/application~1json/schema/$ref", + ], + new_path: [ + "#/components/schemas/TypedProperties/properties/enabled", + "#/paths/~1typed/get/responses/200/content/application~1json/schema/$ref", + ], + comparison: Output, + class: Unhandled, + details: UnknownDifference, + }, +] diff --git a/tests/cases/simple/output/change-default-response.out b/tests/cases/simple/output/change-default-response.out index 4281f65..51a21da 100644 --- a/tests/cases/simple/output/change-default-response.out +++ b/tests/cases/simple/output/change-default-response.out @@ -1,6 +1,6 @@ --- change-default-response.json +++ patched -@@ -397,7 +397,7 @@ +@@ -451,7 +451,7 @@ } } }, diff --git a/tests/cases/simple/output/change-header-parameter.out b/tests/cases/simple/output/change-header-parameter.out index 3202d42..8b8fec2 100644 --- a/tests/cases/simple/output/change-header-parameter.out +++ b/tests/cases/simple/output/change-header-parameter.out @@ -1,6 +1,6 @@ --- change-header-parameter.json +++ patched -@@ -412,7 +412,7 @@ +@@ -466,7 +466,7 @@ "name": "X-Request-Id", "required": true, "schema": { diff --git a/tests/cases/simple/output/change-operation-parameter-requirement.out b/tests/cases/simple/output/change-operation-parameter-requirement.out index 3e59400..dccb0ce 100644 --- a/tests/cases/simple/output/change-operation-parameter-requirement.out +++ b/tests/cases/simple/output/change-operation-parameter-requirement.out @@ -1,6 +1,6 @@ --- change-operation-parameter-requirement.json +++ patched -@@ -217,7 +217,7 @@ +@@ -253,7 +253,7 @@ "description": "Language for the greeting", "in": "query", "name": "language", diff --git a/tests/cases/simple/output/change-operation-parameter-type.out b/tests/cases/simple/output/change-operation-parameter-type.out index 7ece7f4..1a21afd 100644 --- a/tests/cases/simple/output/change-operation-parameter-type.out +++ b/tests/cases/simple/output/change-operation-parameter-type.out @@ -1,6 +1,6 @@ --- change-operation-parameter-type.json +++ patched -@@ -219,7 +219,7 @@ +@@ -255,7 +255,7 @@ "name": "language", "required": false, "schema": { diff --git a/tests/cases/simple/output/inline-to-allof.out b/tests/cases/simple/output/inline-to-allof.out index e27ea8c..5173ba2 100644 --- a/tests/cases/simple/output/inline-to-allof.out +++ b/tests/cases/simple/output/inline-to-allof.out @@ -1,6 +1,6 @@ --- inline-to-allof.json +++ patched -@@ -210,7 +210,12 @@ +@@ -246,7 +246,12 @@ "in": "path", "name": "name", "schema": { diff --git a/tests/cases/simple/output/multi-allof-variant-change.out b/tests/cases/simple/output/multi-allof-variant-change.out new file mode 100644 index 0000000..b2c82ec --- /dev/null +++ b/tests/cases/simple/output/multi-allof-variant-change.out @@ -0,0 +1,30 @@ +--- multi-allof-variant-change.json ++++ patched +@@ -95,7 +95,7 @@ + { + "properties": { + "id": { +- "type": "string" ++ "type": "integer" + } + }, + "type": "object" + + +Result for patch: +[ + Change { + message: "unhandled, 'allOf' schema", + old_path: [ + "#/components/schemas/MultiAllOf/allOf", + "#/paths/~1allof/get/responses/200/content/application~1json/schema/$ref", + ], + new_path: [ + "#/components/schemas/MultiAllOf/allOf", + "#/paths/~1allof/get/responses/200/content/application~1json/schema/$ref", + ], + comparison: Output, + class: Unhandled, + details: UnknownDifference, + }, +] diff --git a/tests/cases/simple/output/multi-anyof-variant-change.out b/tests/cases/simple/output/multi-anyof-variant-change.out new file mode 100644 index 0000000..fc70f50 --- /dev/null +++ b/tests/cases/simple/output/multi-anyof-variant-change.out @@ -0,0 +1,30 @@ +--- multi-anyof-variant-change.json ++++ patched +@@ -4,7 +4,7 @@ + "AnyOfExample": { + "anyOf": [ + { +- "type": "string" ++ "type": "integer" + }, + { + "type": "number" + + +Result for patch: +[ + Change { + message: "unhandled, 'anyOf' schema", + old_path: [ + "#/components/schemas/AnyOfExample", + "#/paths/~1anyof/get/responses/200/content/application~1json/schema/$ref", + ], + new_path: [ + "#/components/schemas/AnyOfExample", + "#/paths/~1anyof/get/responses/200/content/application~1json/schema/$ref", + ], + comparison: Output, + class: Unhandled, + details: UnknownDifference, + }, +] diff --git a/tests/cases/simple/output/multi-oneof-count-change.out b/tests/cases/simple/output/multi-oneof-count-change.out new file mode 100644 index 0000000..8d054d6 --- /dev/null +++ b/tests/cases/simple/output/multi-oneof-count-change.out @@ -0,0 +1,31 @@ +--- multi-oneof-count-change.json ++++ patched +@@ -117,6 +117,9 @@ + }, + { + "type": "integer" ++ }, ++ { ++ "type": "boolean" + } + ] + }, + + +Result for patch: +[ + Change { + message: "oneOf schema count changed", + old_path: [ + "#/components/schemas/MultiOneOf/oneOf", + "#/paths/~1oneof/get/responses/200/content/application~1json/schema/$ref", + ], + new_path: [ + "#/components/schemas/MultiOneOf/oneOf", + "#/paths/~1oneof/get/responses/200/content/application~1json/schema/$ref", + ], + comparison: Output, + class: Unhandled, + details: UnknownDifference, + }, +] diff --git a/tests/cases/simple/output/multi-oneof-variant-change.out b/tests/cases/simple/output/multi-oneof-variant-change.out new file mode 100644 index 0000000..9e67399 --- /dev/null +++ b/tests/cases/simple/output/multi-oneof-variant-change.out @@ -0,0 +1,30 @@ +--- multi-oneof-variant-change.json ++++ patched +@@ -113,7 +113,7 @@ + "MultiOneOf": { + "oneOf": [ + { +- "type": "string" ++ "type": "number" + }, + { + "type": "integer" + + +Result for patch: +[ + Change { + message: "schema types changed", + old_path: [ + "#/components/schemas/MultiOneOf/oneOf/0", + "#/paths/~1oneof/get/responses/200/content/application~1json/schema/$ref", + ], + new_path: [ + "#/components/schemas/MultiOneOf/oneOf/0", + "#/paths/~1oneof/get/responses/200/content/application~1json/schema/$ref", + ], + comparison: Output, + class: Incompatible, + details: UnknownDifference, + }, +] diff --git a/tests/cases/simple/output/param-required-to-optional.out b/tests/cases/simple/output/param-required-to-optional.out index 7d353c3..c955a3c 100644 --- a/tests/cases/simple/output/param-required-to-optional.out +++ b/tests/cases/simple/output/param-required-to-optional.out @@ -1,6 +1,6 @@ --- param-required-to-optional.json +++ patched -@@ -410,7 +410,7 @@ +@@ -464,7 +464,7 @@ { "in": "header", "name": "X-Request-Id", diff --git a/tests/cases/simple/output/param-schema-to-content.out b/tests/cases/simple/output/param-schema-to-content.out index 0b88fc2..b9f44c6 100644 --- a/tests/cases/simple/output/param-schema-to-content.out +++ b/tests/cases/simple/output/param-schema-to-content.out @@ -1,6 +1,6 @@ --- param-schema-to-content.json +++ patched -@@ -214,13 +214,17 @@ +@@ -250,13 +250,17 @@ } }, { diff --git a/tests/cases/simple/output/remove-default-response.out b/tests/cases/simple/output/remove-default-response.out index bb9d379..615e057 100644 --- a/tests/cases/simple/output/remove-default-response.out +++ b/tests/cases/simple/output/remove-default-response.out @@ -1,6 +1,6 @@ --- remove-default-response.json +++ patched -@@ -388,16 +388,6 @@ +@@ -442,16 +442,6 @@ "responses": { "200": { "description": "Success" diff --git a/tests/cases/simple/output/remove-header-parameter.out b/tests/cases/simple/output/remove-header-parameter.out index b3256bf..3f5b122 100644 --- a/tests/cases/simple/output/remove-header-parameter.out +++ b/tests/cases/simple/output/remove-header-parameter.out @@ -1,6 +1,6 @@ --- remove-header-parameter.json +++ patched -@@ -408,14 +408,6 @@ +@@ -462,14 +462,6 @@ "operationId": "with_header", "parameters": [ { diff --git a/tests/cases/simple/output/remove-operation-parameter.out b/tests/cases/simple/output/remove-operation-parameter.out index ef23021..7fc3327 100644 --- a/tests/cases/simple/output/remove-operation-parameter.out +++ b/tests/cases/simple/output/remove-operation-parameter.out @@ -1,6 +1,6 @@ --- remove-operation-parameter.json +++ patched -@@ -212,15 +212,6 @@ +@@ -248,15 +248,6 @@ "schema": { "type": "string" } diff --git a/tests/cases/simple/output/remove-operation.out b/tests/cases/simple/output/remove-operation.out index cc5a839..04ed3a9 100644 --- a/tests/cases/simple/output/remove-operation.out +++ b/tests/cases/simple/output/remove-operation.out @@ -1,7 +1,7 @@ --- remove-operation.json +++ patched -@@ -307,18 +307,7 @@ - "summary": "Get objects" +@@ -361,18 +361,7 @@ + "summary": "Get oneOf schema" } }, - "/ping": { diff --git a/tests/cases/simple/output/remove-optional-body.out b/tests/cases/simple/output/remove-optional-body.out index b03bd5b..4a7a983 100644 --- a/tests/cases/simple/output/remove-optional-body.out +++ b/tests/cases/simple/output/remove-optional-body.out @@ -1,6 +1,6 @@ --- remove-optional-body.json +++ patched -@@ -260,16 +260,6 @@ +@@ -296,16 +296,6 @@ }, "put": { "operationId": "update_item", diff --git a/tests/cases/simple/output/remove-required-body.out b/tests/cases/simple/output/remove-required-body.out index 547ff44..8cb5edc 100644 --- a/tests/cases/simple/output/remove-required-body.out +++ b/tests/cases/simple/output/remove-required-body.out @@ -1,6 +1,6 @@ --- remove-required-body.json +++ patched -@@ -241,16 +241,6 @@ +@@ -277,16 +277,6 @@ "/items": { "post": { "operationId": "create_item", diff --git a/tests/cases/simple/output/remove-response-code.out b/tests/cases/simple/output/remove-response-code.out index 0e5fe6b..6decf76 100644 --- a/tests/cases/simple/output/remove-response-code.out +++ b/tests/cases/simple/output/remove-response-code.out @@ -1,6 +1,6 @@ --- remove-response-code.json +++ patched -@@ -386,9 +386,6 @@ +@@ -440,9 +440,6 @@ "get": { "operationId": "with_default", "responses": { diff --git a/tests/cases/simple/output/remove-unnamed-operation.out b/tests/cases/simple/output/remove-unnamed-operation.out index df4ca49..a895a32 100644 --- a/tests/cases/simple/output/remove-unnamed-operation.out +++ b/tests/cases/simple/output/remove-unnamed-operation.out @@ -1,6 +1,6 @@ --- remove-unnamed-operation.json +++ patched -@@ -372,16 +372,6 @@ +@@ -426,16 +426,6 @@ "summary": "Get typed properties" } }, diff --git a/tests/cases/simple/output/type-rename.out b/tests/cases/simple/output/type-rename.out index bfbf5db..bac28a3 100644 --- a/tests/cases/simple/output/type-rename.out +++ b/tests/cases/simple/output/type-rename.out @@ -9,7 +9,7 @@ "properties": { "message": { "description": "The greeting message", -@@ -228,7 +228,7 @@ +@@ -264,7 +264,7 @@ "content": { "application/json": { "schema": { diff --git a/tests/cases/simple/patch/boolean-enum-change.json b/tests/cases/simple/patch/boolean-enum-change.json new file mode 100644 index 0000000..ea478de --- /dev/null +++ b/tests/cases/simple/patch/boolean-enum-change.json @@ -0,0 +1,7 @@ +[ + { + "op": "add", + "path": "/components/schemas/TypedProperties/properties/enabled/enum", + "value": [true] + } +] diff --git a/tests/cases/simple/patch/multi-allof-variant-change.json b/tests/cases/simple/patch/multi-allof-variant-change.json new file mode 100644 index 0000000..cb1ab4a --- /dev/null +++ b/tests/cases/simple/patch/multi-allof-variant-change.json @@ -0,0 +1,7 @@ +[ + { + "op": "replace", + "path": "/components/schemas/MultiAllOf/allOf/0/properties/id/type", + "value": "integer" + } +] diff --git a/tests/cases/simple/patch/multi-anyof-variant-change.json b/tests/cases/simple/patch/multi-anyof-variant-change.json new file mode 100644 index 0000000..e716659 --- /dev/null +++ b/tests/cases/simple/patch/multi-anyof-variant-change.json @@ -0,0 +1,7 @@ +[ + { + "op": "replace", + "path": "/components/schemas/AnyOfExample/anyOf/0/type", + "value": "integer" + } +] diff --git a/tests/cases/simple/patch/multi-oneof-count-change.json b/tests/cases/simple/patch/multi-oneof-count-change.json new file mode 100644 index 0000000..fe5f938 --- /dev/null +++ b/tests/cases/simple/patch/multi-oneof-count-change.json @@ -0,0 +1,9 @@ +[ + { + "op": "add", + "path": "/components/schemas/MultiOneOf/oneOf/-", + "value": { + "type": "boolean" + } + } +] diff --git a/tests/cases/simple/patch/multi-oneof-variant-change.json b/tests/cases/simple/patch/multi-oneof-variant-change.json new file mode 100644 index 0000000..107db03 --- /dev/null +++ b/tests/cases/simple/patch/multi-oneof-variant-change.json @@ -0,0 +1,7 @@ +[ + { + "op": "replace", + "path": "/components/schemas/MultiOneOf/oneOf/0/type", + "value": "number" + } +]