1 package replace
2
3 import (
4 "path/filepath"
5 "testing"
6
7 "github.com/go-openapi/analysis/internal/antest"
8 "github.com/go-openapi/jsonpointer"
9 "github.com/go-openapi/spec"
10 "github.com/stretchr/testify/assert"
11 "github.com/stretchr/testify/require"
12 )
13
14 var refFixtures = []struct {
15 Key string
16 Ref spec.Ref
17 }{
18 {"#/parameters/someParam/schema", spec.MustCreateRef("#/definitions/record")},
19 {"#/paths/~1some~1where~1{id}/parameters/1/schema", spec.MustCreateRef("#/definitions/record")},
20 {"#/paths/~1some~1where~1{id}/get/parameters/2/schema", spec.MustCreateRef("#/definitions/record")},
21 {"#/responses/someResponse/schema", spec.MustCreateRef("#/definitions/record")},
22 {"#/paths/~1some~1where~1{id}/get/responses/default/schema", spec.MustCreateRef("#/definitions/record")},
23 {"#/paths/~1some~1where~1{id}/get/responses/200/schema", spec.MustCreateRef("#/definitions/record")},
24 {"#/definitions/namedAgain", spec.MustCreateRef("#/definitions/named")},
25 {"#/definitions/datedTag/allOf/1", spec.MustCreateRef("#/definitions/tag")},
26 {"#/definitions/datedRecords/items/1", spec.MustCreateRef("#/definitions/record")},
27 {"#/definitions/datedTaggedRecords/items/1", spec.MustCreateRef("#/definitions/record")},
28 {"#/definitions/datedTaggedRecords/additionalItems", spec.MustCreateRef("#/definitions/tag")},
29 {"#/definitions/otherRecords/items", spec.MustCreateRef("#/definitions/record")},
30 {"#/definitions/tags/additionalProperties", spec.MustCreateRef("#/definitions/tag")},
31 {"#/definitions/namedThing/properties/name", spec.MustCreateRef("#/definitions/named")},
32 }
33
34 func TestUpdateRef(t *testing.T) {
35 t.Parallel()
36
37 bp := filepath.Join("..", "..", "..", "fixtures", "external_definitions.yml")
38 sp := antest.LoadOrFail(t, bp)
39
40 for _, v := range refFixtures {
41 err := UpdateRef(sp, v.Key, v.Ref)
42 require.NoError(t, err)
43
44 ptr, err := jsonpointer.New(v.Key[1:])
45 require.NoError(t, err)
46
47 vv, _, err := ptr.Get(sp)
48 require.NoError(t, err)
49
50 switch tv := vv.(type) {
51 case *spec.Schema:
52 assert.Equal(t, v.Ref.String(), tv.Ref.String())
53 case spec.Schema:
54 assert.Equal(t, v.Ref.String(), tv.Ref.String())
55 case *spec.SchemaOrBool:
56 assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String())
57 case *spec.SchemaOrArray:
58 assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String())
59 default:
60 assert.Fail(t, "unknown type", "got %T", vv)
61 }
62 }
63 }
64
65 func TestRewriteSchemaRef(t *testing.T) {
66 t.Parallel()
67
68 bp := filepath.Join("..", "..", "..", "fixtures", "inline_schemas.yml")
69 sp := antest.LoadOrFail(t, bp)
70
71 for i, v := range refFixtures {
72 err := RewriteSchemaToRef(sp, v.Key, v.Ref)
73 require.NoError(t, err)
74
75 ptr, err := jsonpointer.New(v.Key[1:])
76 require.NoError(t, err)
77
78 vv, _, err := ptr.Get(sp)
79 require.NoError(t, err)
80
81 switch tv := vv.(type) {
82 case *spec.Schema:
83 assert.Equal(t, v.Ref.String(), tv.Ref.String(), "at %d for %s", i, v.Key)
84 case spec.Schema:
85 assert.Equal(t, v.Ref.String(), tv.Ref.String(), "at %d for %s", i, v.Key)
86 case *spec.SchemaOrBool:
87 assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String(), "at %d for %s", i, v.Key)
88 case *spec.SchemaOrArray:
89 assert.Equal(t, v.Ref.String(), tv.Schema.Ref.String(), "at %d for %s", i, v.Key)
90 default:
91 assert.Fail(t, "unknown type", "got %T", vv)
92 }
93 }
94 }
95
96 func TestReplace_ErrorHandling(t *testing.T) {
97 t.Parallel()
98
99 const wantedFailure = "expected a failure"
100 bp := filepath.Join("..", "..", "..", "fixtures", "errors", "fixture-unexpandable-2.yaml")
101 sp := antest.LoadOrFail(t, bp)
102
103 t.Run("with invalid $ref", func(t *testing.T) {
104 const ref = "#/invalidPointer/key"
105
106 require.Errorf(t, RewriteSchemaToRef(sp, ref, spec.Ref{}), wantedFailure)
107 require.Errorf(t, rewriteParentRef(sp, ref, spec.Ref{}), wantedFailure)
108 require.Errorf(t, UpdateRef(sp, ref, spec.Ref{}), wantedFailure)
109 require.Errorf(t, UpdateRefWithSchema(sp, ref, &spec.Schema{}), wantedFailure)
110 _, _, err := getPointerFromKey(sp, ref)
111 require.Errorf(t, err, wantedFailure)
112
113 _, _, _, err = getParentFromKey(sp, ref)
114 require.Errorf(t, err, wantedFailure)
115 })
116
117 t.Run("with invalid jsonpointer formatting", func(t *testing.T) {
118 const pointer = "-->#/invalidJsonPointer"
119
120 _, _, err := getPointerFromKey(sp, pointer)
121 require.Errorf(t, err, wantedFailure)
122
123 _, _, _, err = getParentFromKey(sp, pointer)
124 require.Errorf(t, err, wantedFailure)
125 })
126
127 t.Run("with invalid target", func(t *testing.T) {
128 require.Errorf(t, RewriteSchemaToRef(sp, "#/parameters/someWhere", spec.Ref{}), wantedFailure)
129 })
130
131 t.Run("with invalid response target", func(t *testing.T) {
132 const ref = "#/paths/~1wrong/get/responses/200"
133 require.Errorf(t, RewriteSchemaToRef(sp, ref, spec.Ref{}), wantedFailure)
134 })
135
136 t.Run("with invalid response code", func(t *testing.T) {
137 const ref = "#/paths/~1wrongcode/get/responses/two-hundred"
138 require.Errorf(t, rewriteParentRef(sp, ref, spec.Ref{}), wantedFailure)
139 })
140
141 t.Run("with panic case", func(t *testing.T) {
142 t.Run("should not call with types other than *Schema or *Swagger", func(t *testing.T) {
143 require.Panics(t, func() {
144 _, _, _ = getPointerFromKey("oops", "#/key")
145 })
146
147 require.Panics(t, func() {
148 _, _, _, _ = getParentFromKey("oops", "#/key")
149 })
150
151 require.Panics(t, func() {
152 _ = UpdateRef("oops", "#/key", spec.Ref{})
153 })
154 })
155 })
156 }
157
View as plain text