mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-06 12:37:49 +00:00
Schemas are now rendered on demand. There is no reasonable way to navigate the mayhem that is circular dependencies through multiple inheritance and polymorphism. So now using a msuch simpler design (and MUCH faster), there is a `SchemaProxy` for every schema reference. This holds a reference to the low model and index, that renders the schema on demand. Once rendered, it's done. Any children can also be rendered on demand, and so down the rabbit hole you do (if you want). All circular dependencies are know by the index, so you can decide when you want to stop, or just keep going for ever, however it's now a choice, not something decided for you. Signed-off-by: Dave Shanley <dave@quobix.com>
166 lines
4.1 KiB
Go
166 lines
4.1 KiB
Go
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package v3
|
|
|
|
import (
|
|
"github.com/pb33f/libopenapi/datamodel/low"
|
|
"github.com/pb33f/libopenapi/index"
|
|
"github.com/stretchr/testify/assert"
|
|
"gopkg.in/yaml.v3"
|
|
"testing"
|
|
)
|
|
|
|
func TestHeader_Build(t *testing.T) {
|
|
yml := `description: michelle, meddy and maddy
|
|
required: true
|
|
deprecated: false
|
|
allowEmptyValue: false
|
|
style: beautiful
|
|
explode: true
|
|
allowReserved: true
|
|
schema:
|
|
type: object
|
|
description: my triple M, my loves
|
|
properties:
|
|
michelle:
|
|
type: string
|
|
description: she is my heart.
|
|
meddy:
|
|
type: string
|
|
description: she is my song.
|
|
maddy:
|
|
type: string
|
|
description: he is my champion.
|
|
x-family-love: strong
|
|
example:
|
|
michelle: my love.
|
|
maddy: my champion.
|
|
meddy: my song.
|
|
content:
|
|
family/love:
|
|
schema:
|
|
type: string
|
|
description: family love.`
|
|
|
|
var idxNode yaml.Node
|
|
mErr := yaml.Unmarshal([]byte(yml), &idxNode)
|
|
assert.NoError(t, mErr)
|
|
idx := index.NewSpecIndex(&idxNode)
|
|
|
|
var n Header
|
|
err := low.BuildModel(&idxNode, &n)
|
|
assert.NoError(t, err)
|
|
|
|
err = n.Build(idxNode.Content[0], idx)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "michelle, meddy and maddy", n.Description.Value)
|
|
assert.True(t, n.AllowReserved.Value)
|
|
assert.True(t, n.Explode.Value)
|
|
assert.True(t, n.Required.Value)
|
|
assert.False(t, n.Deprecated.Value)
|
|
assert.NotNil(t, n.Schema.Value)
|
|
assert.Equal(t, "my triple M, my loves", n.Schema.Value.Schema().Description.Value)
|
|
assert.NotNil(t, n.Schema.Value.Schema().Properties.Value)
|
|
assert.Equal(t, "she is my heart.", n.Schema.Value.Schema().FindProperty("michelle").Value.Schema().Description.Value)
|
|
assert.Equal(t, "she is my song.", n.Schema.Value.Schema().FindProperty("meddy").Value.Schema().Description.Value)
|
|
assert.Equal(t, "he is my champion.", n.Schema.Value.Schema().FindProperty("maddy").Value.Schema().Description.Value)
|
|
|
|
if v, ok := n.Example.Value.(map[string]interface{}); ok {
|
|
assert.Equal(t, "my love.", v["michelle"])
|
|
assert.Equal(t, "my song.", v["meddy"])
|
|
assert.Equal(t, "my champion.", v["maddy"])
|
|
} else {
|
|
assert.Fail(t, "should not fail")
|
|
}
|
|
|
|
con := n.FindContent("family/love").Value
|
|
assert.NotNil(t, con)
|
|
assert.Equal(t, "family love.", con.Schema.Value.Schema().Description.Value)
|
|
assert.Nil(t, n.FindContent("unknown"))
|
|
|
|
ext := n.FindExtension("x-family-love").Value
|
|
assert.Equal(t, "strong", ext)
|
|
}
|
|
|
|
func TestHeader_Build_Success_Examples(t *testing.T) {
|
|
yml := `examples:
|
|
family:
|
|
value:
|
|
michelle: my love.
|
|
maddy: my champion.
|
|
meddy: my song.`
|
|
|
|
var idxNode yaml.Node
|
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
|
idx := index.NewSpecIndex(&idxNode)
|
|
|
|
var n Header
|
|
err := low.BuildModel(&idxNode, &n)
|
|
assert.NoError(t, err)
|
|
|
|
err = n.Build(idxNode.Content[0], idx)
|
|
assert.NoError(t, err)
|
|
|
|
exp := n.FindExample("family").Value
|
|
assert.NotNil(t, exp)
|
|
|
|
if v, ok := exp.Value.Value.(map[string]interface{}); ok {
|
|
assert.Equal(t, "my love.", v["michelle"])
|
|
assert.Equal(t, "my song.", v["meddy"])
|
|
assert.Equal(t, "my champion.", v["maddy"])
|
|
} else {
|
|
assert.Fail(t, "should not fail")
|
|
}
|
|
}
|
|
|
|
func TestHeader_Build_Fail_Examples(t *testing.T) {
|
|
yml := `examples:
|
|
family:
|
|
$ref: I AM BORKED`
|
|
|
|
var idxNode yaml.Node
|
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
|
idx := index.NewSpecIndex(&idxNode)
|
|
|
|
var n Header
|
|
err := low.BuildModel(&idxNode, &n)
|
|
assert.NoError(t, err)
|
|
|
|
err = n.Build(idxNode.Content[0], idx)
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestHeader_Build_Fail_Schema(t *testing.T) {
|
|
yml := `schema:
|
|
$ref: I will fail.`
|
|
|
|
var idxNode yaml.Node
|
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
|
idx := index.NewSpecIndex(&idxNode)
|
|
|
|
var n Header
|
|
err := low.BuildModel(&idxNode, &n)
|
|
assert.NoError(t, err)
|
|
|
|
err = n.Build(idxNode.Content[0], idx)
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestHeader_Build_Fail_Content(t *testing.T) {
|
|
yml := `content:
|
|
ohMyStars:
|
|
$ref: fail!`
|
|
|
|
var idxNode yaml.Node
|
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
|
idx := index.NewSpecIndex(&idxNode)
|
|
|
|
var n Header
|
|
err := low.BuildModel(&idxNode, &n)
|
|
assert.NoError(t, err)
|
|
|
|
err = n.Build(idxNode.Content[0], idx)
|
|
assert.Error(t, err)
|
|
}
|