mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
718 lines
17 KiB
Go
718 lines
17 KiB
Go
package loads
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestUnknownSpecVersion(t *testing.T) {
|
|
_, err := Analyzed([]byte{}, "0.9")
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestDefaultsTo20(t *testing.T) {
|
|
d, err := Analyzed(PetStoreJSONMessage, "")
|
|
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, d)
|
|
assert.Equal(t, "2.0", d.Version())
|
|
// assert.Equal(t, "2.0", d.data["swagger"].(string))
|
|
assert.Equal(t, "/api", d.BasePath())
|
|
}
|
|
|
|
func TestLoadsYAMLContent(t *testing.T) {
|
|
d, err := Analyzed(json.RawMessage([]byte(YAMLSpec)), "")
|
|
if assert.NoError(t, err) {
|
|
if assert.NotNil(t, d) {
|
|
sw := d.Spec()
|
|
assert.Equal(t, "1.0.0", sw.Info.Version)
|
|
}
|
|
}
|
|
}
|
|
|
|
// for issue 11
|
|
func TestRegressionExpand(t *testing.T) {
|
|
swaggerFile := "fixtures/yaml/swagger/1/2/3/4/swagger.yaml"
|
|
document, err := Spec(swaggerFile)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, document)
|
|
d, err := document.Expanded()
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, d)
|
|
b, _ := d.Spec().MarshalJSON()
|
|
assert.JSONEq(t, expectedExpanded, string(b))
|
|
}
|
|
|
|
func TestCascadingRefExpand(t *testing.T) {
|
|
swaggerFile := "fixtures/yaml/swagger/spec.yml"
|
|
document, err := Spec(swaggerFile)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, document)
|
|
d, err := document.Expanded()
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, d)
|
|
b, _ := d.Spec().MarshalJSON()
|
|
assert.JSONEq(t, cascadeRefExpanded, string(b))
|
|
}
|
|
|
|
func TestFailsInvalidJSON(t *testing.T) {
|
|
_, err := Analyzed(json.RawMessage([]byte("{]")), "")
|
|
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
var YAMLSpec = `swagger: '2.0'
|
|
|
|
info:
|
|
version: "1.0.0"
|
|
title: Simple Search API
|
|
description: |
|
|
A very simple api description that makes a x-www-form-urlencoded only API to submit searches.
|
|
|
|
produces:
|
|
- application/json
|
|
|
|
consumes:
|
|
- application/json
|
|
|
|
paths:
|
|
/search:
|
|
post:
|
|
operationId: search
|
|
summary: searches tasks
|
|
description: searches the task titles and descriptions for a match
|
|
consumes:
|
|
- application/x-www-form-urlencoded
|
|
parameters:
|
|
- name: q
|
|
in: formData
|
|
type: string
|
|
description: the search string
|
|
required: true
|
|
/tasks:
|
|
get:
|
|
operationId: getTasks
|
|
summary: Gets Task objects.
|
|
description: |
|
|
Optional query param of **size** determines
|
|
size of returned array
|
|
tags:
|
|
- tasks
|
|
parameters:
|
|
- name: size
|
|
in: query
|
|
description: Size of task list
|
|
type: integer
|
|
format: int32
|
|
default: 20
|
|
- name: completed
|
|
in: query
|
|
description: when true shows completed tasks
|
|
type: boolean
|
|
|
|
responses:
|
|
default:
|
|
description: Generic Error
|
|
200:
|
|
description: Successful response
|
|
headers:
|
|
X-Rate-Limit:
|
|
type: integer
|
|
format: int32
|
|
X-Rate-Limit-Remaining:
|
|
type: integer
|
|
format: int32
|
|
default: 42
|
|
X-Rate-Limit-Reset:
|
|
type: integer
|
|
format: int32
|
|
default: "1449875311"
|
|
X-Rate-Limit-Reset-Human:
|
|
type: string
|
|
default: 3 days
|
|
X-Rate-Limit-Reset-Human-Number:
|
|
type: string
|
|
default: 3
|
|
Access-Control-Allow-Origin:
|
|
type: string
|
|
default: "*"
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/definitions/Task"
|
|
post:
|
|
operationId: createTask
|
|
summary: Creates a 'Task' object.
|
|
description: |
|
|
Validates the content property for length etc.
|
|
parameters:
|
|
- name: body
|
|
in: body
|
|
schema:
|
|
$ref: "#/definitions/Task"
|
|
tags:
|
|
- tasks
|
|
responses:
|
|
default:
|
|
description: Generic Error
|
|
201:
|
|
description: Task Created
|
|
|
|
/tasks/{id}:
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
type: integer
|
|
format: int32
|
|
description: The id of the task
|
|
required: true
|
|
minimum: 1
|
|
put:
|
|
operationId: updateTask
|
|
summary: updates a task.
|
|
description: |
|
|
Validates the content property for length etc.
|
|
tags:
|
|
- tasks
|
|
parameters:
|
|
- name: body
|
|
in: body
|
|
description: the updated task
|
|
schema:
|
|
$ref: "#/definitions/Task"
|
|
responses:
|
|
default:
|
|
description: Generic Error
|
|
200:
|
|
description: Task updated
|
|
schema:
|
|
$ref: "#/definitions/Task"
|
|
delete:
|
|
operationId: deleteTask
|
|
summary: deletes a task
|
|
description: |
|
|
Deleting a task is irrevocable.
|
|
tags:
|
|
- tasks
|
|
responses:
|
|
default:
|
|
description: Generic Error
|
|
204:
|
|
description: Task Deleted
|
|
|
|
|
|
definitions:
|
|
Task:
|
|
title: A Task object
|
|
description: |
|
|
This describes a task. Tasks require a content property to be set.
|
|
required:
|
|
- content
|
|
type: object
|
|
properties:
|
|
id:
|
|
title: the unique id of the task
|
|
description: |
|
|
This id property is autogenerated when a task is created.
|
|
type: integer
|
|
format: int64
|
|
readOnly: true
|
|
content:
|
|
title: The content of the task
|
|
description: |
|
|
Task content can contain [GFM](https://help.github.com/articles/github-flavored-markdown/).
|
|
type: string
|
|
minLength: 5
|
|
completed:
|
|
title: when true this task is completed
|
|
type: boolean
|
|
creditcard:
|
|
title: the credit card format usage
|
|
type: string
|
|
format: creditcard
|
|
createdAt:
|
|
title: task creation time
|
|
type: string
|
|
format: date-time
|
|
readOnly: true
|
|
`
|
|
|
|
// PetStoreJSONMessage json raw message for Petstore20
|
|
var PetStoreJSONMessage = json.RawMessage([]byte(PetStore20))
|
|
|
|
// PetStore20 json doc for swagger 2.0 pet store
|
|
const PetStore20 = `{
|
|
"swagger": "2.0",
|
|
"info": {
|
|
"version": "1.0.0",
|
|
"title": "Swagger Petstore",
|
|
"contact": {
|
|
"name": "Wordnik API Team",
|
|
"url": "http://developer.wordnik.com"
|
|
},
|
|
"license": {
|
|
"name": "Creative Commons 4.0 International",
|
|
"url": "http://creativecommons.org/licenses/by/4.0/"
|
|
}
|
|
},
|
|
"host": "petstore.swagger.wordnik.com",
|
|
"basePath": "/api",
|
|
"schemes": [
|
|
"http"
|
|
],
|
|
"paths": {
|
|
"/pets": {
|
|
"get": {
|
|
"security": [
|
|
{
|
|
"basic": []
|
|
}
|
|
],
|
|
"tags": [ "Pet Operations" ],
|
|
"operationId": "getAllPets",
|
|
"parameters": [
|
|
{
|
|
"name": "status",
|
|
"in": "query",
|
|
"description": "The status to filter by",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"name": "limit",
|
|
"in": "query",
|
|
"description": "The maximum number of results to return",
|
|
"type": "integer",
|
|
"format": "int64"
|
|
}
|
|
],
|
|
"summary": "Finds all pets in the system",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Pet response",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/Pet"
|
|
}
|
|
}
|
|
},
|
|
"default": {
|
|
"description": "Unexpected error",
|
|
"schema": {
|
|
"$ref": "#/definitions/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"security": [
|
|
{
|
|
"basic": []
|
|
}
|
|
],
|
|
"tags": [ "Pet Operations" ],
|
|
"operationId": "createPet",
|
|
"summary": "Creates a new pet",
|
|
"consumes": ["application/x-yaml"],
|
|
"produces": ["application/x-yaml"],
|
|
"parameters": [
|
|
{
|
|
"name": "pet",
|
|
"in": "body",
|
|
"description": "The Pet to create",
|
|
"required": true,
|
|
"schema": {
|
|
"$ref": "#/definitions/newPet"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Created Pet response",
|
|
"schema": {
|
|
"$ref": "#/definitions/Pet"
|
|
}
|
|
},
|
|
"default": {
|
|
"description": "Unexpected error",
|
|
"schema": {
|
|
"$ref": "#/definitions/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/pets/{id}": {
|
|
"delete": {
|
|
"security": [
|
|
{
|
|
"apiKey": []
|
|
}
|
|
],
|
|
"description": "Deletes the Pet by id",
|
|
"operationId": "deletePet",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "ID of pet to delete",
|
|
"required": true,
|
|
"type": "integer",
|
|
"format": "int64"
|
|
}
|
|
],
|
|
"responses": {
|
|
"204": {
|
|
"description": "pet deleted"
|
|
},
|
|
"default": {
|
|
"description": "unexpected error",
|
|
"schema": {
|
|
"$ref": "#/definitions/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"get": {
|
|
"tags": [ "Pet Operations" ],
|
|
"operationId": "getPetById",
|
|
"summary": "Finds the pet by id",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Pet response",
|
|
"schema": {
|
|
"$ref": "#/definitions/Pet"
|
|
}
|
|
},
|
|
"default": {
|
|
"description": "Unexpected error",
|
|
"schema": {
|
|
"$ref": "#/definitions/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "ID of pet",
|
|
"required": true,
|
|
"type": "integer",
|
|
"format": "int64"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"definitions": {
|
|
"Category": {
|
|
"id": "Category",
|
|
"properties": {
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"Pet": {
|
|
"id": "Pet",
|
|
"properties": {
|
|
"category": {
|
|
"$ref": "#/definitions/Category"
|
|
},
|
|
"id": {
|
|
"description": "unique identifier for the pet",
|
|
"format": "int64",
|
|
"maximum": 100.0,
|
|
"minimum": 0.0,
|
|
"type": "integer"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"photoUrls": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"status": {
|
|
"description": "pet status in the store",
|
|
"enum": [
|
|
"available",
|
|
"pending",
|
|
"sold"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"tags": {
|
|
"items": {
|
|
"$ref": "#/definitions/Tag"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"name"
|
|
]
|
|
},
|
|
"newPet": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/definitions/Pet"
|
|
},
|
|
{
|
|
"required": [
|
|
"name"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"Tag": {
|
|
"id": "Tag",
|
|
"properties": {
|
|
"id": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"Error": {
|
|
"required": [
|
|
"code",
|
|
"message"
|
|
],
|
|
"properties": {
|
|
"code": {
|
|
"type": "integer",
|
|
"format": "int32"
|
|
},
|
|
"message": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"consumes": [
|
|
"application/json",
|
|
"application/xml"
|
|
],
|
|
"produces": [
|
|
"application/json",
|
|
"application/xml",
|
|
"text/plain",
|
|
"text/html"
|
|
],
|
|
"securityDefinitions": {
|
|
"basic": {
|
|
"type": "basic"
|
|
},
|
|
"apiKey": {
|
|
"type": "apiKey",
|
|
"in": "header",
|
|
"name": "X-API-KEY"
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
const expectedExpanded = `
|
|
{
|
|
"produces":[
|
|
"application/json",
|
|
"plain/text"
|
|
],
|
|
"schemes":[
|
|
"https",
|
|
"http"
|
|
],
|
|
"swagger":"2.0",
|
|
"info":{
|
|
"description":"Something",
|
|
"title":"Something",
|
|
"contact":{
|
|
"name":"Somebody",
|
|
"url":"https://url.com",
|
|
"email":"email@url.com"
|
|
},
|
|
"version":"v1"
|
|
},
|
|
"host":"security.sonusnet.com",
|
|
"basePath":"/api",
|
|
"paths":{
|
|
"/whatnot":{
|
|
"get":{
|
|
"description":"Get something",
|
|
"responses":{
|
|
"200":{
|
|
"description":"The something",
|
|
"schema":{
|
|
"description":"A collection of service events",
|
|
"type":"object",
|
|
"properties":{
|
|
"page":{
|
|
"description":"A description of a paged result",
|
|
"type":"object",
|
|
"properties":{
|
|
"page":{
|
|
"description":"the page that was requested",
|
|
"type":"integer"
|
|
},
|
|
"page_items":{
|
|
"description":"the number of items per page requested",
|
|
"type":"integer"
|
|
},
|
|
"pages":{
|
|
"description":"the total number of pages available",
|
|
"type":"integer"
|
|
},
|
|
"total_items":{
|
|
"description":"the total number of items available",
|
|
"type":"integer",
|
|
"format":"int64"
|
|
}
|
|
}
|
|
},
|
|
"something":{
|
|
"description":"Something",
|
|
"type":"object",
|
|
"properties":{
|
|
"p1":{
|
|
"description":"A string",
|
|
"type":"string"
|
|
},
|
|
"p2":{
|
|
"description":"An integer",
|
|
"type":"integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500":{
|
|
"description":"Oops"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"definitions":{
|
|
"Something":{
|
|
"description":"A collection of service events",
|
|
"type":"object",
|
|
"properties":{
|
|
"page":{
|
|
"description":"A description of a paged result",
|
|
"type":"object",
|
|
"properties":{
|
|
"page":{
|
|
"description":"the page that was requested",
|
|
"type":"integer"
|
|
},
|
|
"page_items":{
|
|
"description":"the number of items per page requested",
|
|
"type":"integer"
|
|
},
|
|
"pages":{
|
|
"description":"the total number of pages available",
|
|
"type":"integer"
|
|
},
|
|
"total_items":{
|
|
"description":"the total number of items available",
|
|
"type":"integer",
|
|
"format":"int64"
|
|
}
|
|
}
|
|
},
|
|
"something":{
|
|
"description":"Something",
|
|
"type":"object",
|
|
"properties":{
|
|
"p1":{
|
|
"description":"A string",
|
|
"type":"string"
|
|
},
|
|
"p2":{
|
|
"description":"An integer",
|
|
"type":"integer"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
const cascadeRefExpanded = `
|
|
{
|
|
"swagger": "2.0",
|
|
"consumes":[
|
|
"application/json"
|
|
],
|
|
"produces":[
|
|
"application/json"
|
|
],
|
|
"schemes":[
|
|
"http"
|
|
],
|
|
"info":{
|
|
"description":"recursively following JSON references",
|
|
"title":"test 1",
|
|
"contact":{
|
|
"name":"Fred"
|
|
},
|
|
"version":"0.1.1"
|
|
},
|
|
"paths":{
|
|
"/getAll":{
|
|
"get":{
|
|
"operationId":"getAll",
|
|
"parameters":[
|
|
{
|
|
"description":"max number of results",
|
|
"name":"a",
|
|
"in":"body",
|
|
"schema":{
|
|
"type":"string"
|
|
}
|
|
}
|
|
],
|
|
"responses":{
|
|
"200":{
|
|
"description":"Success",
|
|
"schema":{
|
|
"type":"array",
|
|
"items":{
|
|
"type":"string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"definitions":{
|
|
"a":{
|
|
"type":"string"
|
|
},
|
|
"b":{
|
|
"type":"array",
|
|
"items":{
|
|
"type":"string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`
|