diff --git a/checker/check_response_property_type_changed_test.go b/checker/check_response_property_type_changed_test.go index 4abc8338..eccaf98d 100644 --- a/checker/check_response_property_type_changed_test.go +++ b/checker/check_response_property_type_changed_test.go @@ -146,3 +146,47 @@ func TestResponseSchemaTypeMultiCheck(t *testing.T) { OperationId: "createOneGroup", }, errs[0]) } + +// BC: changing an additionalResponse property schema type from integer to string is breaking +func TestResponseAdditionalPropertyTypeChangedCheck(t *testing.T) { + s1, err := open("../data/additional-properties/base.yaml") + require.NoError(t, err) + s2, err := open("../data/additional-properties/revision.yaml") + require.NoError(t, err) + + d, osm, err := diff.GetWithOperationsSourcesMap(diff.NewConfig(), s1, s2) + require.NoError(t, err) + errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.ResponsePropertyTypeChangedCheck), d, osm, checker.ERR) + require.Len(t, errs, 1) + require.Equal(t, checker.ApiChange{ + Id: checker.ResponsePropertyTypeChangedId, + Args: []any{"/additionalProperties/property1", utils.StringList{"integer"}, "", utils.StringList{"string"}, "", "200"}, + Level: checker.ERR, + Operation: "GET", + Path: "/value", + Source: load.NewSource("../data/additional-properties/revision.yaml"), + OperationId: "get_value", + }, errs[0]) +} + +// BC: changing an embedded additionalResponse property schema type from integer to string is breaking +func TestResponseEmbeddedAdditionalPropertyTypeChangedCheck(t *testing.T) { + s1, err := open("../data/additional-properties/embedded-base.yaml") + require.NoError(t, err) + s2, err := open("../data/additional-properties/embedded-revision.yaml") + require.NoError(t, err) + + d, osm, err := diff.GetWithOperationsSourcesMap(diff.NewConfig(), s1, s2) + require.NoError(t, err) + errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.ResponsePropertyTypeChangedCheck), d, osm, checker.ERR) + require.Len(t, errs, 1) + require.Equal(t, checker.ApiChange{ + Id: checker.ResponsePropertyTypeChangedId, + Args: []any{"composite-property/additionalProperties/property1", utils.StringList{"integer"}, "", utils.StringList{"string"}, "", "200"}, + Level: checker.ERR, + Operation: "GET", + Path: "/value", + Source: load.NewSource("../data/additional-properties/embedded-revision.yaml"), + OperationId: "get_value", + }, errs[0]) +} diff --git a/checker/checks-utils.go b/checker/checks-utils.go index 5181eddc..4b84a005 100644 --- a/checker/checks-utils.go +++ b/checker/checks-utils.go @@ -105,6 +105,10 @@ func processModifiedPropertiesDiff(propertyPath string, propertyName string, sch processModifiedPropertiesDiff(propertyPath, i, v, schemaDiff, processor) } } + + if schemaDiff.AdditionalPropertiesDiff != nil { + processModifiedPropertiesDiff(fmt.Sprintf("%s/additionalProperties", propertyPath), "", schemaDiff.AdditionalPropertiesDiff, schemaDiff, processor) + } } func CheckAddedPropertiesDiff(schemaDiff *diff.SchemaDiff, processor func(propertyPath string, propertyName string, propertyItem *openapi3.Schema, propertyParentDiff *diff.SchemaDiff)) { diff --git a/data/additional-properties/base.yaml b/data/additional-properties/base.yaml new file mode 100644 index 00000000..16826ae9 --- /dev/null +++ b/data/additional-properties/base.yaml @@ -0,0 +1,28 @@ +openapi: 3.0.1 +info: + title: Test API + version: v1 +components: + schemas: + Schema1: + properties: + property1: + title: Value + type: integer + type: object + Schema2: + additionalProperties: + "$ref": "#/components/schemas/Schema1" + title: Composite + type: object +paths: + "/value": + get: + operationId: get_value + responses: + '200': + content: + application/json: + schema: + "$ref": "#/components/schemas/Schema2" + description: Successful Response diff --git a/data/additional-properties/embedded-base.yaml b/data/additional-properties/embedded-base.yaml new file mode 100644 index 00000000..540d477e --- /dev/null +++ b/data/additional-properties/embedded-base.yaml @@ -0,0 +1,31 @@ +openapi: 3.0.1 +info: + title: Test API + version: v1 +components: + schemas: + Schema1: + properties: + property1: + title: Value + type: integer + type: object + Schema2: + properties: + composite-property: + additionalProperties: + "$ref": "#/components/schemas/Schema1" + title: Composite + type: object + type: object +paths: + "/value": + get: + operationId: get_value + responses: + '200': + content: + application/json: + schema: + "$ref": "#/components/schemas/Schema2" + description: Successful Response diff --git a/data/additional-properties/embedded-revision.yaml b/data/additional-properties/embedded-revision.yaml new file mode 100644 index 00000000..14f7ca31 --- /dev/null +++ b/data/additional-properties/embedded-revision.yaml @@ -0,0 +1,31 @@ +openapi: 3.0.1 +info: + title: Test API + version: v1 +components: + schemas: + Schema1: + properties: + property1: + title: Value + type: string + type: object + Schema2: + properties: + composite-property: + additionalProperties: + "$ref": "#/components/schemas/Schema1" + title: Composite + type: object + type: object +paths: + "/value": + get: + operationId: get_value + responses: + '200': + content: + application/json: + schema: + "$ref": "#/components/schemas/Schema2" + description: Successful Response diff --git a/data/additional-properties/revision.yaml b/data/additional-properties/revision.yaml new file mode 100644 index 00000000..40b16d59 --- /dev/null +++ b/data/additional-properties/revision.yaml @@ -0,0 +1,28 @@ +openapi: 3.0.1 +info: + title: Test API + version: v1 +components: + schemas: + Schema1: + properties: + property1: + title: Value + type: string + type: object + Schema2: + additionalProperties: + "$ref": "#/components/schemas/Schema1" + title: Composite + type: object +paths: + "/value": + get: + operationId: get_value + responses: + '200': + content: + application/json: + schema: + "$ref": "#/components/schemas/Schema2" + description: Successful Response diff --git a/docs/BREAKING-CHANGES-EXAMPLES.md b/docs/BREAKING-CHANGES-EXAMPLES.md index 8862f666..b4a0cbbe 100644 --- a/docs/BREAKING-CHANGES-EXAMPLES.md +++ b/docs/BREAKING-CHANGES-EXAMPLES.md @@ -15,6 +15,8 @@ These examples are automatically generated from unit tests. [changing a response body to nullable is breaking](../checker/check_breaking_property_test.go?plain=1#L217) [changing a response property to nullable is breaking](../checker/check_breaking_property_test.go?plain=1#L249) [changing a response property to optional under AllOf, AnyOf or OneOf is breaking](../checker/check_breaking_property_test.go?plain=1#L660) +[changing an additionalResponse property schema type from integer to string is breaking](../checker/check_response_property_type_changed_test.go?plain=1#L150) +[changing an embedded additionalResponse property schema type from integer to string is breaking](../checker/check_response_property_type_changed_test.go?plain=1#L172) [changing an embedded response property to nullable is breaking](../checker/check_breaking_property_test.go?plain=1#L265) [changing an existing header param from optional to required is breaking](../checker/check_breaking_test.go?plain=1#L190) [changing an existing path param to enum is breaking](../checker/check_breaking_property_test.go?plain=1#L185)