diff --git a/datamodel/low/v3/request_body.go b/datamodel/low/v3/request_body.go index 9601d5d..a56967b 100644 --- a/datamodel/low/v3/request_body.go +++ b/datamodel/low/v3/request_body.go @@ -18,7 +18,7 @@ type RequestBody struct { Extensions map[low.KeyReference[string]]low.ValueReference[any] } -// FindExtension attemps to locate an extension using the provided name. +// FindExtension attempts to locate an extension using the provided name. func (rb *RequestBody) FindExtension(ext string) *low.ValueReference[any] { return low.FindItemInMap[any](ext, rb.Extensions) } diff --git a/what-changed/contact.go b/what-changed/contact.go index 2071edb..6488f75 100644 --- a/what-changed/contact.go +++ b/what-changed/contact.go @@ -4,13 +4,13 @@ package what_changed import ( - lowbase "github.com/pb33f/libopenapi/datamodel/low/base" - lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3" + "github.com/pb33f/libopenapi/datamodel/low/base" + "github.com/pb33f/libopenapi/datamodel/low/v3" ) // ContactChanges Represent changes to a Contact object that is a child of Info, part of an OpenAPI document. type ContactChanges struct { - PropertyChanges[*lowbase.Contact] + PropertyChanges[*base.Contact] } // TotalChanges represents the total number of changes that have occurred to a Contact object @@ -21,16 +21,16 @@ func (c *ContactChanges) TotalChanges() int { // CompareContact will check a left (original) and right (new) Contact object for any changes. If there // were any, a pointer to a ContactChanges object is returned, otherwise if nothing changed - the function // returns nil. -func CompareContact(l, r *lowbase.Contact) *ContactChanges { +func CompareContact(l, r *base.Contact) *ContactChanges { - var changes []*Change[*lowbase.Contact] - var props []*PropertyCheck[*lowbase.Contact] + var changes []*Change[*base.Contact] + var props []*PropertyCheck[*base.Contact] // check URL - props = append(props, &PropertyCheck[*lowbase.Contact]{ + props = append(props, &PropertyCheck[*base.Contact]{ LeftNode: l.URL.ValueNode, RightNode: r.URL.ValueNode, - Label: lowv3.URLLabel, + Label: v3.URLLabel, Changes: &changes, Breaking: false, Original: l, @@ -38,10 +38,10 @@ func CompareContact(l, r *lowbase.Contact) *ContactChanges { }) // check name - props = append(props, &PropertyCheck[*lowbase.Contact]{ + props = append(props, &PropertyCheck[*base.Contact]{ LeftNode: l.Name.ValueNode, RightNode: r.Name.ValueNode, - Label: lowv3.NameLabel, + Label: v3.NameLabel, Changes: &changes, Breaking: false, Original: l, @@ -49,10 +49,10 @@ func CompareContact(l, r *lowbase.Contact) *ContactChanges { }) // check email - props = append(props, &PropertyCheck[*lowbase.Contact]{ + props = append(props, &PropertyCheck[*base.Contact]{ LeftNode: l.Email.ValueNode, RightNode: r.Email.ValueNode, - Label: lowv3.EmailLabel, + Label: v3.EmailLabel, Changes: &changes, Breaking: false, Original: l, diff --git a/what-changed/external_docs.go b/what-changed/external_docs.go index fcbe489..982c7bf 100644 --- a/what-changed/external_docs.go +++ b/what-changed/external_docs.go @@ -4,13 +4,13 @@ package what_changed import ( - lowbase "github.com/pb33f/libopenapi/datamodel/low/base" - lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3" + "github.com/pb33f/libopenapi/datamodel/low/base" + "github.com/pb33f/libopenapi/datamodel/low/v3" ) // ExternalDocChanges represents changes made to any ExternalDoc object from an OpenAPI document. type ExternalDocChanges struct { - PropertyChanges[*lowbase.ExternalDoc] + PropertyChanges[*base.ExternalDoc] ExtensionChanges *ExtensionChanges } @@ -26,15 +26,15 @@ func (e *ExternalDocChanges) TotalChanges() int { // CompareExternalDocs will compare a left (original) and a right (new) slice of ValueReference // nodes for any changes between them. If there are changes, then a pointer to ExternalDocChanges // is returned, otherwise if nothing changed - then nil is returned. -func CompareExternalDocs(l, r *lowbase.ExternalDoc) *ExternalDocChanges { - var changes []*Change[*lowbase.ExternalDoc] - var props []*PropertyCheck[*lowbase.ExternalDoc] +func CompareExternalDocs(l, r *base.ExternalDoc) *ExternalDocChanges { + var changes []*Change[*base.ExternalDoc] + var props []*PropertyCheck[*base.ExternalDoc] // URL - props = append(props, &PropertyCheck[*lowbase.ExternalDoc]{ + props = append(props, &PropertyCheck[*base.ExternalDoc]{ LeftNode: l.URL.ValueNode, RightNode: r.URL.ValueNode, - Label: lowv3.URLLabel, + Label: v3.URLLabel, Changes: &changes, Breaking: false, Original: l, @@ -42,10 +42,10 @@ func CompareExternalDocs(l, r *lowbase.ExternalDoc) *ExternalDocChanges { }) // description. - props = append(props, &PropertyCheck[*lowbase.ExternalDoc]{ + props = append(props, &PropertyCheck[*base.ExternalDoc]{ LeftNode: l.Description.ValueNode, RightNode: r.Description.ValueNode, - Label: lowv3.DescriptionLabel, + Label: v3.DescriptionLabel, Changes: &changes, Breaking: false, Original: l, diff --git a/what-changed/license.go b/what-changed/license.go new file mode 100644 index 0000000..d0bafbb --- /dev/null +++ b/what-changed/license.go @@ -0,0 +1,60 @@ +// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley +// SPDX-License-Identifier: MIT + +package what_changed + +import ( + "github.com/pb33f/libopenapi/datamodel/low/base" + "github.com/pb33f/libopenapi/datamodel/low/v3" +) + +// LicenseChanges represent changes to a License object that is a child of Info object. Part of an OpenAPI document +type LicenseChanges struct { + PropertyChanges[*base.License] +} + +// TotalChanges represents the total number of changes made to a License instance. +func (l *LicenseChanges) TotalChanges() int { + return len(l.Changes) +} + +// CompareLicense will check a left (original) and right (new) License object for any changes. If there +// were any, a pointer to a LicenseChanges object is returned, otherwise if nothing changed - the function +// returns nil. +func CompareLicense(l, r *base.License) *LicenseChanges { + + var changes []*Change[*base.License] + var props []*PropertyCheck[*base.License] + + // check URL + props = append(props, &PropertyCheck[*base.License]{ + LeftNode: l.URL.ValueNode, + RightNode: r.URL.ValueNode, + Label: v3.URLLabel, + Changes: &changes, + Breaking: false, + Original: l, + New: r, + }) + + // check name + props = append(props, &PropertyCheck[*base.License]{ + LeftNode: l.Name.ValueNode, + RightNode: r.Name.ValueNode, + Label: v3.NameLabel, + Changes: &changes, + Breaking: false, + Original: l, + New: r, + }) + + // check everything. + CheckProperties(props) + + lc := new(LicenseChanges) + lc.Changes = changes + if len(changes) <= 0 { + return nil + } + return lc +} diff --git a/what-changed/license_test.go b/what-changed/license_test.go new file mode 100644 index 0000000..57866a9 --- /dev/null +++ b/what-changed/license_test.go @@ -0,0 +1,192 @@ +// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley +// SPDX-License-Identifier: MIT + +package what_changed + +import ( + "github.com/pb33f/libopenapi/datamodel/low" + lowbase "github.com/pb33f/libopenapi/datamodel/low/base" + "github.com/stretchr/testify/assert" + "gopkg.in/yaml.v3" + "testing" +) + +func TestCompareLicense_URLAdded(t *testing.T) { + + left := `name: buckaroo` + + right := `name: buckaroo +url: https://pb33f.io` + + var lNode, rNode yaml.Node + _ = yaml.Unmarshal([]byte(left), &lNode) + _ = yaml.Unmarshal([]byte(right), &rNode) + + // create low level objects + var lDoc lowbase.License + var rDoc lowbase.License + _ = low.BuildModel(&lNode, &lDoc) + _ = low.BuildModel(&rNode, &rDoc) + _ = lDoc.Build(lNode.Content[0], nil) + _ = rDoc.Build(rNode.Content[0], nil) + + // compare. + extChanges := CompareLicense(&lDoc, &rDoc) + assert.Equal(t, 1, extChanges.TotalChanges()) + assert.Equal(t, PropertyAdded, extChanges.Changes[0].ChangeType) + +} + +func TestCompareLicense_URLRemoved(t *testing.T) { + + left := `name: buckaroo +url: https://pb33f.io` + + right := `name: buckaroo` + + var lNode, rNode yaml.Node + _ = yaml.Unmarshal([]byte(left), &lNode) + _ = yaml.Unmarshal([]byte(right), &rNode) + + // create low level objects + var lDoc lowbase.License + var rDoc lowbase.License + _ = low.BuildModel(&lNode, &lDoc) + _ = low.BuildModel(&rNode, &rDoc) + _ = lDoc.Build(lNode.Content[0], nil) + _ = rDoc.Build(rNode.Content[0], nil) + + // compare. + extChanges := CompareLicense(&lDoc, &rDoc) + assert.Equal(t, 1, extChanges.TotalChanges()) + assert.Equal(t, PropertyRemoved, extChanges.Changes[0].ChangeType) + +} + +func TestCompareLicense_NameAdded(t *testing.T) { + + left := `url: https://pb33f.io` + + right := `url: https://pb33f.io +name: buckaroo` + + var lNode, rNode yaml.Node + _ = yaml.Unmarshal([]byte(left), &lNode) + _ = yaml.Unmarshal([]byte(right), &rNode) + + // create low level objects + var lDoc lowbase.License + var rDoc lowbase.License + _ = low.BuildModel(&lNode, &lDoc) + _ = low.BuildModel(&rNode, &rDoc) + _ = lDoc.Build(lNode.Content[0], nil) + _ = rDoc.Build(rNode.Content[0], nil) + + // compare. + extChanges := CompareLicense(&lDoc, &rDoc) + assert.Equal(t, 1, extChanges.TotalChanges()) + assert.Equal(t, PropertyAdded, extChanges.Changes[0].ChangeType) + +} + +func TestCompareLicense_NameRemoved(t *testing.T) { + + left := `url: https://pb33f.io` + + right := `url: https://pb33f.io +name: buckaroo` + + var lNode, rNode yaml.Node + _ = yaml.Unmarshal([]byte(left), &lNode) + _ = yaml.Unmarshal([]byte(right), &rNode) + + // create low level objects + var lDoc lowbase.License + var rDoc lowbase.License + _ = low.BuildModel(&lNode, &lDoc) + _ = low.BuildModel(&rNode, &rDoc) + _ = lDoc.Build(lNode.Content[0], nil) + _ = rDoc.Build(rNode.Content[0], nil) + + // compare. + extChanges := CompareLicense(&lDoc, &rDoc) + assert.Equal(t, 1, extChanges.TotalChanges()) + assert.Equal(t, PropertyAdded, extChanges.Changes[0].ChangeType) + +} + +func TestCompareLicense_URLModified(t *testing.T) { + + left := `url: https://pb33f.io` + + right := `url: https://pb33f.io/new` + + var lNode, rNode yaml.Node + _ = yaml.Unmarshal([]byte(left), &lNode) + _ = yaml.Unmarshal([]byte(right), &rNode) + + // create low level objects + var lDoc lowbase.License + var rDoc lowbase.License + _ = low.BuildModel(&lNode, &lDoc) + _ = low.BuildModel(&rNode, &rDoc) + _ = lDoc.Build(lNode.Content[0], nil) + _ = rDoc.Build(rNode.Content[0], nil) + + // compare. + extChanges := CompareLicense(&lDoc, &rDoc) + assert.Equal(t, 1, extChanges.TotalChanges()) + assert.Equal(t, Modified, extChanges.Changes[0].ChangeType) + +} + +func TestCompareLicense_URLModifiedAndMoved(t *testing.T) { + + left := `name: buckaroo +url: https://pb33f.io` + + right := `url: https://pb33f.io/new` + + var lNode, rNode yaml.Node + _ = yaml.Unmarshal([]byte(left), &lNode) + _ = yaml.Unmarshal([]byte(right), &rNode) + + // create low level objects + var lDoc lowbase.License + var rDoc lowbase.License + _ = low.BuildModel(&lNode, &lDoc) + _ = low.BuildModel(&rNode, &rDoc) + _ = lDoc.Build(lNode.Content[0], nil) + _ = rDoc.Build(rNode.Content[0], nil) + + // compare. + extChanges := CompareLicense(&lDoc, &rDoc) + assert.Equal(t, 2, extChanges.TotalChanges()) + assert.Equal(t, ModifiedAndMoved, extChanges.Changes[0].ChangeType) + assert.Equal(t, PropertyRemoved, extChanges.Changes[1].ChangeType) +} + +func TestCompareLicense_Identical(t *testing.T) { + + left := `name: buckaroo +url: https://pb33f.io` + + right := `name: buckaroo +url: https://pb33f.io` + + var lNode, rNode yaml.Node + _ = yaml.Unmarshal([]byte(left), &lNode) + _ = yaml.Unmarshal([]byte(right), &rNode) + + // create low level objects + var lDoc lowbase.License + var rDoc lowbase.License + _ = low.BuildModel(&lNode, &lDoc) + _ = low.BuildModel(&rNode, &rDoc) + _ = lDoc.Build(lNode.Content[0], nil) + _ = rDoc.Build(rNode.Content[0], nil) + + // compare. + extChanges := CompareLicense(&lDoc, &rDoc) + assert.Nil(t, extChanges) +} diff --git a/what-changed/tags.go b/what-changed/tags.go index 7e5a642..0efb4c6 100644 --- a/what-changed/tags.go +++ b/what-changed/tags.go @@ -5,14 +5,14 @@ package what_changed import ( "github.com/pb33f/libopenapi/datamodel/low" - lowbase "github.com/pb33f/libopenapi/datamodel/low/base" - lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3" + "github.com/pb33f/libopenapi/datamodel/low/base" + "github.com/pb33f/libopenapi/datamodel/low/v3" "strings" ) // TagChanges represents changes made to the Tags object of an OpenAPI document. type TagChanges struct { - PropertyChanges[*lowbase.Tag] + PropertyChanges[*base.Tag] ExternalDocs *ExternalDocChanges ExtensionChanges *ExtensionChanges } @@ -32,12 +32,12 @@ func (t *TagChanges) TotalChanges() int { // CompareTags will compare a left (original) and a right (new) slice of ValueReference nodes for // any changes between them. If there are changes, a pointer to TagChanges is returned, if not then // nil is returned instead. -func CompareTags(l, r []low.ValueReference[*lowbase.Tag]) *TagChanges { +func CompareTags(l, r []low.ValueReference[*base.Tag]) *TagChanges { tc := new(TagChanges) // look at the original and then look through the new. - seenLeft := make(map[string]*low.ValueReference[*lowbase.Tag]) - seenRight := make(map[string]*low.ValueReference[*lowbase.Tag]) + seenLeft := make(map[string]*low.ValueReference[*base.Tag]) + seenRight := make(map[string]*low.ValueReference[*base.Tag]) for i := range l { h := l[i] seenLeft[strings.ToLower(l[i].Value.Name.Value)] = &h @@ -47,23 +47,23 @@ func CompareTags(l, r []low.ValueReference[*lowbase.Tag]) *TagChanges { seenRight[strings.ToLower(r[i].Value.Name.Value)] = &h } - var changes []*Change[*lowbase.Tag] + var changes []*Change[*base.Tag] // check for removals, modifications and moves for i := range seenLeft { - CheckForObjectAdditionOrRemoval[*lowbase.Tag](seenLeft, seenRight, i, &changes, false, true) + CheckForObjectAdditionOrRemoval[*base.Tag](seenLeft, seenRight, i, &changes, false, true) // if the existing tag exists, let's check it. if seenRight[i] != nil { - var props []*PropertyCheck[*lowbase.Tag] + var props []*PropertyCheck[*base.Tag] // Name - props = append(props, &PropertyCheck[*lowbase.Tag]{ + props = append(props, &PropertyCheck[*base.Tag]{ LeftNode: seenLeft[i].Value.Name.ValueNode, RightNode: seenRight[i].Value.Name.ValueNode, - Label: lowv3.NameLabel, + Label: v3.NameLabel, Changes: &changes, Breaking: true, Original: seenLeft[i].Value, @@ -71,10 +71,10 @@ func CompareTags(l, r []low.ValueReference[*lowbase.Tag]) *TagChanges { }) // Description - props = append(props, &PropertyCheck[*lowbase.Tag]{ + props = append(props, &PropertyCheck[*base.Tag]{ LeftNode: seenLeft[i].Value.Description.ValueNode, RightNode: seenRight[i].Value.Description.ValueNode, - Label: lowv3.DescriptionLabel, + Label: v3.DescriptionLabel, Changes: &changes, Breaking: true, Original: seenLeft[i].Value,