blob: 87531b1f1da9324391cf97a527f947ffe1ea67a7 [file] [log] [blame]
// Copyright 2015 go-swagger maintainers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package spec
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/assert"
)
var spec = Swagger{
SwaggerProps: SwaggerProps{
ID: "http://localhost:3849/api-docs",
Swagger: "2.0",
Consumes: []string{"application/json", "application/x-yaml"},
Produces: []string{"application/json"},
Schemes: []string{"http", "https"},
Info: &info,
Host: "some.api.out.there",
BasePath: "/",
Paths: &paths,
Definitions: map[string]Schema{"Category": {SchemaProps: SchemaProps{Type: []string{"string"}}}},
Parameters: map[string]Parameter{
"categoryParam": {ParamProps: ParamProps{Name: "category", In: "query"}, SimpleSchema: SimpleSchema{Type: "string"}},
},
Responses: map[string]Response{
"EmptyAnswer": {
ResponseProps: ResponseProps{
Description: "no data to return for this operation",
},
},
},
SecurityDefinitions: map[string]*SecurityScheme{
"internalApiKey": APIKeyAuth("api_key", "header"),
},
Security: []map[string][]string{
{"internalApiKey": {}},
},
Tags: []Tag{NewTag("pets", "", nil)},
ExternalDocs: &ExternalDocumentation{"the name", "the url"},
},
VendorExtensible: VendorExtensible{map[string]interface{}{
"x-some-extension": "vendor",
"x-schemes": []interface{}{"unix", "amqp"},
}},
}
var specJSON = `{
"id": "http://localhost:3849/api-docs",
"consumes": ["application/json", "application/x-yaml"],
"produces": ["application/json"],
"schemes": ["http", "https"],
"swagger": "2.0",
"info": {
"contact": {
"name": "wordnik api team",
"url": "http://developer.wordnik.com"
},
"description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
"license": {
"name": "Creative Commons 4.0 International",
"url": "http://creativecommons.org/licenses/by/4.0/"
},
"termsOfService": "http://helloreverb.com/terms/",
"title": "Swagger Sample API",
"version": "1.0.9-abcd",
"x-framework": "go-swagger"
},
"host": "some.api.out.there",
"basePath": "/",
"paths": {"x-framework":"go-swagger","/":{"$ref":"cats"}},
"definitions": { "Category": { "type": "string"} },
"parameters": {
"categoryParam": {
"name": "category",
"in": "query",
"type": "string"
}
},
"responses": { "EmptyAnswer": { "description": "no data to return for this operation" } },
"securityDefinitions": {
"internalApiKey": {
"type": "apiKey",
"in": "header",
"name": "api_key"
}
},
"security": [{"internalApiKey":[]}],
"tags": [{"name":"pets"}],
"externalDocs": {"description":"the name","url":"the url"},
"x-some-extension": "vendor",
"x-schemes": ["unix","amqp"]
}`
//
// func verifySpecSerialize(specJSON []byte, spec Swagger) {
// expected := map[string]interface{}{}
// json.Unmarshal(specJSON, &expected)
// b, err := json.MarshalIndent(spec, "", " ")
// So(err, ShouldBeNil)
// var actual map[string]interface{}
// err = json.Unmarshal(b, &actual)
// So(err, ShouldBeNil)
// compareSpecMaps(actual, expected)
// }
/*
// assertEquivalent is currently unused
func assertEquivalent(t testing.TB, actual, expected interface{}) bool {
if actual == nil || expected == nil || reflect.DeepEqual(actual, expected) {
return true
}
actualType := reflect.TypeOf(actual)
expectedType := reflect.TypeOf(expected)
if reflect.TypeOf(actual).ConvertibleTo(expectedType) {
expectedValue := reflect.ValueOf(expected)
if swag.IsZero(expectedValue) && swag.IsZero(reflect.ValueOf(actual)) {
return true
}
// Attempt comparison after type conversion
if reflect.DeepEqual(actual, expectedValue.Convert(actualType).Interface()) {
return true
}
}
// Last ditch effort
if fmt.Sprintf("%#v", expected) == fmt.Sprintf("%#v", actual) {
return true
}
errFmt := "Expected: '%T(%#v)'\nActual: '%T(%#v)'\n(Should be equivalent)!"
return assert.Fail(t, errFmt, expected, expected, actual, actual)
}
// ShouldBeEquivalentTo is currently unused
func ShouldBeEquivalentTo(actual interface{}, expecteds ...interface{}) string {
expected := expecteds[0]
if actual == nil || expected == nil {
return ""
}
if reflect.DeepEqual(expected, actual) {
return ""
}
actualType := reflect.TypeOf(actual)
expectedType := reflect.TypeOf(expected)
if reflect.TypeOf(actual).ConvertibleTo(expectedType) {
expectedValue := reflect.ValueOf(expected)
if swag.IsZero(expectedValue) && swag.IsZero(reflect.ValueOf(actual)) {
return ""
}
// Attempt comparison after type conversion
if reflect.DeepEqual(actual, expectedValue.Convert(actualType).Interface()) {
return ""
}
}
// Last ditch effort
if fmt.Sprintf("%#v", expected) == fmt.Sprintf("%#v", actual) {
return ""
}
errFmt := "Expected: '%T(%#v)'\nActual: '%T(%#v)'\n(Should be equivalent)!"
return fmt.Sprintf(errFmt, expected, expected, actual, actual)
}
// assertSpecMaps is currently unused
func assertSpecMaps(t testing.TB, actual, expected map[string]interface{}) bool {
res := true
if id, ok := expected["id"]; ok {
res = assert.Equal(t, id, actual["id"])
}
res = res && assert.Equal(t, expected["consumes"], actual["consumes"])
res = res && assert.Equal(t, expected["produces"], actual["produces"])
res = res && assert.Equal(t, expected["schemes"], actual["schemes"])
res = res && assert.Equal(t, expected["swagger"], actual["swagger"])
res = res && assert.Equal(t, expected["info"], actual["info"])
res = res && assert.Equal(t, expected["host"], actual["host"])
res = res && assert.Equal(t, expected["basePath"], actual["basePath"])
res = res && assert.Equal(t, expected["paths"], actual["paths"])
res = res && assert.Equal(t, expected["definitions"], actual["definitions"])
res = res && assert.Equal(t, expected["responses"], actual["responses"])
res = res && assert.Equal(t, expected["securityDefinitions"], actual["securityDefinitions"])
res = res && assert.Equal(t, expected["tags"], actual["tags"])
res = res && assert.Equal(t, expected["externalDocs"], actual["externalDocs"])
res = res && assert.Equal(t, expected["x-some-extension"], actual["x-some-extension"])
res = res && assert.Equal(t, expected["x-schemes"], actual["x-schemes"])
return res
}
*/
func assertSpecs(t testing.TB, actual, expected Swagger) bool {
expected.Swagger = "2.0"
return assert.Equal(t, actual, expected)
}
/*
// assertSpecJSON is currently unused
func assertSpecJSON(t testing.TB, specJSON []byte) bool {
var expected map[string]interface{}
if !assert.NoError(t, json.Unmarshal(specJSON, &expected)) {
return false
}
obj := Swagger{}
if !assert.NoError(t, json.Unmarshal(specJSON, &obj)) {
return false
}
cb, err := json.MarshalIndent(obj, "", " ")
if assert.NoError(t, err) {
return false
}
var actual map[string]interface{}
if !assert.NoError(t, json.Unmarshal(cb, &actual)) {
return false
}
return assertSpecMaps(t, actual, expected)
}
*/
func TestSwaggerSpec_Serialize(t *testing.T) {
expected := make(map[string]interface{})
json.Unmarshal([]byte(specJSON), &expected)
b, err := json.MarshalIndent(spec, "", " ")
if assert.NoError(t, err) {
var actual map[string]interface{}
err := json.Unmarshal(b, &actual)
if assert.NoError(t, err) {
assert.EqualValues(t, actual, expected)
}
}
}
func TestSwaggerSpec_Deserialize(t *testing.T) {
var actual Swagger
err := json.Unmarshal([]byte(specJSON), &actual)
if assert.NoError(t, err) {
assert.EqualValues(t, actual, spec)
}
}
func TestVendorExtensionStringSlice(t *testing.T) {
var actual Swagger
err := json.Unmarshal([]byte(specJSON), &actual)
if assert.NoError(t, err) {
schemes, ok := actual.Extensions.GetStringSlice("x-schemes")
if assert.True(t, ok) {
assert.EqualValues(t, []string{"unix", "amqp"}, schemes)
}
notSlice, ok := actual.Extensions.GetStringSlice("x-some-extension")
assert.Nil(t, notSlice)
assert.False(t, ok)
actual.AddExtension("x-another-ext", 100)
notString, ok := actual.Extensions.GetStringSlice("x-another-ext")
assert.Nil(t, notString)
assert.False(t, ok)
actual.AddExtension("x-another-slice-ext", []interface{}{100, 100})
notStringSlice, ok := actual.Extensions.GetStringSlice("x-another-slice-ext")
assert.Nil(t, notStringSlice)
assert.False(t, ok)
_, ok = actual.Extensions.GetStringSlice("x-notfound-ext")
assert.False(t, ok)
}
}
func TestOptionalSwaggerProps_Serialize(t *testing.T) {
minimalJSONSpec := []byte(`{
"swagger": "2.0",
"info": {
"version": "0.0.0",
"title": "Simple API"
},
"paths": {
"/": {
"get": {
"responses": {
"200": {
"description": "OK"
}
}
}
}
}
}`)
var minimalSpec Swagger
err := json.Unmarshal(minimalJSONSpec, &minimalSpec)
if assert.NoError(t, err) {
bytes, err := json.Marshal(&minimalSpec)
if assert.NoError(t, err) {
var ms map[string]interface{}
if err := json.Unmarshal(bytes, &ms); assert.NoError(t, err) {
assert.NotContains(t, ms, "consumes")
assert.NotContains(t, ms, "produces")
assert.NotContains(t, ms, "schemes")
assert.NotContains(t, ms, "host")
assert.NotContains(t, ms, "basePath")
assert.NotContains(t, ms, "definitions")
assert.NotContains(t, ms, "parameters")
assert.NotContains(t, ms, "responses")
assert.NotContains(t, ms, "securityDefinitions")
assert.NotContains(t, ms, "security")
assert.NotContains(t, ms, "tags")
assert.NotContains(t, ms, "externalDocs")
}
}
}
}
func TestSecurityRequirements(t *testing.T) {
minimalJSONSpec := []byte(`{
"swagger": "2.0",
"info": {
"version": "0.0.0",
"title": "Simple API"
},
"securityDefinitions": {
"basic": {
"type": "basic"
},
"apiKey": {
"type": "apiKey",
"in": "header",
"name": "X-API-KEY"
},
"queryKey": {
"type": "apiKey",
"in": "query",
"name": "api_key"
}
},
"paths": {
"/": {
"get": {
"security": [
{
"apiKey": [],
"basic": []
},
{},
{
"queryKey": [],
"basic": []
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
}
}
}`)
var minimalSpec Swagger
err := json.Unmarshal(minimalJSONSpec, &minimalSpec)
if assert.NoError(t, err) {
sec := minimalSpec.Paths.Paths["/"].Get.Security
require.Len(t, sec, 3)
assert.Contains(t, sec[0], "basic")
assert.Contains(t, sec[0], "apiKey")
assert.NotNil(t, sec[1])
assert.Empty(t, sec[1])
assert.Contains(t, sec[2], "queryKey")
}
}