From d2b974829d68138f2263f652c13a9513a9c9600a Mon Sep 17 00:00:00 2001 From: Dave Shanley Date: Sun, 11 Sep 2022 21:09:16 -0400 Subject: [PATCH] Swagger v2 high model at 100% coverage. --- datamodel/high/base/example_test.go | 24 ++ datamodel/high/base/external_doc_test.go | 37 ++++ datamodel/high/base/info_test.go | 50 +++++ datamodel/high/base/schema_test.go | 265 ++++++++++++++++++++++- datamodel/high/base/tag_test.go | 40 ++++ datamodel/low/model_builder.go | 17 +- 6 files changed, 421 insertions(+), 12 deletions(-) create mode 100644 datamodel/high/base/external_doc_test.go create mode 100644 datamodel/high/base/info_test.go create mode 100644 datamodel/high/base/tag_test.go diff --git a/datamodel/high/base/example_test.go b/datamodel/high/base/example_test.go index e27641d..009645a 100644 --- a/datamodel/high/base/example_test.go +++ b/datamodel/high/base/example_test.go @@ -39,3 +39,27 @@ x-hack: code` assert.Equal(t, "a thing", highExample.Value) assert.Equal(t, 4, highExample.GoLow().ExternalValue.ValueNode.Line) } + +func TestExtractExamples(t *testing.T) { + var cNode yaml.Node + + yml := `summary: herbs` + + _ = yaml.Unmarshal([]byte(yml), &cNode) + + // build low + var lowExample lowbase.Example + _ = lowmodel.BuildModel(&cNode, &lowExample) + + _ = lowExample.Build(cNode.Content[0], nil) + + examplesMap := make(map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*lowbase.Example]) + examplesMap[lowmodel.KeyReference[string]{ + Value: "green", + }] = lowmodel.ValueReference[*lowbase.Example]{ + Value: &lowExample, + } + + assert.Equal(t, "herbs", ExtractExamples(examplesMap)["green"].Summary) + +} \ No newline at end of file diff --git a/datamodel/high/base/external_doc_test.go b/datamodel/high/base/external_doc_test.go new file mode 100644 index 0000000..a2f6af8 --- /dev/null +++ b/datamodel/high/base/external_doc_test.go @@ -0,0 +1,37 @@ +// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley +// SPDX-License-Identifier: MIT + +package base + +import ( + lowmodel "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 TestNewExternalDoc(t *testing.T) { + + var cNode yaml.Node + + yml := `description: hack code +url: https://pb33f.io +x-hack: code` + + _ = yaml.Unmarshal([]byte(yml), &cNode) + + var lowExt lowbase.ExternalDoc + _ = lowmodel.BuildModel(&cNode, &lowExt) + + _ = lowExt.Build(cNode.Content[0], nil) + + highExt := NewExternalDoc(&lowExt) + + assert.Equal(t, "hack code", highExt.Description) + assert.Equal(t, "https://pb33f.io", highExt.URL) + assert.Equal(t, "code", highExt.Extensions["x-hack"]) + + wentLow := highExt.GoLow() + assert.Equal(t, 2, wentLow.URL.ValueNode.Line) +} diff --git a/datamodel/high/base/info_test.go b/datamodel/high/base/info_test.go new file mode 100644 index 0000000..7627ec9 --- /dev/null +++ b/datamodel/high/base/info_test.go @@ -0,0 +1,50 @@ +// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley +// SPDX-License-Identifier: MIT + +package base + +import ( + lowmodel "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 TestNewInfo(t *testing.T) { + + var cNode yaml.Node + + yml := `title: chicken +description: nugget +termsOfService: chicken soup +contact: + name: buckaroo +license: + name: pb33f + url: https://pb33f.io +version: 99.99` + + _ = yaml.Unmarshal([]byte(yml), &cNode) + + var lowInfo lowbase.Info + _ = lowmodel.BuildModel(&cNode, &lowInfo) + _ = lowInfo.Build(cNode.Content[0], nil) + + highInfo := NewInfo(&lowInfo) + + assert.Equal(t, "chicken", highInfo.Title) + assert.Equal(t, "nugget", highInfo.Description) + assert.Equal(t, "chicken soup", highInfo.TermsOfService) + assert.Equal(t, "buckaroo", highInfo.Contact.Name) + assert.Equal(t, "pb33f", highInfo.License.Name) + assert.Equal(t, "https://pb33f.io", highInfo.License.URL) + assert.Equal(t, "99.99", highInfo.Version) + + wentLow := highInfo.GoLow() + assert.Equal(t, 9, wentLow.Version.ValueNode.Line) + + wentLower := highInfo.License.GoLow() + assert.Equal(t, 8, wentLower.URL.ValueNode.Line) + +} diff --git a/datamodel/high/base/schema_test.go b/datamodel/high/base/schema_test.go index 2565425..85f8621 100644 --- a/datamodel/high/base/schema_test.go +++ b/datamodel/high/base/schema_test.go @@ -5,7 +5,7 @@ package base import ( "github.com/pb33f/libopenapi/datamodel/low" - v3 "github.com/pb33f/libopenapi/datamodel/low/base" + lowbase "github.com/pb33f/libopenapi/datamodel/low/base" "github.com/pb33f/libopenapi/index" "github.com/stretchr/testify/assert" "gopkg.in/yaml.v3" @@ -39,11 +39,11 @@ func TestNewSchemaProxy(t *testing.T) { _ = yaml.Unmarshal([]byte(yml), &compNode) - sp := new(v3.SchemaProxy) + sp := new(lowbase.SchemaProxy) err := sp.Build(compNode.Content[0], idx) assert.NoError(t, err) - lowproxy := low.NodeReference[*v3.SchemaProxy]{ + lowproxy := low.NodeReference[*lowbase.SchemaProxy]{ Value: sp, ValueNode: idxNode.Content[0], } @@ -51,5 +51,264 @@ func TestNewSchemaProxy(t *testing.T) { sch1 := SchemaProxy{schema: &lowproxy} assert.Nil(t, sch1.Schema()) assert.Error(t, sch1.GetBuildError()) +} + +func TestNewSchemaProxy_WithObject(t *testing.T) { + + testSpec := `type: object +description: something object +discriminator: + propertyName: athing + mapping: + log: cat + pizza: party +allOf: + - type: object + description: an allof thing + properties: + allOfA: + type: string + description: allOfA description + example: 'allOfAExp' + allOfB: + type: string + description: allOfB description + example: 'allOfBExp' +oneOf: + type: object + description: a oneof thing + properties: + oneOfA: + type: string + description: oneOfA description + example: 'oneOfAExp' + oneOfB: + type: string + description: oneOfB description + example: 'oneOfBExp' +anyOf: + type: object + description: an anyOf thing + properties: + anyOfA: + type: string + description: anyOfA description + example: 'anyOfAExp' + anyOfB: + type: string + description: anyOfB description + example: 'anyOfBExp' +not: + type: object + description: a not thing + properties: + notA: + type: string + description: notA description + example: 'notAExp' + notB: + type: string + description: notB description + example: 'notBExp' +items: + type: object + description: an items thing + properties: + itemsA: + type: string + description: itemsA description + example: 'itemsAExp' + itemsB: + type: string + description: itemsB description + example: 'itemsBExp' +properties: + somethingBee: + type: number + somethingThree: + type: number + somethingTwo: + type: number + somethingOne: + type: number + somethingA: + type: number + description: a number + example: 2 + somethingB: + type: object + description: an object + externalDocs: + description: the best docs + url: https://pb33f.io + properties: + somethingBProp: + type: string + description: something b subprop + example: picnics are nice. + xml: + name: an xml thing + namespace: an xml namespace + prefix: a prefix + attribute: true + wrapped: false + x-pizza: love + additionalProperties: + why: yes + thatIs: true +additionalProperties: true +xml: + name: XML Thing +externalDocs: + url: https://pb33f.io/docs +enum: [fish, cake] +required: [cake, fish]` + + var compNode yaml.Node + _ = yaml.Unmarshal([]byte(testSpec), &compNode) + + sp := new(lowbase.SchemaProxy) + err := sp.Build(compNode.Content[0], nil) + assert.NoError(t, err) + + lowproxy := low.NodeReference[*lowbase.SchemaProxy]{ + Value: sp, + ValueNode: compNode.Content[0], + } + + schemaProxy := NewSchemaProxy(&lowproxy) + compiled := schemaProxy.Schema() + + assert.NotNil(t, compiled) + assert.Nil(t, schemaProxy.GetBuildError()) + + wentLow := compiled.GoLow() + assert.Equal(t, 102, wentLow.AdditionalProperties.ValueNode.Line) + +} + +func TestNewSchemaProxy_WithObject_FinishPoly(t *testing.T) { + + testSpec := `type: object +description: something object +discriminator: + propertyName: athing + mapping: + log: cat + pizza: party +allOf: + - type: object + description: an allof thing + properties: + allOfA: + type: string + description: allOfA description + example: 'allOfAExp' + allOfB: + type: string + description: allOfB description + example: 'allOfBExp' +oneOf: + type: object + description: a oneof thing + properties: + oneOfA: + type: string + description: oneOfA description + example: 'oneOfAExp' + oneOfB: + type: string + description: oneOfB description + example: 'oneOfBExp' +anyOf: + type: object + description: an anyOf thing + properties: + anyOfA: + type: string + description: anyOfA description + example: 'anyOfAExp' + anyOfB: + type: string + description: anyOfB description + example: 'anyOfBExp' +not: + type: object + description: a not thing + properties: + notA: + type: string + description: notA description + example: 'notAExp' + notB: + type: string + description: notB description + example: 'notBExp' +items: + type: object + description: an items thing + properties: + itemsA: + type: string + description: itemsA description + example: 'itemsAExp' + itemsB: + type: string + description: itemsB description + example: 'itemsBExp' +properties: + somethingB: + type: object + description: an object + externalDocs: + description: the best docs + url: https://pb33f.io + properties: + somethingBProp: + type: string + description: something b subprop + example: picnics are nice. + xml: + name: an xml thing + namespace: an xml namespace + prefix: a prefix + attribute: true + wrapped: false + x-pizza: love + additionalProperties: + why: yes + thatIs: true +additionalProperties: true +xml: + name: XML Thing +externalDocs: + url: https://pb33f.io/docs +enum: [fish, cake] +required: [cake, fish]` + + var compNode yaml.Node + _ = yaml.Unmarshal([]byte(testSpec), &compNode) + + sp := new(lowbase.SchemaProxy) + err := sp.Build(compNode.Content[0], nil) + assert.NoError(t, err) + + lowproxy := low.NodeReference[*lowbase.SchemaProxy]{ + Value: sp, + ValueNode: compNode.Content[0], + } + + schemaProxy := NewSchemaProxy(&lowproxy) + compiled := schemaProxy.Schema() + + assert.NotNil(t, compiled) + assert.Nil(t, schemaProxy.GetBuildError()) + + wentLow := compiled.GoLow() + assert.Equal(t, 90, wentLow.AdditionalProperties.ValueNode.Line) + assert.Equal(t, 92, wentLow.XML.ValueNode.Line) + + wentLower := compiled.XML.GoLow() + assert.Equal(t, 92, wentLower.Name.ValueNode.Line) } diff --git a/datamodel/high/base/tag_test.go b/datamodel/high/base/tag_test.go new file mode 100644 index 0000000..564a61f --- /dev/null +++ b/datamodel/high/base/tag_test.go @@ -0,0 +1,40 @@ +// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley +// SPDX-License-Identifier: MIT + +package base + +import ( + lowmodel "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 TestNewTag(t *testing.T) { + + var cNode yaml.Node + + yml := `name: chicken +description: nuggets +externalDocs: + url: https://pb33f.io +x-hack: code` + + _ = yaml.Unmarshal([]byte(yml), &cNode) + + var lowTag lowbase.Tag + _ = lowmodel.BuildModel(&cNode, &lowTag) + _ = lowTag.Build(cNode.Content[0], nil) + + highTag := NewTag(&lowTag) + + assert.Equal(t, "chicken", highTag.Name) + assert.Equal(t, "nuggets", highTag.Description) + assert.Equal(t, "https://pb33f.io", highTag.ExternalDocs.URL) + assert.Equal(t, "code", highTag.Extensions["x-hack"]) + + wentLow := highTag.GoLow() + assert.Equal(t, 5, wentLow.FindExtension("x-hack").ValueNode.Line) + +} diff --git a/datamodel/low/model_builder.go b/datamodel/low/model_builder.go index fe927e5..1c684d2 100644 --- a/datamodel/low/model_builder.go +++ b/datamodel/low/model_builder.go @@ -109,7 +109,7 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err continue } items[currentLabel] = NodeReference[string]{ - Value: sliceItem.Value, + Value: fmt.Sprintf("%v", sliceItem.Value), ValueNode: sliceItem, KeyNode: valueNode, } @@ -155,16 +155,15 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err break case reflect.TypeOf(NodeReference[string]{}): if valueNode != nil { - if utils.IsNodeStringValue(valueNode) { - if field.CanSet() { - nr := NodeReference[string]{ - Value: valueNode.Value, - ValueNode: valueNode, - KeyNode: keyNode, - } - field.Set(reflect.ValueOf(nr)) + if field.CanSet() { + nr := NodeReference[string]{ + Value: fmt.Sprintf("%v", valueNode.Value), + ValueNode: valueNode, + KeyNode: keyNode, } + field.Set(reflect.ValueOf(nr)) } + } break case reflect.TypeOf(NodeReference[bool]{}):