Full model is now in place,

Time to revisit each model and build individual tests to ensure all error handling is in place across the model.

Signed-off-by: Dave Shanley <dave@quobix.com>
This commit is contained in:
Dave Shanley
2022-08-10 12:18:13 -04:00
parent 3a41d86ee1
commit 717b7d4610
14 changed files with 302 additions and 133 deletions

View File

@@ -10,6 +10,10 @@ type Callback struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any] Extensions map[low.KeyReference[string]]low.ValueReference[any]
} }
func (cb *Callback) FindExpression(exp string) *low.ValueReference[*PathItem] {
return FindItemInMap[*PathItem](exp, cb.Expression.Value)
}
func (cb *Callback) Build(root *yaml.Node) error { func (cb *Callback) Build(root *yaml.Node) error {
extensionMap, err := ExtractExtensions(root) extensionMap, err := ExtractExtensions(root)
if err != nil { if err != nil {

View File

@@ -36,6 +36,26 @@ func (co *Components) FindSecurityScheme(sScheme string) *low.ValueReference[*Se
return FindItemInMap[*SecurityScheme](sScheme, co.SecuritySchemes.Value) return FindItemInMap[*SecurityScheme](sScheme, co.SecuritySchemes.Value)
} }
func (co *Components) FindExample(example string) *low.ValueReference[*Example] {
return FindItemInMap[*Example](example, co.Examples.Value)
}
func (co *Components) FindRequestBody(requestBody string) *low.ValueReference[*RequestBody] {
return FindItemInMap[*RequestBody](requestBody, co.RequestBodies.Value)
}
func (co *Components) FindHeader(header string) *low.ValueReference[*Header] {
return FindItemInMap[*Header](header, co.Headers.Value)
}
func (co *Components) FindLink(link string) *low.ValueReference[*Link] {
return FindItemInMap[*Link](link, co.Links.Value)
}
func (co *Components) FindCallback(callback string) *low.ValueReference[*Callback] {
return FindItemInMap[*Callback](callback, co.Callbacks.Value)
}
func (co *Components) Build(root *yaml.Node) error { func (co *Components) Build(root *yaml.Node) error {
extensionMap, err := ExtractExtensions(root) extensionMap, err := ExtractExtensions(root)
if err != nil { if err != nil {

View File

@@ -6,10 +6,10 @@ import (
type Discriminator struct { type Discriminator struct {
PropertyName low.NodeReference[string] PropertyName low.NodeReference[string]
Mapping map[low.NodeReference[string]]low.NodeReference[string] Mapping map[low.KeyReference[string]]low.ValueReference[string]
} }
func (d *Discriminator) FindMappingValue(key string) *low.NodeReference[string] { func (d *Discriminator) FindMappingValue(key string) *low.ValueReference[string] {
for k, v := range d.Mapping { for k, v := range d.Mapping {
if k.Value == key { if k.Value == key {
return &v return &v

View File

@@ -10,8 +10,8 @@ type Document struct {
Servers low.NodeReference[[]low.ValueReference[*Server]] Servers low.NodeReference[[]low.ValueReference[*Server]]
Paths low.NodeReference[*Paths] Paths low.NodeReference[*Paths]
Components low.NodeReference[*Components] Components low.NodeReference[*Components]
Security []*SecurityRequirement Security low.NodeReference[*SecurityRequirement]
Tags []low.NodeReference[*Tag] Tags low.NodeReference[[]low.ValueReference[*Tag]]
ExternalDocs *ExternalDoc ExternalDocs low.NodeReference[*ExternalDoc]
Extensions map[low.NodeReference[string]]low.NodeReference[any] Extensions map[low.NodeReference[string]]low.NodeReference[any]
} }

View File

@@ -9,17 +9,6 @@ import (
"sync" "sync"
) )
func FindItemInCollection[T any](item string, collection map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[T]) *low.ValueReference[T] {
for _, c := range collection {
for n, o := range c {
if n.Value == item {
return &o
}
}
}
return nil
}
func FindItemInMap[T any](item string, collection map[low.KeyReference[string]]low.ValueReference[T]) *low.ValueReference[T] { func FindItemInMap[T any](item string, collection map[low.KeyReference[string]]low.ValueReference[T]) *low.ValueReference[T] {
for n, o := range collection { for n, o := range collection {
if n.Value == item { if n.Value == item {

View File

@@ -61,11 +61,11 @@ func BuildModel(node *yaml.Node, model interface{}) error {
func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) error { func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) error {
switch field.Type() { switch field.Type() {
case reflect.TypeOf(map[string]low.ObjectReference{}): case reflect.TypeOf(map[string]low.NodeReference[any]{}):
if valueNode != nil { if valueNode != nil {
if utils.IsNodeMap(valueNode) { if utils.IsNodeMap(valueNode) {
if field.CanSet() { if field.CanSet() {
items := make(map[string]low.ObjectReference) items := make(map[string]low.NodeReference[any])
var currentLabel string var currentLabel string
for i, sliceItem := range valueNode.Content { for i, sliceItem := range valueNode.Content {
if i%2 == 0 { if i%2 == 0 {
@@ -77,7 +77,7 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
if err != nil { if err != nil {
return err return err
} }
items[currentLabel] = low.ObjectReference{ items[currentLabel] = low.NodeReference[any]{
Value: decoded, Value: decoded,
ValueNode: sliceItem, ValueNode: sliceItem,
KeyNode: valueNode, KeyNode: valueNode,
@@ -111,33 +111,33 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
} }
} }
break break
case reflect.TypeOf(low.ObjectReference{}): case reflect.TypeOf(low.NodeReference[any]{}):
if valueNode != nil { if valueNode != nil {
var decoded map[string]interface{} var decoded interface{}
err := valueNode.Decode(&decoded) err := valueNode.Decode(&decoded)
if err != nil { if err != nil {
return err return err
} }
if utils.IsNodeMap(valueNode) { if utils.IsNodeMap(valueNode) {
if field.CanSet() { if field.CanSet() {
or := low.ObjectReference{Value: decoded, ValueNode: valueNode} or := low.NodeReference[any]{Value: decoded, ValueNode: valueNode}
field.Set(reflect.ValueOf(or)) field.Set(reflect.ValueOf(or))
} }
} }
} }
break break
case reflect.TypeOf([]low.ObjectReference{}): case reflect.TypeOf([]low.NodeReference[any]{}):
if valueNode != nil { if valueNode != nil {
if utils.IsNodeArray(valueNode) { if utils.IsNodeArray(valueNode) {
if field.CanSet() { if field.CanSet() {
var items []low.ObjectReference var items []low.NodeReference[any]
for _, sliceItem := range valueNode.Content { for _, sliceItem := range valueNode.Content {
var decoded map[string]interface{} var decoded map[string]interface{}
err := sliceItem.Decode(&decoded) err := sliceItem.Decode(&decoded)
if err != nil { if err != nil {
return err return err
} }
items = append(items, low.ObjectReference{ items = append(items, low.NodeReference[any]{
Value: decoded, Value: decoded,
ValueNode: sliceItem, ValueNode: sliceItem,
KeyNode: valueNode, KeyNode: valueNode,
@@ -341,21 +341,21 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
} }
break break
// helper for unpacking string maps. // helper for unpacking string maps.
case reflect.TypeOf(map[low.NodeReference[string]]low.NodeReference[string]{}): case reflect.TypeOf(map[low.KeyReference[string]]low.ValueReference[string]{}):
if valueNode != nil { if valueNode != nil {
if utils.IsNodeMap(valueNode) { if utils.IsNodeMap(valueNode) {
if field.CanSet() { if field.CanSet() {
items := make(map[low.NodeReference[string]]low.NodeReference[string]) items := make(map[low.KeyReference[string]]low.ValueReference[string])
var cf *yaml.Node var cf *yaml.Node
for i, sliceItem := range valueNode.Content { for i, sliceItem := range valueNode.Content {
if i%2 == 0 { if i%2 == 0 {
cf = sliceItem cf = sliceItem
continue continue
} }
items[low.NodeReference[string]{ items[low.KeyReference[string]{
Value: cf.Value, Value: cf.Value,
KeyNode: cf, KeyNode: cf,
}] = low.NodeReference[string]{ }] = low.ValueReference[string]{
Value: sliceItem.Value, Value: sliceItem.Value,
ValueNode: sliceItem, ValueNode: sliceItem,
} }
@@ -364,19 +364,18 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
} }
} }
} }
case reflect.TypeOf(low.NodeReference[[]low.NodeReference[string]]{}): case reflect.TypeOf(low.NodeReference[[]low.ValueReference[string]]{}):
if valueNode != nil { if valueNode != nil {
if utils.IsNodeArray(valueNode) { if utils.IsNodeArray(valueNode) {
if field.CanSet() { if field.CanSet() {
var items []low.NodeReference[string] var items []low.ValueReference[string]
for _, sliceItem := range valueNode.Content { for _, sliceItem := range valueNode.Content {
items = append(items, low.NodeReference[string]{ items = append(items, low.ValueReference[string]{
Value: sliceItem.Value, Value: sliceItem.Value,
ValueNode: sliceItem, ValueNode: sliceItem,
KeyNode: valueNode,
}) })
} }
n := low.NodeReference[[]low.NodeReference[string]]{ n := low.NodeReference[[]low.ValueReference[string]]{
Value: items, Value: items,
KeyNode: keyNode, KeyNode: keyNode,
ValueNode: valueNode, ValueNode: valueNode,

View File

@@ -22,9 +22,9 @@ type hotdog struct {
Temps []low.NodeReference[int] Temps []low.NodeReference[int]
HighTemps []low.NodeReference[int64] HighTemps []low.NodeReference[int64]
Buns []low.NodeReference[bool] Buns []low.NodeReference[bool]
UnknownElements low.ObjectReference UnknownElements low.NodeReference[any]
LotsOfUnknowns []low.ObjectReference LotsOfUnknowns []low.NodeReference[any]
Where map[string]low.ObjectReference Where map[string]low.NodeReference[any]
There map[string]low.NodeReference[string] There map[string]low.NodeReference[string]
} }

View File

@@ -34,8 +34,8 @@ type Schema struct {
UniqueItems low.NodeReference[int] UniqueItems low.NodeReference[int]
MaxProperties low.NodeReference[int] MaxProperties low.NodeReference[int]
MinProperties low.NodeReference[int] MinProperties low.NodeReference[int]
Required low.NodeReference[[]low.NodeReference[string]] Required low.NodeReference[[]low.ValueReference[string]]
Enum low.NodeReference[[]low.NodeReference[string]] Enum low.NodeReference[[]low.ValueReference[string]]
Type low.NodeReference[string] Type low.NodeReference[string]
AllOf low.NodeReference[[]low.NodeReference[*Schema]] AllOf low.NodeReference[[]low.NodeReference[*Schema]]
OneOf low.NodeReference[[]low.NodeReference[*Schema]] OneOf low.NodeReference[[]low.NodeReference[*Schema]]
@@ -85,12 +85,11 @@ func (s *Schema) BuildLevel(root *yaml.Node, level int) error {
_, addPLabel, addPNode := utils.FindKeyNodeFull(AdditionalPropertiesLabel, root.Content) _, addPLabel, addPNode := utils.FindKeyNodeFull(AdditionalPropertiesLabel, root.Content)
if addPNode != nil { if addPNode != nil {
if utils.IsNodeMap(addPNode) { if utils.IsNodeMap(addPNode) {
var props map[string]interface{} schema, serr := ExtractObjectRaw[*Schema](addPNode)
err = addPNode.Decode(&props) if serr != nil {
if err != nil { return serr
return err
} }
s.AdditionalProperties = low.NodeReference[any]{Value: props, KeyNode: addPLabel, ValueNode: addPNode} s.AdditionalProperties = low.NodeReference[any]{Value: schema, KeyNode: addPLabel, ValueNode: addPNode}
} }
if utils.IsNodeBoolValue(addPNode) { if utils.IsNodeBoolValue(addPNode) {

View File

@@ -24,6 +24,10 @@ type SecurityScheme struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any] Extensions map[low.KeyReference[string]]low.ValueReference[any]
} }
type SecurityRequirement struct {
Value []low.ValueReference[map[low.KeyReference[string]][]low.ValueReference[string]]
}
func (ss *SecurityScheme) Build(root *yaml.Node) error { func (ss *SecurityScheme) Build(root *yaml.Node) error {
extensionMap, err := ExtractExtensions(root) extensionMap, err := ExtractExtensions(root)
if err != nil { if err != nil {
@@ -42,10 +46,6 @@ func (ss *SecurityScheme) Build(root *yaml.Node) error {
return nil return nil
} }
type SecurityRequirement struct {
Value []low.ValueReference[map[low.KeyReference[string]][]low.ValueReference[string]]
}
func (sr *SecurityRequirement) FindRequirement(name string) []low.ValueReference[string] { func (sr *SecurityRequirement) FindRequirement(name string) []low.ValueReference[string] {
for _, r := range sr.Value { for _, r := range sr.Value {
for k, v := range r.Value { for k, v := range r.Value {

View File

@@ -27,12 +27,6 @@ type ValueReference[T any] struct {
ValueNode *yaml.Node ValueNode *yaml.Node
} }
type ObjectReference struct {
Value interface{}
ValueNode *yaml.Node
KeyNode *yaml.Node
}
func (n NodeReference[T]) IsEmpty() bool { func (n NodeReference[T]) IsEmpty() bool {
return n.KeyNode == nil && n.ValueNode == nil return n.KeyNode == nil && n.ValueNode == nil
} }

View File

@@ -162,7 +162,7 @@ func TestSpecIndex_PetstoreV3(t *testing.T) {
} }
var mappedRefs = 9 var mappedRefs = 16
func TestSpecIndex_BurgerShop(t *testing.T) { func TestSpecIndex_BurgerShop(t *testing.T) {
@@ -182,7 +182,7 @@ func TestSpecIndex_BurgerShop(t *testing.T) {
assert.Equal(t, 5, len(index.GetAllSchemas())) assert.Equal(t, 5, len(index.GetAllSchemas()))
assert.Equal(t, 22, len(index.GetAllSequencedReferences())) assert.Equal(t, 30, len(index.GetAllSequencedReferences()))
assert.NotNil(t, index.GetSchemasNode()) assert.NotNil(t, index.GetSchemasNode())
assert.NotNil(t, index.GetParametersNode()) assert.NotNil(t, index.GetParametersNode())
@@ -214,7 +214,7 @@ func TestSpecIndex_BurgerShop(t *testing.T) {
assert.Equal(t, 2, index.componentsInlineParamUniqueCount) assert.Equal(t, 2, index.componentsInlineParamUniqueCount)
assert.Equal(t, 2, index.GetInlineUniqueParamCount()) assert.Equal(t, 2, index.GetInlineUniqueParamCount())
assert.Equal(t, 0, len(index.GetAllRequestBodies())) assert.Equal(t, 1, len(index.GetAllRequestBodies()))
assert.NotNil(t, index.GetRootNode()) assert.NotNil(t, index.GetRootNode())
assert.NotNil(t, index.GetGlobalTagsNode()) assert.NotNil(t, index.GetGlobalTagsNode())
assert.NotNil(t, index.GetPathsNode()) assert.NotNil(t, index.GetPathsNode())
@@ -223,7 +223,7 @@ func TestSpecIndex_BurgerShop(t *testing.T) {
assert.NotNil(t, index.GetOperationParameterReferences()) assert.NotNil(t, index.GetOperationParameterReferences())
assert.Equal(t, 3, len(index.GetAllSecuritySchemes())) assert.Equal(t, 3, len(index.GetAllSecuritySchemes()))
assert.Equal(t, 2, len(index.GetAllParameters())) assert.Equal(t, 2, len(index.GetAllParameters()))
assert.Equal(t, 0, len(index.GetAllResponses())) assert.Equal(t, 1, len(index.GetAllResponses()))
assert.Equal(t, 2, len(index.GetInlineOperationDuplicateParameters())) assert.Equal(t, 2, len(index.GetInlineOperationDuplicateParameters()))
assert.Equal(t, 0, len(index.GetReferencesWithSiblings())) assert.Equal(t, 0, len(index.GetReferencesWithSiblings()))
assert.Equal(t, mappedRefs, len(index.GetAllReferences())) assert.Equal(t, mappedRefs, len(index.GetAllReferences()))

View File

@@ -40,6 +40,8 @@ func CreateDocument(info *datamodel.SpecInfo) (*v3.Document, error) {
extractTags, extractTags,
extractPaths, extractPaths,
extractComponents, extractComponents,
extractSecurity,
extractExternalDocs,
} }
wg.Add(len(extractionFuncs)) wg.Add(len(extractionFuncs))
for _, f := range extractionFuncs { for _, f := range extractionFuncs {
@@ -69,6 +71,24 @@ func extractInfo(info *datamodel.SpecInfo, doc *v3.Document) error {
return nil return nil
} }
func extractSecurity(info *datamodel.SpecInfo, doc *v3.Document) error {
sec, sErr := v3.ExtractObject[*v3.SecurityRequirement](v3.SecurityLabel, info.RootNode)
if sErr != nil {
return sErr
}
doc.Security = sec
return nil
}
func extractExternalDocs(info *datamodel.SpecInfo, doc *v3.Document) error {
extDocs, dErr := v3.ExtractObject[*v3.ExternalDoc](v3.ExternalDocsLabel, info.RootNode)
if dErr != nil {
return dErr
}
doc.ExternalDocs = extDocs
return nil
}
func extractComponents(info *datamodel.SpecInfo, doc *v3.Document) error { func extractComponents(info *datamodel.SpecInfo, doc *v3.Document) error {
_, ln, vn := utils.FindKeyNodeFull(v3.ComponentsLabel, info.RootNode.Content) _, ln, vn := utils.FindKeyNodeFull(v3.ComponentsLabel, info.RootNode.Content)
if vn != nil { if vn != nil {
@@ -117,7 +137,7 @@ func extractTags(info *datamodel.SpecInfo, doc *v3.Document) error {
_, ln, vn := utils.FindKeyNodeFull(v3.TagsLabel, info.RootNode.Content) _, ln, vn := utils.FindKeyNodeFull(v3.TagsLabel, info.RootNode.Content)
if vn != nil { if vn != nil {
if utils.IsNodeArray(vn) { if utils.IsNodeArray(vn) {
var tags []low.NodeReference[*v3.Tag] var tags []low.ValueReference[*v3.Tag]
for _, tagN := range vn.Content { for _, tagN := range vn.Content {
if utils.IsNodeMap(tagN) { if utils.IsNodeMap(tagN) {
tag := v3.Tag{} tag := v3.Tag{}
@@ -126,14 +146,17 @@ func extractTags(info *datamodel.SpecInfo, doc *v3.Document) error {
return err return err
} }
tag.Build(tagN) tag.Build(tagN)
tags = append(tags, low.NodeReference[*v3.Tag]{ tags = append(tags, low.ValueReference[*v3.Tag]{
Value: &tag, Value: &tag,
ValueNode: tagN, ValueNode: tagN,
KeyNode: ln,
}) })
} }
} }
doc.Tags = tags doc.Tags = low.NodeReference[[]low.ValueReference[*v3.Tag]]{
Value: tags,
KeyNode: ln,
ValueNode: vn,
}
} }
} }
return nil return nil

View File

@@ -64,17 +64,17 @@ func TestCreateDocument_Servers(t *testing.T) {
} }
func TestCreateDocument_Tags(t *testing.T) { func TestCreateDocument_Tags(t *testing.T) {
assert.Len(t, doc.Tags, 2) assert.Len(t, doc.Tags.Value, 2)
// tag1 // tag1
assert.Equal(t, "Burgers", doc.Tags[0].Value.Name.Value) assert.Equal(t, "Burgers", doc.Tags.Value[0].Value.Name.Value)
assert.NotEmpty(t, doc.Tags[0].Value.Description.Value) assert.NotEmpty(t, doc.Tags.Value[0].Value.Description.Value)
assert.NotNil(t, doc.Tags[0].Value.ExternalDocs.Value) assert.NotNil(t, doc.Tags.Value[0].Value.ExternalDocs.Value)
assert.Equal(t, "https://pb33f.io", doc.Tags[0].Value.ExternalDocs.Value.URL.Value) assert.Equal(t, "https://pb33f.io", doc.Tags.Value[0].Value.ExternalDocs.Value.URL.Value)
assert.NotEmpty(t, doc.Tags[0].Value.ExternalDocs.Value.URL.Value) assert.NotEmpty(t, doc.Tags.Value[0].Value.ExternalDocs.Value.URL.Value)
assert.Len(t, doc.Tags[0].Value.Extensions, 7) assert.Len(t, doc.Tags.Value[0].Value.Extensions, 7)
for key, extension := range doc.Tags[0].Value.Extensions { for key, extension := range doc.Tags.Value[0].Value.Extensions {
switch key.Value { switch key.Value {
case "x-internal-ting": case "x-internal-ting":
assert.Equal(t, "somethingSpecial", extension.Value) assert.Equal(t, "somethingSpecial", extension.Value)
@@ -99,12 +99,12 @@ func TestCreateDocument_Tags(t *testing.T) {
} }
/// tag2 /// tag2
assert.Equal(t, "Dressing", doc.Tags[1].Value.Name.Value) assert.Equal(t, "Dressing", doc.Tags.Value[1].Value.Name.Value)
assert.NotEmpty(t, doc.Tags[1].Value.Description.Value) assert.NotEmpty(t, doc.Tags.Value[1].Value.Description.Value)
assert.NotNil(t, doc.Tags[1].Value.ExternalDocs.Value) assert.NotNil(t, doc.Tags.Value[1].Value.ExternalDocs.Value)
assert.Equal(t, "https://pb33f.io", doc.Tags[1].Value.ExternalDocs.Value.URL.Value) assert.Equal(t, "https://pb33f.io", doc.Tags.Value[1].Value.ExternalDocs.Value.URL.Value)
assert.NotEmpty(t, doc.Tags[1].Value.ExternalDocs.Value.URL.Value) assert.NotEmpty(t, doc.Tags.Value[1].Value.ExternalDocs.Value.URL.Value)
assert.Len(t, doc.Tags[1].Value.Extensions, 0) assert.Len(t, doc.Tags.Value[1].Value.Extensions, 0)
} }
@@ -257,7 +257,10 @@ func TestCreateDocument_Components_Schemas(t *testing.T) {
assert.Equal(t, "a frosty cold beverage can be coke or sprite", assert.Equal(t, "a frosty cold beverage can be coke or sprite",
fries.Value.FindProperty("favoriteDrink").Value.Description.Value) fries.Value.FindProperty("favoriteDrink").Value.Description.Value)
// check security schemes }
func TestCreateDocument_Components_SecuritySchemes(t *testing.T) {
components := doc.Components.Value
securitySchemes := components.SecuritySchemes.Value securitySchemes := components.SecuritySchemes.Value
assert.Len(t, securitySchemes, 3) assert.Len(t, securitySchemes, 3)
@@ -283,3 +286,113 @@ func TestCreateDocument_Components_Schemas(t *testing.T) {
assert.Equal(t, "modify burgers and stuff", readScope.Value) assert.Equal(t, "modify burgers and stuff", readScope.Value)
} }
func TestCreateDocument_Components_Responses(t *testing.T) {
components := doc.Components.Value
responses := components.Responses.Value
assert.Len(t, responses, 1)
dressingResponse := components.FindResponse("DressingResponse")
assert.NotNil(t, dressingResponse.Value)
assert.Equal(t, "all the dressings for a burger.", dressingResponse.Value.Description.Value)
assert.Len(t, dressingResponse.Value.Content.Value, 1)
}
func TestCreateDocument_Components_Examples(t *testing.T) {
components := doc.Components.Value
examples := components.Examples.Value
assert.Len(t, examples, 1)
quarterPounder := components.FindExample("QuarterPounder")
assert.NotNil(t, quarterPounder.Value)
assert.Equal(t, "A juicy two hander sammich", quarterPounder.Value.Summary.Value)
assert.NotNil(t, quarterPounder.Value.Value.Value)
}
func TestCreateDocument_Components_RequestBodies(t *testing.T) {
components := doc.Components.Value
requestBodies := components.RequestBodies.Value
assert.Len(t, requestBodies, 1)
burgerRequest := components.FindRequestBody("BurgerRequest")
assert.NotNil(t, burgerRequest.Value)
assert.Equal(t, "Give us the new burger!", burgerRequest.Value.Description.Value)
assert.Len(t, burgerRequest.Value.Content.Value, 1)
}
func TestCreateDocument_Components_Headers(t *testing.T) {
components := doc.Components.Value
headers := components.Headers.Value
assert.Len(t, headers, 1)
useOil := components.FindHeader("UseOil")
assert.NotNil(t, useOil.Value)
assert.Equal(t, "this is a header", useOil.Value.Description.Value)
assert.Equal(t, "string", useOil.Value.Schema.Value.Type.Value)
}
func TestCreateDocument_Components_Links(t *testing.T) {
components := doc.Components.Value
links := components.Links.Value
assert.Len(t, links, 2)
locateBurger := components.FindLink("LocateBurger")
assert.NotNil(t, locateBurger.Value)
assert.Equal(t, "Go and get a tasty burger", locateBurger.Value.Description.Value)
anotherLocateBurger := components.FindLink("AnotherLocateBurger")
assert.NotNil(t, anotherLocateBurger.Value)
assert.Equal(t, "Go and get another really tasty burger", anotherLocateBurger.Value.Description.Value)
}
func TestCreateDocument_Doc_Security(t *testing.T) {
security := doc.Security.Value
assert.NotNil(t, security)
assert.Len(t, security.Value, 1)
oAuth := security.FindRequirement("OAuthScheme")
assert.Len(t, oAuth, 2)
}
func TestCreateDocument_Callbacks(t *testing.T) {
callbacks := doc.Components.Value.Callbacks.Value
assert.Len(t, callbacks, 1)
bCallback := doc.Components.Value.FindCallback("BurgerCallback")
assert.NotNil(t, bCallback.Value)
assert.Len(t, callbacks, 1)
exp := bCallback.Value.FindExpression("{$request.query.queryUrl}")
assert.NotNil(t, exp.Value)
assert.NotNil(t, exp.Value.Post.Value)
assert.Equal(t, "Callback payload", exp.Value.Post.Value.RequestBody.Value.Description.Value)
}
func TestCreateDocument_Component_Discriminator(t *testing.T) {
components := doc.Components.Value
dsc := components.FindSchema("Drink").Value.Discriminator.Value
assert.NotNil(t, dsc)
assert.Equal(t, "drinkType", dsc.PropertyName.Value)
assert.Equal(t, "some value", dsc.FindMappingValue("drink").Value)
assert.Nil(t, dsc.FindMappingValue("don't exist"))
}
func TestCreateDocument_CheckAdditionalProperties_Schema(t *testing.T) {
components := doc.Components.Value
d := components.FindSchema("Dressing")
assert.NotNil(t, d.Value.AdditionalProperties.Value)
if n, ok := d.Value.AdditionalProperties.Value.(*v3.Schema); ok {
assert.Equal(t, "something in here.", n.Description.Value)
} else {
assert.Fail(t, "should be a schema")
}
}
func TestCreateDocument_CheckAdditionalProperties_Bool(t *testing.T) {
components := doc.Components.Value
d := components.FindSchema("Drink")
assert.NotNil(t, d.Value.AdditionalProperties.Value)
assert.True(t, d.Value.AdditionalProperties.Value.(bool))
}

View File

@@ -12,6 +12,10 @@ info:
name: pb33f name: pb33f
url: https://pb33f.io/made-up url: https://pb33f.io/made-up
version: "1.2" version: "1.2"
security:
- OAuthScheme:
- read:burgers
- write:burgers
tags: tags:
- name: "Burgers" - name: "Burgers"
description: "All kinds of yummy burgers." description: "All kinds of yummy burgers."
@@ -66,29 +70,12 @@ paths:
summary: Create a new burger summary: Create a new burger
description: A new burger for our menu, yummy yum yum. description: A new burger for our menu, yummy yum yum.
requestBody: requestBody:
description: Give us the new burger! $ref: '#/components/requestBodies/BurgerRequest'
content:
application/json:
schema:
$ref: '#/components/schemas/Burger'
examples:
pbjBurger:
summary: A horrible, nutty, sticky mess.
value:
name: Peanut And Jelly
numPatties: 3
cakeBurger:
summary: A sickly, sweet, atrocity
value:
name: Chocolate Cake Burger
numPatties: 5
responses: responses:
"200": "200":
headers: headers:
UseOil: UseOil:
description: this is a header $ref: '#/components/headers/UseOil'
schema:
type: string
description: A tasty burger for you to eat. description: A tasty burger for you to eat.
content: content:
application/json: application/json:
@@ -96,10 +83,7 @@ paths:
$ref: '#/components/schemas/Burger' $ref: '#/components/schemas/Burger'
examples: examples:
quarterPounder: quarterPounder:
summary: a yummy tasty two patty burger, filled with beefy goodness. $ref: '#/components/examples/QuarterPounder'
value:
name: Quarter Pounder with Cheese
numPatties: 1
filetOFish: filetOFish:
summary: a cripsy fish sammich filled with ocean goodness. summary: a cripsy fish sammich filled with ocean goodness.
value: value:
@@ -107,15 +91,9 @@ paths:
numPatties: 1 numPatties: 1
links: links:
LocateBurger: LocateBurger:
operationId: locateBurger $ref: '#/components/links/LocateBurger'
parameters:
burgerId: '$response.body#/id'
description: Go and get a tasty burger
AnotherLocateBurger: AnotherLocateBurger:
operationId: locateBurger $ref: '#/components/links/AnotherLocateBurger'
parameters:
burgerId: '$response.body#/id'
description: Go and get a another really tasty burger
"500": "500":
description: Unexpected error creating a new burger. Sorry. description: Unexpected error creating a new burger. Sorry.
content: content:
@@ -149,17 +127,7 @@ paths:
get: get:
callbacks: callbacks:
burgerCallback: burgerCallback:
"{$request.query.queryUrl}": $ref: '#/components/callbacks/BurgerCallback'
post:
requestBody:
description: Callback payload
content:
'application/json':
schema:
$ref: '#/components/schemas/SomePayload'
responses:
'200':
description: callback successfully processed
operationId: locateBurger operationId: locateBurger
tags: tags:
- "Burgers" - "Burgers"
@@ -177,10 +145,7 @@ paths:
$ref: '#/components/schemas/Burger' $ref: '#/components/schemas/Burger'
examples: examples:
quarterPounder: quarterPounder:
summary: A juicy two handler sammich $ref: '#/components/examples/QuarterPounder'
value:
name: Quarter Pounder with Cheese
numPatties: 1
filetOFish: filetOFish:
summary: A tasty treat from the sea summary: A tasty treat from the sea
value: value:
@@ -231,15 +196,7 @@ paths:
required: true required: true
responses: responses:
"200": "200":
description: all the dressings for a burger. $ref: '#/components/responses/DressingResponse'
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Dressing'
example:
- name: Thousand Island
"404": "404":
description: Cannot find your burger in which to list dressings. Sorry description: Cannot find your burger in which to list dressings. Sorry
content: content:
@@ -331,6 +288,70 @@ paths:
example: example:
message: "failed looking up all dressings, something went wrong." message: "failed looking up all dressings, something went wrong."
components: components:
callbacks:
BurgerCallback:
"{$request.query.queryUrl}":
post:
requestBody:
description: Callback payload
content:
'application/json':
schema:
$ref: '#/components/schemas/SomePayload'
responses:
'200':
description: callback successfully processes
links:
LocateBurger:
operationId: locateBurger
parameters:
burgerId: '$response.body#/id'
description: Go and get a tasty burger
AnotherLocateBurger:
operationId: locateBurger
parameters:
burgerId: '$response.body#/id'
description: Go and get another really tasty burger
headers:
UseOil:
description: this is a header
schema:
type: string
requestBodies:
BurgerRequest:
description: Give us the new burger!
content:
application/json:
schema:
$ref: '#/components/schemas/Burger'
examples:
pbjBurger:
summary: A horrible, nutty, sticky mess.
value:
name: Peanut And Jelly
numPatties: 3
cakeBurger:
summary: A sickly, sweet, atrocity
value:
name: Chocolate Cake Burger
numPatties: 5
examples:
QuarterPounder:
summary: A juicy two hander sammich
value:
name: Quarter Pounder with Cheese
numPatties: 1
responses:
DressingResponse:
description: all the dressings for a burger.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Dressing'
example:
- name: Thousand Island
securitySchemes: securitySchemes:
APIKeyScheme: APIKeyScheme:
type: apiKey type: apiKey
@@ -463,6 +484,9 @@ components:
type: string type: string
description: The name of your dressing you can pick up from the menu description: The name of your dressing you can pick up from the menu
example: Cheese example: Cheese
additionalProperties:
type: object
description: something in here.
Drink: Drink:
type: object type: object
description: a frosty cold beverage can be coke or sprite description: a frosty cold beverage can be coke or sprite
@@ -481,4 +505,8 @@ components:
type: string type: string
description: what size man? S/M/L description: what size man? S/M/L
example: M example: M
additionalProperties: true
discriminator:
propertyName: drinkType
mapping:
drink: some value