diff --git a/BREAKING-CHANGES-EXAMPLES.md b/BREAKING-CHANGES-EXAMPLES.md index bbb644a5..f935d9e4 100644 --- a/BREAKING-CHANGES-EXAMPLES.md +++ b/BREAKING-CHANGES-EXAMPLES.md @@ -153,7 +153,7 @@ These examples are automatically generated from unit tests. [adding a new media type to response](checker/check-response-mediatype-updated_test.go?plain=1#L11) [adding a new oauth security scope](checker/check-components-security-updated_test.go?plain=1#L95) [adding a new operation id](checker/check-api-operation-id-updated_test.go?plain=1#L61) -[adding a new optional request property](checker/check-request-property-updated_test.go?plain=1#L33) +[adding a new optional request property](checker/check-request-property-updated_test.go?plain=1#L64) [adding a new required request property](checker/check-request-property-updated_test.go?plain=1#L11) [adding a new security component](checker/check-components-security-updated_test.go?plain=1#L55) [adding a new security to the API endpoint](checker/check-api-security-updated_test.go?plain=1#L93) @@ -174,6 +174,7 @@ These examples are automatically generated from unit tests. [adding request property enum values](checker/check-request-property-enum-value-updated_test.go?plain=1#L37) [adding request property pattern](checker/check-request-property-pattern-added-or-changed_test.go?plain=1#L36) [adding response property pattern](checker/check-response-pattern-added-or-changed_test.go?plain=1#L37) +[adding two new request properties, one required, one optional](checker/check-request-property-updated_test.go?plain=1#L33) [changing a response property schema format](checker/check-response-property-type-changed_test.go?plain=1#L59) [changing a response property schema type](checker/check-response-property-type-changed_test.go?plain=1#L34) [changing a response schema type](checker/check-response-property-type-changed_test.go?plain=1#L11) @@ -275,7 +276,7 @@ These examples are automatically generated from unit tests. [removing a new security component](checker/check-components-security-updated_test.go?plain=1#L75) [removing a new security to the API endpoint](checker/check-api-security-updated_test.go?plain=1#L116) [removing a non-success response status](checker/check-response-status-updated_test.go?plain=1#L63) -[removing a required request property](checker/check-request-property-updated_test.go?plain=1#L56) +[removing a required request property](checker/check-request-property-updated_test.go?plain=1#L87) [removing a required write-only property that was required in response body is detected](checker/check-response-required-property-updated_test.go?plain=1#L85) [removing a security scope from an API endpoint security](checker/check-api-security-updated_test.go?plain=1#L139) [removing a security scope from an API global security](checker/check-api-security-updated_test.go?plain=1#L51) diff --git a/checker/check-request-property-updated.go b/checker/check-request-property-updated.go index 0cd45ba7..35c5a694 100644 --- a/checker/check-request-property-updated.go +++ b/checker/check-request-property-updated.go @@ -44,35 +44,31 @@ func RequestPropertyUpdatedCheck(diffReport *diff.Diff, operationsSources *diff. CheckAddedPropertiesDiff( mediaTypeDiff.SchemaDiff, func(propertyPath string, propertyName string, propertyItem *openapi3.Schema, parent *diff.SchemaDiff) { - CheckAddedPropertiesDiff( - mediaTypeDiff.SchemaDiff, - func(propertyPath string, propertyName string, propertyItem *openapi3.Schema, parent *diff.SchemaDiff) { - source := (*operationsSources)[operationItem.Revision] - if propertyItem.ReadOnly { - return - } - if slices.Contains(parent.Revision.Value.Required, propertyName) { - result = append(result, ApiChange{ - Id: "new-required-request-property", - Level: ERR, - Text: fmt.Sprintf(config.i18n("new-required-request-property"), ColorizedValue(propertyFullName(propertyPath, propertyName))), - Operation: operation, - OperationId: operationItem.Revision.OperationID, - Path: path, - Source: source, - }) - } else { - result = append(result, ApiChange{ - Id: "new-optional-request-property", - Level: INFO, - Text: fmt.Sprintf(config.i18n("new-optional-request-property"), ColorizedValue(propertyFullName(propertyPath, propertyName))), - Operation: operation, - OperationId: operationItem.Revision.OperationID, - Path: path, - Source: source, - }) - } + source := (*operationsSources)[operationItem.Revision] + if propertyItem.ReadOnly { + return + } + if slices.Contains(parent.Revision.Value.Required, propertyName) { + result = append(result, ApiChange{ + Id: "new-required-request-property", + Level: ERR, + Text: fmt.Sprintf(config.i18n("new-required-request-property"), ColorizedValue(propertyFullName(propertyPath, propertyName))), + Operation: operation, + OperationId: operationItem.Revision.OperationID, + Path: path, + Source: source, }) + } else { + result = append(result, ApiChange{ + Id: "new-optional-request-property", + Level: INFO, + Text: fmt.Sprintf(config.i18n("new-optional-request-property"), ColorizedValue(propertyFullName(propertyPath, propertyName))), + Operation: operation, + OperationId: operationItem.Revision.OperationID, + Path: path, + Source: source, + }) + } }) } } diff --git a/checker/check-request-property-updated_test.go b/checker/check-request-property-updated_test.go index e065513b..c9d00495 100644 --- a/checker/check-request-property-updated_test.go +++ b/checker/check-request-property-updated_test.go @@ -30,6 +30,37 @@ func TestRequiredRequestPropertyAdded(t *testing.T) { }, errs[0]) } +// CL: adding two new request properties, one required, one optional +func TestRequiredRequestPropertiesAdded(t *testing.T) { + s1, err := open("../data/checker/request_property_added_base.yaml") + require.NoError(t, err) + s2, err := open("../data/checker/request_property_added_revision2.yaml") + require.NoError(t, err) + + d, osm, err := diff.GetWithOperationsSourcesMap(getConfig(), s1, s2) + require.NoError(t, err) + errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.RequestPropertyUpdatedCheck), d, osm, checker.INFO) + require.ElementsMatch(t, []checker.ApiChange{ + { + Id: "new-required-request-property", + Text: "added the new required request property 'description'", + Level: checker.ERR, + Operation: "POST", + Path: "/products", + Source: "../data/checker/request_property_added_revision2.yaml", + OperationId: "addProduct", + }, + { + Id: "new-optional-request-property", + Text: "added the new optional request property 'info'", + Level: checker.INFO, + Operation: "POST", + Path: "/products", + Source: "../data/checker/request_property_added_revision2.yaml", + OperationId: "addProduct", + }}, errs) +} + // CL: adding a new optional request property func TestRequiredOptionalPropertyAdded(t *testing.T) { s1, err := open("../data/checker/request_property_added_base.yaml") diff --git a/data/checker/request_property_added_revision2.yaml b/data/checker/request_property_added_revision2.yaml new file mode 100644 index 00000000..a4fbdd4f --- /dev/null +++ b/data/checker/request_property_added_revision2.yaml @@ -0,0 +1,26 @@ +openapi: 3.0.0 +info: + title: Sample API + version: 1.0.0 +paths: + /products: + post: + operationId: addProduct + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: + type: string + info: + type: string + required: + - name + - description + responses: + '200': + description: OK