mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-10 20:47:44 +00:00
Schemas now working, still need to check polymorphic work
However the painbarrier seems to have been smashed, now all polymorphic references can be tracked to circular references. confidence is now up 100%.
This commit is contained in:
@@ -121,13 +121,50 @@ func TestNewDocument_Tags(t *testing.T) {
|
||||
assert.Equal(t, 20, wentLower.Description.ValueNode.Column)
|
||||
}
|
||||
|
||||
func TestNewDocument_Components(t *testing.T) {
|
||||
func TestNewDocument_Components_Links(t *testing.T) {
|
||||
h := NewDocument(doc)
|
||||
assert.Len(t, h.Components.Links, 2)
|
||||
assert.Equal(t, "locateBurger", h.Components.Links["LocateBurger"].OperationId)
|
||||
assert.Equal(t, "$response.body#/id", h.Components.Links["LocateBurger"].Parameters["burgerId"])
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_Callbacks(t *testing.T) {
|
||||
h := NewDocument(doc)
|
||||
assert.Len(t, h.Components.Callbacks, 1)
|
||||
assert.Equal(t, "Callback payload",
|
||||
h.Components.Callbacks["BurgerCallback"].Expression["{$request.query.queryUrl}"].Post.RequestBody.Description)
|
||||
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_Schemas(t *testing.T) {
|
||||
h := NewDocument(doc)
|
||||
assert.Len(t, h.Components.Schemas, 6)
|
||||
|
||||
a := h.Components.Schemas["Error"]
|
||||
assert.Equal(t, "No such burger as 'Big-Whopper'", a.Properties["message"].Example)
|
||||
|
||||
b := h.Components.Schemas["Burger"]
|
||||
assert.Len(t, b.Required, 2)
|
||||
assert.Equal(t, "golden slices of happy fun joy", b.Properties["fries"].Description)
|
||||
assert.Equal(t, int64(2), b.Properties["numPatties"].Example)
|
||||
|
||||
f := h.Components.Schemas["Fries"]
|
||||
assert.Equal(t, "salt", f.Properties["seasoning"].Items.Example)
|
||||
assert.Len(t, f.Properties["favoriteDrink"].Properties["drinkType"].Enum, 2)
|
||||
|
||||
d := h.Components.Schemas["Drink"]
|
||||
assert.Len(t, d.Required, 2)
|
||||
assert.True(t, d.AdditionalProperties.(bool))
|
||||
assert.Equal(t, "drinkType", d.Discriminator.PropertyName)
|
||||
assert.Equal(t, "some value", d.Discriminator.Mapping["drink"])
|
||||
|
||||
ext := h.Components.Extensions
|
||||
assert.Equal(t, "loud", ext["x-screaming-baby"])
|
||||
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_Headers(t *testing.T) {
|
||||
h := NewDocument(doc)
|
||||
assert.Len(t, h.Components.Headers, 1)
|
||||
assert.Equal(t, "this is a header", h.Components.Headers["UseOil"].Description)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ type Schema struct {
|
||||
OneOf []*Schema
|
||||
AnyOf []*Schema
|
||||
Not []*Schema
|
||||
Items []*Schema
|
||||
Items *Schema
|
||||
Properties map[string]*Schema
|
||||
AdditionalProperties any
|
||||
Description string
|
||||
@@ -94,7 +94,7 @@ func NewSchema(schema *low.Schema) *Schema {
|
||||
|
||||
var enum []string
|
||||
for i := range schema.Enum.Value {
|
||||
enum = append(req, schema.Enum.Value[i].Value)
|
||||
enum = append(enum, schema.Enum.Value[i].Value)
|
||||
}
|
||||
s.Enum = enum
|
||||
|
||||
@@ -111,7 +111,7 @@ func NewSchema(schema *low.Schema) *Schema {
|
||||
bChan := make(chan *Schema)
|
||||
|
||||
// for every item, build schema async
|
||||
buildSchema := func(sch lowmodel.NodeReference[*low.Schema], bChan chan *Schema) {
|
||||
buildSchemaChild := func(sch lowmodel.NodeReference[*low.Schema], bChan chan *Schema) {
|
||||
if ss := getSeenSchema(sch.GenerateMapKey()); ss != nil {
|
||||
bChan <- ss
|
||||
return
|
||||
@@ -122,7 +122,7 @@ func NewSchema(schema *low.Schema) *Schema {
|
||||
}
|
||||
totalSchemas := len(schemas)
|
||||
for v := range schemas {
|
||||
go buildSchema(schemas[v], bChan)
|
||||
go buildSchemaChild(schemas[v], bChan)
|
||||
}
|
||||
j := 0
|
||||
for j < totalSchemas {
|
||||
@@ -178,15 +178,23 @@ func NewSchema(schema *low.Schema) *Schema {
|
||||
go buildOutSchema(schema.Not.Value, ¬, polyCompletedChan)
|
||||
}
|
||||
if !schema.Items.IsEmpty() {
|
||||
go buildOutSchema(schema.Items.Value, &items, polyCompletedChan)
|
||||
// items is only a single prop, however the method uses an array, so pack it up in one.
|
||||
var itms []lowmodel.NodeReference[*low.Schema]
|
||||
itms = append(itms, lowmodel.NodeReference[*low.Schema]{
|
||||
Value: schema.Items.Value,
|
||||
KeyNode: schema.Items.KeyNode,
|
||||
ValueNode: schema.Items.ValueNode,
|
||||
})
|
||||
go buildOutSchema(itms, &items, polyCompletedChan)
|
||||
}
|
||||
|
||||
completePoly := 0
|
||||
completedProps := 0
|
||||
totalProps := len(schema.Properties.Value)
|
||||
totalPoly := len(schema.AllOf.Value) + len(schema.OneOf.Value) + len(schema.AnyOf.Value) + len(schema.Not.Value) +
|
||||
len(schema.Items.Value)
|
||||
|
||||
totalPoly := len(schema.AllOf.Value) + len(schema.OneOf.Value) + len(schema.AnyOf.Value) + len(schema.Not.Value)
|
||||
if !schema.Items.IsEmpty() {
|
||||
totalPoly++ // only a single item can be present.
|
||||
}
|
||||
if totalProps+totalPoly > 0 {
|
||||
allDone:
|
||||
for true {
|
||||
@@ -208,10 +216,13 @@ func NewSchema(schema *low.Schema) *Schema {
|
||||
s.AnyOf = anyOf
|
||||
s.AllOf = allOf
|
||||
s.Not = not
|
||||
s.Items = items
|
||||
if len(items) > 0 {
|
||||
s.Items = items[0] // there will only ever be one.
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Schema) GoLow() *low.Schema {
|
||||
return s.low
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -205,16 +206,20 @@ func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
totalComponents := 0
|
||||
for i, v := range nodeValue.Content {
|
||||
// always ignore extensions
|
||||
if i%2 == 0 {
|
||||
currentLabel = v
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(strings.ToLower(currentLabel.Value), "x-") {
|
||||
continue
|
||||
}
|
||||
totalComponents++
|
||||
go buildComponent(currentLabel, v, bChan, errorChan)
|
||||
}
|
||||
|
||||
totalComponents := len(nodeValue.Content) / 2
|
||||
completedComponents := 0
|
||||
for completedComponents < totalComponents {
|
||||
select {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -67,3 +68,19 @@ func (ex *Example) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExtractExampleValue(exp *yaml.Node) any {
|
||||
if utils.IsNodeBoolValue(exp) {
|
||||
v, _ := strconv.ParseBool(exp.Value)
|
||||
return v
|
||||
}
|
||||
if utils.IsNodeIntValue(exp) {
|
||||
v, _ := strconv.ParseInt(exp.Value, 10, 64)
|
||||
return v
|
||||
}
|
||||
if utils.IsNodeFloatValue(exp) {
|
||||
v, _ := strconv.ParseFloat(exp.Value, 64)
|
||||
return v
|
||||
}
|
||||
return exp.Value
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ type Schema struct {
|
||||
OneOf low.NodeReference[[]low.NodeReference[*Schema]]
|
||||
AnyOf low.NodeReference[[]low.NodeReference[*Schema]]
|
||||
Not low.NodeReference[[]low.NodeReference[*Schema]]
|
||||
Items low.NodeReference[[]low.NodeReference[*Schema]]
|
||||
Items low.NodeReference[*Schema]
|
||||
Properties low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Schema]]
|
||||
AdditionalProperties low.NodeReference[any]
|
||||
Description low.NodeReference[string]
|
||||
@@ -93,7 +93,7 @@ func (s *Schema) BuildLevel(root *yaml.Node, idx *index.SpecIndex, level int) er
|
||||
// handle example if set.
|
||||
_, expLabel, expNode := utils.FindKeyNodeFull(ExampleLabel, root.Content)
|
||||
if expNode != nil {
|
||||
s.Example = low.NodeReference[any]{Value: expNode.Value, KeyNode: expLabel, ValueNode: expNode}
|
||||
s.Example = low.NodeReference[any]{Value: ExtractExampleValue(expNode), KeyNode: expLabel, ValueNode: expNode}
|
||||
}
|
||||
|
||||
_, addPLabel, addPNode := utils.FindKeyNodeFull(AdditionalPropertiesLabel, root.Content)
|
||||
@@ -265,8 +265,9 @@ func (s *Schema) BuildLevel(root *yaml.Node, idx *index.SpecIndex, level int) er
|
||||
}
|
||||
}
|
||||
if len(items) > 0 {
|
||||
s.Items = low.NodeReference[[]low.NodeReference[*Schema]]{
|
||||
Value: items,
|
||||
// items can only be a single def, so only extract a single value
|
||||
s.Items = low.NodeReference[*Schema]{
|
||||
Value: items[0].Value,
|
||||
KeyNode: itemsLabel,
|
||||
ValueNode: itemsValue,
|
||||
}
|
||||
|
||||
@@ -197,15 +197,15 @@ additionalProperties: true `
|
||||
assert.Equal(t, "notBExp", v.Value.Example.Value)
|
||||
|
||||
// check values Items
|
||||
assert.Equal(t, "an items thing", sch.Items.Value[0].Value.Description.Value)
|
||||
assert.Len(t, sch.Items.Value[0].Value.Properties.Value, 2)
|
||||
assert.Equal(t, "an items thing", sch.Items.Value.Description.Value)
|
||||
assert.Len(t, sch.Items.Value.Properties.Value, 2)
|
||||
|
||||
v = sch.Items.Value[0].Value.FindProperty("itemsA")
|
||||
v = sch.Items.Value.FindProperty("itemsA")
|
||||
assert.NotNil(t, v)
|
||||
assert.Equal(t, "itemsA description", v.Value.Description.Value)
|
||||
assert.Equal(t, "itemsAExp", v.Value.Example.Value)
|
||||
|
||||
v = sch.Items.Value[0].Value.FindProperty("itemsB")
|
||||
v = sch.Items.Value.FindProperty("itemsB")
|
||||
assert.NotNil(t, v)
|
||||
assert.Equal(t, "itemsB description", v.Value.Description.Value)
|
||||
assert.Equal(t, "itemsBExp", v.Value.Example.Value)
|
||||
@@ -456,7 +456,7 @@ items:
|
||||
assert.Equal(t, desc, sch.AnyOf.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.AllOf.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.Not.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.Items.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.Items.Value.Description.Value)
|
||||
}
|
||||
|
||||
func Test_Schema_Polymorphism_Array_Ref_Fail(t *testing.T) {
|
||||
@@ -546,7 +546,7 @@ items:
|
||||
assert.Equal(t, desc, sch.AnyOf.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.AllOf.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.Not.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.Items.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.Items.Value.Description.Value)
|
||||
}
|
||||
|
||||
func Test_Schema_Polymorphism_Map_Ref_Fail(t *testing.T) {
|
||||
|
||||
@@ -511,6 +511,7 @@ components:
|
||||
SomePayload:
|
||||
type: string
|
||||
description: some kind of payload for something.
|
||||
x-screaming-baby: loud
|
||||
x-something-something: darkside
|
||||
externalDocs:
|
||||
description: "Find out more information about our products)"
|
||||
|
||||
Reference in New Issue
Block a user