mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-07 20:47:45 +00:00
(feat): Circular / resolving errors returned with document creation. #18
Tristan made a good point, part of the doc building process performs a resolving check and circular reference check, which is ignored by the returned errors. So resolving errors are now unpacked into standard errors and returned. Not sure why gofmt has shifted everything around however.
This commit is contained in:
@@ -4,393 +4,389 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var lowDoc *lowv3.Document
|
||||
|
||||
func initTest() {
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
lowDoc, err = lowv3.CreateDocument(info)
|
||||
if err != nil {
|
||||
panic("broken something")
|
||||
}
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
lowDoc, err = lowv3.CreateDocument(info)
|
||||
if err != nil {
|
||||
panic("broken something")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNewDocument(b *testing.B) {
|
||||
initTest()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = NewDocument(lowDoc)
|
||||
}
|
||||
initTest()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = NewDocument(lowDoc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDocument_Extensions(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Equal(t, "darkside", h.Extensions["x-something-something"])
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Equal(t, "darkside", h.Extensions["x-something-something"])
|
||||
}
|
||||
|
||||
func TestNewDocument_ExternalDocs(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Equal(t, "https://pb33f.io", h.ExternalDocs.URL)
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Equal(t, "https://pb33f.io", h.ExternalDocs.URL)
|
||||
}
|
||||
|
||||
func TestNewDocument_Info(t *testing.T) {
|
||||
initTest()
|
||||
highDoc := NewDocument(lowDoc)
|
||||
assert.Equal(t, "3.1.0", highDoc.Version)
|
||||
assert.Equal(t, "Burger Shop", highDoc.Info.Title)
|
||||
assert.Equal(t, "https://pb33f.io", highDoc.Info.TermsOfService)
|
||||
assert.Equal(t, "pb33f", highDoc.Info.Contact.Name)
|
||||
assert.Equal(t, "buckaroo@pb33f.io", highDoc.Info.Contact.Email)
|
||||
assert.Equal(t, "https://pb33f.io", highDoc.Info.Contact.URL)
|
||||
assert.Equal(t, "pb33f", highDoc.Info.License.Name)
|
||||
assert.Equal(t, "https://pb33f.io/made-up", highDoc.Info.License.URL)
|
||||
assert.Equal(t, "1.2", highDoc.Info.Version)
|
||||
assert.Equal(t, "https://pb33f.io/schema", highDoc.JsonSchemaDialect)
|
||||
initTest()
|
||||
highDoc := NewDocument(lowDoc)
|
||||
assert.Equal(t, "3.1.0", highDoc.Version)
|
||||
assert.Equal(t, "Burger Shop", highDoc.Info.Title)
|
||||
assert.Equal(t, "https://pb33f.io", highDoc.Info.TermsOfService)
|
||||
assert.Equal(t, "pb33f", highDoc.Info.Contact.Name)
|
||||
assert.Equal(t, "buckaroo@pb33f.io", highDoc.Info.Contact.Email)
|
||||
assert.Equal(t, "https://pb33f.io", highDoc.Info.Contact.URL)
|
||||
assert.Equal(t, "pb33f", highDoc.Info.License.Name)
|
||||
assert.Equal(t, "https://pb33f.io/made-up", highDoc.Info.License.URL)
|
||||
assert.Equal(t, "1.2", highDoc.Info.Version)
|
||||
assert.Equal(t, "https://pb33f.io/schema", highDoc.JsonSchemaDialect)
|
||||
|
||||
wentLow := highDoc.GoLow()
|
||||
assert.Equal(t, 1, wentLow.Version.ValueNode.Line)
|
||||
assert.Equal(t, 3, wentLow.Info.Value.Title.KeyNode.Line)
|
||||
wentLow := highDoc.GoLow()
|
||||
assert.Equal(t, 1, wentLow.Version.ValueNode.Line)
|
||||
assert.Equal(t, 3, wentLow.Info.Value.Title.KeyNode.Line)
|
||||
|
||||
wentLower := highDoc.Info.Contact.GoLow()
|
||||
assert.Equal(t, 8, wentLower.Name.ValueNode.Line)
|
||||
assert.Equal(t, 11, wentLower.Name.ValueNode.Column)
|
||||
wentLower := highDoc.Info.Contact.GoLow()
|
||||
assert.Equal(t, 8, wentLower.Name.ValueNode.Line)
|
||||
assert.Equal(t, 11, wentLower.Name.ValueNode.Column)
|
||||
|
||||
wentLowAgain := highDoc.Info.GoLow()
|
||||
assert.Equal(t, 3, wentLowAgain.Title.ValueNode.Line)
|
||||
assert.Equal(t, 10, wentLowAgain.Title.ValueNode.Column)
|
||||
wentLowAgain := highDoc.Info.GoLow()
|
||||
assert.Equal(t, 3, wentLowAgain.Title.ValueNode.Line)
|
||||
assert.Equal(t, 10, wentLowAgain.Title.ValueNode.Column)
|
||||
|
||||
wentOnceMore := highDoc.Info.License.GoLow()
|
||||
assert.Equal(t, 12, wentOnceMore.Name.ValueNode.Line)
|
||||
assert.Equal(t, 11, wentOnceMore.Name.ValueNode.Column)
|
||||
wentOnceMore := highDoc.Info.License.GoLow()
|
||||
assert.Equal(t, 12, wentOnceMore.Name.ValueNode.Line)
|
||||
assert.Equal(t, 11, wentOnceMore.Name.ValueNode.Column)
|
||||
|
||||
}
|
||||
|
||||
func TestNewDocument_Servers(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Servers, 2)
|
||||
assert.Equal(t, "{scheme}://api.pb33f.io", h.Servers[0].URL)
|
||||
assert.Equal(t, "this is our main API server, for all fun API things.", h.Servers[0].Description)
|
||||
assert.Len(t, h.Servers[0].Variables, 1)
|
||||
assert.Equal(t, "https", h.Servers[0].Variables["scheme"].Default)
|
||||
assert.Len(t, h.Servers[0].Variables["scheme"].Enum, 2)
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Servers, 2)
|
||||
assert.Equal(t, "{scheme}://api.pb33f.io", h.Servers[0].URL)
|
||||
assert.Equal(t, "this is our main API server, for all fun API things.", h.Servers[0].Description)
|
||||
assert.Len(t, h.Servers[0].Variables, 1)
|
||||
assert.Equal(t, "https", h.Servers[0].Variables["scheme"].Default)
|
||||
assert.Len(t, h.Servers[0].Variables["scheme"].Enum, 2)
|
||||
|
||||
assert.Equal(t, "https://{domain}.{host}.com", h.Servers[1].URL)
|
||||
assert.Equal(t, "this is our second API server, for all fun API things.", h.Servers[1].Description)
|
||||
assert.Len(t, h.Servers[1].Variables, 2)
|
||||
assert.Equal(t, "api", h.Servers[1].Variables["domain"].Default)
|
||||
assert.Equal(t, "pb33f.io", h.Servers[1].Variables["host"].Default)
|
||||
assert.Equal(t, "https://{domain}.{host}.com", h.Servers[1].URL)
|
||||
assert.Equal(t, "this is our second API server, for all fun API things.", h.Servers[1].Description)
|
||||
assert.Len(t, h.Servers[1].Variables, 2)
|
||||
assert.Equal(t, "api", h.Servers[1].Variables["domain"].Default)
|
||||
assert.Equal(t, "pb33f.io", h.Servers[1].Variables["host"].Default)
|
||||
|
||||
wentLow := h.GoLow()
|
||||
assert.Equal(t, 45, wentLow.Servers.Value[0].Value.Description.KeyNode.Line)
|
||||
assert.Equal(t, 5, wentLow.Servers.Value[0].Value.Description.KeyNode.Column)
|
||||
assert.Equal(t, 45, wentLow.Servers.Value[0].Value.Description.ValueNode.Line)
|
||||
assert.Equal(t, 18, wentLow.Servers.Value[0].Value.Description.ValueNode.Column)
|
||||
wentLow := h.GoLow()
|
||||
assert.Equal(t, 45, wentLow.Servers.Value[0].Value.Description.KeyNode.Line)
|
||||
assert.Equal(t, 5, wentLow.Servers.Value[0].Value.Description.KeyNode.Column)
|
||||
assert.Equal(t, 45, wentLow.Servers.Value[0].Value.Description.ValueNode.Line)
|
||||
assert.Equal(t, 18, wentLow.Servers.Value[0].Value.Description.ValueNode.Column)
|
||||
|
||||
wentLower := h.Servers[0].GoLow()
|
||||
assert.Equal(t, 45, wentLower.Description.ValueNode.Line)
|
||||
assert.Equal(t, 18, wentLower.Description.ValueNode.Column)
|
||||
wentLower := h.Servers[0].GoLow()
|
||||
assert.Equal(t, 45, wentLower.Description.ValueNode.Line)
|
||||
assert.Equal(t, 18, wentLower.Description.ValueNode.Column)
|
||||
|
||||
wentLowest := h.Servers[0].Variables["scheme"].GoLow()
|
||||
assert.Equal(t, 50, wentLowest.Description.ValueNode.Line)
|
||||
assert.Equal(t, 22, wentLowest.Description.ValueNode.Column)
|
||||
wentLowest := h.Servers[0].Variables["scheme"].GoLow()
|
||||
assert.Equal(t, 50, wentLowest.Description.ValueNode.Line)
|
||||
assert.Equal(t, 22, wentLowest.Description.ValueNode.Column)
|
||||
|
||||
}
|
||||
|
||||
func TestNewDocument_Tags(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Tags, 2)
|
||||
assert.Equal(t, "Burgers", h.Tags[0].Name)
|
||||
assert.Equal(t, "All kinds of yummy burgers.", h.Tags[0].Description)
|
||||
assert.Equal(t, "Find out more", h.Tags[0].ExternalDocs.Description)
|
||||
assert.Equal(t, "https://pb33f.io", h.Tags[0].ExternalDocs.URL)
|
||||
assert.Equal(t, "somethingSpecial", h.Tags[0].Extensions["x-internal-ting"])
|
||||
assert.Equal(t, int64(1), h.Tags[0].Extensions["x-internal-tong"])
|
||||
assert.Equal(t, 1.2, h.Tags[0].Extensions["x-internal-tang"])
|
||||
assert.True(t, h.Tags[0].Extensions["x-internal-tung"].(bool))
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Tags, 2)
|
||||
assert.Equal(t, "Burgers", h.Tags[0].Name)
|
||||
assert.Equal(t, "All kinds of yummy burgers.", h.Tags[0].Description)
|
||||
assert.Equal(t, "Find out more", h.Tags[0].ExternalDocs.Description)
|
||||
assert.Equal(t, "https://pb33f.io", h.Tags[0].ExternalDocs.URL)
|
||||
assert.Equal(t, "somethingSpecial", h.Tags[0].Extensions["x-internal-ting"])
|
||||
assert.Equal(t, int64(1), h.Tags[0].Extensions["x-internal-tong"])
|
||||
assert.Equal(t, 1.2, h.Tags[0].Extensions["x-internal-tang"])
|
||||
assert.True(t, h.Tags[0].Extensions["x-internal-tung"].(bool))
|
||||
|
||||
wentLow := h.Tags[1].GoLow()
|
||||
assert.Equal(t, 39, wentLow.Description.KeyNode.Line)
|
||||
assert.Equal(t, 5, wentLow.Description.KeyNode.Column)
|
||||
wentLow := h.Tags[1].GoLow()
|
||||
assert.Equal(t, 39, wentLow.Description.KeyNode.Line)
|
||||
assert.Equal(t, 5, wentLow.Description.KeyNode.Column)
|
||||
|
||||
wentLower := h.Tags[0].ExternalDocs.GoLow()
|
||||
assert.Equal(t, 23, wentLower.Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, wentLower.Description.ValueNode.Column)
|
||||
wentLower := h.Tags[0].ExternalDocs.GoLow()
|
||||
assert.Equal(t, 23, wentLower.Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, wentLower.Description.ValueNode.Column)
|
||||
}
|
||||
|
||||
func TestNewDocument_Webhooks(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Webhooks, 1)
|
||||
assert.Equal(t, "Information about a new burger", h.Webhooks["someHook"].Post.RequestBody.Description)
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Webhooks, 1)
|
||||
assert.Equal(t, "Information about a new burger", h.Webhooks["someHook"].Post.RequestBody.Description)
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_Links(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
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"])
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
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"])
|
||||
|
||||
wentLow := h.Components.Links["LocateBurger"].GoLow()
|
||||
assert.Equal(t, 305, wentLow.OperationId.ValueNode.Line)
|
||||
assert.Equal(t, 20, wentLow.OperationId.ValueNode.Column)
|
||||
wentLow := h.Components.Links["LocateBurger"].GoLow()
|
||||
assert.Equal(t, 305, wentLow.OperationId.ValueNode.Line)
|
||||
assert.Equal(t, 20, wentLow.OperationId.ValueNode.Column)
|
||||
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_Callbacks(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Callbacks, 1)
|
||||
assert.Equal(t, "Callback payload",
|
||||
h.Components.Callbacks["BurgerCallback"].Expression["{$request.query.queryUrl}"].Post.RequestBody.Description)
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Callbacks, 1)
|
||||
assert.Equal(t, "Callback payload",
|
||||
h.Components.Callbacks["BurgerCallback"].Expression["{$request.query.queryUrl}"].Post.RequestBody.Description)
|
||||
|
||||
assert.Equal(t, 293,
|
||||
h.Components.Callbacks["BurgerCallback"].GoLow().FindExpression("{$request.query.queryUrl}").ValueNode.Line)
|
||||
assert.Equal(t, 9,
|
||||
h.Components.Callbacks["BurgerCallback"].GoLow().FindExpression("{$request.query.queryUrl}").ValueNode.Column)
|
||||
assert.Equal(t, 293,
|
||||
h.Components.Callbacks["BurgerCallback"].GoLow().FindExpression("{$request.query.queryUrl}").ValueNode.Line)
|
||||
assert.Equal(t, 9,
|
||||
h.Components.Callbacks["BurgerCallback"].GoLow().FindExpression("{$request.query.queryUrl}").ValueNode.Column)
|
||||
|
||||
assert.Equal(t, "please", h.Components.Callbacks["BurgerCallback"].Extensions["x-break-everything"])
|
||||
assert.Equal(t, "please", h.Components.Callbacks["BurgerCallback"].Extensions["x-break-everything"])
|
||||
|
||||
for k := range h.Components.GoLow().Callbacks.Value {
|
||||
if k.Value == "BurgerCallback" {
|
||||
assert.Equal(t, 290, k.KeyNode.Line)
|
||||
assert.Equal(t, 5, k.KeyNode.Column)
|
||||
}
|
||||
}
|
||||
for k := range h.Components.GoLow().Callbacks.Value {
|
||||
if k.Value == "BurgerCallback" {
|
||||
assert.Equal(t, 290, k.KeyNode.Line)
|
||||
assert.Equal(t, 5, k.KeyNode.Column)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_Schemas(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Schemas, 6)
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Schemas, 6)
|
||||
|
||||
goLow := h.Components.GoLow()
|
||||
goLow := h.Components.GoLow()
|
||||
|
||||
a := h.Components.Schemas["Error"]
|
||||
abcd := a.Schema().Properties["message"].Schema().Example
|
||||
assert.Equal(t, "No such burger as 'Big-Whopper'", abcd)
|
||||
assert.Equal(t, 428, goLow.Schemas.KeyNode.Line)
|
||||
assert.Equal(t, 3, goLow.Schemas.KeyNode.Column)
|
||||
assert.Equal(t, 431, a.Schema().GoLow().Description.KeyNode.Line)
|
||||
a := h.Components.Schemas["Error"]
|
||||
abcd := a.Schema().Properties["message"].Schema().Example
|
||||
assert.Equal(t, "No such burger as 'Big-Whopper'", abcd)
|
||||
assert.Equal(t, 428, goLow.Schemas.KeyNode.Line)
|
||||
assert.Equal(t, 3, goLow.Schemas.KeyNode.Column)
|
||||
assert.Equal(t, 431, a.Schema().GoLow().Description.KeyNode.Line)
|
||||
|
||||
b := h.Components.Schemas["Burger"]
|
||||
assert.Len(t, b.Schema().Required, 2)
|
||||
assert.Equal(t, "golden slices of happy fun joy", b.Schema().Properties["fries"].Schema().Description)
|
||||
assert.Equal(t, int64(2), b.Schema().Properties["numPatties"].Schema().Example)
|
||||
assert.Equal(t, 443, goLow.FindSchema("Burger").Value.Schema().Properties.KeyNode.Line)
|
||||
assert.Equal(t, 7, goLow.FindSchema("Burger").Value.Schema().Properties.KeyNode.Column)
|
||||
assert.Equal(t, 445, b.Schema().GoLow().FindProperty("name").ValueNode.Line)
|
||||
b := h.Components.Schemas["Burger"]
|
||||
assert.Len(t, b.Schema().Required, 2)
|
||||
assert.Equal(t, "golden slices of happy fun joy", b.Schema().Properties["fries"].Schema().Description)
|
||||
assert.Equal(t, int64(2), b.Schema().Properties["numPatties"].Schema().Example)
|
||||
assert.Equal(t, 443, goLow.FindSchema("Burger").Value.Schema().Properties.KeyNode.Line)
|
||||
assert.Equal(t, 7, goLow.FindSchema("Burger").Value.Schema().Properties.KeyNode.Column)
|
||||
assert.Equal(t, 445, b.Schema().GoLow().FindProperty("name").ValueNode.Line)
|
||||
|
||||
f := h.Components.Schemas["Fries"]
|
||||
assert.Equal(t, "salt", f.Schema().Properties["seasoning"].Schema().Items[0].Schema().Example)
|
||||
assert.Len(t, f.Schema().Properties["favoriteDrink"].Schema().Properties["drinkType"].Schema().Enum, 2)
|
||||
f := h.Components.Schemas["Fries"]
|
||||
assert.Equal(t, "salt", f.Schema().Properties["seasoning"].Schema().Items[0].Schema().Example)
|
||||
assert.Len(t, f.Schema().Properties["favoriteDrink"].Schema().Properties["drinkType"].Schema().Enum, 2)
|
||||
|
||||
d := h.Components.Schemas["Drink"]
|
||||
assert.Len(t, d.Schema().Required, 2)
|
||||
assert.True(t, d.Schema().AdditionalProperties.(bool))
|
||||
assert.Equal(t, "drinkType", d.Schema().Discriminator.PropertyName)
|
||||
assert.Equal(t, "some value", d.Schema().Discriminator.Mapping["drink"])
|
||||
assert.Equal(t, 511, d.Schema().Discriminator.GoLow().PropertyName.ValueNode.Line)
|
||||
assert.Equal(t, 23, d.Schema().Discriminator.GoLow().PropertyName.ValueNode.Column)
|
||||
d := h.Components.Schemas["Drink"]
|
||||
assert.Len(t, d.Schema().Required, 2)
|
||||
assert.True(t, d.Schema().AdditionalProperties.(bool))
|
||||
assert.Equal(t, "drinkType", d.Schema().Discriminator.PropertyName)
|
||||
assert.Equal(t, "some value", d.Schema().Discriminator.Mapping["drink"])
|
||||
assert.Equal(t, 511, d.Schema().Discriminator.GoLow().PropertyName.ValueNode.Line)
|
||||
assert.Equal(t, 23, d.Schema().Discriminator.GoLow().PropertyName.ValueNode.Column)
|
||||
|
||||
pl := h.Components.Schemas["SomePayload"]
|
||||
assert.Equal(t, "is html programming? yes.", pl.Schema().XML.Name)
|
||||
assert.Equal(t, 518, pl.Schema().XML.GoLow().Name.ValueNode.Line)
|
||||
pl := h.Components.Schemas["SomePayload"]
|
||||
assert.Equal(t, "is html programming? yes.", pl.Schema().XML.Name)
|
||||
assert.Equal(t, 518, pl.Schema().XML.GoLow().Name.ValueNode.Line)
|
||||
|
||||
ext := h.Components.Extensions
|
||||
assert.Equal(t, "loud", ext["x-screaming-baby"])
|
||||
ext := h.Components.Extensions
|
||||
assert.Equal(t, "loud", ext["x-screaming-baby"])
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_Headers(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Headers, 1)
|
||||
assert.Equal(t, "this is a header example for UseOil", h.Components.Headers["UseOil"].Description)
|
||||
assert.Equal(t, 318, h.Components.Headers["UseOil"].GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, h.Components.Headers["UseOil"].GoLow().Description.ValueNode.Column)
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Headers, 1)
|
||||
assert.Equal(t, "this is a header example for UseOil", h.Components.Headers["UseOil"].Description)
|
||||
assert.Equal(t, 318, h.Components.Headers["UseOil"].GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, h.Components.Headers["UseOil"].GoLow().Description.ValueNode.Column)
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_RequestBodies(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.RequestBodies, 1)
|
||||
assert.Equal(t, "Give us the new burger!", h.Components.RequestBodies["BurgerRequest"].Description)
|
||||
assert.Equal(t, 323, h.Components.RequestBodies["BurgerRequest"].GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, h.Components.RequestBodies["BurgerRequest"].GoLow().Description.ValueNode.Column)
|
||||
assert.Len(t, h.Components.RequestBodies["BurgerRequest"].Content["application/json"].Examples, 2)
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.RequestBodies, 1)
|
||||
assert.Equal(t, "Give us the new burger!", h.Components.RequestBodies["BurgerRequest"].Description)
|
||||
assert.Equal(t, 323, h.Components.RequestBodies["BurgerRequest"].GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, h.Components.RequestBodies["BurgerRequest"].GoLow().Description.ValueNode.Column)
|
||||
assert.Len(t, h.Components.RequestBodies["BurgerRequest"].Content["application/json"].Examples, 2)
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_Examples(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Examples, 1)
|
||||
assert.Equal(t, "A juicy two hander sammich", h.Components.Examples["QuarterPounder"].Summary)
|
||||
assert.Equal(t, 341, h.Components.Examples["QuarterPounder"].GoLow().Summary.ValueNode.Line)
|
||||
assert.Equal(t, 16, h.Components.Examples["QuarterPounder"].GoLow().Summary.ValueNode.Column)
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Examples, 1)
|
||||
assert.Equal(t, "A juicy two hander sammich", h.Components.Examples["QuarterPounder"].Summary)
|
||||
assert.Equal(t, 341, h.Components.Examples["QuarterPounder"].GoLow().Summary.ValueNode.Line)
|
||||
assert.Equal(t, 16, h.Components.Examples["QuarterPounder"].GoLow().Summary.ValueNode.Column)
|
||||
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_Responses(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Responses, 1)
|
||||
assert.Equal(t, "all the dressings for a burger.", h.Components.Responses["DressingResponse"].Description)
|
||||
assert.Equal(t, "array", h.Components.Responses["DressingResponse"].Content["application/json"].Schema.Schema().Type[0])
|
||||
assert.Equal(t, 347, h.Components.Responses["DressingResponse"].GoLow().Description.KeyNode.Line)
|
||||
assert.Equal(t, 7, h.Components.Responses["DressingResponse"].GoLow().Description.KeyNode.Column)
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Responses, 1)
|
||||
assert.Equal(t, "all the dressings for a burger.", h.Components.Responses["DressingResponse"].Description)
|
||||
assert.Equal(t, "array", h.Components.Responses["DressingResponse"].Content["application/json"].Schema.Schema().Type[0])
|
||||
assert.Equal(t, 347, h.Components.Responses["DressingResponse"].GoLow().Description.KeyNode.Line)
|
||||
assert.Equal(t, 7, h.Components.Responses["DressingResponse"].GoLow().Description.KeyNode.Column)
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_SecuritySchemes(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.SecuritySchemes, 3)
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.SecuritySchemes, 3)
|
||||
|
||||
api := h.Components.SecuritySchemes["APIKeyScheme"]
|
||||
assert.Equal(t, "an apiKey security scheme", api.Description)
|
||||
assert.Equal(t, 359, api.GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, api.GoLow().Description.ValueNode.Column)
|
||||
api := h.Components.SecuritySchemes["APIKeyScheme"]
|
||||
assert.Equal(t, "an apiKey security scheme", api.Description)
|
||||
assert.Equal(t, 359, api.GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, api.GoLow().Description.ValueNode.Column)
|
||||
|
||||
jwt := h.Components.SecuritySchemes["JWTScheme"]
|
||||
assert.Equal(t, "an JWT security scheme", jwt.Description)
|
||||
assert.Equal(t, 364, jwt.GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, jwt.GoLow().Description.ValueNode.Column)
|
||||
jwt := h.Components.SecuritySchemes["JWTScheme"]
|
||||
assert.Equal(t, "an JWT security scheme", jwt.Description)
|
||||
assert.Equal(t, 364, jwt.GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, jwt.GoLow().Description.ValueNode.Column)
|
||||
|
||||
oAuth := h.Components.SecuritySchemes["OAuthScheme"]
|
||||
assert.Equal(t, "an oAuth security scheme", oAuth.Description)
|
||||
assert.Equal(t, 370, oAuth.GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, oAuth.GoLow().Description.ValueNode.Column)
|
||||
assert.Len(t, oAuth.Flows.Implicit.Scopes, 2)
|
||||
assert.Equal(t, "read all burgers", oAuth.Flows.Implicit.Scopes["read:burgers"])
|
||||
assert.Equal(t, "https://pb33f.io/oauth", oAuth.Flows.AuthorizationCode.AuthorizationUrl)
|
||||
oAuth := h.Components.SecuritySchemes["OAuthScheme"]
|
||||
assert.Equal(t, "an oAuth security scheme", oAuth.Description)
|
||||
assert.Equal(t, 370, oAuth.GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, oAuth.GoLow().Description.ValueNode.Column)
|
||||
assert.Len(t, oAuth.Flows.Implicit.Scopes, 2)
|
||||
assert.Equal(t, "read all burgers", oAuth.Flows.Implicit.Scopes["read:burgers"])
|
||||
assert.Equal(t, "https://pb33f.io/oauth", oAuth.Flows.AuthorizationCode.AuthorizationUrl)
|
||||
|
||||
// check the lowness is low.
|
||||
assert.Equal(t, 375, oAuth.Flows.GoLow().Implicit.Value.Scopes.KeyNode.Line)
|
||||
assert.Equal(t, 11, oAuth.Flows.GoLow().Implicit.Value.Scopes.KeyNode.Column)
|
||||
assert.Equal(t, 375, oAuth.Flows.Implicit.GoLow().Scopes.KeyNode.Line)
|
||||
assert.Equal(t, 11, oAuth.Flows.Implicit.GoLow().Scopes.KeyNode.Column)
|
||||
// check the lowness is low.
|
||||
assert.Equal(t, 375, oAuth.Flows.GoLow().Implicit.Value.Scopes.KeyNode.Line)
|
||||
assert.Equal(t, 11, oAuth.Flows.GoLow().Implicit.Value.Scopes.KeyNode.Column)
|
||||
assert.Equal(t, 375, oAuth.Flows.Implicit.GoLow().Scopes.KeyNode.Line)
|
||||
assert.Equal(t, 11, oAuth.Flows.Implicit.GoLow().Scopes.KeyNode.Column)
|
||||
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_Parameters(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Parameters, 2)
|
||||
bh := h.Components.Parameters["BurgerHeader"]
|
||||
assert.Equal(t, "burgerHeader", bh.Name)
|
||||
assert.Equal(t, 387, bh.GoLow().Name.KeyNode.Line)
|
||||
assert.Len(t, bh.Schema.Schema().Properties, 2)
|
||||
assert.Equal(t, "big-mac", bh.Example)
|
||||
assert.True(t, bh.Required)
|
||||
assert.Equal(t, "this is a header",
|
||||
bh.Content["application/json"].Encoding["burgerTheme"].Headers["someHeader"].Description)
|
||||
assert.Len(t, bh.Content["application/json"].Schema.Schema().Properties, 2)
|
||||
assert.Equal(t, 404, bh.Content["application/json"].Encoding["burgerTheme"].GoLow().ContentType.ValueNode.Line)
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Parameters, 2)
|
||||
bh := h.Components.Parameters["BurgerHeader"]
|
||||
assert.Equal(t, "burgerHeader", bh.Name)
|
||||
assert.Equal(t, 387, bh.GoLow().Name.KeyNode.Line)
|
||||
assert.Len(t, bh.Schema.Schema().Properties, 2)
|
||||
assert.Equal(t, "big-mac", bh.Example)
|
||||
assert.True(t, bh.Required)
|
||||
assert.Equal(t, "this is a header",
|
||||
bh.Content["application/json"].Encoding["burgerTheme"].Headers["someHeader"].Description)
|
||||
assert.Len(t, bh.Content["application/json"].Schema.Schema().Properties, 2)
|
||||
assert.Equal(t, 404, bh.Content["application/json"].Encoding["burgerTheme"].GoLow().ContentType.ValueNode.Line)
|
||||
|
||||
}
|
||||
|
||||
func TestNewDocument_Paths(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Paths.PathItems, 5)
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Paths.PathItems, 5)
|
||||
|
||||
burgersOp := h.Paths.PathItems["/burgers"]
|
||||
assert.Equal(t, "meaty", burgersOp.Extensions["x-burger-meta"])
|
||||
assert.Nil(t, burgersOp.Get)
|
||||
assert.Nil(t, burgersOp.Put)
|
||||
assert.Nil(t, burgersOp.Patch)
|
||||
assert.Nil(t, burgersOp.Head)
|
||||
assert.Nil(t, burgersOp.Options)
|
||||
assert.Nil(t, burgersOp.Trace)
|
||||
assert.Equal(t, 64, burgersOp.GoLow().Post.KeyNode.Line)
|
||||
assert.Equal(t, "createBurger", burgersOp.Post.OperationId)
|
||||
assert.Len(t, burgersOp.Post.Tags, 1)
|
||||
assert.Equal(t, "A new burger for our menu, yummy yum yum.", burgersOp.Post.Description)
|
||||
assert.Equal(t, "Give us the new burger!", burgersOp.Post.RequestBody.Description)
|
||||
assert.Len(t, burgersOp.Post.Responses.Codes, 3)
|
||||
assert.Equal(t, 63, h.Paths.GoLow().FindPath("/burgers").ValueNode.Line)
|
||||
burgersOp := h.Paths.PathItems["/burgers"]
|
||||
assert.Equal(t, "meaty", burgersOp.Extensions["x-burger-meta"])
|
||||
assert.Nil(t, burgersOp.Get)
|
||||
assert.Nil(t, burgersOp.Put)
|
||||
assert.Nil(t, burgersOp.Patch)
|
||||
assert.Nil(t, burgersOp.Head)
|
||||
assert.Nil(t, burgersOp.Options)
|
||||
assert.Nil(t, burgersOp.Trace)
|
||||
assert.Equal(t, 64, burgersOp.GoLow().Post.KeyNode.Line)
|
||||
assert.Equal(t, "createBurger", burgersOp.Post.OperationId)
|
||||
assert.Len(t, burgersOp.Post.Tags, 1)
|
||||
assert.Equal(t, "A new burger for our menu, yummy yum yum.", burgersOp.Post.Description)
|
||||
assert.Equal(t, "Give us the new burger!", burgersOp.Post.RequestBody.Description)
|
||||
assert.Len(t, burgersOp.Post.Responses.Codes, 3)
|
||||
assert.Equal(t, 63, h.Paths.GoLow().FindPath("/burgers").ValueNode.Line)
|
||||
|
||||
okResp := burgersOp.Post.Responses.FindResponseByCode(200)
|
||||
assert.Len(t, okResp.Headers, 1)
|
||||
assert.Equal(t, "A tasty burger for you to eat.", okResp.Description)
|
||||
assert.Equal(t, 69, burgersOp.Post.GoLow().Description.ValueNode.Line)
|
||||
assert.Len(t, okResp.Content["application/json"].Examples, 2)
|
||||
assert.Equal(t, "a cripsy fish sammich filled with ocean goodness.",
|
||||
okResp.Content["application/json"].Examples["filetOFish"].Summary)
|
||||
assert.Equal(t, 74, burgersOp.Post.Responses.GoLow().FindResponseByCode("200").ValueNode.Line)
|
||||
okResp := burgersOp.Post.Responses.FindResponseByCode(200)
|
||||
assert.Len(t, okResp.Headers, 1)
|
||||
assert.Equal(t, "A tasty burger for you to eat.", okResp.Description)
|
||||
assert.Equal(t, 69, burgersOp.Post.GoLow().Description.ValueNode.Line)
|
||||
assert.Len(t, okResp.Content["application/json"].Examples, 2)
|
||||
assert.Equal(t, "a cripsy fish sammich filled with ocean goodness.",
|
||||
okResp.Content["application/json"].Examples["filetOFish"].Summary)
|
||||
assert.Equal(t, 74, burgersOp.Post.Responses.GoLow().FindResponseByCode("200").ValueNode.Line)
|
||||
|
||||
assert.Equal(t, 80, okResp.Content["application/json"].GoLow().Schema.KeyNode.Line)
|
||||
assert.Equal(t, 15, okResp.Content["application/json"].GoLow().Schema.KeyNode.Column)
|
||||
assert.Equal(t, 80, okResp.Content["application/json"].GoLow().Schema.KeyNode.Line)
|
||||
assert.Equal(t, 15, okResp.Content["application/json"].GoLow().Schema.KeyNode.Column)
|
||||
|
||||
assert.Equal(t, 77, okResp.GoLow().Description.KeyNode.Line)
|
||||
assert.Len(t, okResp.Links, 2)
|
||||
assert.Equal(t, "locateBurger", okResp.Links["LocateBurger"].OperationId)
|
||||
assert.Equal(t, 305, okResp.Links["LocateBurger"].GoLow().OperationId.ValueNode.Line)
|
||||
assert.Len(t, burgersOp.Post.Security[0].Requirements, 1)
|
||||
assert.Len(t, burgersOp.Post.Security[0].Requirements["OAuthScheme"], 2)
|
||||
assert.Equal(t, "read:burgers", burgersOp.Post.Security[0].Requirements["OAuthScheme"][0])
|
||||
assert.Equal(t, 118, burgersOp.Post.Security[0].GoLow().Requirements.ValueNode.Line)
|
||||
assert.Len(t, burgersOp.Post.Servers, 1)
|
||||
assert.Equal(t, "https://pb33f.io", burgersOp.Post.Servers[0].URL)
|
||||
assert.Equal(t, 77, okResp.GoLow().Description.KeyNode.Line)
|
||||
assert.Len(t, okResp.Links, 2)
|
||||
assert.Equal(t, "locateBurger", okResp.Links["LocateBurger"].OperationId)
|
||||
assert.Equal(t, 305, okResp.Links["LocateBurger"].GoLow().OperationId.ValueNode.Line)
|
||||
assert.Len(t, burgersOp.Post.Security[0].Requirements, 1)
|
||||
assert.Len(t, burgersOp.Post.Security[0].Requirements["OAuthScheme"], 2)
|
||||
assert.Equal(t, "read:burgers", burgersOp.Post.Security[0].Requirements["OAuthScheme"][0])
|
||||
assert.Equal(t, 118, burgersOp.Post.Security[0].GoLow().Requirements.ValueNode.Line)
|
||||
assert.Len(t, burgersOp.Post.Servers, 1)
|
||||
assert.Equal(t, "https://pb33f.io", burgersOp.Post.Servers[0].URL)
|
||||
|
||||
}
|
||||
|
||||
func TestStripeAsDoc(t *testing.T) {
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/stripe.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
lowDoc, err = lowv3.CreateDocument(info)
|
||||
if err != nil {
|
||||
panic("broken something")
|
||||
}
|
||||
d := NewDocument(lowDoc)
|
||||
fmt.Println(d)
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/stripe.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
lowDoc, err = lowv3.CreateDocument(info)
|
||||
assert.Len(t, err, 21)
|
||||
d := NewDocument(lowDoc)
|
||||
fmt.Println(d)
|
||||
}
|
||||
|
||||
func TestAsanaAsDoc(t *testing.T) {
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/asana.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
lowDoc, err = lowv3.CreateDocument(info)
|
||||
if err != nil {
|
||||
panic("broken something")
|
||||
}
|
||||
d := NewDocument(lowDoc)
|
||||
fmt.Println(d)
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/asana.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
lowDoc, err = lowv3.CreateDocument(info)
|
||||
if err != nil {
|
||||
panic("broken something")
|
||||
}
|
||||
d := NewDocument(lowDoc)
|
||||
fmt.Println(d)
|
||||
}
|
||||
|
||||
func TestPetstoreAsDoc(t *testing.T) {
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/petstorev3.json")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
lowDoc, err = lowv3.CreateDocument(info)
|
||||
if err != nil {
|
||||
panic("broken something")
|
||||
}
|
||||
d := NewDocument(lowDoc)
|
||||
fmt.Println(d)
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/petstorev3.json")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
lowDoc, err = lowv3.CreateDocument(info)
|
||||
if err != nil {
|
||||
panic("broken something")
|
||||
}
|
||||
d := NewDocument(lowDoc)
|
||||
fmt.Println(d)
|
||||
}
|
||||
|
||||
func TestCircularReferencesDoc(t *testing.T) {
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/circular-tests.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
lowDoc, err = lowv3.CreateDocument(info)
|
||||
if err != nil {
|
||||
panic("broken something")
|
||||
}
|
||||
d := NewDocument(lowDoc)
|
||||
assert.Len(t, d.Components.Schemas, 9)
|
||||
assert.Len(t, d.Index.GetCircularReferences(), 3)
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/circular-tests.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
lowDoc, err = lowv3.CreateDocument(info)
|
||||
assert.Len(t, err, 3)
|
||||
d := NewDocument(lowDoc)
|
||||
assert.Len(t, d.Components.Schemas, 9)
|
||||
assert.Len(t, d.Index.GetCircularReferences(), 3)
|
||||
}
|
||||
|
||||
@@ -12,12 +12,13 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/resolver"
|
||||
"gopkg.in/yaml.v3"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/resolver"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// processes a property of a Swagger document asynchronously using bool and error channels for signals.
|
||||
@@ -26,242 +27,250 @@ type documentFunction func(root *yaml.Node, doc *Swagger, idx *index.SpecIndex,
|
||||
// Swagger represents a high-level Swagger / OpenAPI 2 document. An instance of Swagger is the root of the specification.
|
||||
type Swagger struct {
|
||||
|
||||
// Swagger is the version of Swagger / OpenAPI being used, extracted from the 'swagger: 2.x' definition.
|
||||
Swagger low.ValueReference[string]
|
||||
// Swagger is the version of Swagger / OpenAPI being used, extracted from the 'swagger: 2.x' definition.
|
||||
Swagger low.ValueReference[string]
|
||||
|
||||
// Info represents a specification Info definition.
|
||||
// Provides metadata about the API. The metadata can be used by the clients if needed.
|
||||
// - https://swagger.io/specification/v2/#infoObject
|
||||
Info low.NodeReference[*base.Info]
|
||||
// Info represents a specification Info definition.
|
||||
// Provides metadata about the API. The metadata can be used by the clients if needed.
|
||||
// - https://swagger.io/specification/v2/#infoObject
|
||||
Info low.NodeReference[*base.Info]
|
||||
|
||||
// Host is The host (name or ip) serving the API. This MUST be the host only and does not include the scheme nor
|
||||
// sub-paths. It MAY include a port. If the host is not included, the host serving the documentation is to be used
|
||||
// (including the port). The host does not support path templating.
|
||||
Host low.NodeReference[string]
|
||||
// Host is The host (name or ip) serving the API. This MUST be the host only and does not include the scheme nor
|
||||
// sub-paths. It MAY include a port. If the host is not included, the host serving the documentation is to be used
|
||||
// (including the port). The host does not support path templating.
|
||||
Host low.NodeReference[string]
|
||||
|
||||
// BasePath is The base path on which the API is served, which is relative to the host. If it is not included,
|
||||
// the API is served directly under the host. The value MUST start with a leading slash (/).
|
||||
// The basePath does not support path templating.
|
||||
BasePath low.NodeReference[string]
|
||||
// BasePath is The base path on which the API is served, which is relative to the host. If it is not included,
|
||||
// the API is served directly under the host. The value MUST start with a leading slash (/).
|
||||
// The basePath does not support path templating.
|
||||
BasePath low.NodeReference[string]
|
||||
|
||||
// Schemes represents the transfer protocol of the API. Requirements MUST be from the list: "http", "https", "ws", "wss".
|
||||
// If the schemes is not included, the default scheme to be used is the one used to access
|
||||
// the Swagger definition itself.
|
||||
Schemes low.NodeReference[[]low.ValueReference[string]]
|
||||
// Schemes represents the transfer protocol of the API. Requirements MUST be from the list: "http", "https", "ws", "wss".
|
||||
// If the schemes is not included, the default scheme to be used is the one used to access
|
||||
// the Swagger definition itself.
|
||||
Schemes low.NodeReference[[]low.ValueReference[string]]
|
||||
|
||||
// Consumes is a list of MIME types the APIs can consume. This is global to all APIs but can be overridden on
|
||||
// specific API calls. Value MUST be as described under Mime Types.
|
||||
Consumes low.NodeReference[[]low.ValueReference[string]]
|
||||
// Consumes is a list of MIME types the APIs can consume. This is global to all APIs but can be overridden on
|
||||
// specific API calls. Value MUST be as described under Mime Types.
|
||||
Consumes low.NodeReference[[]low.ValueReference[string]]
|
||||
|
||||
// Produces is a list of MIME types the APIs can produce. This is global to all APIs but can be overridden on
|
||||
// specific API calls. Value MUST be as described under Mime Types.
|
||||
Produces low.NodeReference[[]low.ValueReference[string]]
|
||||
// Produces is a list of MIME types the APIs can produce. This is global to all APIs but can be overridden on
|
||||
// specific API calls. Value MUST be as described under Mime Types.
|
||||
Produces low.NodeReference[[]low.ValueReference[string]]
|
||||
|
||||
// Paths are the paths and operations for the API. Perhaps the most important part of the specification.
|
||||
// - https://swagger.io/specification/v2/#pathsObject
|
||||
Paths low.NodeReference[*Paths]
|
||||
// Paths are the paths and operations for the API. Perhaps the most important part of the specification.
|
||||
// - https://swagger.io/specification/v2/#pathsObject
|
||||
Paths low.NodeReference[*Paths]
|
||||
|
||||
// Definitions is an object to hold data types produced and consumed by operations. It's composed of Schema instances
|
||||
// - https://swagger.io/specification/v2/#definitionsObject
|
||||
Definitions low.NodeReference[*Definitions]
|
||||
// Definitions is an object to hold data types produced and consumed by operations. It's composed of Schema instances
|
||||
// - https://swagger.io/specification/v2/#definitionsObject
|
||||
Definitions low.NodeReference[*Definitions]
|
||||
|
||||
// SecurityDefinitions represents security scheme definitions that can be used across the specification.
|
||||
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
||||
SecurityDefinitions low.NodeReference[*SecurityDefinitions]
|
||||
// SecurityDefinitions represents security scheme definitions that can be used across the specification.
|
||||
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
||||
SecurityDefinitions low.NodeReference[*SecurityDefinitions]
|
||||
|
||||
// Parameters is an object to hold parameters that can be used across operations.
|
||||
// This property does not define global parameters for all operations.
|
||||
// - https://swagger.io/specification/v2/#parametersDefinitionsObject
|
||||
Parameters low.NodeReference[*ParameterDefinitions]
|
||||
// Parameters is an object to hold parameters that can be used across operations.
|
||||
// This property does not define global parameters for all operations.
|
||||
// - https://swagger.io/specification/v2/#parametersDefinitionsObject
|
||||
Parameters low.NodeReference[*ParameterDefinitions]
|
||||
|
||||
// Responses is an object to hold responses that can be used across operations.
|
||||
// This property does not define global responses for all operations.
|
||||
// - https://swagger.io/specification/v2/#responsesDefinitionsObject
|
||||
Responses low.NodeReference[*ResponsesDefinitions]
|
||||
// Responses is an object to hold responses that can be used across operations.
|
||||
// This property does not define global responses for all operations.
|
||||
// - https://swagger.io/specification/v2/#responsesDefinitionsObject
|
||||
Responses low.NodeReference[*ResponsesDefinitions]
|
||||
|
||||
// Security is a declaration of which security schemes are applied for the API as a whole. The list of values
|
||||
// describes alternative security schemes that can be used (that is, there is a logical OR between the security
|
||||
// requirements). Individual operations can override this definition.
|
||||
// - https://swagger.io/specification/v2/#securityRequirementObject
|
||||
Security low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]
|
||||
// Security is a declaration of which security schemes are applied for the API as a whole. The list of values
|
||||
// describes alternative security schemes that can be used (that is, there is a logical OR between the security
|
||||
// requirements). Individual operations can override this definition.
|
||||
// - https://swagger.io/specification/v2/#securityRequirementObject
|
||||
Security low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]
|
||||
|
||||
// Tags are A list of tags used by the specification with additional metadata.
|
||||
// The order of the tags can be used to reflect on their order by the parsing tools. Not all tags that are used
|
||||
// by the Operation Object must be declared. The tags that are not declared may be organized randomly or based
|
||||
// on the tools' logic. Each tag name in the list MUST be unique.
|
||||
// - https://swagger.io/specification/v2/#tagObject
|
||||
Tags low.NodeReference[[]low.ValueReference[*base.Tag]]
|
||||
// Tags are A list of tags used by the specification with additional metadata.
|
||||
// The order of the tags can be used to reflect on their order by the parsing tools. Not all tags that are used
|
||||
// by the Operation Object must be declared. The tags that are not declared may be organized randomly or based
|
||||
// on the tools' logic. Each tag name in the list MUST be unique.
|
||||
// - https://swagger.io/specification/v2/#tagObject
|
||||
Tags low.NodeReference[[]low.ValueReference[*base.Tag]]
|
||||
|
||||
// ExternalDocs is an instance of base.ExternalDoc for.. well, obvious really, innit mate?
|
||||
ExternalDocs low.NodeReference[*base.ExternalDoc]
|
||||
// ExternalDocs is an instance of base.ExternalDoc for.. well, obvious really, innit mate?
|
||||
ExternalDocs low.NodeReference[*base.ExternalDoc]
|
||||
|
||||
// Extensions contains all custom extensions defined for the top-level document.
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
// Extensions contains all custom extensions defined for the top-level document.
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
|
||||
// Index is a reference to the index.SpecIndex that was created for the document and used
|
||||
// as a guide when building out the Document. Ideal if further processing is required on the model and
|
||||
// the original details are required to continue the work.
|
||||
//
|
||||
// This property is not a part of the OpenAPI schema, this is custom to libopenapi.
|
||||
Index *index.SpecIndex
|
||||
// Index is a reference to the index.SpecIndex that was created for the document and used
|
||||
// as a guide when building out the Document. Ideal if further processing is required on the model and
|
||||
// the original details are required to continue the work.
|
||||
//
|
||||
// This property is not a part of the OpenAPI schema, this is custom to libopenapi.
|
||||
Index *index.SpecIndex
|
||||
|
||||
// SpecInfo is a reference to the datamodel.SpecInfo instance created when the specification was read.
|
||||
//
|
||||
// This property is not a part of the OpenAPI schema, this is custom to libopenapi.
|
||||
SpecInfo *datamodel.SpecInfo
|
||||
// SpecInfo is a reference to the datamodel.SpecInfo instance created when the specification was read.
|
||||
//
|
||||
// This property is not a part of the OpenAPI schema, this is custom to libopenapi.
|
||||
SpecInfo *datamodel.SpecInfo
|
||||
}
|
||||
|
||||
// FindExtension locates an extension from the root of the Swagger document.
|
||||
func (s *Swagger) FindExtension(ext string) *low.ValueReference[any] {
|
||||
return low.FindItemInMap[any](ext, s.Extensions)
|
||||
return low.FindItemInMap[any](ext, s.Extensions)
|
||||
}
|
||||
|
||||
func CreateDocument(info *datamodel.SpecInfo) (*Swagger, []error) {
|
||||
|
||||
doc := Swagger{Swagger: low.ValueReference[string]{Value: info.Version, ValueNode: info.RootNode}}
|
||||
doc.Extensions = low.ExtractExtensions(info.RootNode.Content[0])
|
||||
doc := Swagger{Swagger: low.ValueReference[string]{Value: info.Version, ValueNode: info.RootNode}}
|
||||
doc.Extensions = low.ExtractExtensions(info.RootNode.Content[0])
|
||||
|
||||
// build an index
|
||||
idx := index.NewSpecIndex(info.RootNode)
|
||||
doc.Index = idx
|
||||
doc.SpecInfo = info
|
||||
// build an index
|
||||
idx := index.NewSpecIndex(info.RootNode)
|
||||
doc.Index = idx
|
||||
doc.SpecInfo = info
|
||||
|
||||
var errors []error
|
||||
var errors []error
|
||||
|
||||
// build out swagger scalar variables.
|
||||
_ = low.BuildModel(info.RootNode.Content[0], &doc)
|
||||
// build out swagger scalar variables.
|
||||
_ = low.BuildModel(info.RootNode.Content[0], &doc)
|
||||
|
||||
// extract externalDocs
|
||||
extDocs, err := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, info.RootNode, idx)
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
// extract externalDocs
|
||||
extDocs, err := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, info.RootNode, idx)
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
|
||||
doc.ExternalDocs = extDocs
|
||||
doc.ExternalDocs = extDocs
|
||||
|
||||
// create resolver and check for circular references.
|
||||
resolve := resolver.NewResolver(idx)
|
||||
_ = resolve.CheckForCircularReferences()
|
||||
// create resolver and check for circular references.
|
||||
resolve := resolver.NewResolver(idx)
|
||||
resolvingErrors := resolve.CheckForCircularReferences()
|
||||
|
||||
extractionFuncs := []documentFunction{
|
||||
extractInfo,
|
||||
extractPaths,
|
||||
extractDefinitions,
|
||||
extractParamDefinitions,
|
||||
extractResponsesDefinitions,
|
||||
extractSecurityDefinitions,
|
||||
extractTags,
|
||||
extractSecurity,
|
||||
}
|
||||
doneChan := make(chan bool)
|
||||
errChan := make(chan error)
|
||||
for i := range extractionFuncs {
|
||||
go extractionFuncs[i](info.RootNode.Content[0], &doc, idx, doneChan, errChan)
|
||||
}
|
||||
completedExtractions := 0
|
||||
for completedExtractions < len(extractionFuncs) {
|
||||
select {
|
||||
case <-doneChan:
|
||||
completedExtractions++
|
||||
case e := <-errChan:
|
||||
completedExtractions++
|
||||
errors = append(errors, e)
|
||||
}
|
||||
}
|
||||
if len(resolvingErrors) > 0 {
|
||||
for r := range resolvingErrors {
|
||||
errors = append(errors,
|
||||
fmt.Errorf("%s (%s) [%d:%d]", resolvingErrors[r].Error.Error(),
|
||||
resolvingErrors[r].Path, resolvingErrors[r].Node.Line, resolvingErrors[r].Node.Column))
|
||||
}
|
||||
}
|
||||
|
||||
return &doc, errors
|
||||
extractionFuncs := []documentFunction{
|
||||
extractInfo,
|
||||
extractPaths,
|
||||
extractDefinitions,
|
||||
extractParamDefinitions,
|
||||
extractResponsesDefinitions,
|
||||
extractSecurityDefinitions,
|
||||
extractTags,
|
||||
extractSecurity,
|
||||
}
|
||||
doneChan := make(chan bool)
|
||||
errChan := make(chan error)
|
||||
for i := range extractionFuncs {
|
||||
go extractionFuncs[i](info.RootNode.Content[0], &doc, idx, doneChan, errChan)
|
||||
}
|
||||
completedExtractions := 0
|
||||
for completedExtractions < len(extractionFuncs) {
|
||||
select {
|
||||
case <-doneChan:
|
||||
completedExtractions++
|
||||
case e := <-errChan:
|
||||
completedExtractions++
|
||||
errors = append(errors, e)
|
||||
}
|
||||
}
|
||||
|
||||
return &doc, errors
|
||||
}
|
||||
|
||||
func (s *Swagger) GetExternalDocs() *low.NodeReference[any] {
|
||||
return &low.NodeReference[any]{
|
||||
KeyNode: s.ExternalDocs.KeyNode,
|
||||
ValueNode: s.ExternalDocs.ValueNode,
|
||||
Value: s.ExternalDocs.Value,
|
||||
}
|
||||
return &low.NodeReference[any]{
|
||||
KeyNode: s.ExternalDocs.KeyNode,
|
||||
ValueNode: s.ExternalDocs.ValueNode,
|
||||
Value: s.ExternalDocs.Value,
|
||||
}
|
||||
}
|
||||
|
||||
func extractInfo(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
info, err := low.ExtractObject[*base.Info](base.InfoLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Info = info
|
||||
c <- true
|
||||
info, err := low.ExtractObject[*base.Info](base.InfoLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Info = info
|
||||
c <- true
|
||||
}
|
||||
|
||||
func extractPaths(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
paths, err := low.ExtractObject[*Paths](PathsLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Paths = paths
|
||||
c <- true
|
||||
paths, err := low.ExtractObject[*Paths](PathsLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Paths = paths
|
||||
c <- true
|
||||
}
|
||||
func extractDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
def, err := low.ExtractObject[*Definitions](DefinitionsLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Definitions = def
|
||||
c <- true
|
||||
def, err := low.ExtractObject[*Definitions](DefinitionsLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Definitions = def
|
||||
c <- true
|
||||
}
|
||||
func extractParamDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
param, err := low.ExtractObject[*ParameterDefinitions](ParametersLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Parameters = param
|
||||
c <- true
|
||||
param, err := low.ExtractObject[*ParameterDefinitions](ParametersLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Parameters = param
|
||||
c <- true
|
||||
}
|
||||
|
||||
func extractResponsesDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
resp, err := low.ExtractObject[*ResponsesDefinitions](ResponsesLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Responses = resp
|
||||
c <- true
|
||||
resp, err := low.ExtractObject[*ResponsesDefinitions](ResponsesLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Responses = resp
|
||||
c <- true
|
||||
}
|
||||
|
||||
func extractSecurityDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
sec, err := low.ExtractObject[*SecurityDefinitions](SecurityDefinitionsLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.SecurityDefinitions = sec
|
||||
c <- true
|
||||
sec, err := low.ExtractObject[*SecurityDefinitions](SecurityDefinitionsLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.SecurityDefinitions = sec
|
||||
c <- true
|
||||
}
|
||||
|
||||
func extractTags(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
tags, ln, vn, err := low.ExtractArray[*base.Tag](base.TagsLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Tags = low.NodeReference[[]low.ValueReference[*base.Tag]]{
|
||||
Value: tags,
|
||||
KeyNode: ln,
|
||||
ValueNode: vn,
|
||||
}
|
||||
c <- true
|
||||
tags, ln, vn, err := low.ExtractArray[*base.Tag](base.TagsLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Tags = low.NodeReference[[]low.ValueReference[*base.Tag]]{
|
||||
Value: tags,
|
||||
KeyNode: ln,
|
||||
ValueNode: vn,
|
||||
}
|
||||
c <- true
|
||||
}
|
||||
|
||||
func extractSecurity(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Security = low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]{
|
||||
Value: sec,
|
||||
KeyNode: ln,
|
||||
ValueNode: vn,
|
||||
}
|
||||
c <- true
|
||||
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Security = low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]{
|
||||
Value: sec,
|
||||
KeyNode: ln,
|
||||
ValueNode: vn,
|
||||
}
|
||||
c <- true
|
||||
}
|
||||
|
||||
@@ -4,333 +4,343 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var doc *Swagger
|
||||
|
||||
func initTest() {
|
||||
if doc != nil {
|
||||
return
|
||||
}
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/petstorev2-complete.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Print(err)
|
||||
panic(err)
|
||||
}
|
||||
if doc != nil {
|
||||
return
|
||||
}
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/petstorev2-complete.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Print(err)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCreateDocument(b *testing.B) {
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/petstorev2-complete.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
for i := 0; i < b.N; i++ {
|
||||
doc, _ = CreateDocument(info)
|
||||
}
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/petstorev2-complete.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
for i := 0; i < b.N; i++ {
|
||||
doc, _ = CreateDocument(info)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateDocument(t *testing.T) {
|
||||
initTest()
|
||||
doc := doc
|
||||
assert.Equal(t, "2.0", doc.SpecInfo.Version)
|
||||
assert.Equal(t, "1.0.6", doc.Info.Value.Version.Value)
|
||||
assert.Equal(t, "petstore.swagger.io", doc.Host.Value)
|
||||
assert.Equal(t, "/v2", doc.BasePath.Value)
|
||||
assert.Len(t, doc.Parameters.Value.Definitions, 1)
|
||||
assert.Len(t, doc.Tags.Value, 3)
|
||||
assert.Len(t, doc.Schemes.Value, 2)
|
||||
assert.Len(t, doc.Definitions.Value.Schemas, 6)
|
||||
assert.Len(t, doc.SecurityDefinitions.Value.Definitions, 3)
|
||||
assert.Len(t, doc.Paths.Value.PathItems, 15)
|
||||
assert.Len(t, doc.Responses.Value.Definitions, 2)
|
||||
assert.Equal(t, "http://swagger.io", doc.ExternalDocs.Value.URL.Value)
|
||||
assert.Equal(t, true, doc.FindExtension("x-pet").Value)
|
||||
assert.Equal(t, true, doc.FindExtension("X-Pet").Value)
|
||||
assert.NotNil(t, doc.GetExternalDocs())
|
||||
initTest()
|
||||
doc := doc
|
||||
assert.Equal(t, "2.0", doc.SpecInfo.Version)
|
||||
assert.Equal(t, "1.0.6", doc.Info.Value.Version.Value)
|
||||
assert.Equal(t, "petstore.swagger.io", doc.Host.Value)
|
||||
assert.Equal(t, "/v2", doc.BasePath.Value)
|
||||
assert.Len(t, doc.Parameters.Value.Definitions, 1)
|
||||
assert.Len(t, doc.Tags.Value, 3)
|
||||
assert.Len(t, doc.Schemes.Value, 2)
|
||||
assert.Len(t, doc.Definitions.Value.Schemas, 6)
|
||||
assert.Len(t, doc.SecurityDefinitions.Value.Definitions, 3)
|
||||
assert.Len(t, doc.Paths.Value.PathItems, 15)
|
||||
assert.Len(t, doc.Responses.Value.Definitions, 2)
|
||||
assert.Equal(t, "http://swagger.io", doc.ExternalDocs.Value.URL.Value)
|
||||
assert.Equal(t, true, doc.FindExtension("x-pet").Value)
|
||||
assert.Equal(t, true, doc.FindExtension("X-Pet").Value)
|
||||
assert.NotNil(t, doc.GetExternalDocs())
|
||||
}
|
||||
|
||||
func TestCreateDocument_Info(t *testing.T) {
|
||||
initTest()
|
||||
assert.Equal(t, "Swagger Petstore", doc.Info.Value.Title.Value)
|
||||
assert.Equal(t, "apiteam@swagger.io", doc.Info.Value.Contact.Value.Email.Value)
|
||||
assert.Equal(t, "Apache 2.0", doc.Info.Value.License.Value.Name.Value)
|
||||
initTest()
|
||||
assert.Equal(t, "Swagger Petstore", doc.Info.Value.Title.Value)
|
||||
assert.Equal(t, "apiteam@swagger.io", doc.Info.Value.Contact.Value.Email.Value)
|
||||
assert.Equal(t, "Apache 2.0", doc.Info.Value.License.Value.Name.Value)
|
||||
}
|
||||
|
||||
func TestCreateDocument_Parameters(t *testing.T) {
|
||||
initTest()
|
||||
simpleParam := doc.Parameters.Value.FindParameter("simpleParam")
|
||||
assert.NotNil(t, simpleParam)
|
||||
assert.Equal(t, "simple", simpleParam.Value.Name.Value)
|
||||
assert.Equal(t, "nuggets", simpleParam.Value.FindExtension("x-chicken").Value)
|
||||
initTest()
|
||||
simpleParam := doc.Parameters.Value.FindParameter("simpleParam")
|
||||
assert.NotNil(t, simpleParam)
|
||||
assert.Equal(t, "simple", simpleParam.Value.Name.Value)
|
||||
assert.Equal(t, "nuggets", simpleParam.Value.FindExtension("x-chicken").Value)
|
||||
|
||||
}
|
||||
|
||||
func TestCreateDocument_Tags(t *testing.T) {
|
||||
initTest()
|
||||
assert.Equal(t, "pet", doc.Tags.Value[0].Value.Name.Value)
|
||||
assert.Equal(t, "http://swagger.io", doc.Tags.Value[0].Value.ExternalDocs.Value.URL.Value)
|
||||
assert.Equal(t, "store", doc.Tags.Value[1].Value.Name.Value)
|
||||
assert.Equal(t, "user", doc.Tags.Value[2].Value.Name.Value)
|
||||
assert.Equal(t, "http://swagger.io", doc.Tags.Value[2].Value.ExternalDocs.Value.URL.Value)
|
||||
initTest()
|
||||
assert.Equal(t, "pet", doc.Tags.Value[0].Value.Name.Value)
|
||||
assert.Equal(t, "http://swagger.io", doc.Tags.Value[0].Value.ExternalDocs.Value.URL.Value)
|
||||
assert.Equal(t, "store", doc.Tags.Value[1].Value.Name.Value)
|
||||
assert.Equal(t, "user", doc.Tags.Value[2].Value.Name.Value)
|
||||
assert.Equal(t, "http://swagger.io", doc.Tags.Value[2].Value.ExternalDocs.Value.URL.Value)
|
||||
}
|
||||
|
||||
func TestCreateDocument_SecurityDefinitions(t *testing.T) {
|
||||
initTest()
|
||||
apiKey := doc.SecurityDefinitions.Value.FindSecurityDefinition("api_key")
|
||||
assert.Equal(t, "apiKey", apiKey.Value.Type.Value)
|
||||
petStoreAuth := doc.SecurityDefinitions.Value.FindSecurityDefinition("petstore_auth")
|
||||
assert.Equal(t, "oauth2", petStoreAuth.Value.Type.Value)
|
||||
assert.Equal(t, "implicit", petStoreAuth.Value.Flow.Value)
|
||||
assert.Len(t, petStoreAuth.Value.Scopes.Value.Values, 2)
|
||||
assert.Equal(t, "read your pets", petStoreAuth.Value.Scopes.Value.FindScope("read:pets").Value)
|
||||
initTest()
|
||||
apiKey := doc.SecurityDefinitions.Value.FindSecurityDefinition("api_key")
|
||||
assert.Equal(t, "apiKey", apiKey.Value.Type.Value)
|
||||
petStoreAuth := doc.SecurityDefinitions.Value.FindSecurityDefinition("petstore_auth")
|
||||
assert.Equal(t, "oauth2", petStoreAuth.Value.Type.Value)
|
||||
assert.Equal(t, "implicit", petStoreAuth.Value.Flow.Value)
|
||||
assert.Len(t, petStoreAuth.Value.Scopes.Value.Values, 2)
|
||||
assert.Equal(t, "read your pets", petStoreAuth.Value.Scopes.Value.FindScope("read:pets").Value)
|
||||
}
|
||||
|
||||
func TestCreateDocument_Definitions(t *testing.T) {
|
||||
initTest()
|
||||
apiResp := doc.Definitions.Value.FindSchema("ApiResponse").Value.Schema()
|
||||
assert.NotNil(t, apiResp)
|
||||
assert.Len(t, apiResp.Properties.Value, 3)
|
||||
assert.Equal(t, "integer", apiResp.FindProperty("code").Value.Schema().Type.Value.A)
|
||||
initTest()
|
||||
apiResp := doc.Definitions.Value.FindSchema("ApiResponse").Value.Schema()
|
||||
assert.NotNil(t, apiResp)
|
||||
assert.Len(t, apiResp.Properties.Value, 3)
|
||||
assert.Equal(t, "integer", apiResp.FindProperty("code").Value.Schema().Type.Value.A)
|
||||
|
||||
pet := doc.Definitions.Value.FindSchema("Pet").Value.Schema()
|
||||
assert.NotNil(t, pet)
|
||||
assert.Len(t, pet.Required.Value, 2)
|
||||
pet := doc.Definitions.Value.FindSchema("Pet").Value.Schema()
|
||||
assert.NotNil(t, pet)
|
||||
assert.Len(t, pet.Required.Value, 2)
|
||||
|
||||
// perform a deep inline lookup on a schema to ensure chains work
|
||||
assert.Equal(t, "Category", pet.FindProperty("category").Value.Schema().XML.Value.Name.Value)
|
||||
// perform a deep inline lookup on a schema to ensure chains work
|
||||
assert.Equal(t, "Category", pet.FindProperty("category").Value.Schema().XML.Value.Name.Value)
|
||||
|
||||
// check enums
|
||||
assert.Len(t, pet.FindProperty("status").Value.Schema().Enum.Value, 3)
|
||||
// check enums
|
||||
assert.Len(t, pet.FindProperty("status").Value.Schema().Enum.Value, 3)
|
||||
}
|
||||
|
||||
func TestCreateDocument_ResponseDefinitions(t *testing.T) {
|
||||
initTest()
|
||||
apiResp := doc.Responses.Value.FindResponse("200")
|
||||
assert.NotNil(t, apiResp)
|
||||
assert.Equal(t, "OK", apiResp.Value.Description.Value)
|
||||
assert.Equal(t, "morning", apiResp.Value.FindExtension("x-coffee").Value)
|
||||
initTest()
|
||||
apiResp := doc.Responses.Value.FindResponse("200")
|
||||
assert.NotNil(t, apiResp)
|
||||
assert.Equal(t, "OK", apiResp.Value.Description.Value)
|
||||
assert.Equal(t, "morning", apiResp.Value.FindExtension("x-coffee").Value)
|
||||
|
||||
header := apiResp.Value.FindHeader("noHeader")
|
||||
assert.NotNil(t, header)
|
||||
assert.True(t, header.Value.FindExtension("x-empty").Value.(bool))
|
||||
header := apiResp.Value.FindHeader("noHeader")
|
||||
assert.NotNil(t, header)
|
||||
assert.True(t, header.Value.FindExtension("x-empty").Value.(bool))
|
||||
|
||||
header = apiResp.Value.FindHeader("myHeader")
|
||||
if k, ok := header.Value.Items.Value.Default.Value.(map[string]interface{}); ok {
|
||||
assert.Equal(t, "here", k["something"])
|
||||
} else {
|
||||
panic("should not fail.")
|
||||
}
|
||||
if k, ok := header.Value.Items.Value.Items.Value.Default.Value.([]interface{}); ok {
|
||||
assert.Len(t, k, 2)
|
||||
assert.Equal(t, "two", k[1])
|
||||
} else {
|
||||
panic("should not fail.")
|
||||
}
|
||||
header = apiResp.Value.FindHeader("myHeader")
|
||||
if k, ok := header.Value.Items.Value.Default.Value.(map[string]interface{}); ok {
|
||||
assert.Equal(t, "here", k["something"])
|
||||
} else {
|
||||
panic("should not fail.")
|
||||
}
|
||||
if k, ok := header.Value.Items.Value.Items.Value.Default.Value.([]interface{}); ok {
|
||||
assert.Len(t, k, 2)
|
||||
assert.Equal(t, "two", k[1])
|
||||
} else {
|
||||
panic("should not fail.")
|
||||
}
|
||||
|
||||
header = apiResp.Value.FindHeader("yourHeader")
|
||||
assert.Equal(t, "somethingSimple", header.Value.Items.Value.Default.Value)
|
||||
header = apiResp.Value.FindHeader("yourHeader")
|
||||
assert.Equal(t, "somethingSimple", header.Value.Items.Value.Default.Value)
|
||||
|
||||
assert.NotNil(t, apiResp.Value.Examples.Value.FindExample("application/json").Value)
|
||||
assert.NotNil(t, apiResp.Value.Examples.Value.FindExample("application/json").Value)
|
||||
|
||||
}
|
||||
|
||||
func TestCreateDocument_Paths(t *testing.T) {
|
||||
initTest()
|
||||
uploadImage := doc.Paths.Value.FindPath("/pet/{petId}/uploadImage").Value
|
||||
assert.NotNil(t, uploadImage)
|
||||
assert.Nil(t, doc.Paths.Value.FindPath("/nothing-nowhere-nohow"))
|
||||
assert.Equal(t, "man", uploadImage.FindExtension("x-potato").Value)
|
||||
assert.Equal(t, "fresh", doc.Paths.Value.FindExtension("x-minty").Value)
|
||||
assert.Equal(t, "successful operation",
|
||||
uploadImage.Post.Value.Responses.Value.FindResponseByCode("200").Value.Description.Value)
|
||||
initTest()
|
||||
uploadImage := doc.Paths.Value.FindPath("/pet/{petId}/uploadImage").Value
|
||||
assert.NotNil(t, uploadImage)
|
||||
assert.Nil(t, doc.Paths.Value.FindPath("/nothing-nowhere-nohow"))
|
||||
assert.Equal(t, "man", uploadImage.FindExtension("x-potato").Value)
|
||||
assert.Equal(t, "fresh", doc.Paths.Value.FindExtension("x-minty").Value)
|
||||
assert.Equal(t, "successful operation",
|
||||
uploadImage.Post.Value.Responses.Value.FindResponseByCode("200").Value.Description.Value)
|
||||
|
||||
}
|
||||
|
||||
func TestCreateDocument_Bad(t *testing.T) {
|
||||
|
||||
yml := `swagger:
|
||||
yml := `swagger:
|
||||
$ref: bork`
|
||||
|
||||
info, err := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
assert.Nil(t, info)
|
||||
assert.Error(t, err)
|
||||
info, err := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
assert.Nil(t, info)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestCreateDocument_ExternalDocsBad(t *testing.T) {
|
||||
|
||||
yml := `externalDocs:
|
||||
yml := `externalDocs:
|
||||
$ref: bork`
|
||||
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
}
|
||||
|
||||
func TestCreateDocument_TagsBad(t *testing.T) {
|
||||
|
||||
yml := `tags:
|
||||
yml := `tags:
|
||||
$ref: bork`
|
||||
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
}
|
||||
|
||||
func TestCreateDocument_PathsBad(t *testing.T) {
|
||||
|
||||
yml := `paths:
|
||||
yml := `paths:
|
||||
"/hey":
|
||||
post:
|
||||
responses:
|
||||
"200":
|
||||
$ref: bork`
|
||||
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
}
|
||||
|
||||
func TestCreateDocument_SecurityBad(t *testing.T) {
|
||||
|
||||
yml := `security:
|
||||
yml := `security:
|
||||
$ref: `
|
||||
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
}
|
||||
|
||||
func TestCreateDocument_SecurityDefinitionsBad(t *testing.T) {
|
||||
|
||||
yml := `securityDefinitions:
|
||||
yml := `securityDefinitions:
|
||||
$ref: `
|
||||
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
}
|
||||
|
||||
func TestCreateDocument_ResponsesBad(t *testing.T) {
|
||||
|
||||
yml := `responses:
|
||||
yml := `responses:
|
||||
$ref: `
|
||||
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
}
|
||||
|
||||
func TestCreateDocument_ParametersBad(t *testing.T) {
|
||||
|
||||
yml := `parameters:
|
||||
yml := `parameters:
|
||||
$ref: `
|
||||
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
}
|
||||
|
||||
func TestCreateDocument_DefinitionsBad(t *testing.T) {
|
||||
|
||||
yml := `definitions:
|
||||
yml := `definitions:
|
||||
$ref: `
|
||||
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
}
|
||||
|
||||
func TestCreateDocument_InfoBad(t *testing.T) {
|
||||
|
||||
yml := `info:
|
||||
yml := `info:
|
||||
$ref: `
|
||||
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
wait := true
|
||||
for wait {
|
||||
select {
|
||||
case <-info.JsonParsingChannel:
|
||||
wait = false
|
||||
}
|
||||
}
|
||||
assert.Len(t, err, 1)
|
||||
}
|
||||
|
||||
func TestCircularReferenceError(t *testing.T) {
|
||||
|
||||
data, _ := ioutil.ReadFile("../../../test_specs/swagger-circular-tests.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
circDoc, err := CreateDocument(info)
|
||||
assert.NotNil(t, circDoc)
|
||||
assert.Len(t, err, 3)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,203 +1,213 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/resolver"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"sync"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/resolver"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func CreateDocument(info *datamodel.SpecInfo) (*Document, []error) {
|
||||
|
||||
_, labelNode, versionNode := utils.FindKeyNodeFull(OpenAPILabel, info.RootNode.Content)
|
||||
var version low.NodeReference[string]
|
||||
if versionNode == nil {
|
||||
return nil, []error{errors.New("no openapi version/tag found, cannot create document")}
|
||||
}
|
||||
version = low.NodeReference[string]{Value: versionNode.Value, KeyNode: labelNode, ValueNode: versionNode}
|
||||
doc := Document{Version: version}
|
||||
_, labelNode, versionNode := utils.FindKeyNodeFull(OpenAPILabel, info.RootNode.Content)
|
||||
var version low.NodeReference[string]
|
||||
if versionNode == nil {
|
||||
return nil, []error{errors.New("no openapi version/tag found, cannot create document")}
|
||||
}
|
||||
version = low.NodeReference[string]{Value: versionNode.Value, KeyNode: labelNode, ValueNode: versionNode}
|
||||
doc := Document{Version: version}
|
||||
|
||||
// build an index
|
||||
idx := index.NewSpecIndex(info.RootNode)
|
||||
doc.Index = idx
|
||||
// build an index
|
||||
idx := index.NewSpecIndex(info.RootNode)
|
||||
doc.Index = idx
|
||||
|
||||
// create resolver and check for circular references.
|
||||
resolve := resolver.NewResolver(idx)
|
||||
_ = resolve.CheckForCircularReferences()
|
||||
var errors []error
|
||||
|
||||
var wg sync.WaitGroup
|
||||
var errors []error
|
||||
// create resolver and check for circular references.
|
||||
resolve := resolver.NewResolver(idx)
|
||||
resolvingErrors := resolve.CheckForCircularReferences()
|
||||
|
||||
doc.Extensions = low.ExtractExtensions(info.RootNode.Content[0])
|
||||
if len(resolvingErrors) > 0 {
|
||||
for r := range resolvingErrors {
|
||||
errors = append(errors,
|
||||
fmt.Errorf("%s: %s [%d:%d]", resolvingErrors[r].Error.Error(),
|
||||
resolvingErrors[r].Path, resolvingErrors[r].Node.Line, resolvingErrors[r].Node.Column))
|
||||
}
|
||||
}
|
||||
|
||||
// if set, extract jsonSchemaDialect (3.1)
|
||||
_, dialectLabel, dialectNode := utils.FindKeyNodeFull(JSONSchemaDialectLabel, info.RootNode.Content)
|
||||
if dialectNode != nil {
|
||||
doc.JsonSchemaDialect = low.NodeReference[string]{
|
||||
Value: dialectNode.Value, KeyNode: dialectLabel, ValueNode: dialectNode}
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
|
||||
var runExtraction = func(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex,
|
||||
runFunc func(i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error,
|
||||
ers *[]error,
|
||||
wg *sync.WaitGroup) {
|
||||
doc.Extensions = low.ExtractExtensions(info.RootNode.Content[0])
|
||||
|
||||
if er := runFunc(info, doc, idx); er != nil {
|
||||
*ers = append(*ers, er)
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
extractionFuncs := []func(i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error{
|
||||
extractInfo,
|
||||
extractServers,
|
||||
extractTags,
|
||||
extractComponents,
|
||||
extractSecurity,
|
||||
extractExternalDocs,
|
||||
extractPaths,
|
||||
extractWebhooks,
|
||||
}
|
||||
// if set, extract jsonSchemaDialect (3.1)
|
||||
_, dialectLabel, dialectNode := utils.FindKeyNodeFull(JSONSchemaDialectLabel, info.RootNode.Content)
|
||||
if dialectNode != nil {
|
||||
doc.JsonSchemaDialect = low.NodeReference[string]{
|
||||
Value: dialectNode.Value, KeyNode: dialectLabel, ValueNode: dialectNode}
|
||||
}
|
||||
|
||||
wg.Add(len(extractionFuncs))
|
||||
for _, f := range extractionFuncs {
|
||||
go runExtraction(info, &doc, idx, f, &errors, &wg)
|
||||
}
|
||||
wg.Wait()
|
||||
return &doc, errors
|
||||
var runExtraction = func(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex,
|
||||
runFunc func(i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error,
|
||||
ers *[]error,
|
||||
wg *sync.WaitGroup) {
|
||||
|
||||
if er := runFunc(info, doc, idx); er != nil {
|
||||
*ers = append(*ers, er)
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
extractionFuncs := []func(i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error{
|
||||
extractInfo,
|
||||
extractServers,
|
||||
extractTags,
|
||||
extractComponents,
|
||||
extractSecurity,
|
||||
extractExternalDocs,
|
||||
extractPaths,
|
||||
extractWebhooks,
|
||||
}
|
||||
|
||||
wg.Add(len(extractionFuncs))
|
||||
for _, f := range extractionFuncs {
|
||||
go runExtraction(info, &doc, idx, f, &errors, &wg)
|
||||
}
|
||||
wg.Wait()
|
||||
return &doc, errors
|
||||
}
|
||||
|
||||
func extractInfo(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
_, ln, vn := utils.FindKeyNodeFullTop(base.InfoLabel, info.RootNode.Content[0].Content)
|
||||
if vn != nil {
|
||||
ir := base.Info{}
|
||||
_ = low.BuildModel(vn, &ir)
|
||||
_ = ir.Build(vn, idx)
|
||||
nr := low.NodeReference[*base.Info]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
||||
doc.Info = nr
|
||||
}
|
||||
return nil
|
||||
_, ln, vn := utils.FindKeyNodeFullTop(base.InfoLabel, info.RootNode.Content[0].Content)
|
||||
if vn != nil {
|
||||
ir := base.Info{}
|
||||
_ = low.BuildModel(vn, &ir)
|
||||
_ = ir.Build(vn, idx)
|
||||
nr := low.NodeReference[*base.Info]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
||||
doc.Info = nr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractSecurity(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, info.RootNode.Content[0], idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
doc.Security = low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]{
|
||||
Value: sec,
|
||||
KeyNode: ln,
|
||||
ValueNode: vn,
|
||||
}
|
||||
return nil
|
||||
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, info.RootNode.Content[0], idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
doc.Security = low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]{
|
||||
Value: sec,
|
||||
KeyNode: ln,
|
||||
ValueNode: vn,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractExternalDocs(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, info.RootNode.Content[0], idx)
|
||||
if dErr != nil {
|
||||
return dErr
|
||||
}
|
||||
doc.ExternalDocs = extDocs
|
||||
return nil
|
||||
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, info.RootNode.Content[0], idx)
|
||||
if dErr != nil {
|
||||
return dErr
|
||||
}
|
||||
doc.ExternalDocs = extDocs
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractComponents(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
_, ln, vn := utils.FindKeyNodeFullTop(ComponentsLabel, info.RootNode.Content[0].Content)
|
||||
if vn != nil {
|
||||
ir := Components{}
|
||||
_ = low.BuildModel(vn, &ir)
|
||||
err := ir.Build(vn, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nr := low.NodeReference[*Components]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
||||
doc.Components = nr
|
||||
}
|
||||
return nil
|
||||
_, ln, vn := utils.FindKeyNodeFullTop(ComponentsLabel, info.RootNode.Content[0].Content)
|
||||
if vn != nil {
|
||||
ir := Components{}
|
||||
_ = low.BuildModel(vn, &ir)
|
||||
err := ir.Build(vn, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nr := low.NodeReference[*Components]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
||||
doc.Components = nr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractServers(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
_, ln, vn := utils.FindKeyNodeFull(ServersLabel, info.RootNode.Content[0].Content)
|
||||
if vn != nil {
|
||||
if utils.IsNodeArray(vn) {
|
||||
var servers []low.ValueReference[*Server]
|
||||
for _, srvN := range vn.Content {
|
||||
if utils.IsNodeMap(srvN) {
|
||||
srvr := Server{}
|
||||
_ = low.BuildModel(srvN, &srvr)
|
||||
_ = srvr.Build(srvN, idx)
|
||||
servers = append(servers, low.ValueReference[*Server]{
|
||||
Value: &srvr,
|
||||
ValueNode: srvN,
|
||||
})
|
||||
}
|
||||
}
|
||||
doc.Servers = low.NodeReference[[]low.ValueReference[*Server]]{
|
||||
Value: servers,
|
||||
KeyNode: ln,
|
||||
ValueNode: vn,
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
_, ln, vn := utils.FindKeyNodeFull(ServersLabel, info.RootNode.Content[0].Content)
|
||||
if vn != nil {
|
||||
if utils.IsNodeArray(vn) {
|
||||
var servers []low.ValueReference[*Server]
|
||||
for _, srvN := range vn.Content {
|
||||
if utils.IsNodeMap(srvN) {
|
||||
srvr := Server{}
|
||||
_ = low.BuildModel(srvN, &srvr)
|
||||
_ = srvr.Build(srvN, idx)
|
||||
servers = append(servers, low.ValueReference[*Server]{
|
||||
Value: &srvr,
|
||||
ValueNode: srvN,
|
||||
})
|
||||
}
|
||||
}
|
||||
doc.Servers = low.NodeReference[[]low.ValueReference[*Server]]{
|
||||
Value: servers,
|
||||
KeyNode: ln,
|
||||
ValueNode: vn,
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractTags(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
_, ln, vn := utils.FindKeyNodeFull(base.TagsLabel, info.RootNode.Content[0].Content)
|
||||
if vn != nil {
|
||||
if utils.IsNodeArray(vn) {
|
||||
var tags []low.ValueReference[*base.Tag]
|
||||
for _, tagN := range vn.Content {
|
||||
if utils.IsNodeMap(tagN) {
|
||||
tag := base.Tag{}
|
||||
_ = low.BuildModel(tagN, &tag)
|
||||
if err := tag.Build(tagN, idx); err != nil {
|
||||
return err
|
||||
}
|
||||
tags = append(tags, low.ValueReference[*base.Tag]{
|
||||
Value: &tag,
|
||||
ValueNode: tagN,
|
||||
})
|
||||
}
|
||||
}
|
||||
doc.Tags = low.NodeReference[[]low.ValueReference[*base.Tag]]{
|
||||
Value: tags,
|
||||
KeyNode: ln,
|
||||
ValueNode: vn,
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
_, ln, vn := utils.FindKeyNodeFull(base.TagsLabel, info.RootNode.Content[0].Content)
|
||||
if vn != nil {
|
||||
if utils.IsNodeArray(vn) {
|
||||
var tags []low.ValueReference[*base.Tag]
|
||||
for _, tagN := range vn.Content {
|
||||
if utils.IsNodeMap(tagN) {
|
||||
tag := base.Tag{}
|
||||
_ = low.BuildModel(tagN, &tag)
|
||||
if err := tag.Build(tagN, idx); err != nil {
|
||||
return err
|
||||
}
|
||||
tags = append(tags, low.ValueReference[*base.Tag]{
|
||||
Value: &tag,
|
||||
ValueNode: tagN,
|
||||
})
|
||||
}
|
||||
}
|
||||
doc.Tags = low.NodeReference[[]low.ValueReference[*base.Tag]]{
|
||||
Value: tags,
|
||||
KeyNode: ln,
|
||||
ValueNode: vn,
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractPaths(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
_, ln, vn := utils.FindKeyNodeFull(PathsLabel, info.RootNode.Content[0].Content)
|
||||
if vn != nil {
|
||||
ir := Paths{}
|
||||
err := ir.Build(vn, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nr := low.NodeReference[*Paths]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
||||
doc.Paths = nr
|
||||
}
|
||||
return nil
|
||||
_, ln, vn := utils.FindKeyNodeFull(PathsLabel, info.RootNode.Content[0].Content)
|
||||
if vn != nil {
|
||||
ir := Paths{}
|
||||
err := ir.Build(vn, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nr := low.NodeReference[*Paths]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
||||
doc.Paths = nr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractWebhooks(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
hooks, hooksL, hooksN, eErr := low.ExtractMap[*PathItem](WebhooksLabel, info.RootNode, idx)
|
||||
if eErr != nil {
|
||||
return eErr
|
||||
}
|
||||
if hooks != nil {
|
||||
doc.Webhooks = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*PathItem]]{
|
||||
Value: hooks,
|
||||
KeyNode: hooksL,
|
||||
ValueNode: hooksN,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
hooks, hooksL, hooksN, eErr := low.ExtractMap[*PathItem](WebhooksLabel, info.RootNode, idx)
|
||||
if eErr != nil {
|
||||
return eErr
|
||||
}
|
||||
if hooks != nil {
|
||||
doc.Webhooks = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*PathItem]]{
|
||||
Value: hooks,
|
||||
KeyNode: hooksL,
|
||||
ValueNode: hooksN,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
574
document_test.go
574
document_test.go
@@ -4,303 +4,303 @@
|
||||
package libopenapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadDocument_Simple_V2(t *testing.T) {
|
||||
|
||||
yml := `swagger: 2.0.1`
|
||||
doc, err := NewDocument([]byte(yml))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "2.0.1", doc.GetVersion())
|
||||
yml := `swagger: 2.0.1`
|
||||
doc, err := NewDocument([]byte(yml))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "2.0.1", doc.GetVersion())
|
||||
|
||||
v2Doc, docErr := doc.BuildV2Model()
|
||||
assert.Len(t, docErr, 0)
|
||||
assert.NotNil(t, v2Doc)
|
||||
assert.NotNil(t, doc.GetSpecInfo())
|
||||
v2Doc, docErr := doc.BuildV2Model()
|
||||
assert.Len(t, docErr, 0)
|
||||
assert.NotNil(t, v2Doc)
|
||||
assert.NotNil(t, doc.GetSpecInfo())
|
||||
|
||||
fmt.Print()
|
||||
fmt.Print()
|
||||
|
||||
}
|
||||
|
||||
func TestLoadDocument_Simple_V2_Error(t *testing.T) {
|
||||
|
||||
yml := `swagger: 2.0`
|
||||
doc, err := NewDocument([]byte(yml))
|
||||
assert.NoError(t, err)
|
||||
yml := `swagger: 2.0`
|
||||
doc, err := NewDocument([]byte(yml))
|
||||
assert.NoError(t, err)
|
||||
|
||||
v2Doc, docErr := doc.BuildV3Model()
|
||||
assert.Len(t, docErr, 1)
|
||||
assert.Nil(t, v2Doc)
|
||||
v2Doc, docErr := doc.BuildV3Model()
|
||||
assert.Len(t, docErr, 1)
|
||||
assert.Nil(t, v2Doc)
|
||||
}
|
||||
|
||||
func TestLoadDocument_Simple_V2_Error_BadSpec(t *testing.T) {
|
||||
|
||||
yml := `swagger: 2.0
|
||||
yml := `swagger: 2.0
|
||||
definitions:
|
||||
thing:
|
||||
$ref: bork`
|
||||
doc, err := NewDocument([]byte(yml))
|
||||
assert.NoError(t, err)
|
||||
doc, err := NewDocument([]byte(yml))
|
||||
assert.NoError(t, err)
|
||||
|
||||
v2Doc, docErr := doc.BuildV2Model()
|
||||
assert.Len(t, docErr, 1)
|
||||
assert.Nil(t, v2Doc)
|
||||
v2Doc, docErr := doc.BuildV2Model()
|
||||
assert.Len(t, docErr, 2)
|
||||
assert.Nil(t, v2Doc)
|
||||
}
|
||||
|
||||
func TestLoadDocument_Simple_V3_Error(t *testing.T) {
|
||||
|
||||
yml := `openapi: 3.0.1`
|
||||
doc, err := NewDocument([]byte(yml))
|
||||
assert.NoError(t, err)
|
||||
yml := `openapi: 3.0.1`
|
||||
doc, err := NewDocument([]byte(yml))
|
||||
assert.NoError(t, err)
|
||||
|
||||
v2Doc, docErr := doc.BuildV2Model()
|
||||
assert.Len(t, docErr, 1)
|
||||
assert.Nil(t, v2Doc)
|
||||
v2Doc, docErr := doc.BuildV2Model()
|
||||
assert.Len(t, docErr, 1)
|
||||
assert.Nil(t, v2Doc)
|
||||
}
|
||||
|
||||
func TestLoadDocument_Error_V2NoSpec(t *testing.T) {
|
||||
|
||||
doc := new(document) // not how this should be instantiated.
|
||||
_, err := doc.BuildV2Model()
|
||||
assert.Len(t, err, 1)
|
||||
doc := new(document) // not how this should be instantiated.
|
||||
_, err := doc.BuildV2Model()
|
||||
assert.Len(t, err, 1)
|
||||
}
|
||||
|
||||
func TestLoadDocument_Error_V3NoSpec(t *testing.T) {
|
||||
|
||||
doc := new(document) // not how this should be instantiated.
|
||||
_, err := doc.BuildV3Model()
|
||||
assert.Len(t, err, 1)
|
||||
doc := new(document) // not how this should be instantiated.
|
||||
_, err := doc.BuildV3Model()
|
||||
assert.Len(t, err, 1)
|
||||
}
|
||||
|
||||
func TestLoadDocument_Empty(t *testing.T) {
|
||||
yml := ``
|
||||
_, err := NewDocument([]byte(yml))
|
||||
assert.Error(t, err)
|
||||
yml := ``
|
||||
_, err := NewDocument([]byte(yml))
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestLoadDocument_Simple_V3(t *testing.T) {
|
||||
|
||||
yml := `openapi: 3.0.1`
|
||||
doc, err := NewDocument([]byte(yml))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "3.0.1", doc.GetVersion())
|
||||
yml := `openapi: 3.0.1`
|
||||
doc, err := NewDocument([]byte(yml))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "3.0.1", doc.GetVersion())
|
||||
|
||||
v3Doc, docErr := doc.BuildV3Model()
|
||||
assert.Len(t, docErr, 0)
|
||||
assert.NotNil(t, v3Doc)
|
||||
v3Doc, docErr := doc.BuildV3Model()
|
||||
assert.Len(t, docErr, 0)
|
||||
assert.NotNil(t, v3Doc)
|
||||
}
|
||||
|
||||
func TestLoadDocument_Simple_V3_Error_BadSpec(t *testing.T) {
|
||||
|
||||
yml := `openapi: 3.0
|
||||
yml := `openapi: 3.0
|
||||
paths:
|
||||
"/some":
|
||||
$ref: bork`
|
||||
doc, err := NewDocument([]byte(yml))
|
||||
assert.NoError(t, err)
|
||||
doc, err := NewDocument([]byte(yml))
|
||||
assert.NoError(t, err)
|
||||
|
||||
v3Doc, docErr := doc.BuildV3Model()
|
||||
assert.Len(t, docErr, 1)
|
||||
assert.Nil(t, v3Doc)
|
||||
v3Doc, docErr := doc.BuildV3Model()
|
||||
assert.Len(t, docErr, 1)
|
||||
assert.Nil(t, v3Doc)
|
||||
}
|
||||
|
||||
func TestDocument_Serialize_Error(t *testing.T) {
|
||||
doc := new(document) // not how this should be instantiated.
|
||||
_, err := doc.Serialize()
|
||||
assert.Error(t, err)
|
||||
doc := new(document) // not how this should be instantiated.
|
||||
_, err := doc.Serialize()
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestDocument_Serialize(t *testing.T) {
|
||||
|
||||
yml := `openapi: 3.0
|
||||
yml := `openapi: 3.0
|
||||
info:
|
||||
title: The magic API
|
||||
`
|
||||
doc, _ := NewDocument([]byte(yml))
|
||||
serial, err := doc.Serialize()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, yml, string(serial))
|
||||
doc, _ := NewDocument([]byte(yml))
|
||||
serial, err := doc.Serialize()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, yml, string(serial))
|
||||
}
|
||||
|
||||
func TestDocument_Serialize_Modified(t *testing.T) {
|
||||
|
||||
yml := `openapi: 3.0
|
||||
yml := `openapi: 3.0
|
||||
info:
|
||||
title: The magic API
|
||||
`
|
||||
|
||||
ymlModified := `openapi: 3.0
|
||||
ymlModified := `openapi: 3.0
|
||||
info:
|
||||
title: The magic API - but now, altered!
|
||||
`
|
||||
doc, _ := NewDocument([]byte(yml))
|
||||
doc, _ := NewDocument([]byte(yml))
|
||||
|
||||
v3Doc, _ := doc.BuildV3Model()
|
||||
v3Doc, _ := doc.BuildV3Model()
|
||||
|
||||
v3Doc.Model.Info.GoLow().Title.Mutate("The magic API - but now, altered!")
|
||||
v3Doc.Model.Info.GoLow().Title.Mutate("The magic API - but now, altered!")
|
||||
|
||||
serial, err := doc.Serialize()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ymlModified, string(serial))
|
||||
serial, err := doc.Serialize()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, ymlModified, string(serial))
|
||||
}
|
||||
|
||||
func TestDocument_Serialize_JSON_Modified(t *testing.T) {
|
||||
|
||||
json := `{ 'openapi': '3.0',
|
||||
json := `{ 'openapi': '3.0',
|
||||
'info': {
|
||||
'title': 'The magic API'
|
||||
}
|
||||
}
|
||||
`
|
||||
jsonModified := `{"info":{"title":"The magic API - but now, altered!"},"openapi":"3.0"}`
|
||||
doc, _ := NewDocument([]byte(json))
|
||||
jsonModified := `{"info":{"title":"The magic API - but now, altered!"},"openapi":"3.0"}`
|
||||
doc, _ := NewDocument([]byte(json))
|
||||
|
||||
v3Doc, _ := doc.BuildV3Model()
|
||||
v3Doc, _ := doc.BuildV3Model()
|
||||
|
||||
// eventually this will be encapsulated up high.
|
||||
// mutation does not replace low model, eventually pointers will be used.
|
||||
newTitle := v3Doc.Model.Info.GoLow().Title.Mutate("The magic API - but now, altered!")
|
||||
v3Doc.Model.Info.GoLow().Title = newTitle
|
||||
// eventually this will be encapsulated up high.
|
||||
// mutation does not replace low model, eventually pointers will be used.
|
||||
newTitle := v3Doc.Model.Info.GoLow().Title.Mutate("The magic API - but now, altered!")
|
||||
v3Doc.Model.Info.GoLow().Title = newTitle
|
||||
|
||||
assert.Equal(t, "The magic API - but now, altered!", v3Doc.Model.Info.GoLow().Title.Value)
|
||||
assert.Equal(t, "The magic API - but now, altered!", v3Doc.Model.Info.GoLow().Title.Value)
|
||||
|
||||
serial, err := doc.Serialize()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, jsonModified, string(serial))
|
||||
serial, err := doc.Serialize()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, jsonModified, string(serial))
|
||||
}
|
||||
|
||||
func ExampleNewDocument_fromOpenAPI3Document() {
|
||||
|
||||
// How to read in an OpenAPI 3 Specification, into a Document.
|
||||
// How to read in an OpenAPI 3 Specification, into a Document.
|
||||
|
||||
// load an OpenAPI 3 specification from bytes
|
||||
petstore, _ := ioutil.ReadFile("test_specs/petstorev3.json")
|
||||
// load an OpenAPI 3 specification from bytes
|
||||
petstore, _ := ioutil.ReadFile("test_specs/petstorev3.json")
|
||||
|
||||
// create a new document from specification bytes
|
||||
document, err := NewDocument(petstore)
|
||||
// create a new document from specification bytes
|
||||
document, err := NewDocument(petstore)
|
||||
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
|
||||
// because we know this is a v3 spec, we can build a ready to go model from it.
|
||||
v3Model, errors := document.BuildV3Model()
|
||||
// because we know this is a v3 spec, we can build a ready to go model from it.
|
||||
v3Model, errors := document.BuildV3Model()
|
||||
|
||||
// if anything went wrong when building the v3 model, a slice of errors will be returned
|
||||
if len(errors) > 0 {
|
||||
for i := range errors {
|
||||
fmt.Printf("error: %e\n", errors[i])
|
||||
}
|
||||
panic(fmt.Sprintf("cannot create v3 model from document: %d errors reported", len(errors)))
|
||||
}
|
||||
// if anything went wrong when building the v3 model, a slice of errors will be returned
|
||||
if len(errors) > 0 {
|
||||
for i := range errors {
|
||||
fmt.Printf("error: %e\n", errors[i])
|
||||
}
|
||||
panic(fmt.Sprintf("cannot create v3 model from document: %d errors reported", len(errors)))
|
||||
}
|
||||
|
||||
// get a count of the number of paths and schemas.
|
||||
paths := len(v3Model.Model.Paths.PathItems)
|
||||
schemas := len(v3Model.Model.Components.Schemas)
|
||||
// get a count of the number of paths and schemas.
|
||||
paths := len(v3Model.Model.Paths.PathItems)
|
||||
schemas := len(v3Model.Model.Components.Schemas)
|
||||
|
||||
// print the number of paths and schemas in the document
|
||||
fmt.Printf("There are %d paths and %d schemas in the document", paths, schemas)
|
||||
// Output: There are 13 paths and 8 schemas in the document
|
||||
// print the number of paths and schemas in the document
|
||||
fmt.Printf("There are %d paths and %d schemas in the document", paths, schemas)
|
||||
// Output: There are 13 paths and 8 schemas in the document
|
||||
}
|
||||
|
||||
func ExampleNewDocument_fromSwaggerDocument() {
|
||||
|
||||
// How to read in a Swagger / OpenAPI 2 Specification, into a Document.
|
||||
// How to read in a Swagger / OpenAPI 2 Specification, into a Document.
|
||||
|
||||
// load a Swagger specification from bytes
|
||||
petstore, _ := ioutil.ReadFile("test_specs/petstorev2.json")
|
||||
// load a Swagger specification from bytes
|
||||
petstore, _ := ioutil.ReadFile("test_specs/petstorev2.json")
|
||||
|
||||
// create a new document from specification bytes
|
||||
document, err := NewDocument(petstore)
|
||||
// create a new document from specification bytes
|
||||
document, err := NewDocument(petstore)
|
||||
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
|
||||
// because we know this is a v2 spec, we can build a ready to go model from it.
|
||||
v2Model, errors := document.BuildV2Model()
|
||||
// because we know this is a v2 spec, we can build a ready to go model from it.
|
||||
v2Model, errors := document.BuildV2Model()
|
||||
|
||||
// if anything went wrong when building the v3 model, a slice of errors will be returned
|
||||
if len(errors) > 0 {
|
||||
for i := range errors {
|
||||
fmt.Printf("error: %e\n", errors[i])
|
||||
}
|
||||
panic(fmt.Sprintf("cannot create v3 model from document: %d errors reported", len(errors)))
|
||||
}
|
||||
// if anything went wrong when building the v3 model, a slice of errors will be returned
|
||||
if len(errors) > 0 {
|
||||
for i := range errors {
|
||||
fmt.Printf("error: %e\n", errors[i])
|
||||
}
|
||||
panic(fmt.Sprintf("cannot create v3 model from document: %d errors reported", len(errors)))
|
||||
}
|
||||
|
||||
// get a count of the number of paths and schemas.
|
||||
paths := len(v2Model.Model.Paths.PathItems)
|
||||
schemas := len(v2Model.Model.Definitions.Definitions)
|
||||
// get a count of the number of paths and schemas.
|
||||
paths := len(v2Model.Model.Paths.PathItems)
|
||||
schemas := len(v2Model.Model.Definitions.Definitions)
|
||||
|
||||
// print the number of paths and schemas in the document
|
||||
fmt.Printf("There are %d paths and %d schemas in the document", paths, schemas)
|
||||
// Output: There are 14 paths and 6 schemas in the document
|
||||
// print the number of paths and schemas in the document
|
||||
fmt.Printf("There are %d paths and %d schemas in the document", paths, schemas)
|
||||
// Output: There are 14 paths and 6 schemas in the document
|
||||
}
|
||||
|
||||
func ExampleNewDocument_fromUnknownVersion() {
|
||||
|
||||
// load an unknown version of an OpenAPI spec
|
||||
petstore, _ := ioutil.ReadFile("test_specs/burgershop.openapi.yaml")
|
||||
// load an unknown version of an OpenAPI spec
|
||||
petstore, _ := ioutil.ReadFile("test_specs/burgershop.openapi.yaml")
|
||||
|
||||
// create a new document from specification bytes
|
||||
document, err := NewDocument(petstore)
|
||||
// create a new document from specification bytes
|
||||
document, err := NewDocument(petstore)
|
||||
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
|
||||
var paths, schemas int
|
||||
var errors []error
|
||||
var paths, schemas int
|
||||
var errors []error
|
||||
|
||||
// We don't know which type of document this is, so we can use the spec info to inform us
|
||||
if document.GetSpecInfo().SpecType == utils.OpenApi3 {
|
||||
v3Model, errs := document.BuildV3Model()
|
||||
if len(errs) > 0 {
|
||||
errors = errs
|
||||
}
|
||||
if len(errors) <= 0 {
|
||||
paths = len(v3Model.Model.Paths.PathItems)
|
||||
schemas = len(v3Model.Model.Components.Schemas)
|
||||
}
|
||||
}
|
||||
if document.GetSpecInfo().SpecType == utils.OpenApi2 {
|
||||
v2Model, errs := document.BuildV2Model()
|
||||
if len(errs) > 0 {
|
||||
errors = errs
|
||||
}
|
||||
if len(errors) <= 0 {
|
||||
paths = len(v2Model.Model.Paths.PathItems)
|
||||
schemas = len(v2Model.Model.Definitions.Definitions)
|
||||
}
|
||||
}
|
||||
// We don't know which type of document this is, so we can use the spec info to inform us
|
||||
if document.GetSpecInfo().SpecType == utils.OpenApi3 {
|
||||
v3Model, errs := document.BuildV3Model()
|
||||
if len(errs) > 0 {
|
||||
errors = errs
|
||||
}
|
||||
if len(errors) <= 0 {
|
||||
paths = len(v3Model.Model.Paths.PathItems)
|
||||
schemas = len(v3Model.Model.Components.Schemas)
|
||||
}
|
||||
}
|
||||
if document.GetSpecInfo().SpecType == utils.OpenApi2 {
|
||||
v2Model, errs := document.BuildV2Model()
|
||||
if len(errs) > 0 {
|
||||
errors = errs
|
||||
}
|
||||
if len(errors) <= 0 {
|
||||
paths = len(v2Model.Model.Paths.PathItems)
|
||||
schemas = len(v2Model.Model.Definitions.Definitions)
|
||||
}
|
||||
}
|
||||
|
||||
// if anything went wrong when building the model, report errors.
|
||||
if len(errors) > 0 {
|
||||
for i := range errors {
|
||||
fmt.Printf("error: %e\n", errors[i])
|
||||
}
|
||||
panic(fmt.Sprintf("cannot create v3 model from document: %d errors reported", len(errors)))
|
||||
}
|
||||
// if anything went wrong when building the model, report errors.
|
||||
if len(errors) > 0 {
|
||||
for i := range errors {
|
||||
fmt.Printf("error: %e\n", errors[i])
|
||||
}
|
||||
panic(fmt.Sprintf("cannot create v3 model from document: %d errors reported", len(errors)))
|
||||
}
|
||||
|
||||
// print the number of paths and schemas in the document
|
||||
fmt.Printf("There are %d paths and %d schemas in the document", paths, schemas)
|
||||
// Output: There are 5 paths and 6 schemas in the document
|
||||
// print the number of paths and schemas in the document
|
||||
fmt.Printf("There are %d paths and %d schemas in the document", paths, schemas)
|
||||
// Output: There are 5 paths and 6 schemas in the document
|
||||
}
|
||||
|
||||
func ExampleNewDocument_mutateValuesAndSerialize() {
|
||||
|
||||
// How to mutate values in an OpenAPI Specification, without re-ordering original content.
|
||||
// How to mutate values in an OpenAPI Specification, without re-ordering original content.
|
||||
|
||||
// create very small, and useless spec that does nothing useful, except showcase this feature.
|
||||
spec := `
|
||||
// create very small, and useless spec that does nothing useful, except showcase this feature.
|
||||
spec := `
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: This is a title
|
||||
@@ -310,155 +310,155 @@ info:
|
||||
license:
|
||||
url: http://some-place-on-the-internet.com/license
|
||||
`
|
||||
// create a new document from specification bytes
|
||||
document, err := NewDocument([]byte(spec))
|
||||
// create a new document from specification bytes
|
||||
document, err := NewDocument([]byte(spec))
|
||||
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
|
||||
// because we know this is a v3 spec, we can build a ready to go model from it.
|
||||
v3Model, errors := document.BuildV3Model()
|
||||
// because we know this is a v3 spec, we can build a ready to go model from it.
|
||||
v3Model, errors := document.BuildV3Model()
|
||||
|
||||
// if anything went wrong when building the v3 model, a slice of errors will be returned
|
||||
if len(errors) > 0 {
|
||||
for i := range errors {
|
||||
fmt.Printf("error: %e\n", errors[i])
|
||||
}
|
||||
panic(fmt.Sprintf("cannot create v3 model from document: %d errors reported", len(errors)))
|
||||
}
|
||||
// if anything went wrong when building the v3 model, a slice of errors will be returned
|
||||
if len(errors) > 0 {
|
||||
for i := range errors {
|
||||
fmt.Printf("error: %e\n", errors[i])
|
||||
}
|
||||
panic(fmt.Sprintf("cannot create v3 model from document: %d errors reported", len(errors)))
|
||||
}
|
||||
|
||||
// mutate the title, to do this we currently need to drop down to the low-level API.
|
||||
v3Model.Model.GoLow().Info.Value.Title.Mutate("A new title for a useless spec")
|
||||
// mutate the title, to do this we currently need to drop down to the low-level API.
|
||||
v3Model.Model.GoLow().Info.Value.Title.Mutate("A new title for a useless spec")
|
||||
|
||||
// mutate the email address in the contact object.
|
||||
v3Model.Model.GoLow().Info.Value.Contact.Value.Email.Mutate("buckaroo@pb33f.io")
|
||||
// mutate the email address in the contact object.
|
||||
v3Model.Model.GoLow().Info.Value.Contact.Value.Email.Mutate("buckaroo@pb33f.io")
|
||||
|
||||
// mutate the name in the contact object.
|
||||
v3Model.Model.GoLow().Info.Value.Contact.Value.Name.Mutate("Buckaroo")
|
||||
// mutate the name in the contact object.
|
||||
v3Model.Model.GoLow().Info.Value.Contact.Value.Name.Mutate("Buckaroo")
|
||||
|
||||
// mutate the URL for the license object.
|
||||
v3Model.Model.GoLow().Info.Value.License.Value.URL.Mutate("https://pb33f.io/license")
|
||||
// mutate the URL for the license object.
|
||||
v3Model.Model.GoLow().Info.Value.License.Value.URL.Mutate("https://pb33f.io/license")
|
||||
|
||||
// serialize the document back into the original YAML or JSON
|
||||
mutatedSpec, serialError := document.Serialize()
|
||||
// serialize the document back into the original YAML or JSON
|
||||
mutatedSpec, serialError := document.Serialize()
|
||||
|
||||
// if something went wrong serializing
|
||||
if serialError != nil {
|
||||
panic(fmt.Sprintf("cannot serialize document: %e", serialError))
|
||||
}
|
||||
// if something went wrong serializing
|
||||
if serialError != nil {
|
||||
panic(fmt.Sprintf("cannot serialize document: %e", serialError))
|
||||
}
|
||||
|
||||
// print our modified spec!
|
||||
fmt.Println(string(mutatedSpec))
|
||||
// Output: openapi: 3.1.0
|
||||
//info:
|
||||
// title: A new title for a useless spec
|
||||
// contact:
|
||||
// name: Buckaroo
|
||||
// email: buckaroo@pb33f.io
|
||||
// license:
|
||||
// url: https://pb33f.io/license
|
||||
// print our modified spec!
|
||||
fmt.Println(string(mutatedSpec))
|
||||
// Output: openapi: 3.1.0
|
||||
//info:
|
||||
// title: A new title for a useless spec
|
||||
// contact:
|
||||
// name: Buckaroo
|
||||
// email: buckaroo@pb33f.io
|
||||
// license:
|
||||
// url: https://pb33f.io/license
|
||||
}
|
||||
|
||||
func ExampleCompareDocuments_openAPI() {
|
||||
|
||||
// How to compare two different OpenAPI specifications.
|
||||
// How to compare two different OpenAPI specifications.
|
||||
|
||||
// load an original OpenAPI 3 specification from bytes
|
||||
burgerShopOriginal, _ := ioutil.ReadFile("test_specs/burgershop.openapi.yaml")
|
||||
// load an original OpenAPI 3 specification from bytes
|
||||
burgerShopOriginal, _ := ioutil.ReadFile("test_specs/burgershop.openapi.yaml")
|
||||
|
||||
// load an **updated** OpenAPI 3 specification from bytes
|
||||
burgerShopUpdated, _ := ioutil.ReadFile("test_specs/burgershop.openapi-modified.yaml")
|
||||
// load an **updated** OpenAPI 3 specification from bytes
|
||||
burgerShopUpdated, _ := ioutil.ReadFile("test_specs/burgershop.openapi-modified.yaml")
|
||||
|
||||
// create a new document from original specification bytes
|
||||
originalDoc, err := NewDocument(burgerShopOriginal)
|
||||
// create a new document from original specification bytes
|
||||
originalDoc, err := NewDocument(burgerShopOriginal)
|
||||
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
|
||||
// create a new document from updated specification bytes
|
||||
updatedDoc, err := NewDocument(burgerShopUpdated)
|
||||
// create a new document from updated specification bytes
|
||||
updatedDoc, err := NewDocument(burgerShopUpdated)
|
||||
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
|
||||
// Compare documents for all changes made
|
||||
documentChanges, errs := CompareDocuments(originalDoc, updatedDoc)
|
||||
// Compare documents for all changes made
|
||||
documentChanges, errs := CompareDocuments(originalDoc, updatedDoc)
|
||||
|
||||
// If anything went wrong when building models for documents.
|
||||
if len(errs) > 0 {
|
||||
for i := range errs {
|
||||
fmt.Printf("error: %e\n", errs[i])
|
||||
}
|
||||
panic(fmt.Sprintf("cannot compare documents: %d errors reported", len(errs)))
|
||||
}
|
||||
// If anything went wrong when building models for documents.
|
||||
if len(errs) > 0 {
|
||||
for i := range errs {
|
||||
fmt.Printf("error: %e\n", errs[i])
|
||||
}
|
||||
panic(fmt.Sprintf("cannot compare documents: %d errors reported", len(errs)))
|
||||
}
|
||||
|
||||
// Extract SchemaChanges from components changes.
|
||||
schemaChanges := documentChanges.ComponentsChanges.SchemaChanges
|
||||
// Extract SchemaChanges from components changes.
|
||||
schemaChanges := documentChanges.ComponentsChanges.SchemaChanges
|
||||
|
||||
// Print out some interesting stats about the OpenAPI document changes.
|
||||
fmt.Printf("There are %d changes, of which %d are breaking. %v schemas have changes.",
|
||||
documentChanges.TotalChanges(), documentChanges.TotalBreakingChanges(), len(schemaChanges))
|
||||
//Output: There are 67 changes, of which 17 are breaking. 5 schemas have changes.
|
||||
// Print out some interesting stats about the OpenAPI document changes.
|
||||
fmt.Printf("There are %d changes, of which %d are breaking. %v schemas have changes.",
|
||||
documentChanges.TotalChanges(), documentChanges.TotalBreakingChanges(), len(schemaChanges))
|
||||
//Output: There are 67 changes, of which 17 are breaking. 5 schemas have changes.
|
||||
|
||||
}
|
||||
|
||||
func ExampleCompareDocuments_swagger() {
|
||||
|
||||
// How to compare two different Swagger specifications.
|
||||
// How to compare two different Swagger specifications.
|
||||
|
||||
// load an original OpenAPI 3 specification from bytes
|
||||
petstoreOriginal, _ := ioutil.ReadFile("test_specs/petstorev2-complete.yaml")
|
||||
// load an original OpenAPI 3 specification from bytes
|
||||
petstoreOriginal, _ := ioutil.ReadFile("test_specs/petstorev2-complete.yaml")
|
||||
|
||||
// load an **updated** OpenAPI 3 specification from bytes
|
||||
petstoreUpdated, _ := ioutil.ReadFile("test_specs/petstorev2-complete-modified.yaml")
|
||||
// load an **updated** OpenAPI 3 specification from bytes
|
||||
petstoreUpdated, _ := ioutil.ReadFile("test_specs/petstorev2-complete-modified.yaml")
|
||||
|
||||
// create a new document from original specification bytes
|
||||
originalDoc, err := NewDocument(petstoreOriginal)
|
||||
// create a new document from original specification bytes
|
||||
originalDoc, err := NewDocument(petstoreOriginal)
|
||||
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
|
||||
// create a new document from updated specification bytes
|
||||
updatedDoc, err := NewDocument(petstoreUpdated)
|
||||
// create a new document from updated specification bytes
|
||||
updatedDoc, err := NewDocument(petstoreUpdated)
|
||||
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
|
||||
// Compare documents for all changes made
|
||||
documentChanges, errs := CompareDocuments(originalDoc, updatedDoc)
|
||||
// Compare documents for all changes made
|
||||
documentChanges, errs := CompareDocuments(originalDoc, updatedDoc)
|
||||
|
||||
// If anything went wrong when building models for documents.
|
||||
if len(errs) > 0 {
|
||||
for i := range errs {
|
||||
fmt.Printf("error: %e\n", errs[i])
|
||||
}
|
||||
panic(fmt.Sprintf("cannot compare documents: %d errors reported", len(errs)))
|
||||
}
|
||||
// If anything went wrong when building models for documents.
|
||||
if len(errs) > 0 {
|
||||
for i := range errs {
|
||||
fmt.Printf("error: %e\n", errs[i])
|
||||
}
|
||||
panic(fmt.Sprintf("cannot compare documents: %d errors reported", len(errs)))
|
||||
}
|
||||
|
||||
// Extract SchemaChanges from components changes.
|
||||
schemaChanges := documentChanges.ComponentsChanges.SchemaChanges
|
||||
// Extract SchemaChanges from components changes.
|
||||
schemaChanges := documentChanges.ComponentsChanges.SchemaChanges
|
||||
|
||||
// Print out some interesting stats about the Swagger document changes.
|
||||
fmt.Printf("There are %d changes, of which %d are breaking. %v schemas have changes.",
|
||||
documentChanges.TotalChanges(), documentChanges.TotalBreakingChanges(), len(schemaChanges))
|
||||
//Output: There are 52 changes, of which 27 are breaking. 5 schemas have changes.
|
||||
// Print out some interesting stats about the Swagger document changes.
|
||||
fmt.Printf("There are %d changes, of which %d are breaking. %v schemas have changes.",
|
||||
documentChanges.TotalChanges(), documentChanges.TotalBreakingChanges(), len(schemaChanges))
|
||||
//Output: There are 52 changes, of which 27 are breaking. 5 schemas have changes.
|
||||
|
||||
}
|
||||
|
||||
func TestDocument_Paths_As_Array(t *testing.T) {
|
||||
|
||||
// paths can now be wrapped in an array.
|
||||
spec := `{
|
||||
// paths can now be wrapped in an array.
|
||||
spec := `{
|
||||
"openapi": "3.1.0",
|
||||
"paths": [
|
||||
"/": {
|
||||
@@ -467,13 +467,13 @@ func TestDocument_Paths_As_Array(t *testing.T) {
|
||||
]
|
||||
}
|
||||
`
|
||||
// create a new document from specification bytes
|
||||
doc, err := NewDocument([]byte(spec))
|
||||
// create a new document from specification bytes
|
||||
doc, err := NewDocument([]byte(spec))
|
||||
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
v3Model, _ := doc.BuildV3Model()
|
||||
assert.NotNil(t, v3Model)
|
||||
// if anything went wrong, an error is thrown
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot create new document: %e", err))
|
||||
}
|
||||
v3Model, _ := doc.BuildV3Model()
|
||||
assert.NotNil(t, v3Model)
|
||||
}
|
||||
|
||||
51
test_specs/swagger-circular-tests.yaml
Normal file
51
test_specs/swagger-circular-tests.yaml
Normal file
@@ -0,0 +1,51 @@
|
||||
swagger: "2.0"
|
||||
paths:
|
||||
/burgers:
|
||||
post:
|
||||
responses:
|
||||
200:
|
||||
schema:
|
||||
$ref: '#/definitions/Nine'
|
||||
definitions:
|
||||
One:
|
||||
description: "test one"
|
||||
properties:
|
||||
things:
|
||||
"$ref": "#/definitions/Two"
|
||||
Two:
|
||||
description: "test two"
|
||||
properties:
|
||||
testThing:
|
||||
"$ref": "#/definitions/One"
|
||||
Three:
|
||||
description: "test three"
|
||||
properties:
|
||||
tester:
|
||||
"$ref": "#/definitions/Four"
|
||||
bester:
|
||||
"$ref": "#/definitions/Seven"
|
||||
yester:
|
||||
"$ref": "#/definitions/Seven"
|
||||
Four:
|
||||
description: "test four"
|
||||
properties:
|
||||
lemons:
|
||||
"$ref": "#/definitions/Nine"
|
||||
Five:
|
||||
properties:
|
||||
rice:
|
||||
"$ref": "#/definitions/Six"
|
||||
Six:
|
||||
properties:
|
||||
mints:
|
||||
"$ref": "#/definitions/Nine"
|
||||
Seven:
|
||||
properties:
|
||||
wow:
|
||||
"$ref": "#/definitions/Three"
|
||||
Nine:
|
||||
description: done.
|
||||
Ten:
|
||||
properties:
|
||||
yeah:
|
||||
"$ref": "#/definitions/Ten"
|
||||
Reference in New Issue
Block a user