Skip to content

Commit

Permalink
Merge branch 'main' into discriminators-2
Browse files Browse the repository at this point in the history
  • Loading branch information
blva committed Aug 2, 2023
2 parents 63f39e4 + 59ebb96 commit 6bc459e
Show file tree
Hide file tree
Showing 26 changed files with 1,136 additions and 118 deletions.
19 changes: 19 additions & 0 deletions BREAKING-CHANGES-EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ 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 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)
[adding a new tag](checker/check-api-tag-updated_test.go?plain=1#L11)
Expand All @@ -178,27 +180,43 @@ These examples are automatically generated from unit tests.
[changing an existing header param from required to optional](checker/checker_request_parameter_required_value_updated_test.go?plain=1#L35)
[changing an existing header param to optional](checker/checker_not_breaking_test.go?plain=1#L133)
[changing an existing request body from required to optional](checker/checker_not_breaking_test.go?plain=1#L53)
[changing optional request property to not read-only](checker/check-request-property-write-only-read-only_test.go?plain=1#L86)
[changing optional request property to not write-only](checker/check-request-property-write-only-read-only_test.go?plain=1#L36)
[changing optional request property to read-only](checker/check-request-property-write-only-read-only_test.go?plain=1#L61)
[changing optional request property to write-only](checker/check-request-property-write-only-read-only_test.go?plain=1#L11)
[changing optional response property to not read-only](checker/check-response-optional-property-write-only-read-only_test.go?plain=1#L88)
[changing optional response property to not write-only](checker/check-response-optional-property-write-only-read-only_test.go?plain=1#L37)
[changing optional response property to read-only](checker/check-response-optional-property-write-only-read-only_test.go?plain=1#L62)
[changing optional response property to required](checker/check-response-property-became-required_test.go?plain=1#L11)
[changing optional response property to write-only](checker/check-response-optional-property-write-only-read-only_test.go?plain=1#L11)
[changing optional response write-only property to required](checker/check-response-property-became-required_test.go?plain=1#L33)
[changing pattern of request parameters](checker/check-request-parameter-pattern-added-or-changed_test.go?plain=1#L11)
[changing request body default value](checker/check-request-property-default-value-changed_test.go?plain=1#L11)
[changing request body to not nullable](checker/check-request-property-became-not-nuallable_test.go?plain=1#L84)
[changing request body to nullable](checker/check-request-property-became-not-nuallable_test.go?plain=1#L58)
[changing request body type](checker/check-request-property-type-changed_test.go?plain=1#L11)
[changing request header parameter format](checker/check-request-parameters-type-changed_test.go?plain=1#L136)
[changing request header parameter type](checker/check-request-parameters-type-changed_test.go?plain=1#L61)
[changing request parameter default value](checker/check-request-parameters-default-value-changed_test.go?plain=1#L11)
[changing request parameter type to enum](checker/check-request-parameter-became-enum_test.go?plain=1#L11)
[changing request path parameter format](checker/check-request-parameters-type-changed_test.go?plain=1#L86)
[changing request path parameter type](checker/check-request-parameters-type-changed_test.go?plain=1#L11)
[changing request property default value](checker/check-request-property-default-value-changed_test.go?plain=1#L34)
[changing request property format](checker/check-request-property-type-changed_test.go?plain=1#L84)
[changing request property pattern](checker/check-request-property-pattern-added-or-changed_test.go?plain=1#L11)
[changing request property required value to false](checker/check-request-property-required-updated_test.go?plain=1#L34)
[changing request property required value to true](checker/check-request-property-required-updated_test.go?plain=1#L11)
[changing request property to not nullable](checker/check-request-property-became-not-nuallable_test.go?plain=1#L11)
[changing request property to nullable](checker/check-request-property-became-not-nuallable_test.go?plain=1#L34)
[changing request property type](checker/check-request-property-type-changed_test.go?plain=1#L61)
[changing request query parameter format](checker/check-request-parameters-type-changed_test.go?plain=1#L111)
[changing request query parameter type](checker/check-request-parameters-type-changed_test.go?plain=1#L36)
[changing request's body to optional](checker/check-request-body-required-value-updated_test.go?plain=1#L36)
[changing request's body to required is breaking](checker/check-request-body-required-value-updated_test.go?plain=1#L11)
[changing required request property to not read-only](checker/check-request-property-write-only-read-only_test.go?plain=1#L186)
[changing required request property to not write-only](checker/check-request-property-write-only-read-only_test.go?plain=1#L136)
[changing required request property to read-only](checker/check-request-property-write-only-read-only_test.go?plain=1#L161)
[changing required request property to write-only](checker/check-request-property-write-only-read-only_test.go?plain=1#L111)
[changing required response property to not read-only](checker/check-response-required-property-write-only-read-only_test.go?plain=1#L89)
[changing required response property to not write-only](checker/check-response-required-property-write-only-read-only_test.go?plain=1#L37)
[changing required response property to optional](checker/check-response-property-became-optional_test.go?plain=1#L11)
Expand Down Expand Up @@ -257,6 +275,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 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)
Expand Down
49 changes: 0 additions & 49 deletions checker/check-new-required-request-property.go

This file was deleted.

55 changes: 39 additions & 16 deletions checker/check-request-property-became-not-nuallable.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (

const requestPropertyBecameNotNullableId = "request-property-became-not-nullable"
const requestBodyBecameNotNullableId = "request-body-became-not-nullable"
const requestPropertyBecameNullableId = "request-property-became-nullable"
const requestBodyBecameNullableId = "request-body-became-nullable"

func RequestPropertyBecameNotNullableCheck(diffReport *diff.Diff, operationsSources *diff.OperationsSourcesMap, config Config) Changes {
result := make(Changes, 0)
Expand All @@ -34,12 +36,23 @@ func RequestPropertyBecameNotNullableCheck(diffReport *diff.Diff, operationsSour

if mediaTypeDiff.SchemaDiff.NullableDiff != nil && mediaTypeDiff.SchemaDiff.NullableDiff.From == true {
result = append(result, ApiChange{
Id: requestBodyBecameNotNullableId,
Level: ERR,
Text: config.i18n(requestBodyBecameNotNullableId),
Operation: operation,
Path: path,
Source: source,
Id: requestBodyBecameNotNullableId,
Level: ERR,
Text: config.i18n(requestBodyBecameNotNullableId),
Operation: operation,
Path: path,
Source: source,
OperationId: operationItem.Revision.OperationID,
})
} else if mediaTypeDiff.SchemaDiff.NullableDiff != nil && mediaTypeDiff.SchemaDiff.NullableDiff.To == true {
result = append(result, ApiChange{
Id: requestBodyBecameNullableId,
Level: INFO,
Text: config.i18n(requestBodyBecameNullableId),
Operation: operation,
Path: path,
Source: source,
OperationId: operationItem.Revision.OperationID,
})
}

Expand All @@ -50,18 +63,28 @@ func RequestPropertyBecameNotNullableCheck(diffReport *diff.Diff, operationsSour
if nullableDiff == nil {
return
}
if nullableDiff.From != true {
return
if nullableDiff.From == true {
result = append(result, ApiChange{
Id: requestPropertyBecameNotNullableId,
Level: ERR,
Text: fmt.Sprintf(config.i18n(requestPropertyBecameNotNullableId), ColorizedValue(propertyFullName(propertyPath, propertyName))),
Operation: operation,
Path: path,
Source: source,
OperationId: operationItem.Revision.OperationID,
})
} else if nullableDiff.To == true {
result = append(result, ApiChange{
Id: requestPropertyBecameNullableId,
Level: INFO,
Text: fmt.Sprintf(config.i18n(requestPropertyBecameNullableId), ColorizedValue(propertyFullName(propertyPath, propertyName))),
Operation: operation,
Path: path,
Source: source,
OperationId: operationItem.Revision.OperationID,
})
}

result = append(result, ApiChange{
Id: requestPropertyBecameNotNullableId,
Level: ERR,
Text: fmt.Sprintf(config.i18n(requestPropertyBecameNotNullableId), ColorizedValue(propertyFullName(propertyPath, propertyName))),
Operation: operation,
Path: path,
Source: source,
})
})
}
}
Expand Down
108 changes: 108 additions & 0 deletions checker/check-request-property-became-not-nuallable_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package checker_test

import (
"testing"

"github.com/stretchr/testify/require"
"github.com/tufin/oasdiff/checker"
"github.com/tufin/oasdiff/diff"
)

// CL: changing request property to not nullable
func TestRequestPropertyBecameNotNullable(t *testing.T) {
s1, err := open("../data/checker/request_property_became_nullable_revision.yaml")
require.NoError(t, err)
s2, err := open("../data/checker/request_property_became_nullable_base.yaml")
require.NoError(t, err)

d, osm, err := diff.GetWithOperationsSourcesMap(getConfig(), s1, s2)
require.NoError(t, err)
errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.RequestPropertyBecameNotNullableCheck), d, osm, checker.INFO)
require.Len(t, errs, 1)
require.Equal(t, checker.ApiChange{
Id: "request-property-became-not-nullable",
Text: "the request property 'name' became not nullable",
Comment: "",
Level: checker.ERR,
Operation: "POST",
Path: "/products",
Source: "../data/checker/request_property_became_nullable_base.yaml",
OperationId: "addProduct",
}, errs[0])
}

// CL: changing request property to nullable
func TestRequestPropertyBecameNullable(t *testing.T) {
s1, err := open("../data/checker/request_property_became_nullable_base.yaml")
require.NoError(t, err)
s2, err := open("../data/checker/request_property_became_nullable_revision.yaml")
require.NoError(t, err)

d, osm, err := diff.GetWithOperationsSourcesMap(getConfig(), s1, s2)
require.NoError(t, err)
errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.RequestPropertyBecameNotNullableCheck), d, osm, checker.INFO)
require.Len(t, errs, 1)
require.Equal(t, checker.ApiChange{
Id: "request-property-became-nullable",
Text: "the request property 'name' became nullable",
Comment: "",
Level: checker.INFO,
Operation: "POST",
Path: "/products",
Source: "../data/checker/request_property_became_nullable_revision.yaml",
OperationId: "addProduct",
}, errs[0])

}

// CL: changing request body to nullable
func TestRequestBodyBecameNullable(t *testing.T) {
s1, err := open("../data/checker/request_property_became_nullable_base.yaml")
require.NoError(t, err)
s2, err := open("../data/checker/request_property_became_nullable_base.yaml")
require.NoError(t, err)

s2.Spec.Paths["/products"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Nullable = true

d, osm, err := diff.GetWithOperationsSourcesMap(getConfig(), s1, s2)
require.NoError(t, err)

errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.RequestPropertyBecameNotNullableCheck), d, osm, checker.INFO)
require.Len(t, errs, 1)
require.Equal(t, checker.ApiChange{
Id: "request-body-became-nullable",
Text: "the request's body became nullable",
Comment: "",
Level: checker.INFO,
Operation: "POST",
Path: "/products",
Source: "../data/checker/request_property_became_nullable_base.yaml",
OperationId: "addProduct",
}, errs[0])
}

// CL: changing request body to not nullable
func TestRequestBodyBecameNotNullable(t *testing.T) {
s1, err := open("../data/checker/request_property_became_nullable_base.yaml")
require.NoError(t, err)
s2, err := open("../data/checker/request_property_became_nullable_base.yaml")
require.NoError(t, err)

s1.Spec.Paths["/products"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Nullable = true

d, osm, err := diff.GetWithOperationsSourcesMap(getConfig(), s1, s2)
require.NoError(t, err)

errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.RequestPropertyBecameNotNullableCheck), d, osm, checker.ERR)
require.Len(t, errs, 1)
require.Equal(t, checker.ApiChange{
Id: "request-body-became-not-nullable",
Text: "the request's body became not nullable",
Comment: "",
Level: checker.ERR,
Operation: "POST",
Path: "/products",
Source: "../data/checker/request_property_became_nullable_base.yaml",
OperationId: "addProduct",
}, errs[0])
}
64 changes: 64 additions & 0 deletions checker/check-request-property-default-value-changed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package checker

import (
"fmt"

"github.com/tufin/oasdiff/diff"
)

func RequestPropertyDefaultValueChangedCheck(diffReport *diff.Diff, operationsSources *diff.OperationsSourcesMap, config Config) Changes {
result := make(Changes, 0)
if diffReport.PathsDiff == nil {
return result
}
for path, pathItem := range diffReport.PathsDiff.Modified {
if pathItem.OperationsDiff == nil {
continue
}
for operation, operationItem := range pathItem.OperationsDiff.Modified {
if operationItem.RequestBodyDiff == nil ||
operationItem.RequestBodyDiff.ContentDiff == nil ||
operationItem.RequestBodyDiff.ContentDiff.MediaTypeModified == nil {
continue
}
source := (*operationsSources)[operationItem.Revision]

modifiedMediaTypes := operationItem.RequestBodyDiff.ContentDiff.MediaTypeModified
for mediaType, mediaTypeDiff := range modifiedMediaTypes {
if mediaTypeDiff.SchemaDiff != nil && mediaTypeDiff.SchemaDiff.DefaultDiff != nil {
defaultValueDiff := mediaTypeDiff.SchemaDiff.DefaultDiff
result = append(result, ApiChange{
Id: "request-body-default-value-changed",
Level: INFO,
Text: fmt.Sprintf(config.i18n("request-body-default-value-changed"), ColorizedValue(mediaType), empty2none(defaultValueDiff.From), empty2none(defaultValueDiff.To)),
Operation: operation,
OperationId: operationItem.Revision.OperationID,
Path: path,
Source: source,
})
}

CheckModifiedPropertiesDiff(
mediaTypeDiff.SchemaDiff,
func(propertyPath string, propertyName string, propertyDiff *diff.SchemaDiff, parent *diff.SchemaDiff) {
if propertyDiff == nil || propertyDiff.Revision == nil || propertyDiff.Revision.Value == nil || propertyDiff.DefaultDiff == nil {
return
}

defaultValueDiff := propertyDiff.DefaultDiff

result = append(result, ApiChange{
Id: "request-property-default-value-changed",
Level: INFO,
Text: fmt.Sprintf(config.i18n("request-property-default-value-changed"), ColorizedValue(propertyName), empty2none(defaultValueDiff.From), empty2none(defaultValueDiff.To)),
Operation: operation,
OperationId: operationItem.Revision.OperationID,
Path: path,
Source: source,
})
})
}
}
}
return result
}
Loading

0 comments on commit 6bc459e

Please sign in to comment.