Add SetUI & other http methods
This commit is contained in:
parent
7b5e1d762c
commit
0a9d6de748
18
assets.go
18
assets.go
@ -1,14 +1,17 @@
|
||||
package echoswagger
|
||||
|
||||
// CDN refer to https://www.jsdelivr.com/package/npm/swagger-ui-dist
|
||||
const DefaultCDN = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@3.18.1"
|
||||
|
||||
const SwaggerUIContent = `{{define "swagger"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{{.title}}</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@3.17.6/swagger-ui.css" crossorigin="anonymous" />
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@3.17.6/favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@3.17.6/favicon-16x16.png" sizes="16x16" />
|
||||
<link rel="stylesheet" href="{{.cdn}}/swagger-ui.css" crossorigin="anonymous" />
|
||||
<link rel="icon" type="image/png" href="{{.cdn}}/favicon-32x32.png" sizes="32x32" />
|
||||
<link rel="icon" type="image/png" href="{{.cdn}}/favicon-16x16.png" sizes="16x16" />
|
||||
<style>
|
||||
html
|
||||
{
|
||||
@ -29,14 +32,19 @@ const SwaggerUIContent = `{{define "swagger"}}
|
||||
margin:0;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
{{if .hideTop}}#swagger-ui>.swagger-container>.topbar
|
||||
{
|
||||
display: none;
|
||||
}{{end}}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@3.17.6/swagger-ui-bundle.js" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@3.17.6/swagger-ui-standalone-preset.js" crossorigin="anonymous"></script>
|
||||
<script src="{{.cdn}}/swagger-ui-bundle.js" crossorigin="anonymous"></script>
|
||||
<script src="{{.cdn}}/swagger-ui-standalone-preset.js" crossorigin="anonymous"></script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
|
||||
|
14
internal.go
14
internal.go
@ -37,11 +37,18 @@ func (r *Root) docHandler(swaggerPath string) echo.HandlerFunc {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cdn := DefaultCDN
|
||||
if r.ui.CDN != "" {
|
||||
cdn = r.ui.CDN
|
||||
}
|
||||
|
||||
return func(c echo.Context) error {
|
||||
buf := new(bytes.Buffer)
|
||||
t.Execute(buf, map[string]interface{}{
|
||||
"title": r.spec.Info.Title,
|
||||
"url": c.Scheme() + "://" + c.Request().Host + swaggerPath,
|
||||
"title": r.spec.Info.Title,
|
||||
"url": c.Scheme() + "://" + c.Request().Host + swaggerPath,
|
||||
"hideTop": r.ui.HideTop,
|
||||
"cdn": cdn,
|
||||
})
|
||||
return c.HTMLBlob(http.StatusOK, buf.Bytes())
|
||||
}
|
||||
@ -62,14 +69,13 @@ func (r *RawDefineDic) getKey(v reflect.Value) (bool, string) {
|
||||
return false, name
|
||||
}
|
||||
|
||||
func (r *routers) appendRoute(method string, route *echo.Route) *api {
|
||||
func (r *routers) appendRoute(route *echo.Route) *api {
|
||||
opr := Operation{
|
||||
Responses: make(map[string]*Response),
|
||||
}
|
||||
a := api{
|
||||
route: route,
|
||||
defs: r.defs,
|
||||
method: method,
|
||||
operation: opr,
|
||||
}
|
||||
r.apis = append(r.apis, a)
|
||||
|
12
spec.go
12
spec.go
@ -69,10 +69,10 @@ func (r *Root) transfer(a *api) error {
|
||||
}
|
||||
|
||||
if p, ok := r.spec.Paths[path]; ok {
|
||||
p.(*Path).oprationAssign(a.method, &a.operation)
|
||||
p.(*Path).oprationAssign(a.route.Method, &a.operation)
|
||||
} else {
|
||||
p := &Path{}
|
||||
p.oprationAssign(a.method, &a.operation)
|
||||
p.oprationAssign(a.route.Method, &a.operation)
|
||||
r.spec.Paths[path] = p
|
||||
}
|
||||
return nil
|
||||
@ -86,10 +86,14 @@ func (p *Path) oprationAssign(method string, operation *Operation) {
|
||||
p.Post = operation
|
||||
case echo.PUT:
|
||||
p.Put = operation
|
||||
case echo.PATCH:
|
||||
p.Patch = operation
|
||||
case echo.DELETE:
|
||||
p.Delete = operation
|
||||
case echo.OPTIONS:
|
||||
p.Options = operation
|
||||
case echo.HEAD:
|
||||
p.Head = operation
|
||||
case echo.PATCH:
|
||||
p.Patch = operation
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ func isValidParam(t reflect.Type, nest, inner bool) bool {
|
||||
case reflect.Ptr:
|
||||
return isValidParam(t.Elem(), nest, inner)
|
||||
case reflect.Struct:
|
||||
if t == reflect.TypeOf(time.Time{}) {
|
||||
if t == reflect.TypeOf(time.Time{}) && (!nest || nest && inner) {
|
||||
return true
|
||||
} else if !inner {
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
|
114
wrapper.go
114
wrapper.go
@ -21,23 +21,32 @@ Notice:
|
||||
*/
|
||||
|
||||
type ApiRouter interface {
|
||||
// GET overrides `Echo#GET()` for sub-routes within the ApiGroup.
|
||||
// GET overrides `Echo#GET()` and creates Api.
|
||||
GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api
|
||||
|
||||
// POST overrides `Echo#POST()` for sub-routes within the ApiGroup.
|
||||
// POST overrides `Echo#POST()` and creates Api.
|
||||
POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api
|
||||
|
||||
// PUT overrides `Echo#PUT()` for sub-routes within the ApiGroup.
|
||||
// PUT overrides `Echo#PUT()` and creates Api.
|
||||
PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api
|
||||
|
||||
// DELETE overrides `Echo#DELETE()` for sub-routes within the ApiGroup.
|
||||
// DELETE overrides `Echo#DELETE()` and creates Api.
|
||||
DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api
|
||||
|
||||
// OPTIONS overrides `Echo#OPTIONS()` and creates Api.
|
||||
OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api
|
||||
|
||||
// HEAD overrides `Echo#HEAD()` and creates Api.
|
||||
HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api
|
||||
|
||||
// PATCH overrides `Echo#PATCH()` and creates Api.
|
||||
PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api
|
||||
}
|
||||
|
||||
type ApiRoot interface {
|
||||
ApiRouter
|
||||
|
||||
// ApiGroup creates ApiGroup. Use this instead of Echo#ApiGroup.
|
||||
// Group overrides `Echo#Group()` and creates ApiGroup.
|
||||
Group(name, prefix string, m ...echo.MiddlewareFunc) ApiGroup
|
||||
|
||||
// SetRequestContentType sets request content types.
|
||||
@ -58,13 +67,16 @@ type ApiRoot interface {
|
||||
// AddSecurityOAuth2 adds `SecurityDefinition` with type oauth2.
|
||||
AddSecurityOAuth2(name, desc string, flow OAuth2FlowType, authorizationUrl, tokenUrl string, scopes map[string]string) ApiRoot
|
||||
|
||||
// SetUI sets UI setting.
|
||||
SetUI(ui UISetting) ApiRoot
|
||||
|
||||
// GetRaw returns raw `Swagger`. Only special case should use.
|
||||
GetRaw() *Swagger
|
||||
|
||||
// SetRaw sets raw `Swagger` to ApiRoot. Only special case should use.
|
||||
SetRaw(s *Swagger) ApiRoot
|
||||
|
||||
// Echo returns the embeded echo instance
|
||||
// Echo returns the embedded Echo instance
|
||||
Echo() *echo.Echo
|
||||
}
|
||||
|
||||
@ -78,16 +90,16 @@ type ApiGroup interface {
|
||||
SetExternalDocs(desc, url string) ApiGroup
|
||||
|
||||
// SetSecurity sets Security for all operations within the ApiGroup
|
||||
// which names are reigisters by AddSecurity... functions.
|
||||
// which names are reigistered by AddSecurity... functions.
|
||||
SetSecurity(names ...string) ApiGroup
|
||||
|
||||
// SetSecurity sets Security with scopes for all operations
|
||||
// within the ApiGroup which names are reigisters
|
||||
// SetSecurityWithScope sets Security with scopes for all operations
|
||||
// within the ApiGroup which names are reigistered
|
||||
// by AddSecurity... functions.
|
||||
// Should only use when Security type is oauth2.
|
||||
SetSecurityWithScope(s map[string][]string) ApiGroup
|
||||
|
||||
// EchoGroup returns `*echo.Group` within the ApiGroup.
|
||||
// EchoGroup returns the embedded `echo.Group` instance.
|
||||
EchoGroup() *echo.Group
|
||||
}
|
||||
|
||||
@ -96,36 +108,41 @@ type Api interface {
|
||||
AddParamPath(p interface{}, name, desc string) Api
|
||||
|
||||
// AddParamPathNested adds path parameters nested in p.
|
||||
// P must be struct type.
|
||||
AddParamPathNested(p interface{}) Api
|
||||
|
||||
// AddParamQuery adds query parameter.
|
||||
AddParamQuery(p interface{}, name, desc string, required bool) Api
|
||||
|
||||
// AddParamQueryNested adds query parameters nested in p.
|
||||
// P must be struct type.
|
||||
AddParamQueryNested(p interface{}) Api
|
||||
|
||||
// AddParamForm adds formData parameter.
|
||||
AddParamForm(p interface{}, name, desc string, required bool) Api
|
||||
|
||||
// AddParamFormNested adds formData parameters nested in p.
|
||||
// P must be struct type.
|
||||
AddParamFormNested(p interface{}) Api
|
||||
|
||||
// AddParamHeader adds header parameter.
|
||||
AddParamHeader(p interface{}, name, desc string, required bool) Api
|
||||
|
||||
// AddParamHeaderNested adds header parameters nested in p.
|
||||
// P must be struct type.
|
||||
AddParamHeaderNested(p interface{}) Api
|
||||
|
||||
// AddParamBody adds body parameter.
|
||||
AddParamBody(p interface{}, name, desc string, required bool) Api
|
||||
|
||||
// AddParamBody adds file parameter.
|
||||
// AddParamFile adds file parameter.
|
||||
AddParamFile(name, desc string, required bool) Api
|
||||
|
||||
// AddResponse adds response for Api.
|
||||
// Header must be struct type.
|
||||
AddResponse(code int, desc string, schema interface{}, header interface{}) Api
|
||||
|
||||
// SetResponseContentType sets request content types.
|
||||
// SetRequestContentType sets request content types.
|
||||
SetRequestContentType(types ...string) Api
|
||||
|
||||
// SetResponseContentType sets response content types.
|
||||
@ -134,7 +151,7 @@ type Api interface {
|
||||
// SetOperationId sets operationId
|
||||
SetOperationId(id string) Api
|
||||
|
||||
// SetDescription marks Api as deprecated.
|
||||
// SetDeprecated marks Api as deprecated.
|
||||
SetDeprecated() Api
|
||||
|
||||
// SetDescription sets description.
|
||||
@ -143,19 +160,20 @@ type Api interface {
|
||||
// SetExternalDocs sets external docs.
|
||||
SetExternalDocs(desc, url string) Api
|
||||
|
||||
// SetExternalDocs sets summary.
|
||||
// SetSummary sets summary.
|
||||
SetSummary(summary string) Api
|
||||
|
||||
// SetSecurity sets Security which names are reigisters
|
||||
// SetSecurity sets Security which names are reigistered
|
||||
// by AddSecurity... functions.
|
||||
SetSecurity(names ...string) Api
|
||||
|
||||
// SetSecurity sets Security for Api which names are
|
||||
// reigisters by AddSecurity... functions.
|
||||
// SetSecurityWithScope sets Security for Api which names are
|
||||
// reigistered by AddSecurity... functions.
|
||||
// Should only use when Security type is oauth2.
|
||||
SetSecurityWithScope(s map[string][]string) Api
|
||||
|
||||
// TODO return echo.Router
|
||||
// Route returns the embedded `echo.Route` instance.
|
||||
Route() *echo.Route
|
||||
}
|
||||
|
||||
type routers struct {
|
||||
@ -168,6 +186,7 @@ type Root struct {
|
||||
spec *Swagger
|
||||
echo *echo.Echo
|
||||
groups []group
|
||||
ui UISetting
|
||||
once sync.Once
|
||||
err error
|
||||
}
|
||||
@ -183,7 +202,6 @@ type api struct {
|
||||
route *echo.Route
|
||||
defs *RawDefineDic
|
||||
security []map[string][]string
|
||||
method string
|
||||
operation Operation
|
||||
}
|
||||
|
||||
@ -227,24 +245,36 @@ func New(e *echo.Echo, basePath, docPath string, i *Info) ApiRoot {
|
||||
}
|
||||
|
||||
func (r *Root) GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
return r.appendRoute(echo.GET, r.echo.GET(path, h, m...))
|
||||
return r.appendRoute(r.echo.GET(path, h, m...))
|
||||
}
|
||||
|
||||
func (r *Root) POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
return r.appendRoute(echo.POST, r.echo.POST(path, h, m...))
|
||||
return r.appendRoute(r.echo.POST(path, h, m...))
|
||||
}
|
||||
|
||||
func (r *Root) PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
return r.appendRoute(echo.PUT, r.echo.PUT(path, h, m...))
|
||||
return r.appendRoute(r.echo.PUT(path, h, m...))
|
||||
}
|
||||
|
||||
func (r *Root) DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
return r.appendRoute(echo.DELETE, r.echo.DELETE(path, h, m...))
|
||||
return r.appendRoute(r.echo.DELETE(path, h, m...))
|
||||
}
|
||||
|
||||
func (r *Root) OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
return r.appendRoute(r.echo.OPTIONS(path, h, m...))
|
||||
}
|
||||
|
||||
func (r *Root) HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
return r.appendRoute(r.echo.HEAD(path, h, m...))
|
||||
}
|
||||
|
||||
func (r *Root) PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
return r.appendRoute(r.echo.PATCH(path, h, m...))
|
||||
}
|
||||
|
||||
func (r *Root) Group(name, prefix string, m ...echo.MiddlewareFunc) ApiGroup {
|
||||
if name == "" {
|
||||
panic("echowagger: invalid name of ApiGroup")
|
||||
panic("echoswagger: invalid name of ApiGroup")
|
||||
}
|
||||
echoGroup := r.echo.Group(prefix, m...)
|
||||
group := group{
|
||||
@ -330,6 +360,11 @@ func (r *Root) AddSecurityOAuth2(name, desc string, flow OAuth2FlowType, authori
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Root) SetUI(ui UISetting) ApiRoot {
|
||||
r.ui = ui
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Root) GetRaw() *Swagger {
|
||||
return r.spec
|
||||
}
|
||||
@ -344,25 +379,43 @@ func (r *Root) Echo() *echo.Echo {
|
||||
}
|
||||
|
||||
func (g *group) GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
a := g.appendRoute(echo.GET, g.echoGroup.GET(path, h, m...))
|
||||
a := g.appendRoute(g.echoGroup.GET(path, h, m...))
|
||||
a.operation.Tags = []string{g.tag.Name}
|
||||
return a
|
||||
}
|
||||
|
||||
func (g *group) POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
a := g.appendRoute(echo.POST, g.echoGroup.POST(path, h, m...))
|
||||
a := g.appendRoute(g.echoGroup.POST(path, h, m...))
|
||||
a.operation.Tags = []string{g.tag.Name}
|
||||
return a
|
||||
}
|
||||
|
||||
func (g *group) PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
a := g.appendRoute(echo.PUT, g.echoGroup.PUT(path, h, m...))
|
||||
a := g.appendRoute(g.echoGroup.PUT(path, h, m...))
|
||||
a.operation.Tags = []string{g.tag.Name}
|
||||
return a
|
||||
}
|
||||
|
||||
func (g *group) DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
a := g.appendRoute(echo.DELETE, g.echoGroup.DELETE(path, h, m...))
|
||||
a := g.appendRoute(g.echoGroup.DELETE(path, h, m...))
|
||||
a.operation.Tags = []string{g.tag.Name}
|
||||
return a
|
||||
}
|
||||
|
||||
func (g *group) OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
a := g.appendRoute(g.echoGroup.OPTIONS(path, h, m...))
|
||||
a.operation.Tags = []string{g.tag.Name}
|
||||
return a
|
||||
}
|
||||
|
||||
func (g *group) HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
a := g.appendRoute(g.echoGroup.HEAD(path, h, m...))
|
||||
a.operation.Tags = []string{g.tag.Name}
|
||||
return a
|
||||
}
|
||||
|
||||
func (g *group) PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api {
|
||||
a := g.appendRoute(g.echoGroup.PATCH(path, h, m...))
|
||||
a.operation.Tags = []string{g.tag.Name}
|
||||
return a
|
||||
}
|
||||
@ -445,7 +498,6 @@ func (a *api) AddParamFile(name, desc string, required bool) Api {
|
||||
return a
|
||||
}
|
||||
|
||||
// Notice: header must be nested in a struct.
|
||||
func (a *api) AddResponse(code int, desc string, schema interface{}, header interface{}) Api {
|
||||
r := &Response{
|
||||
Description: desc,
|
||||
@ -522,3 +574,7 @@ func (a *api) SetSecurityWithScope(s map[string][]string) Api {
|
||||
a.security = setSecurityWithScope(a.security, s)
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *api) Route() *echo.Route {
|
||||
return a.route
|
||||
}
|
||||
|
355
wrapper_test.go
355
wrapper_test.go
@ -1,12 +1,31 @@
|
||||
package echoswagger
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func prepareApiRoot() ApiRoot {
|
||||
return New(echo.New(), "/", "doc/", nil)
|
||||
}
|
||||
|
||||
func prepareApiGroup() ApiGroup {
|
||||
r := prepareApiRoot()
|
||||
return r.Group("G", "/g")
|
||||
}
|
||||
|
||||
func prepareApi() Api {
|
||||
g := prepareApiGroup()
|
||||
var h func(e echo.Context) error
|
||||
return g.POST("", h)
|
||||
}
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
tests := []struct {
|
||||
echo *echo.Echo
|
||||
@ -56,22 +75,342 @@ func TestNew(t *testing.T) {
|
||||
apiRoot := New(tt.echo, tt.basePath, tt.docPath, tt.info)
|
||||
assert.NotNil(t, apiRoot.(*Root))
|
||||
|
||||
root := apiRoot.(*Root)
|
||||
assert.NotNil(t, root.spec)
|
||||
r := apiRoot.(*Root)
|
||||
assert.NotNil(t, r.spec)
|
||||
|
||||
assert.Equal(t, root.spec.BasePath, tt.basePath)
|
||||
assert.Equal(t, r.spec.BasePath, tt.basePath)
|
||||
if tt.info == nil {
|
||||
assert.Equal(t, root.spec.Info.Title, "Project APIs")
|
||||
assert.Equal(t, r.spec.Info.Title, "Project APIs")
|
||||
} else {
|
||||
assert.Equal(t, root.spec.Info, tt.info)
|
||||
assert.Equal(t, r.spec.Info, tt.info)
|
||||
}
|
||||
|
||||
assert.NotNil(t, root.echo)
|
||||
assert.Len(t, root.echo.Routes(), 2)
|
||||
res := root.echo.Routes()
|
||||
assert.NotNil(t, r.echo)
|
||||
assert.Len(t, r.echo.Routes(), 2)
|
||||
res := r.echo.Routes()
|
||||
paths := []string{res[0].Path, res[1].Path}
|
||||
assert.ElementsMatch(t, paths, tt.expectPaths)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroup(t *testing.T) {
|
||||
r := prepareApiRoot()
|
||||
t.Run("Normal", func(t *testing.T) {
|
||||
g := r.Group("Users", "users")
|
||||
assert.Equal(t, g.(*group).defs, r.(*Root).defs)
|
||||
})
|
||||
|
||||
t.Run("Invalid name", func(t *testing.T) {
|
||||
assert.Panics(t, func() {
|
||||
r.Group("", "")
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Repeat name", func(t *testing.T) {
|
||||
ga := r.Group("Users", "users")
|
||||
assert.Equal(t, ga.(*group).tag.Name, "Users_1")
|
||||
|
||||
gb := r.Group("Users", "users")
|
||||
assert.Equal(t, gb.(*group).tag.Name, "Users_2")
|
||||
})
|
||||
}
|
||||
|
||||
func TestRouters(t *testing.T) {
|
||||
r := prepareApiRoot()
|
||||
var h echo.HandlerFunc
|
||||
r.GET("/:id", h)
|
||||
r.POST("/:id", h)
|
||||
r.PUT("/:id", h)
|
||||
r.DELETE("/:id", h)
|
||||
r.OPTIONS("/:id", h)
|
||||
r.HEAD("/:id", h)
|
||||
r.PATCH("/:id", h)
|
||||
assert.Len(t, r.(*Root).apis, 7)
|
||||
|
||||
g := prepareApiGroup()
|
||||
g.GET("/:id", h)
|
||||
g.POST("/:id", h)
|
||||
g.PUT("/:id", h)
|
||||
g.DELETE("/:id", h)
|
||||
g.OPTIONS("/:id", h)
|
||||
g.HEAD("/:id", h)
|
||||
g.PATCH("/:id", h)
|
||||
assert.Len(t, g.(*group).apis, 7)
|
||||
}
|
||||
|
||||
func TestAddParam(t *testing.T) {
|
||||
name := "name"
|
||||
desc := "Param desc"
|
||||
type nested struct {
|
||||
Name string `json:"name" form:"name" query:"name"`
|
||||
Enable bool `json:"-" form:"-" query:"-"`
|
||||
}
|
||||
|
||||
t.Run("File", func(t *testing.T) {
|
||||
a := prepareApi()
|
||||
a.AddParamFile(name, desc, true)
|
||||
assert.Len(t, a.(*api).operation.Parameters, 1)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Name, name)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].In, string(ParamInFormData))
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Description, desc)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Required, true)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Type, "file")
|
||||
})
|
||||
|
||||
t.Run("Path", func(t *testing.T) {
|
||||
a := prepareApi()
|
||||
a.AddParamPath(time.Now(), name, desc)
|
||||
assert.Len(t, a.(*api).operation.Parameters, 1)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Name, name)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].In, string(ParamInPath))
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Description, desc)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Required, true)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Type, "string")
|
||||
|
||||
a.AddParamPathNested(&nested{})
|
||||
assert.Len(t, a.(*api).operation.Parameters, 2)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[1].Name, "name_")
|
||||
assert.Equal(t, a.(*api).operation.Parameters[1].In, string(ParamInPath))
|
||||
assert.Equal(t, a.(*api).operation.Parameters[1].Type, "string")
|
||||
})
|
||||
|
||||
t.Run("Query", func(t *testing.T) {
|
||||
a := prepareApi()
|
||||
a.AddParamQuery(time.Now(), name, desc, true)
|
||||
assert.Len(t, a.(*api).operation.Parameters, 1)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Name, name)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].In, string(ParamInQuery))
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Description, desc)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Required, true)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Type, "string")
|
||||
|
||||
a.AddParamQueryNested(&nested{})
|
||||
assert.Len(t, a.(*api).operation.Parameters, 2)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[1].Name, "name_")
|
||||
assert.Equal(t, a.(*api).operation.Parameters[1].In, string(ParamInQuery))
|
||||
assert.Equal(t, a.(*api).operation.Parameters[1].Type, "string")
|
||||
})
|
||||
|
||||
t.Run("FormData", func(t *testing.T) {
|
||||
a := prepareApi()
|
||||
a.AddParamForm(time.Now(), name, desc, true)
|
||||
assert.Len(t, a.(*api).operation.Parameters, 1)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Name, name)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].In, string(ParamInFormData))
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Description, desc)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Required, true)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Type, "string")
|
||||
|
||||
a.AddParamFormNested(&nested{})
|
||||
assert.Len(t, a.(*api).operation.Parameters, 2)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[1].Name, "name_")
|
||||
assert.Equal(t, a.(*api).operation.Parameters[1].In, string(ParamInFormData))
|
||||
assert.Equal(t, a.(*api).operation.Parameters[1].Type, "string")
|
||||
})
|
||||
|
||||
t.Run("Header", func(t *testing.T) {
|
||||
a := prepareApi()
|
||||
a.AddParamHeader(time.Now(), name, desc, true)
|
||||
assert.Len(t, a.(*api).operation.Parameters, 1)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Name, name)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].In, string(ParamInHeader))
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Description, desc)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Required, true)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Type, "string")
|
||||
|
||||
a.AddParamHeaderNested(&nested{})
|
||||
assert.Len(t, a.(*api).operation.Parameters, 2)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[1].Name, "name_")
|
||||
assert.Equal(t, a.(*api).operation.Parameters[1].In, string(ParamInHeader))
|
||||
assert.Equal(t, a.(*api).operation.Parameters[1].Type, "string")
|
||||
})
|
||||
}
|
||||
|
||||
func TestAddSchema(t *testing.T) {
|
||||
type body struct {
|
||||
Name string `json:"name"`
|
||||
Enable bool `json:"-"`
|
||||
}
|
||||
|
||||
t.Run("Multiple", func(t *testing.T) {
|
||||
a := prepareApi()
|
||||
a.AddParamBody(&body{}, "body", "body desc", true)
|
||||
assert.Len(t, a.(*api).operation.Parameters, 1)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Name, "body")
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].In, string(ParamInBody))
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Description, "body desc")
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Required, true)
|
||||
|
||||
assert.Panics(t, func() {
|
||||
a.AddParamBody(body{}, "body", "body desc", true)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("GetKey", func(t *testing.T) {
|
||||
a := prepareApi()
|
||||
a.AddParamBody(&body{}, "body", "body desc", true)
|
||||
assert.Len(t, a.(*api).operation.Parameters, 1)
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Name, "body")
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].In, string(ParamInBody))
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Description, "body desc")
|
||||
assert.Equal(t, a.(*api).operation.Parameters[0].Required, true)
|
||||
|
||||
a.AddResponse(http.StatusOK, "response desc", body{}, nil)
|
||||
ca := strconv.Itoa(http.StatusOK)
|
||||
assert.Len(t, a.(*api).operation.Responses, 1)
|
||||
assert.Equal(t, a.(*api).operation.Responses[ca].Description, "response desc")
|
||||
|
||||
assert.NotNil(t, a.(*api).defs)
|
||||
da := a.(*api).defs
|
||||
assert.Len(t, (*da), 1)
|
||||
assert.NotNil(t, (*da)["body"])
|
||||
|
||||
a.AddResponse(http.StatusBadRequest, "response desc", body{Name: "name"}, nil)
|
||||
cb := strconv.Itoa(http.StatusBadRequest)
|
||||
assert.Len(t, a.(*api).operation.Responses, 2)
|
||||
assert.Equal(t, a.(*api).operation.Responses[cb].Description, "response desc")
|
||||
|
||||
assert.NotNil(t, a.(*api).defs)
|
||||
db := a.(*api).defs
|
||||
assert.Len(t, (*db), 2)
|
||||
assert.NotNil(t, (*db)["body"])
|
||||
})
|
||||
}
|
||||
|
||||
func TestAddResponse(t *testing.T) {
|
||||
a := prepareApi()
|
||||
a.AddResponse(http.StatusOK, "successful", nil, nil)
|
||||
var f = func() {}
|
||||
assert.Panics(t, func() {
|
||||
a.AddResponse(http.StatusBadRequest, "bad request", f, nil)
|
||||
})
|
||||
assert.Panics(t, func() {
|
||||
a.AddResponse(http.StatusBadRequest, "bad request", nil, time.Now())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUI(t *testing.T) {
|
||||
r := New(echo.New(), "/", "doc/", nil)
|
||||
cdn := "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.18.1"
|
||||
r.SetUI(UISetting{
|
||||
HideTop: true,
|
||||
CDN: cdn,
|
||||
})
|
||||
se := r.(*Root)
|
||||
req := httptest.NewRequest(echo.GET, "/doc/", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
c := se.echo.NewContext(req, rec)
|
||||
|
||||
h := se.docHandler("/doc/swagger.json")
|
||||
if assert.NoError(t, h(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
assert.Contains(t, rec.Body.String(), cdn)
|
||||
assert.Contains(t, rec.Body.String(), "#swagger-ui>.swagger-container>.topbar")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRaw(t *testing.T) {
|
||||
r := prepareApiRoot()
|
||||
s := r.GetRaw()
|
||||
assert.NotNil(t, s)
|
||||
assert.NotNil(t, s.Info)
|
||||
assert.Equal(t, s.Info.Version, "")
|
||||
|
||||
s.Info.Version = "1.0"
|
||||
r.SetRaw(s)
|
||||
assert.Equal(t, s.Info.Version, "1.0")
|
||||
}
|
||||
|
||||
func TestContentType(t *testing.T) {
|
||||
c := []string{"application/x-www-form-urlencoded", "multipart/form-data"}
|
||||
p := []string{"application/vnd.github.v3+json", "application/vnd.github.v3.raw+json", "application/vnd.github.v3.text+json"}
|
||||
|
||||
t.Run("In Root", func(t *testing.T) {
|
||||
r := prepareApiRoot()
|
||||
r.SetRequestContentType(c...)
|
||||
r.SetResponseContentType(p...)
|
||||
assert.NotNil(t, r.(*Root))
|
||||
assert.NotNil(t, r.(*Root).spec)
|
||||
assert.Len(t, r.(*Root).spec.Consumes, 2)
|
||||
assert.ElementsMatch(t, r.(*Root).spec.Consumes, c)
|
||||
assert.Len(t, r.(*Root).spec.Produces, 3)
|
||||
assert.ElementsMatch(t, r.(*Root).spec.Produces, p)
|
||||
})
|
||||
|
||||
t.Run("In Api", func(t *testing.T) {
|
||||
a := prepareApi()
|
||||
a.SetRequestContentType(c...)
|
||||
a.SetResponseContentType(p...)
|
||||
assert.NotNil(t, a.(*api))
|
||||
assert.Len(t, a.(*api).operation.Consumes, 2)
|
||||
assert.ElementsMatch(t, a.(*api).operation.Consumes, c)
|
||||
assert.Len(t, a.(*api).operation.Produces, 3)
|
||||
assert.ElementsMatch(t, a.(*api).operation.Produces, p)
|
||||
})
|
||||
}
|
||||
|
||||
func TestOperationId(t *testing.T) {
|
||||
id := "TestOperation"
|
||||
|
||||
a := prepareApi()
|
||||
a.SetOperationId(id)
|
||||
assert.Equal(t, a.(*api).operation.OperationID, id)
|
||||
}
|
||||
|
||||
func TestDeprecated(t *testing.T) {
|
||||
a := prepareApi()
|
||||
a.SetDeprecated()
|
||||
assert.Equal(t, a.(*api).operation.Deprecated, true)
|
||||
}
|
||||
|
||||
func TestDescription(t *testing.T) {
|
||||
d := "Test desc"
|
||||
|
||||
g := prepareApiGroup()
|
||||
g.SetDescription(d)
|
||||
assert.Equal(t, g.(*group).tag.Description, d)
|
||||
|
||||
a := prepareApi()
|
||||
a.SetDescription(d)
|
||||
assert.Equal(t, a.(*api).operation.Description, d)
|
||||
}
|
||||
|
||||
func TestExternalDocs(t *testing.T) {
|
||||
e := ExternalDocs{
|
||||
Description: "Test desc",
|
||||
URL: "http://127.0.0.1/",
|
||||
}
|
||||
|
||||
r := prepareApiRoot()
|
||||
r.SetExternalDocs(e.Description, e.URL)
|
||||
assert.Equal(t, r.(*Root).spec.ExternalDocs, &e)
|
||||
|
||||
g := prepareApiGroup()
|
||||
g.SetExternalDocs(e.Description, e.URL)
|
||||
assert.Equal(t, g.(*group).tag.ExternalDocs, &e)
|
||||
|
||||
a := prepareApi()
|
||||
a.SetExternalDocs(e.Description, e.URL)
|
||||
assert.Equal(t, a.(*api).operation.ExternalDocs, &e)
|
||||
}
|
||||
|
||||
func TestSummary(t *testing.T) {
|
||||
s := "Test summary"
|
||||
|
||||
a := prepareApi()
|
||||
a.SetSummary(s)
|
||||
assert.Equal(t, a.(*api).operation.Summary, s)
|
||||
}
|
||||
|
||||
func TestEcho(t *testing.T) {
|
||||
r := prepareApiRoot()
|
||||
assert.NotNil(t, r.Echo())
|
||||
|
||||
g := prepareApiGroup()
|
||||
assert.NotNil(t, g.EchoGroup())
|
||||
|
||||
a := prepareApi()
|
||||
assert.NotNil(t, a.Route())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user