1 package spec
2
3 import (
4 "encoding/json"
5 "net/http"
6 "net/http/httptest"
7 "os"
8 "path/filepath"
9 "testing"
10
11 "github.com/go-openapi/jsonpointer"
12 "github.com/stretchr/testify/assert"
13 "github.com/stretchr/testify/require"
14 )
15
16 func TestResolveRef(t *testing.T) {
17 var root interface{}
18 require.NoError(t, json.Unmarshal([]byte(PetStore20), &root))
19
20 ref, err := NewRef("#/definitions/Category")
21 require.NoError(t, err)
22
23 sch, err := ResolveRef(root, &ref)
24 require.NoError(t, err)
25
26 b, err := sch.MarshalJSON()
27 require.NoError(t, err)
28
29 assert.JSONEq(t, `{"id":"Category","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}}}`, string(b))
30
31
32 sch, err = ResolveRefWithBase(root, &ref, &ExpandOptions{
33 RelativeBase: "/",
34 })
35 require.NoError(t, err)
36
37 b, err = sch.MarshalJSON()
38 require.NoError(t, err)
39
40 assert.JSONEq(t, `{"id":"Category","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}}}`, string(b))
41 }
42
43 func TestResolveResponse(t *testing.T) {
44 specDoc, err := jsonDoc(filepath.Join("fixtures", "expansion", "all-the-things.json"))
45 require.NoError(t, err)
46
47 spec := new(Swagger)
48 require.NoError(t, json.Unmarshal(specDoc, spec))
49
50
51 resp := spec.Paths.Paths["/"].Get.Responses.StatusCodeResponses[200]
52 resp2, err := ResolveResponse(spec, resp.Ref)
53 require.NoError(t, err)
54
55
56 jazon := asJSON(t, resp2)
57
58 assert.JSONEq(t, `{
59 "$ref": "#/responses/petResponse"
60 }`, jazon)
61 }
62
63 func TestResolveResponseWithBase(t *testing.T) {
64 specDoc, err := jsonDoc(crossFileRefFixture)
65 require.NoError(t, err)
66
67 spec := new(Swagger)
68 require.NoError(t, json.Unmarshal(specDoc, spec))
69
70
71 resp := spec.Paths.Paths["/"].Get.Responses.StatusCodeResponses[200]
72 resp2, err := ResolveResponseWithBase(spec, resp.Ref, &ExpandOptions{RelativeBase: crossFileRefFixture})
73 require.NoError(t, err)
74
75
76 jazon := asJSON(t, resp2)
77
78 assert.JSONEq(t, `{
79 "$ref": "#/responses/petResponse"
80 }`, jazon)
81 }
82
83 func TestResolveParam(t *testing.T) {
84 specDoc, err := jsonDoc(filepath.Join("fixtures", "expansion", "all-the-things.json"))
85 require.NoError(t, err)
86
87 var spec Swagger
88 require.NoError(t, json.Unmarshal(specDoc, &spec))
89
90 param := spec.Paths.Paths["/pets/{id}"].Get.Parameters[0]
91 par, err := ResolveParameter(spec, param.Ref)
92 require.NoError(t, err)
93
94 jazon := asJSON(t, par)
95
96 assert.JSONEq(t, `{
97 "name": "id",
98 "in": "path",
99 "description": "ID of pet to fetch",
100 "required": true,
101 "type": "integer",
102 "format": "int64"
103 }`, jazon)
104 }
105
106 func TestResolveParamWithBase(t *testing.T) {
107 specDoc, err := jsonDoc(crossFileRefFixture)
108 require.NoError(t, err)
109
110 var spec Swagger
111 require.NoError(t, json.Unmarshal(specDoc, &spec))
112
113 param := spec.Paths.Paths["/pets"].Get.Parameters[0]
114 par, err := ResolveParameterWithBase(spec, param.Ref, &ExpandOptions{RelativeBase: crossFileRefFixture})
115 require.NoError(t, err)
116
117 jazon := asJSON(t, par)
118
119 assert.JSONEq(t, `{
120 "description":"ID of pet to fetch",
121 "format":"int64",
122 "in":"path",
123 "name":"id",
124 "required":true,
125 "type":"integer"
126 }`, jazon)
127 }
128
129 func TestResolveRemoteRef_RootSame(t *testing.T) {
130 fileserver := http.FileServer(http.Dir(specs))
131 server := httptest.NewServer(fileserver)
132 defer server.Close()
133
134 rootDoc := new(Swagger)
135 b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
136 require.NoError(t, err)
137 require.NoError(t, json.Unmarshal(b, rootDoc))
138
139
140 specBase := normalizeBase(filepath.Join(specs, "anyotherfile.json"))
141
142 var result0 Swagger
143 ref0, _ := NewRef(server.URL + "/refed.json#")
144 resolver0 := defaultSchemaLoader(rootDoc, nil, nil, nil)
145 require.NoError(t, resolver0.Resolve(&ref0, &result0, ""))
146 assertSpecs(t, result0, *rootDoc)
147
148 var result1 Swagger
149 ref1, _ := NewRef("./refed.json")
150 resolver1 := defaultSchemaLoader(rootDoc, &ExpandOptions{
151 RelativeBase: specBase,
152 }, nil, nil)
153 require.NoError(t, resolver1.Resolve(&ref1, &result1, specBase))
154 assertSpecs(t, result1, *rootDoc)
155 }
156
157 func TestResolveRemoteRef_FromFragment(t *testing.T) {
158 fileserver := http.FileServer(http.Dir(specs))
159 server := httptest.NewServer(fileserver)
160 defer server.Close()
161
162 rootDoc := new(Swagger)
163 b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
164 require.NoError(t, err)
165 require.NoError(t, json.Unmarshal(b, rootDoc))
166
167 var tgt Schema
168 ref, err := NewRef(server.URL + "/refed.json#/definitions/pet")
169 require.NoError(t, err)
170
171 context := newResolverContext(&ExpandOptions{PathLoader: jsonDoc})
172 resolver := &schemaLoader{root: rootDoc, cache: defaultResolutionCache(), context: context}
173 require.NoError(t, resolver.Resolve(&ref, &tgt, ""))
174 assert.Equal(t, []string{"id", "name"}, tgt.Required)
175 }
176
177 func TestResolveRemoteRef_FromInvalidFragment(t *testing.T) {
178 fileserver := http.FileServer(http.Dir(specs))
179 server := httptest.NewServer(fileserver)
180 defer server.Close()
181
182 rootDoc := new(Swagger)
183 b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
184 require.NoError(t, err)
185 require.NoError(t, json.Unmarshal(b, rootDoc))
186
187 var tgt Schema
188 ref, err := NewRef(server.URL + "/refed.json#/definitions/NotThere")
189 require.NoError(t, err)
190
191 resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
192 require.Error(t, resolver.Resolve(&ref, &tgt, ""))
193 }
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214 func TestResolveRemoteRef_ToParameter(t *testing.T) {
215 fileserver := http.FileServer(http.Dir(specs))
216 server := httptest.NewServer(fileserver)
217 defer server.Close()
218
219 rootDoc := new(Swagger)
220 b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
221 require.NoError(t, err)
222 require.NoError(t, json.Unmarshal(b, rootDoc))
223
224 var tgt Parameter
225 ref, err := NewRef(server.URL + "/refed.json#/parameters/idParam")
226 require.NoError(t, err)
227
228 resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
229 require.NoError(t, resolver.Resolve(&ref, &tgt, ""))
230
231 assert.Equal(t, "id", tgt.Name)
232 assert.Equal(t, "path", tgt.In)
233 assert.Equal(t, "ID of pet to fetch", tgt.Description)
234 assert.True(t, tgt.Required)
235 assert.Equal(t, "integer", tgt.Type)
236 assert.Equal(t, "int64", tgt.Format)
237 }
238
239 func TestResolveRemoteRef_ToPathItem(t *testing.T) {
240 fileserver := http.FileServer(http.Dir(specs))
241 server := httptest.NewServer(fileserver)
242 defer server.Close()
243
244 rootDoc := new(Swagger)
245 b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
246 require.NoError(t, err)
247 require.NoError(t, json.Unmarshal(b, rootDoc))
248
249 var tgt PathItem
250 ref, err := NewRef(server.URL + "/refed.json#/paths/" + jsonpointer.Escape("/pets/{id}"))
251 require.NoError(t, err)
252
253 resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
254 require.NoError(t, resolver.Resolve(&ref, &tgt, ""))
255 assert.Equal(t, rootDoc.Paths.Paths["/pets/{id}"].Get, tgt.Get)
256 }
257
258 func TestResolveRemoteRef_ToResponse(t *testing.T) {
259 fileserver := http.FileServer(http.Dir(specs))
260 server := httptest.NewServer(fileserver)
261 defer server.Close()
262
263 rootDoc := new(Swagger)
264 b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
265 require.NoError(t, err)
266 require.NoError(t, json.Unmarshal(b, rootDoc))
267
268 var tgt Response
269 ref, err := NewRef(server.URL + "/refed.json#/responses/petResponse")
270 require.NoError(t, err)
271
272 resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
273 require.NoError(t, resolver.Resolve(&ref, &tgt, ""))
274 assert.Equal(t, rootDoc.Responses["petResponse"], tgt)
275 }
276
277 func TestResolveLocalRef_SameRoot(t *testing.T) {
278 rootDoc := new(Swagger)
279 require.NoError(t, json.Unmarshal(PetStoreJSONMessage, rootDoc))
280
281 result := new(Swagger)
282 ref, _ := NewRef("#")
283 resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
284 require.NoError(t, resolver.Resolve(&ref, result, ""))
285 assert.Equal(t, rootDoc, result)
286 }
287
288 func TestResolveLocalRef_FromFragment(t *testing.T) {
289 rootDoc := new(Swagger)
290 require.NoError(t, json.Unmarshal(PetStoreJSONMessage, rootDoc))
291
292 var tgt Schema
293 ref, err := NewRef("#/definitions/Category")
294 require.NoError(t, err)
295
296 resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
297 require.NoError(t, resolver.Resolve(&ref, &tgt, ""))
298 assert.Equal(t, "Category", tgt.ID)
299 }
300
301 func TestResolveLocalRef_FromInvalidFragment(t *testing.T) {
302 rootDoc := new(Swagger)
303 require.NoError(t, json.Unmarshal(PetStoreJSONMessage, rootDoc))
304
305 var tgt Schema
306 ref, err := NewRef("#/definitions/NotThere")
307 require.NoError(t, err)
308
309 resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
310 require.Error(t, resolver.Resolve(&ref, &tgt, ""))
311 }
312
313 func TestResolveLocalRef_Parameter(t *testing.T) {
314 rootDoc := new(Swagger)
315 b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
316 require.NoError(t, err)
317
318 basePath := filepath.Join(specs, "refed.json")
319 require.NoError(t, json.Unmarshal(b, rootDoc))
320
321 var tgt Parameter
322 ref, err := NewRef("#/parameters/idParam")
323 require.NoError(t, err)
324
325 resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
326 require.NoError(t, resolver.Resolve(&ref, &tgt, basePath))
327
328 assert.Equal(t, "id", tgt.Name)
329 assert.Equal(t, "path", tgt.In)
330 assert.Equal(t, "ID of pet to fetch", tgt.Description)
331 assert.True(t, tgt.Required)
332 assert.Equal(t, "integer", tgt.Type)
333 assert.Equal(t, "int64", tgt.Format)
334 }
335
336 func TestResolveLocalRef_PathItem(t *testing.T) {
337 rootDoc := new(Swagger)
338 b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
339 require.NoError(t, err)
340
341 basePath := filepath.Join(specs, "refed.json")
342 require.NoError(t, json.Unmarshal(b, rootDoc))
343
344 var tgt PathItem
345 ref, err := NewRef("#/paths/" + jsonpointer.Escape("/pets/{id}"))
346 require.NoError(t, err)
347
348 resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
349 require.NoError(t, resolver.Resolve(&ref, &tgt, basePath))
350 assert.Equal(t, rootDoc.Paths.Paths["/pets/{id}"].Get, tgt.Get)
351 }
352
353 func TestResolveLocalRef_Response(t *testing.T) {
354 rootDoc := new(Swagger)
355 b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
356 require.NoError(t, err)
357
358 basePath := filepath.Join(specs, "refed.json")
359 require.NoError(t, json.Unmarshal(b, rootDoc))
360
361 var tgt Response
362 ref, err := NewRef("#/responses/petResponse")
363 require.NoError(t, err)
364
365 resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
366 require.NoError(t, resolver.Resolve(&ref, &tgt, basePath))
367 assert.Equal(t, rootDoc.Responses["petResponse"], tgt)
368 }
369
370 func TestResolvePathItem(t *testing.T) {
371 spec := new(Swagger)
372 specDoc, err := jsonDoc(pathItemsFixture)
373 require.NoError(t, err)
374
375 require.NoError(t, json.Unmarshal(specDoc, spec))
376
377
378 pth := spec.Paths.Paths["/todos"]
379 pathItem, err := ResolvePathItem(spec, pth.Ref, &ExpandOptions{RelativeBase: pathItemsFixture})
380 require.NoError(t, err)
381
382 jazon := asJSON(t, pathItem)
383
384 assert.JSONEq(t, `{
385 "get": {
386 "responses": {
387 "200": {
388 "description": "List Todos",
389 "schema": {
390 "type": "array",
391 "items": {
392 "type": "string"
393 }
394 }
395 },
396 "404": {
397 "description": "error"
398 }
399 }
400 }
401 }`, jazon)
402 }
403
404 func TestResolveExtraItem(t *testing.T) {
405
406 spec := new(Swagger)
407 specDoc, err := jsonDoc(extraRefFixture)
408 require.NoError(t, err)
409
410 require.NoError(t, json.Unmarshal(specDoc, spec))
411
412
413 parm := spec.Paths.Paths["/employees"].Get.Parameters[0]
414 parmItem, err := ResolveItems(spec, parm.Items.Ref, &ExpandOptions{RelativeBase: extraRefFixture})
415 require.NoError(t, err)
416
417 jazon := asJSON(t, parmItem)
418
419 assert.JSONEq(t, `{
420 "type": "integer",
421 "format": "int32"
422 }`, jazon)
423
424
425 hdr := spec.Paths.Paths["/employees"].Get.Responses.StatusCodeResponses[200].Headers["X-header"]
426 hdrItem, err := ResolveItems(spec, hdr.Items.Ref, &ExpandOptions{RelativeBase: extraRefFixture})
427 require.NoError(t, err)
428
429 jazon = asJSON(t, hdrItem)
430
431 assert.JSONEq(t, `{
432 "type": "string",
433 "format": "uuid"
434 }`, jazon)
435 }
436
View as plain text