mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-06 04:20:11 +00:00
99.9 % coverage & full OpenAPI v3 support
A single line that tries to read an HTTP response body and fails is very hard to test without mocking, and the mock does not add value to a single line of code to check for an error that can rarely ever be triggered. Going to settle for 99.9% for now.
This commit is contained in:
30
index/circular_reference_result_test.go
Normal file
30
index/circular_reference_result_test.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package index
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCircularReferenceResult_GenerateJourneyPath(t *testing.T) {
|
||||||
|
|
||||||
|
refs := []*Reference{
|
||||||
|
{Name: "chicken"},
|
||||||
|
{Name: "nuggets"},
|
||||||
|
{Name: "chicken"},
|
||||||
|
{Name: "soup"},
|
||||||
|
{Name: "chicken"},
|
||||||
|
{Name: "nuggets"},
|
||||||
|
{Name: "for"},
|
||||||
|
{Name: "me"},
|
||||||
|
{Name: "and"},
|
||||||
|
{Name: "you"},
|
||||||
|
}
|
||||||
|
|
||||||
|
cr := &CircularReferenceResult{Journey: refs}
|
||||||
|
assert.Equal(t, "chicken -> nuggets -> chicken -> soup -> "+
|
||||||
|
"chicken -> nuggets -> for -> me -> and -> you", cr.GenerateJourneyPath())
|
||||||
|
|
||||||
|
}
|
||||||
@@ -454,6 +454,11 @@ func (index *SpecIndex) GetParametersNode() *yaml.Node {
|
|||||||
return index.parametersNode
|
return index.parametersNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetReferenceIndexErrors will return any errors that occurred when indexing references
|
||||||
|
func (index *SpecIndex) GetReferenceIndexErrors() []*IndexingError {
|
||||||
|
return index.refErrors
|
||||||
|
}
|
||||||
|
|
||||||
// GetOperationParametersIndexErrors any errors that occurred when indexing operation parameters
|
// GetOperationParametersIndexErrors any errors that occurred when indexing operation parameters
|
||||||
func (index *SpecIndex) GetOperationParametersIndexErrors() []*IndexingError {
|
func (index *SpecIndex) GetOperationParametersIndexErrors() []*IndexingError {
|
||||||
return index.operationParamErrors
|
return index.operationParamErrors
|
||||||
@@ -1687,49 +1692,51 @@ func (index *SpecIndex) extractComponentSecuritySchemes(securitySchemesNode *yam
|
|||||||
func (index *SpecIndex) performExternalLookup(uri []string, componentId string,
|
func (index *SpecIndex) performExternalLookup(uri []string, componentId string,
|
||||||
lookupFunction ExternalLookupFunction, parent *yaml.Node) *Reference {
|
lookupFunction ExternalLookupFunction, parent *yaml.Node) *Reference {
|
||||||
|
|
||||||
externalSpecIndex := index.externalSpecIndex[uri[0]]
|
if len(uri) > 0 {
|
||||||
var foundNode *yaml.Node
|
externalSpecIndex := index.externalSpecIndex[uri[0]]
|
||||||
if externalSpecIndex == nil {
|
var foundNode *yaml.Node
|
||||||
|
if externalSpecIndex == nil {
|
||||||
|
|
||||||
n, newRoot, err := lookupFunction(componentId)
|
n, newRoot, err := lookupFunction(componentId)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
indexError := &IndexingError{
|
indexError := &IndexingError{
|
||||||
Error: err,
|
Error: err,
|
||||||
Node: parent,
|
Node: parent,
|
||||||
Path: componentId,
|
Path: componentId,
|
||||||
|
}
|
||||||
|
index.refErrors = append(index.refErrors, indexError)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != nil {
|
||||||
|
foundNode = n
|
||||||
|
}
|
||||||
|
|
||||||
|
// cool, cool, lets index this spec also. This is a recursive action and will keep going
|
||||||
|
// until all remote references have been found.
|
||||||
|
newIndex := NewSpecIndex(newRoot)
|
||||||
|
index.externalSpecIndex[uri[0]] = newIndex
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
foundRef := externalSpecIndex.FindComponentInRoot(uri[1])
|
||||||
|
if foundRef != nil {
|
||||||
|
foundNode = foundRef.Node
|
||||||
}
|
}
|
||||||
index.refErrors = append(index.refErrors, indexError)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if n != nil {
|
if foundNode != nil {
|
||||||
foundNode = n
|
nameSegs := strings.Split(uri[1], "/")
|
||||||
|
ref := &Reference{
|
||||||
|
Definition: componentId,
|
||||||
|
Name: nameSegs[len(nameSegs)-1],
|
||||||
|
Node: foundNode,
|
||||||
|
IsRemote: true,
|
||||||
|
RemoteLocation: componentId,
|
||||||
|
}
|
||||||
|
return ref
|
||||||
}
|
}
|
||||||
|
|
||||||
// cool, cool, lets index this spec also. This is a recursive action and will keep going
|
|
||||||
// until all remote references have been found.
|
|
||||||
newIndex := NewSpecIndex(newRoot)
|
|
||||||
index.externalSpecIndex[uri[0]] = newIndex
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
foundRef := externalSpecIndex.FindComponentInRoot(uri[1])
|
|
||||||
if foundRef != nil {
|
|
||||||
foundNode = foundRef.Node
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if foundNode != nil {
|
|
||||||
nameSegs := strings.Split(uri[1], "/")
|
|
||||||
ref := &Reference{
|
|
||||||
Definition: componentId,
|
|
||||||
Name: nameSegs[len(nameSegs)-1],
|
|
||||||
Node: foundNode,
|
|
||||||
IsRemote: true,
|
|
||||||
RemoteLocation: componentId,
|
|
||||||
}
|
|
||||||
return ref
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -1895,10 +1902,6 @@ func (index *SpecIndex) lookupRemoteReference(ref string) (*yaml.Node, *yaml.Nod
|
|||||||
index.remoteLock.Unlock()
|
index.remoteLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
if parsedRemoteDocument == nil {
|
|
||||||
return nil, nil, fmt.Errorf("unable to parse remote reference: '%s'", uri[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
// lookup item from reference by using a path query.
|
// lookup item from reference by using a path query.
|
||||||
query := fmt.Sprintf("$%s", strings.ReplaceAll(uri[1], "/", "."))
|
query := fmt.Sprintf("$%s", strings.ReplaceAll(uri[1], "/", "."))
|
||||||
|
|
||||||
@@ -1910,14 +1913,10 @@ func (index *SpecIndex) lookupRemoteReference(ref string) (*yaml.Node, *yaml.Nod
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
result, err := path.Find(parsedRemoteDocument)
|
result, _ := path.Find(parsedRemoteDocument)
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
if len(result) == 1 {
|
if len(result) == 1 {
|
||||||
return result[0], parsedRemoteDocument, nil
|
return result[0], parsedRemoteDocument, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1951,10 +1950,6 @@ func (index *SpecIndex) lookupFileReference(ref string) (*yaml.Node, *yaml.Node,
|
|||||||
index.seenRemoteSources[file] = &remoteDoc
|
index.seenRemoteSources[file] = &remoteDoc
|
||||||
}
|
}
|
||||||
|
|
||||||
if parsedRemoteDocument == nil {
|
|
||||||
return nil, nil, fmt.Errorf("unable to parse file reference: '%s'", file)
|
|
||||||
}
|
|
||||||
|
|
||||||
// lookup item from reference by using a path query.
|
// lookup item from reference by using a path query.
|
||||||
query := fmt.Sprintf("$%s", strings.ReplaceAll(uri[1], "/", "."))
|
query := fmt.Sprintf("$%s", strings.ReplaceAll(uri[1], "/", "."))
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
|
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package index
|
package index
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -430,5 +434,141 @@ paths:
|
|||||||
|
|
||||||
index := NewSpecIndex(&rootNode)
|
index := NewSpecIndex(&rootNode)
|
||||||
assert.Equal(t, 4, index.GetGlobalCallbacksCount())
|
assert.Equal(t, 4, index.GetGlobalCallbacksCount())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_ExtractComponentsFromRefs(t *testing.T) {
|
||||||
|
yml := `components:
|
||||||
|
schemas:
|
||||||
|
pizza:
|
||||||
|
properties:
|
||||||
|
something:
|
||||||
|
$ref: '#/components/\schemas/\something'
|
||||||
|
something:
|
||||||
|
description: something`
|
||||||
|
|
||||||
|
var rootNode yaml.Node
|
||||||
|
yaml.Unmarshal([]byte(yml), &rootNode)
|
||||||
|
|
||||||
|
index := NewSpecIndex(&rootNode)
|
||||||
|
assert.Len(t, index.GetReferenceIndexErrors(), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_FindComponent(t *testing.T) {
|
||||||
|
yml := `components:
|
||||||
|
schemas:
|
||||||
|
pizza:
|
||||||
|
properties:
|
||||||
|
something:
|
||||||
|
$ref: '#/components/schemas/something'
|
||||||
|
something:
|
||||||
|
description: something`
|
||||||
|
|
||||||
|
var rootNode yaml.Node
|
||||||
|
yaml.Unmarshal([]byte(yml), &rootNode)
|
||||||
|
|
||||||
|
index := NewSpecIndex(&rootNode)
|
||||||
|
assert.Nil(t, index.FindComponent("I-do-not-exist", nil))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_performExternalLookup(t *testing.T) {
|
||||||
|
yml := `components:
|
||||||
|
schemas:
|
||||||
|
pizza:
|
||||||
|
properties:
|
||||||
|
something:
|
||||||
|
$ref: '#/components/schemas/something'
|
||||||
|
something:
|
||||||
|
description: something`
|
||||||
|
|
||||||
|
var rootNode yaml.Node
|
||||||
|
yaml.Unmarshal([]byte(yml), &rootNode)
|
||||||
|
|
||||||
|
index := NewSpecIndex(&rootNode)
|
||||||
|
assert.Nil(t, index.performExternalLookup(nil, "unknown", nil, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_lookupRemoteReference_SeenSourceSimulation_Error(t *testing.T) {
|
||||||
|
index := new(SpecIndex)
|
||||||
|
index.seenRemoteSources = make(map[string]*yaml.Node)
|
||||||
|
index.seenRemoteSources["https://no-hope-for-a-dope.com"] = &yaml.Node{}
|
||||||
|
_, _, err := index.lookupRemoteReference("https://no-hope-for-a-dope.com#/$.....#[;]something")
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_lookupRemoteReference_SeenSourceSimulation_BadFind(t *testing.T) {
|
||||||
|
index := new(SpecIndex)
|
||||||
|
index.seenRemoteSources = make(map[string]*yaml.Node)
|
||||||
|
index.seenRemoteSources["https://no-hope-for-a-dope.com"] = &yaml.Node{}
|
||||||
|
a, b, err := index.lookupRemoteReference("https://no-hope-for-a-dope.com#/hey")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Nil(t, a)
|
||||||
|
assert.Nil(t, b)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_lookupRemoteReference_SeenSourceSimulation_BadJSON(t *testing.T) {
|
||||||
|
index := new(SpecIndex)
|
||||||
|
a, b, err := index.lookupRemoteReference("https://google.com#/hey")
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Nil(t, a)
|
||||||
|
assert.Nil(t, b)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_lookupFileReference_BadFileName(t *testing.T) {
|
||||||
|
index := new(SpecIndex)
|
||||||
|
_, _, err := index.lookupFileReference("not-a-reference")
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_lookupFileReference_SeenSourceSimulation_Error(t *testing.T) {
|
||||||
|
index := new(SpecIndex)
|
||||||
|
index.seenRemoteSources = make(map[string]*yaml.Node)
|
||||||
|
index.seenRemoteSources["magic-money-file.json"] = &yaml.Node{}
|
||||||
|
_, _, err := index.lookupFileReference("magic-money-file.json#something")
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_lookupFileReference_BadFile(t *testing.T) {
|
||||||
|
index := new(SpecIndex)
|
||||||
|
_, _, err := index.lookupFileReference("chickers.json#no-rice")
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_lookupFileReference_BadFileDataRead(t *testing.T) {
|
||||||
|
|
||||||
|
_ = ioutil.WriteFile("chickers.yaml", []byte("broke: the: thing: [again]"), 0664)
|
||||||
|
defer os.Remove("chickers.yaml")
|
||||||
|
|
||||||
|
index := new(SpecIndex)
|
||||||
|
_, _, err := index.lookupFileReference("chickers.yaml#no-rice")
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_lookupFileReference_MultiRes(t *testing.T) {
|
||||||
|
|
||||||
|
_ = ioutil.WriteFile("embie.yaml", []byte("naughty:\n - puppy: dog\n - puppy: naughty\npuppy:\n - naughty: puppy"), 0664)
|
||||||
|
defer os.Remove("embie.yaml")
|
||||||
|
|
||||||
|
index := new(SpecIndex)
|
||||||
|
index.seenRemoteSources = make(map[string]*yaml.Node)
|
||||||
|
k, doc, err := index.lookupFileReference("embie.yaml#/.naughty")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, doc)
|
||||||
|
assert.Nil(t, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSpecIndex_lookupFileReference(t *testing.T) {
|
||||||
|
|
||||||
|
_ = ioutil.WriteFile("fox.yaml", []byte("good:\n - puppy: dog\n - puppy: forever-more"), 0664)
|
||||||
|
defer os.Remove("fox.yaml")
|
||||||
|
|
||||||
|
index := new(SpecIndex)
|
||||||
|
index.seenRemoteSources = make(map[string]*yaml.Node)
|
||||||
|
k, doc, err := index.lookupFileReference("fox.yaml#/good")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, doc)
|
||||||
|
assert.NotNil(t, k)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,38 @@ func TestResolver_ResolveComponents_CircularSpec(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResolver_CheckForCircularReferences(t *testing.T) {
|
||||||
|
|
||||||
|
circular, _ := ioutil.ReadFile("../test_specs/circular-tests.yaml")
|
||||||
|
var rootNode yaml.Node
|
||||||
|
yaml.Unmarshal(circular, &rootNode)
|
||||||
|
|
||||||
|
index := index.NewSpecIndex(&rootNode)
|
||||||
|
|
||||||
|
resolver := NewResolver(index)
|
||||||
|
assert.NotNil(t, resolver)
|
||||||
|
|
||||||
|
circ := resolver.CheckForCircularReferences()
|
||||||
|
assert.Len(t, circ, 3)
|
||||||
|
assert.Len(t, resolver.GetResolvingErrors(), 3)
|
||||||
|
assert.Len(t, resolver.GetCircularErrors(), 3)
|
||||||
|
|
||||||
|
_, err := yaml.Marshal(resolver.resolvedRoot)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResolver_DeepJourney(t *testing.T) {
|
||||||
|
|
||||||
|
var journey []*index.Reference
|
||||||
|
for f := 0; f < 200; f++ {
|
||||||
|
journey = append(journey, nil)
|
||||||
|
}
|
||||||
|
index := index.NewSpecIndex(nil)
|
||||||
|
resolver := NewResolver(index)
|
||||||
|
assert.Nil(t, resolver.extractRelatives(nil, nil, journey, false))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestResolver_ResolveComponents_Stripe(t *testing.T) {
|
func TestResolver_ResolveComponents_Stripe(t *testing.T) {
|
||||||
|
|
||||||
stripe, _ := ioutil.ReadFile("../test_specs/stripe.yaml")
|
stripe, _ := ioutil.ReadFile("../test_specs/stripe.yaml")
|
||||||
@@ -60,6 +92,57 @@ func TestResolver_ResolveComponents_Stripe(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResolver_ResolveComponents_BurgerShop(t *testing.T) {
|
||||||
|
|
||||||
|
mixedref, _ := ioutil.ReadFile("../test_specs/burgershop.openapi.yaml")
|
||||||
|
var rootNode yaml.Node
|
||||||
|
yaml.Unmarshal(mixedref, &rootNode)
|
||||||
|
|
||||||
|
index := index.NewSpecIndex(&rootNode)
|
||||||
|
|
||||||
|
resolver := NewResolver(index)
|
||||||
|
assert.NotNil(t, resolver)
|
||||||
|
|
||||||
|
circ := resolver.Resolve()
|
||||||
|
assert.Len(t, circ, 0)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResolver_ResolveComponents_PolyNonCircRef(t *testing.T) {
|
||||||
|
|
||||||
|
yml := `paths:
|
||||||
|
/hey:
|
||||||
|
get:
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
$ref: '#/components/schemas/crackers'
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
cheese:
|
||||||
|
description: cheese
|
||||||
|
anyOf:
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/crackers'
|
||||||
|
crackers:
|
||||||
|
description: crackers
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/tea'
|
||||||
|
tea:
|
||||||
|
description: tea`
|
||||||
|
|
||||||
|
var rootNode yaml.Node
|
||||||
|
yaml.Unmarshal([]byte(yml), &rootNode)
|
||||||
|
|
||||||
|
index := index.NewSpecIndex(&rootNode)
|
||||||
|
|
||||||
|
resolver := NewResolver(index)
|
||||||
|
assert.NotNil(t, resolver)
|
||||||
|
|
||||||
|
circ := resolver.CheckForCircularReferences()
|
||||||
|
assert.Len(t, circ, 0)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestResolver_ResolveComponents_MixedRef(t *testing.T) {
|
func TestResolver_ResolveComponents_MixedRef(t *testing.T) {
|
||||||
|
|
||||||
mixedref, _ := ioutil.ReadFile("../test_specs/mixedref-burgershop.openapi.yaml")
|
mixedref, _ := ioutil.ReadFile("../test_specs/mixedref-burgershop.openapi.yaml")
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const (
|
|||||||
KebabCase
|
KebabCase
|
||||||
ScreamingKebabCase
|
ScreamingKebabCase
|
||||||
RegularCase
|
RegularCase
|
||||||
|
UnknownCase
|
||||||
)
|
)
|
||||||
|
|
||||||
// FindNodes will find a node based on JSONPath, it accepts raw yaml/json as input.
|
// FindNodes will find a node based on JSONPath, it accepts raw yaml/json as input.
|
||||||
@@ -169,7 +170,7 @@ func FindFirstKeyNode(key string, nodes []*yaml.Node, depth int) (keyNode *yaml.
|
|||||||
for i, v := range nodes {
|
for i, v := range nodes {
|
||||||
if key != "" && key == v.Value {
|
if key != "" && key == v.Value {
|
||||||
if i+1 >= len(nodes) {
|
if i+1 >= len(nodes) {
|
||||||
return v, nodes[i] // next node is what we need.
|
return v, nodes[i] // this is the node we need.
|
||||||
}
|
}
|
||||||
return v, nodes[i+1] // next node is what we need.
|
return v, nodes[i+1] // next node is what we need.
|
||||||
}
|
}
|
||||||
@@ -239,21 +240,23 @@ func FindKeyNode(key string, nodes []*yaml.Node) (keyNode *yaml.Node, valueNode
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindKeyNodeFull is an overloaded version of FindKeyNode. Thins version however returns keys, labels and values.
|
||||||
|
// generally different things are required from different node trees, so depending on what this function is looking at
|
||||||
|
// it will return different things.
|
||||||
func FindKeyNodeFull(key string, nodes []*yaml.Node) (keyNode *yaml.Node, labelNode *yaml.Node, valueNode *yaml.Node) {
|
func FindKeyNodeFull(key string, nodes []*yaml.Node) (keyNode *yaml.Node, labelNode *yaml.Node, valueNode *yaml.Node) {
|
||||||
for i, v := range nodes {
|
for i := range nodes {
|
||||||
if i%2 == 0 && key == v.Value {
|
if i%2 == 0 && key == nodes[i].Value {
|
||||||
return v, nodes[i], nodes[i+1] // next node is what we need.
|
return nodes[i], nodes[i], nodes[i+1] // next node is what we need.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, v := range nodes {
|
for _, v := range nodes {
|
||||||
for x, j := range v.Content {
|
for x := range v.Content {
|
||||||
if key == j.Value {
|
if key == v.Content[x].Value {
|
||||||
if IsNodeMap(v) {
|
if IsNodeMap(v) {
|
||||||
if x+1 == len(v.Content) {
|
if x+1 == len(v.Content) {
|
||||||
return v, v.Content[x], v.Content[x]
|
return v, v.Content[x], v.Content[x]
|
||||||
}
|
}
|
||||||
return v, v.Content[x], v.Content[x+1] // next node is what we need.
|
return v, v.Content[x], v.Content[x+1]
|
||||||
|
|
||||||
}
|
}
|
||||||
if IsNodeArray(v) {
|
if IsNodeArray(v) {
|
||||||
return v, v.Content[x], v.Content[x]
|
return v, v.Content[x], v.Content[x]
|
||||||
@@ -356,14 +359,6 @@ func IsNodeIntValue(node *yaml.Node) bool {
|
|||||||
return node.Tag == "!!int"
|
return node.Tag == "!!int"
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNodeNullValue Checks of the input is null or not.
|
|
||||||
func IsNodeNullValue(node *yaml.Node) bool {
|
|
||||||
if node == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return node.Tag == "!!null"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNodeFloatValue will check is a node is a float value.
|
// IsNodeFloatValue will check is a node is a float value.
|
||||||
func IsNodeFloatValue(node *yaml.Node) bool {
|
func IsNodeFloatValue(node *yaml.Node) bool {
|
||||||
if node == nil {
|
if node == nil {
|
||||||
@@ -539,7 +534,7 @@ func ConvertCase(input string, convert Case) string {
|
|||||||
func DetectCase(input string) Case {
|
func DetectCase(input string) Case {
|
||||||
trim := strings.TrimSpace(input)
|
trim := strings.TrimSpace(input)
|
||||||
if trim == "" {
|
if trim == "" {
|
||||||
return -1
|
return UnknownCase
|
||||||
}
|
}
|
||||||
|
|
||||||
pascalCase := regexp.MustCompile("^[A-Z][a-z]+(?:[A-Z][a-z]+)*$")
|
pascalCase := regexp.MustCompile("^[A-Z][a-z]+(?:[A-Z][a-z]+)*$")
|
||||||
|
|||||||
@@ -30,7 +30,15 @@ func TestRenderCodeSnippet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
rendered := RenderCodeSnippet(startNode, code, 1, 3)
|
rendered := RenderCodeSnippet(startNode, code, 1, 3)
|
||||||
assert.Equal(t, "hey\nho\nlet's\n", rendered)
|
assert.Equal(t, "hey\nho\nlet's\n", rendered)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderCodeSnippet_BelowStart(t *testing.T) {
|
||||||
|
code := []string{"hey", "ho", "let's", "go!"}
|
||||||
|
startNode := &yaml.Node{
|
||||||
|
Line: 0,
|
||||||
|
}
|
||||||
|
rendered := RenderCodeSnippet(startNode, code, 1, 3)
|
||||||
|
assert.Equal(t, "hey\nho\nlet's\n", rendered)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindNodes(t *testing.T) {
|
func TestFindNodes(t *testing.T) {
|
||||||
@@ -221,6 +229,29 @@ func TestFindFirstKeyNode_NotFound(t *testing.T) {
|
|||||||
assert.Nil(t, value)
|
assert.Nil(t, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFindFirstKeyNode_TooDeep(t *testing.T) {
|
||||||
|
a, b := FindFirstKeyNode("", nil, 900)
|
||||||
|
assert.Nil(t, a)
|
||||||
|
assert.Nil(t, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindFirstKeyNode_ValueIsKey(t *testing.T) {
|
||||||
|
|
||||||
|
a := &yaml.Node{
|
||||||
|
Value: "chicken",
|
||||||
|
}
|
||||||
|
|
||||||
|
b := &yaml.Node{
|
||||||
|
Value: "nuggets",
|
||||||
|
Content: []*yaml.Node{a},
|
||||||
|
}
|
||||||
|
|
||||||
|
c, d := FindFirstKeyNode("nuggets", []*yaml.Node{b}, 0)
|
||||||
|
assert.NotNil(t, c)
|
||||||
|
assert.NotNil(t, d)
|
||||||
|
assert.Equal(t, c, d)
|
||||||
|
}
|
||||||
|
|
||||||
func TestFindFirstKeyNode_Map(t *testing.T) {
|
func TestFindFirstKeyNode_Map(t *testing.T) {
|
||||||
nodes, _ := FindNodes(getPetstore(), "$")
|
nodes, _ := FindNodes(getPetstore(), "$")
|
||||||
key, value := FindFirstKeyNode("pet", nodes, 0)
|
key, value := FindFirstKeyNode("pet", nodes, 0)
|
||||||
@@ -252,6 +283,140 @@ func TestFindKeyNode(t *testing.T) {
|
|||||||
assert.Equal(t, 47, k.Line)
|
assert.Equal(t, 47, k.Line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFindKeyNode_ValueIsKey(t *testing.T) {
|
||||||
|
|
||||||
|
a := &yaml.Node{
|
||||||
|
Value: "chicken",
|
||||||
|
}
|
||||||
|
|
||||||
|
b := &yaml.Node{
|
||||||
|
Tag: "!!map",
|
||||||
|
Value: "nuggets",
|
||||||
|
Content: []*yaml.Node{a},
|
||||||
|
}
|
||||||
|
|
||||||
|
c, d := FindKeyNode("nuggets", []*yaml.Node{b, a})
|
||||||
|
assert.Equal(t, "nuggets", c.Value)
|
||||||
|
assert.Equal(t, "chicken", d.Value)
|
||||||
|
|
||||||
|
e := &yaml.Node{
|
||||||
|
Value: "pizza",
|
||||||
|
}
|
||||||
|
f := &yaml.Node{
|
||||||
|
Value: "pie",
|
||||||
|
}
|
||||||
|
b.Content = append(b.Content, e, f)
|
||||||
|
|
||||||
|
c, d = FindKeyNode("pie", []*yaml.Node{b, a})
|
||||||
|
assert.Equal(t, "nuggets", c.Value)
|
||||||
|
assert.Equal(t, "pie", d.Value)
|
||||||
|
|
||||||
|
b.Tag = "!!seq"
|
||||||
|
|
||||||
|
c, d = FindKeyNode("pie", []*yaml.Node{b, a})
|
||||||
|
assert.Equal(t, "nuggets", c.Value)
|
||||||
|
assert.Equal(t, "pie", d.Value)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindExtensionNodes(t *testing.T) {
|
||||||
|
|
||||||
|
a := &yaml.Node{
|
||||||
|
Value: "x-coffee",
|
||||||
|
}
|
||||||
|
b := &yaml.Node{
|
||||||
|
Value: "required",
|
||||||
|
}
|
||||||
|
c := &yaml.Node{
|
||||||
|
Content: []*yaml.Node{a, b},
|
||||||
|
}
|
||||||
|
exts := FindExtensionNodes(c.Content)
|
||||||
|
assert.Len(t, exts, 1)
|
||||||
|
assert.Equal(t, "required", exts[0].Value.Value)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindKeyNodeFull(t *testing.T) {
|
||||||
|
|
||||||
|
a := &yaml.Node{
|
||||||
|
Value: "fish",
|
||||||
|
}
|
||||||
|
b := &yaml.Node{
|
||||||
|
Value: "paste",
|
||||||
|
}
|
||||||
|
|
||||||
|
c, d, e := FindKeyNodeFull("fish", []*yaml.Node{a, b})
|
||||||
|
assert.Equal(t, "fish", c.Value)
|
||||||
|
assert.Equal(t, "fish", d.Value)
|
||||||
|
assert.Equal(t, "paste", e.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindKeyNodeFull_MapValueIsLastNode(t *testing.T) {
|
||||||
|
|
||||||
|
f := &yaml.Node{
|
||||||
|
Value: "cheese",
|
||||||
|
}
|
||||||
|
h := &yaml.Node{
|
||||||
|
Tag: "!!map",
|
||||||
|
Value: "deserts", // this is invalid btw, but helps with mechanical understanding
|
||||||
|
Content: []*yaml.Node{f},
|
||||||
|
}
|
||||||
|
|
||||||
|
c, d, e := FindKeyNodeFull("cheese", []*yaml.Node{h})
|
||||||
|
assert.Equal(t, "deserts", c.Value)
|
||||||
|
assert.Equal(t, "cheese", d.Value)
|
||||||
|
assert.Equal(t, "cheese", e.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindKeyNodeFull_Map(t *testing.T) {
|
||||||
|
|
||||||
|
f := &yaml.Node{
|
||||||
|
Value: "cheese",
|
||||||
|
}
|
||||||
|
g := &yaml.Node{
|
||||||
|
Value: "cake",
|
||||||
|
}
|
||||||
|
h := &yaml.Node{
|
||||||
|
Tag: "!!map",
|
||||||
|
Value: "deserts", // this is invalid btw, but helps with mechanical understanding
|
||||||
|
Content: []*yaml.Node{f, g},
|
||||||
|
}
|
||||||
|
|
||||||
|
c, d, e := FindKeyNodeFull("cheese", []*yaml.Node{h})
|
||||||
|
assert.Equal(t, "deserts", c.Value)
|
||||||
|
assert.Equal(t, "cheese", d.Value)
|
||||||
|
assert.Equal(t, "cake", e.Value)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindKeyNodeFull_Array(t *testing.T) {
|
||||||
|
|
||||||
|
f := &yaml.Node{
|
||||||
|
Value: "cheese",
|
||||||
|
}
|
||||||
|
g := &yaml.Node{
|
||||||
|
Value: "cake",
|
||||||
|
}
|
||||||
|
h := &yaml.Node{
|
||||||
|
Tag: "!!seq",
|
||||||
|
Value: "deserts", // this is invalid btw, but helps with mechanical understanding
|
||||||
|
Content: []*yaml.Node{f, g},
|
||||||
|
}
|
||||||
|
|
||||||
|
c, d, e := FindKeyNodeFull("cheese", []*yaml.Node{h})
|
||||||
|
assert.Equal(t, "deserts", c.Value)
|
||||||
|
assert.Equal(t, "cheese", d.Value)
|
||||||
|
assert.Equal(t, "cheese", e.Value)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindKeyNodeFull_Nothing(t *testing.T) {
|
||||||
|
c, d, e := FindKeyNodeFull("cheese", []*yaml.Node{})
|
||||||
|
assert.Nil(t, c)
|
||||||
|
assert.Nil(t, d)
|
||||||
|
assert.Nil(t, e)
|
||||||
|
}
|
||||||
|
|
||||||
func TestFindKeyNode_NotFound(t *testing.T) {
|
func TestFindKeyNode_NotFound(t *testing.T) {
|
||||||
nodes, _ := FindNodes(getPetstore(), "$")
|
nodes, _ := FindNodes(getPetstore(), "$")
|
||||||
k, v := FindKeyNode("I am not anything at all", nodes[0].Content)
|
k, v := FindKeyNode("I am not anything at all", nodes[0].Content)
|
||||||
@@ -414,6 +579,12 @@ func TestConvertComponentIdIntoFriendlyPathSearch(t *testing.T) {
|
|||||||
assert.Equal(t, "cake", segment)
|
assert.Equal(t, "cake", segment)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConvertComponentIdIntoFriendlyPathSearch_WithRootSymbol(t *testing.T) {
|
||||||
|
segment, path := ConvertComponentIdIntoFriendlyPathSearch("/chicken/chips/pizza/cake")
|
||||||
|
assert.Equal(t, "$.chicken.chips.pizza['cake']", path)
|
||||||
|
assert.Equal(t, "cake", segment)
|
||||||
|
}
|
||||||
|
|
||||||
func TestConvertComponentIdIntoPath(t *testing.T) {
|
func TestConvertComponentIdIntoPath(t *testing.T) {
|
||||||
segment, path := ConvertComponentIdIntoPath("#/chicken/chips/pizza/cake")
|
segment, path := ConvertComponentIdIntoPath("#/chicken/chips/pizza/cake")
|
||||||
assert.Equal(t, "$.chicken.chips.pizza.cake", path)
|
assert.Equal(t, "$.chicken.chips.pizza.cake", path)
|
||||||
@@ -439,3 +610,52 @@ func TestConvertCase(t *testing.T) {
|
|||||||
assert.Equal(t, "CHICKEN-NUGGETS-CHICKEN-SOUP", ConvertCase(str1, ScreamingKebabCase))
|
assert.Equal(t, "CHICKEN-NUGGETS-CHICKEN-SOUP", ConvertCase(str1, ScreamingKebabCase))
|
||||||
assert.Equal(t, "CHICKEN_NUGGETS_CHICKEN_SOUP", ConvertCase(str1, ScreamingSnakeCase))
|
assert.Equal(t, "CHICKEN_NUGGETS_CHICKEN_SOUP", ConvertCase(str1, ScreamingSnakeCase))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConvertCase_NoInput(t *testing.T) {
|
||||||
|
assert.Empty(t, ConvertCase("", ScreamingKebabCase))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDetectCase_NoInput(t *testing.T) {
|
||||||
|
assert.Equal(t, UnknownCase, DetectCase(""))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsNodeRefValue(t *testing.T) {
|
||||||
|
|
||||||
|
f := &yaml.Node{
|
||||||
|
Value: "$ref",
|
||||||
|
}
|
||||||
|
g := &yaml.Node{
|
||||||
|
Value: "'#/somewhere/out-there'",
|
||||||
|
}
|
||||||
|
h := &yaml.Node{
|
||||||
|
Tag: "!!map",
|
||||||
|
Content: []*yaml.Node{f, g},
|
||||||
|
}
|
||||||
|
|
||||||
|
ref, node, val := IsNodeRefValue(h)
|
||||||
|
|
||||||
|
assert.True(t, ref)
|
||||||
|
assert.Equal(t, "$ref", node.Value)
|
||||||
|
assert.Equal(t, "'#/somewhere/out-there'", val)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsNodeRefValue_False(t *testing.T) {
|
||||||
|
|
||||||
|
f := &yaml.Node{
|
||||||
|
Value: "woof",
|
||||||
|
}
|
||||||
|
g := &yaml.Node{
|
||||||
|
Value: "dog",
|
||||||
|
}
|
||||||
|
h := &yaml.Node{
|
||||||
|
Tag: "!!map",
|
||||||
|
Content: []*yaml.Node{f, g},
|
||||||
|
}
|
||||||
|
|
||||||
|
ref, node, val := IsNodeRefValue(h)
|
||||||
|
|
||||||
|
assert.False(t, ref)
|
||||||
|
assert.Nil(t, node)
|
||||||
|
assert.Empty(t, val)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user