Skip to content

Commit

Permalink
openapi3: reference originating locations in YAML specs - step 2 (#1024)
Browse files Browse the repository at this point in the history
* add origin to example

* remove unneeded test

* add origin to xml

* document origin extra field in example
  • Loading branch information
reuvenharrison authored Oct 23, 2024
1 parent c333b34 commit 7145b2c
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 22 deletions.
2 changes: 2 additions & 0 deletions .github/docs/openapi3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ func (encoding *Encoding) WithHeaderRef(name string, ref *HeaderRef) *Encoding

type Example struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`

Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
Expand Down Expand Up @@ -2240,6 +2241,7 @@ type ValidationOptions struct {

type XML struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`

Name string `json:"name,omitempty" yaml:"name,omitempty"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
Expand Down
2 changes: 2 additions & 0 deletions openapi3/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#example-object
type Example struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`

Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
Expand Down Expand Up @@ -59,6 +60,7 @@ func (example *Example) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "summary")
delete(x.Extensions, "description")
delete(x.Extensions, "value")
Expand Down
91 changes: 69 additions & 22 deletions openapi3/origin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,11 @@ package openapi3

import (
"context"
"fmt"
"os"
"testing"

"github.com/stretchr/testify/require"
)

func TestOrigin_All(t *testing.T) {
loader := NewLoader()
loader.IsExternalRefsAllowed = true
loader.IncludeOrigin = true
loader.Context = context.Background()

const dir = "testdata/origin/"
items, _ := os.ReadDir(dir)
for _, item := range items {
t.Run(item.Name(), func(t *testing.T) {
doc, err := loader.LoadFromFile(fmt.Sprintf("%s/%s", dir, item.Name()))
require.NoError(t, err)
if doc.Paths == nil {
t.Skip("no paths")
}
require.NotEmpty(t, doc.Paths.Origin)
})
}
}

func TestOrigin_Info(t *testing.T) {
loader := NewLoader()
loader.IsExternalRefsAllowed = true
Expand Down Expand Up @@ -301,3 +279,72 @@ func TestOrigin_Security(t *testing.T) {
},
base.Flows.Implicit.Origin.Fields["authorizationUrl"])
}

func TestOrigin_Example(t *testing.T) {
loader := NewLoader()
loader.IsExternalRefsAllowed = true
loader.IncludeOrigin = true
loader.Context = context.Background()

doc, err := loader.LoadFromFile("testdata/origin/example.yaml")
require.NoError(t, err)

base := doc.Paths.Find("/subscribe").Post.RequestBody.Value.Content["application/json"].Examples["bar"].Value
require.NotNil(t, base.Origin)
require.Equal(t,
&Location{
Line: 14,
Column: 15,
},
base.Origin.Key)

require.Equal(t,
Location{
Line: 15,
Column: 17,
},
base.Origin.Fields["summary"])

// Note:
// Example.Value contains an extra field: "origin".
//
// Explanation:
// The example value is defined in the original yaml file as a json object: {"bar": "baz"}
// This json object is also valid in YAML, so yaml.3 decodes it as a map and adds an "origin" field.
require.Contains(t,
base.Value,
originKey)
}

func TestOrigin_XML(t *testing.T) {
loader := NewLoader()
loader.IsExternalRefsAllowed = true
loader.IncludeOrigin = true
loader.Context = context.Background()

doc, err := loader.LoadFromFile("testdata/origin/xml.yaml")
require.NoError(t, err)

base := doc.Paths.Find("/subscribe").Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties["name"].Value.XML
require.NotNil(t, base.Origin)
require.Equal(t,
&Location{
Line: 21,
Column: 19,
},
base.Origin.Key)

require.Equal(t,
Location{
Line: 22,
Column: 21,
},
base.Origin.Fields["namespace"])

require.Equal(t,
Location{
Line: 23,
Column: 21,
},
base.Origin.Fields["prefix"])
}
19 changes: 19 additions & 0 deletions openapi3/testdata/origin/example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
openapi: 3.0.0
info:
title: Security Requirement Example
version: 1.0.0
paths:
/subscribe:
post:
requestBody:
content:
application/json:
schema:
type: object
examples:
bar:
summary: A bar example
value: {"bar": "baz"}
responses:
"200":
description: OK
26 changes: 26 additions & 0 deletions openapi3/testdata/origin/xml.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
openapi: 3.0.0
info:
title: Security Requirement Example
version: 1.0.0
paths:
/subscribe:
post:
requestBody:
content:
application/json:
schema:
type: object
properties:
id:
type: integer
format: int32
xml:
attribute: true
name:
type: string
xml:
namespace: http://example.com/schema/sample
prefix: sample
responses:
"200":
description: OK
2 changes: 2 additions & 0 deletions openapi3/xml.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#xml-object
type XML struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"origin,omitempty" yaml:"origin,omitempty"`

Name string `json:"name,omitempty" yaml:"name,omitempty"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
Expand Down Expand Up @@ -58,6 +59,7 @@ func (xml *XML) UnmarshalJSON(data []byte) error {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, originKey)
delete(x.Extensions, "name")
delete(x.Extensions, "namespace")
delete(x.Extensions, "prefix")
Expand Down

0 comments on commit 7145b2c

Please sign in to comment.