File: //proc/thread-self/root/opt/go/pkg/mod/github.com/go-openapi/
[email protected]/resolver_test.go
package spec
import (
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
"github.com/go-openapi/jsonpointer"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestResolveRef(t *testing.T) {
var root interface{}
require.NoError(t, json.Unmarshal([]byte(PetStore20), &root))
ref, err := NewRef("#/definitions/Category")
require.NoError(t, err)
sch, err := ResolveRef(root, &ref)
require.NoError(t, err)
b, err := sch.MarshalJSON()
require.NoError(t, err)
assert.JSONEq(t, `{"id":"Category","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}}}`, string(b))
// WithBase variant
sch, err = ResolveRefWithBase(root, &ref, &ExpandOptions{
RelativeBase: "/",
})
require.NoError(t, err)
b, err = sch.MarshalJSON()
require.NoError(t, err)
assert.JSONEq(t, `{"id":"Category","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"}}}`, string(b))
}
func TestResolveResponse(t *testing.T) {
specDoc, err := jsonDoc(filepath.Join("fixtures", "expansion", "all-the-things.json"))
require.NoError(t, err)
spec := new(Swagger)
require.NoError(t, json.Unmarshal(specDoc, spec))
// Resolve with root version
resp := spec.Paths.Paths["/"].Get.Responses.StatusCodeResponses[200]
resp2, err := ResolveResponse(spec, resp.Ref)
require.NoError(t, err)
// resolve resolves the ref, but dos not expand
jazon := asJSON(t, resp2)
assert.JSONEq(t, `{
"$ref": "#/responses/petResponse"
}`, jazon)
}
func TestResolveResponseWithBase(t *testing.T) {
specDoc, err := jsonDoc(crossFileRefFixture)
require.NoError(t, err)
spec := new(Swagger)
require.NoError(t, json.Unmarshal(specDoc, spec))
// Resolve with root version
resp := spec.Paths.Paths["/"].Get.Responses.StatusCodeResponses[200]
resp2, err := ResolveResponseWithBase(spec, resp.Ref, &ExpandOptions{RelativeBase: crossFileRefFixture})
require.NoError(t, err)
// resolve resolves the ref, but dos not expand
jazon := asJSON(t, resp2)
assert.JSONEq(t, `{
"$ref": "#/responses/petResponse"
}`, jazon)
}
func TestResolveParam(t *testing.T) {
specDoc, err := jsonDoc(filepath.Join("fixtures", "expansion", "all-the-things.json"))
require.NoError(t, err)
var spec Swagger
require.NoError(t, json.Unmarshal(specDoc, &spec))
param := spec.Paths.Paths["/pets/{id}"].Get.Parameters[0]
par, err := ResolveParameter(spec, param.Ref)
require.NoError(t, err)
jazon := asJSON(t, par)
assert.JSONEq(t, `{
"name": "id",
"in": "path",
"description": "ID of pet to fetch",
"required": true,
"type": "integer",
"format": "int64"
}`, jazon)
}
func TestResolveParamWithBase(t *testing.T) {
specDoc, err := jsonDoc(crossFileRefFixture)
require.NoError(t, err)
var spec Swagger
require.NoError(t, json.Unmarshal(specDoc, &spec))
param := spec.Paths.Paths["/pets"].Get.Parameters[0]
par, err := ResolveParameterWithBase(spec, param.Ref, &ExpandOptions{RelativeBase: crossFileRefFixture})
require.NoError(t, err)
jazon := asJSON(t, par)
assert.JSONEq(t, `{
"description":"ID of pet to fetch",
"format":"int64",
"in":"path",
"name":"id",
"required":true,
"type":"integer"
}`, jazon)
}
func TestResolveRemoteRef_RootSame(t *testing.T) {
fileserver := http.FileServer(http.Dir(specs))
server := httptest.NewServer(fileserver)
defer server.Close()
rootDoc := new(Swagger)
b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
require.NoError(t, err)
require.NoError(t, json.Unmarshal(b, rootDoc))
// the filename doesn't matter because ref will eventually point to refed.json
specBase := normalizeBase(filepath.Join(specs, "anyotherfile.json"))
var result0 Swagger
ref0, _ := NewRef(server.URL + "/refed.json#")
resolver0 := defaultSchemaLoader(rootDoc, nil, nil, nil)
require.NoError(t, resolver0.Resolve(&ref0, &result0, ""))
assertSpecs(t, result0, *rootDoc)
var result1 Swagger
ref1, _ := NewRef("./refed.json")
resolver1 := defaultSchemaLoader(rootDoc, &ExpandOptions{
RelativeBase: specBase,
}, nil, nil)
require.NoError(t, resolver1.Resolve(&ref1, &result1, specBase))
assertSpecs(t, result1, *rootDoc)
}
func TestResolveRemoteRef_FromFragment(t *testing.T) {
fileserver := http.FileServer(http.Dir(specs))
server := httptest.NewServer(fileserver)
defer server.Close()
rootDoc := new(Swagger)
b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
require.NoError(t, err)
require.NoError(t, json.Unmarshal(b, rootDoc))
var tgt Schema
ref, err := NewRef(server.URL + "/refed.json#/definitions/pet")
require.NoError(t, err)
context := newResolverContext(&ExpandOptions{PathLoader: jsonDoc})
resolver := &schemaLoader{root: rootDoc, cache: defaultResolutionCache(), context: context}
require.NoError(t, resolver.Resolve(&ref, &tgt, ""))
assert.Equal(t, []string{"id", "name"}, tgt.Required)
}
func TestResolveRemoteRef_FromInvalidFragment(t *testing.T) {
fileserver := http.FileServer(http.Dir(specs))
server := httptest.NewServer(fileserver)
defer server.Close()
rootDoc := new(Swagger)
b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
require.NoError(t, err)
require.NoError(t, json.Unmarshal(b, rootDoc))
var tgt Schema
ref, err := NewRef(server.URL + "/refed.json#/definitions/NotThere")
require.NoError(t, err)
resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
require.Error(t, resolver.Resolve(&ref, &tgt, ""))
}
/* This next test will have to wait until we do full $ID analysis for every subschema on every file that is referenced */
/* For now, TestResolveRemoteRef_WithNestedResolutionContext replaces this next test */
// func TestResolveRemoteRef_WithNestedResolutionContextWithFragment_WithParentID(t *testing.T) {
// server := resolutionContextServer()
// defer server.Close()
//
// rootDoc := new(Swagger)
// b, err := os.ReadFile("fixtures/specs/refed.json")
// require.NoError(t, err) && assert.NoError(t, json.Unmarshal(b, rootDoc))
//
// var tgt Schema
// ref, err := NewRef(server.URL + "/resolution2.json#/items/items")
// require.NoError(t, err)
//
// resolver := defaultSchemaLoader(rootDoc, nil, nil,nil)
// require.NoError(t, resolver.Resolve(&ref, &tgt, ""))
// assert.Equal(t, StringOrArray([]string{"file"}), tgt.Type)
// }
func TestResolveRemoteRef_ToParameter(t *testing.T) {
fileserver := http.FileServer(http.Dir(specs))
server := httptest.NewServer(fileserver)
defer server.Close()
rootDoc := new(Swagger)
b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
require.NoError(t, err)
require.NoError(t, json.Unmarshal(b, rootDoc))
var tgt Parameter
ref, err := NewRef(server.URL + "/refed.json#/parameters/idParam")
require.NoError(t, err)
resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
require.NoError(t, resolver.Resolve(&ref, &tgt, ""))
assert.Equal(t, "id", tgt.Name)
assert.Equal(t, "path", tgt.In)
assert.Equal(t, "ID of pet to fetch", tgt.Description)
assert.True(t, tgt.Required)
assert.Equal(t, "integer", tgt.Type)
assert.Equal(t, "int64", tgt.Format)
}
func TestResolveRemoteRef_ToPathItem(t *testing.T) {
fileserver := http.FileServer(http.Dir(specs))
server := httptest.NewServer(fileserver)
defer server.Close()
rootDoc := new(Swagger)
b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
require.NoError(t, err)
require.NoError(t, json.Unmarshal(b, rootDoc))
var tgt PathItem
ref, err := NewRef(server.URL + "/refed.json#/paths/" + jsonpointer.Escape("/pets/{id}"))
require.NoError(t, err)
resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
require.NoError(t, resolver.Resolve(&ref, &tgt, ""))
assert.Equal(t, rootDoc.Paths.Paths["/pets/{id}"].Get, tgt.Get)
}
func TestResolveRemoteRef_ToResponse(t *testing.T) {
fileserver := http.FileServer(http.Dir(specs))
server := httptest.NewServer(fileserver)
defer server.Close()
rootDoc := new(Swagger)
b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
require.NoError(t, err)
require.NoError(t, json.Unmarshal(b, rootDoc))
var tgt Response
ref, err := NewRef(server.URL + "/refed.json#/responses/petResponse")
require.NoError(t, err)
resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
require.NoError(t, resolver.Resolve(&ref, &tgt, ""))
assert.Equal(t, rootDoc.Responses["petResponse"], tgt)
}
func TestResolveLocalRef_SameRoot(t *testing.T) {
rootDoc := new(Swagger)
require.NoError(t, json.Unmarshal(PetStoreJSONMessage, rootDoc))
result := new(Swagger)
ref, _ := NewRef("#")
resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
require.NoError(t, resolver.Resolve(&ref, result, ""))
assert.Equal(t, rootDoc, result)
}
func TestResolveLocalRef_FromFragment(t *testing.T) {
rootDoc := new(Swagger)
require.NoError(t, json.Unmarshal(PetStoreJSONMessage, rootDoc))
var tgt Schema
ref, err := NewRef("#/definitions/Category")
require.NoError(t, err)
resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
require.NoError(t, resolver.Resolve(&ref, &tgt, ""))
assert.Equal(t, "Category", tgt.ID)
}
func TestResolveLocalRef_FromInvalidFragment(t *testing.T) {
rootDoc := new(Swagger)
require.NoError(t, json.Unmarshal(PetStoreJSONMessage, rootDoc))
var tgt Schema
ref, err := NewRef("#/definitions/NotThere")
require.NoError(t, err)
resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
require.Error(t, resolver.Resolve(&ref, &tgt, ""))
}
func TestResolveLocalRef_Parameter(t *testing.T) {
rootDoc := new(Swagger)
b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
require.NoError(t, err)
basePath := filepath.Join(specs, "refed.json")
require.NoError(t, json.Unmarshal(b, rootDoc))
var tgt Parameter
ref, err := NewRef("#/parameters/idParam")
require.NoError(t, err)
resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
require.NoError(t, resolver.Resolve(&ref, &tgt, basePath))
assert.Equal(t, "id", tgt.Name)
assert.Equal(t, "path", tgt.In)
assert.Equal(t, "ID of pet to fetch", tgt.Description)
assert.True(t, tgt.Required)
assert.Equal(t, "integer", tgt.Type)
assert.Equal(t, "int64", tgt.Format)
}
func TestResolveLocalRef_PathItem(t *testing.T) {
rootDoc := new(Swagger)
b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
require.NoError(t, err)
basePath := filepath.Join(specs, "refed.json")
require.NoError(t, json.Unmarshal(b, rootDoc))
var tgt PathItem
ref, err := NewRef("#/paths/" + jsonpointer.Escape("/pets/{id}"))
require.NoError(t, err)
resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
require.NoError(t, resolver.Resolve(&ref, &tgt, basePath))
assert.Equal(t, rootDoc.Paths.Paths["/pets/{id}"].Get, tgt.Get)
}
func TestResolveLocalRef_Response(t *testing.T) {
rootDoc := new(Swagger)
b, err := os.ReadFile(filepath.Join(specs, "refed.json"))
require.NoError(t, err)
basePath := filepath.Join(specs, "refed.json")
require.NoError(t, json.Unmarshal(b, rootDoc))
var tgt Response
ref, err := NewRef("#/responses/petResponse")
require.NoError(t, err)
resolver := defaultSchemaLoader(rootDoc, nil, nil, nil)
require.NoError(t, resolver.Resolve(&ref, &tgt, basePath))
assert.Equal(t, rootDoc.Responses["petResponse"], tgt)
}
func TestResolvePathItem(t *testing.T) {
spec := new(Swagger)
specDoc, err := jsonDoc(pathItemsFixture)
require.NoError(t, err)
require.NoError(t, json.Unmarshal(specDoc, spec))
// Resolve use case
pth := spec.Paths.Paths["/todos"]
pathItem, err := ResolvePathItem(spec, pth.Ref, &ExpandOptions{RelativeBase: pathItemsFixture})
require.NoError(t, err)
jazon := asJSON(t, pathItem)
assert.JSONEq(t, `{
"get": {
"responses": {
"200": {
"description": "List Todos",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
"404": {
"description": "error"
}
}
}
}`, jazon)
}
func TestResolveExtraItem(t *testing.T) {
// go-openapi extra goodie: $ref in simple schema Items and Headers
spec := new(Swagger)
specDoc, err := jsonDoc(extraRefFixture)
require.NoError(t, err)
require.NoError(t, json.Unmarshal(specDoc, spec))
// Resolve param Items use case: here we explicitly resolve the unsuppord case
parm := spec.Paths.Paths["/employees"].Get.Parameters[0]
parmItem, err := ResolveItems(spec, parm.Items.Ref, &ExpandOptions{RelativeBase: extraRefFixture})
require.NoError(t, err)
jazon := asJSON(t, parmItem)
assert.JSONEq(t, `{
"type": "integer",
"format": "int32"
}`, jazon)
// Resolve header Items use case: here we explicitly resolve the unsuppord case
hdr := spec.Paths.Paths["/employees"].Get.Responses.StatusCodeResponses[200].Headers["X-header"]
hdrItem, err := ResolveItems(spec, hdr.Items.Ref, &ExpandOptions{RelativeBase: extraRefFixture})
require.NoError(t, err)
jazon = asJSON(t, hdrItem)
assert.JSONEq(t, `{
"type": "string",
"format": "uuid"
}`, jazon)
}