gf/net/goai/goai_z_unit_test.go
2023-08-07 20:39:01 +08:00

1194 lines
40 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package goai_test
import (
"context"
"fmt"
"net/http"
"testing"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/net/goai"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/util/gmeta"
"github.com/gogf/gf/v2/util/gtag"
)
func Test_Basic(t *testing.T) {
type CommonReq struct {
AppId int64 `json:"appId" v:"required" in:"cookie" description:"应用Id"`
ResourceId string `json:"resourceId" in:"query" description:"资源Id"`
}
type SetSpecInfo struct {
StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" description:"StorageType"`
Shards int32 `description:"shards 分片数"`
Params []string `description:"默认参数(json 串-ClickHouseParams)"`
}
type CreateResourceReq struct {
CommonReq
gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"`
Name string `description:"实例名称"`
Product string `description:"业务类型"`
Region string `v:"required" description:"区域"`
SetMap map[string]*SetSpecInfo `v:"required" description:"配置Map"`
SetSlice []SetSpecInfo `v:"required" description:"配置Slice"`
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
req = new(CreateResourceReq)
)
err = oai.Add(goai.AddInput{
Object: req,
})
t.AssertNil(err)
// Schema asserts.
t.Assert(len(oai.Components.Schemas.Map()), 2)
t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Type, goai.TypeObject)
t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Map()), 7)
t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Get(`appId`).Value.Type, goai.TypeInteger)
t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Get(`resourceId`).Value.Type, goai.TypeString)
t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Map()), 3)
t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Get(`Params`).Value.Type, goai.TypeArray)
})
}
func TestOpenApiV3_Add(t *testing.T) {
type CommonReq struct {
AppId int64 `json:"appId" v:"required" in:"path" description:"应用Id"`
ResourceId string `json:"resourceId" in:"query" description:"资源Id"`
}
type SetSpecInfo struct {
StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" description:"StorageType"`
Shards int32 `description:"shards 分片数"`
Params []string `description:"默认参数(json 串-ClickHouseParams)"`
}
type CreateResourceReq struct {
CommonReq
gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"`
Name string `description:"实例名称"`
Product string `description:"业务类型"`
Region string `v:"required" description:"区域"`
SetMap map[string]*SetSpecInfo `v:"required" description:"配置Map"`
SetSlice []SetSpecInfo `v:"required" description:"配置Slice"`
}
type CreateResourceRes struct {
gmeta.Meta `description:"Demo Response Struct"`
FlowId int64 `description:"创建实例流程id"`
}
f := func(ctx context.Context, req *CreateResourceReq) (res *CreateResourceRes, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
err = oai.Add(goai.AddInput{
Path: "/test1/{appId}",
Method: http.MethodPut,
Object: f,
})
t.AssertNil(err)
err = oai.Add(goai.AddInput{
Path: "/test1/{appId}",
Method: http.MethodPost,
Object: f,
})
t.AssertNil(err)
// fmt.Println(oai.String())
// Schema asserts.
t.Assert(len(oai.Components.Schemas.Map()), 3)
t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Type, goai.TypeObject)
t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Map()), 7)
t.Assert(len(oai.Paths["/test1/{appId}"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 5)
t.Assert(len(oai.Paths["/test1/{appId}"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 5)
t.Assert(oai.Paths["/test1/{appId}"].Post.Parameters[0].Value.Schema.Value.Type, goai.TypeInteger)
t.Assert(oai.Paths["/test1/{appId}"].Post.Parameters[1].Value.Schema.Value.Type, goai.TypeString)
t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Map()), 3)
t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Get(`Params`).Value.Type, goai.TypeArray)
// Paths.
t.Assert(len(oai.Paths), 1)
t.AssertNE(oai.Paths[`/test1/{appId}`].Put, nil)
t.Assert(len(oai.Paths[`/test1/{appId}`].Put.Tags), 1)
t.Assert(len(oai.Paths[`/test1/{appId}`].Put.Parameters), 2)
t.AssertNE(oai.Paths[`/test1/{appId}`].Post, nil)
t.Assert(len(oai.Paths[`/test1/{appId}`].Post.Tags), 1)
t.Assert(len(oai.Paths[`/test1/{appId}`].Post.Parameters), 2)
})
}
func TestOpenApiV3_Add_Recursive(t *testing.T) {
type CategoryTreeItem struct {
Id uint `json:"id"`
ParentId uint `json:"parent_id"`
Items []*CategoryTreeItem `json:"items,omitempty"`
}
type CategoryGetTreeReq struct {
gmeta.Meta `path:"/category-get-tree" method:"GET" tags:"default"`
ContentType string `in:"query"`
}
type CategoryGetTreeRes struct {
List []*CategoryTreeItem
}
f := func(ctx context.Context, req *CategoryGetTreeReq) (res *CategoryGetTreeRes, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
err = oai.Add(goai.AddInput{
Path: "/tree",
Object: f,
})
t.AssertNil(err)
// Schema asserts.
t.Assert(len(oai.Components.Schemas.Map()), 3)
t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CategoryTreeItem`).Value.Type, goai.TypeObject)
t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CategoryTreeItem`).Value.Properties.Map()), 3)
})
}
func TestOpenApiV3_Add_EmptyReqAndRes(t *testing.T) {
type CaptchaIndexReq struct {
gmeta.Meta `method:"PUT" summary:"获取默认的验证码" description:"注意直接返回的是图片二进制内容" tags:"前台-验证码"`
}
type CaptchaIndexRes struct {
gmeta.Meta `mime:"png" description:"验证码二进制内容" `
}
f := func(ctx context.Context, req *CaptchaIndexReq) (res *CaptchaIndexRes, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
err = oai.Add(goai.AddInput{
Path: "/tree",
Object: f,
})
t.AssertNil(err)
// Schema asserts.
fmt.Println(oai.String())
})
}
func TestOpenApiV3_Add_AutoDetectIn(t *testing.T) {
type Req struct {
gmeta.Meta `method:"get" tags:"default"`
Name string
Product string
Region string
}
type Res struct {
gmeta.Meta `description:"Demo Response Struct"`
}
f := func(ctx context.Context, req *Req) (res *Res, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
path = `/test/{product}/{name}`
)
err = oai.Add(goai.AddInput{
Path: path,
Method: http.MethodGet,
Object: f,
})
t.AssertNil(err)
fmt.Println(oai.String())
t.Assert(len(oai.Components.Schemas.Map()), 2)
t.Assert(len(oai.Paths), 1)
t.AssertNE(oai.Paths[path].Get, nil)
t.Assert(len(oai.Paths[path].Get.Parameters), 3)
t.Assert(oai.Paths[path].Get.Parameters[0].Value.Name, `Name`)
t.Assert(oai.Paths[path].Get.Parameters[0].Value.In, goai.ParameterInPath)
t.Assert(oai.Paths[path].Get.Parameters[1].Value.Name, `Product`)
t.Assert(oai.Paths[path].Get.Parameters[1].Value.In, goai.ParameterInPath)
t.Assert(oai.Paths[path].Get.Parameters[2].Value.Name, `Region`)
t.Assert(oai.Paths[path].Get.Parameters[2].Value.In, goai.ParameterInQuery)
})
}
func TestOpenApiV3_CommonRequest(t *testing.T) {
type CommonRequest struct {
Code int `json:"code" description:"Error code"`
Message string `json:"message" description:"Error message"`
Data interface{} `json:"data" description:"Result data for certain request according API definition"`
}
type Req struct {
gmeta.Meta `method:"PUT"`
Product string `json:"product" v:"required" description:"Unique product key"`
Name string `json:"name" v:"required" description:"Instance name"`
}
type Res struct {
Product string `json:"product" v:"required" description:"Unique product key"`
TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
Version string `json:"version" v:"required" description:"Workflow template version"`
TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"`
Globals string `json:"globals" description:"Globals"`
}
f := func(ctx context.Context, req *Req) (res *Res, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
oai.Config.CommonRequest = CommonRequest{}
oai.Config.CommonRequestDataField = `Data`
err = oai.Add(goai.AddInput{
Path: "/index",
Object: f,
})
t.AssertNil(err)
// Schema asserts.
t.Assert(len(oai.Components.Schemas.Map()), 3)
t.Assert(len(oai.Paths), 1)
t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3)
})
}
func TestOpenApiV3_CommonRequest_WithoutDataField_Setting(t *testing.T) {
type CommonRequest struct {
Code int `json:"code" description:"Error code"`
Message string `json:"message" description:"Error message"`
Data interface{} `json:"data" description:"Result data for certain request according API definition"`
}
type PutReq struct {
gmeta.Meta `method:"PUT"`
Product string `json:"product" in:"query" v:"required" description:"Unique product key"`
Name string `json:"name" in:"query" v:"required" description:"Instance name"`
}
type PostReq struct {
gmeta.Meta `method:"POST"`
Product string `json:"product" v:"required" description:"Unique product key"`
Name string `json:"name" v:"required" description:"Instance name"`
}
type Res struct {
Product string `json:"product" v:"required" description:"Unique product key"`
TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
Version string `json:"version" v:"required" description:"Workflow template version"`
TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"`
Globals string `json:"globals" description:"Globals"`
}
f := func(ctx context.Context, req *PutReq) (res *Res, err error) {
return
}
f2 := func(ctx context.Context, req *PostReq) (res *Res, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
oai.Config.CommonRequest = CommonRequest{}
err = oai.Add(goai.AddInput{
Path: "/index",
Object: f,
})
t.AssertNil(err)
err = oai.Add(goai.AddInput{
Path: "/index",
Object: f2,
})
t.AssertNil(err)
// Schema asserts.
// fmt.Println(oai.String())
t.Assert(len(oai.Components.Schemas.Map()), 4)
t.Assert(len(oai.Paths), 1)
t.Assert(len(oai.Paths["/index"].Put.Parameters), 2)
t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3)
t.Assert(len(oai.Paths["/index"].Post.Parameters), 0)
t.Assert(len(oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 5)
})
}
func TestOpenApiV3_CommonRequest_EmptyRequest(t *testing.T) {
type CommonRequest struct {
Code int `json:"code" description:"Error code"`
Message string `json:"message" description:"Error message"`
Data interface{} `json:"data" description:"Result data for certain request according API definition"`
}
type Req struct {
gmeta.Meta `method:"Put"`
Product string `json:"product" in:"query" v:"required" description:"Unique product key"`
Name string `json:"name" in:"query" v:"required" description:"Instance name"`
}
type Res struct{}
f := func(ctx context.Context, req *Req) (res *Res, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
oai.Config.CommonRequest = CommonRequest{}
oai.Config.CommonRequestDataField = `Data`
err = oai.Add(goai.AddInput{
Path: "/index",
Object: f,
})
t.AssertNil(err)
// Schema asserts.
// fmt.Println(oai.String())
t.Assert(len(oai.Components.Schemas.Map()), 3)
t.Assert(len(oai.Paths), 1)
t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3)
})
}
func TestOpenApiV3_CommonRequest_SubDataField(t *testing.T) {
type CommonReqError struct {
Code string `description:"错误码"`
Message string `description:"错误描述"`
}
type CommonReqRequest struct {
RequestId string `description:"RequestId"`
Error *CommonReqError `json:",omitempty" description:"执行错误信息"`
}
type CommonReq struct {
Request CommonReqRequest
}
type PutReq struct {
gmeta.Meta `method:"Put"`
Product string `json:"product" in:"query" v:"required" description:"Unique product key"`
Name string `json:"name" in:"query" v:"required" description:"Instance name"`
}
type PostReq struct {
gmeta.Meta `method:"Post"`
Product string `json:"product" v:"required" description:"Unique product key"`
Name string `json:"name" v:"required" description:"Instance name"`
}
type Res struct {
Product string `json:"product" v:"required" description:"Unique product key"`
TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
Version string `json:"version" v:"required" description:"Workflow template version"`
TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"`
Globals string `json:"globals" description:"Globals"`
}
f := func(ctx context.Context, req *PutReq) (res *Res, err error) {
return
}
f2 := func(ctx context.Context, req *PostReq) (res *Res, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
oai.Config.CommonRequest = CommonReq{}
oai.Config.CommonRequestDataField = `Request.`
err = oai.Add(goai.AddInput{
Path: "/index",
Object: f,
})
t.AssertNil(err)
err = oai.Add(goai.AddInput{
Path: "/index",
Object: f2,
})
t.AssertNil(err)
// Schema asserts.
// fmt.Println(oai.String())
t.Assert(len(oai.Components.Schemas.Map()), 5)
t.Assert(len(oai.Paths), 1)
t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 1)
t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Get(`Request`).Value.Properties.Map()), 2)
t.Assert(len(oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 1)
t.Assert(len(oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Get(`Request`).Value.Properties.Map()), 4)
})
}
func TestOpenApiV3_CommonResponse(t *testing.T) {
type CommonResponse struct {
Code int `json:"code" description:"Error code"`
Message string `json:"message" description:"Error message"`
Data interface{} `json:"data" description:"Result data for certain request according API definition"`
}
type Req struct {
gmeta.Meta `method:"GET"`
Product string `json:"product" in:"query" v:"required" description:"Unique product key"`
Name string `json:"name" in:"query" v:"required" description:"Instance name"`
}
type Res struct {
Product string `json:"product" v:"required" description:"Unique product key"`
TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
Version string `json:"version" v:"required" description:"Workflow template version"`
TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"`
Globals string `json:"globals" description:"Globals"`
}
f := func(ctx context.Context, req *Req) (res *Res, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
oai.Config.CommonResponse = CommonResponse{}
oai.Config.CommonResponseDataField = `Data`
err = oai.Add(goai.AddInput{
Path: "/index",
Object: f,
})
t.AssertNil(err)
//g.Dump(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map())
// Schema asserts.
t.Assert(len(oai.Components.Schemas.Map()), 3)
t.Assert(len(oai.Paths), 1)
t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3)
t.Assert(
oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Get("data").Value.Description,
`Result data for certain request according API definition`,
)
})
}
func TestOpenApiV3_CommonResponse_WithoutDataField_Setting(t *testing.T) {
type CommonResponse struct {
Code int `json:"code" description:"Error code"`
Message string `json:"message" description:"Error message"`
Data interface{} `json:"data" description:"Result data for certain request according API definition"`
}
type Req struct {
gmeta.Meta `method:"GET"`
Product string `json:"product" in:"query" v:"required" description:"Unique product key"`
Name string `json:"name" in:"query" v:"required" description:"Instance name"`
}
type Res struct {
Product string `json:"product" v:"required" description:"Unique product key"`
TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
Version string `json:"version" v:"required" description:"Workflow template version"`
TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"`
Globals string `json:"globals" description:"Globals"`
}
f := func(ctx context.Context, req *Req) (res *Res, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
oai.Config.CommonResponse = CommonResponse{}
err = oai.Add(goai.AddInput{
Path: "/index",
Object: f,
})
t.AssertNil(err)
// Schema asserts.
fmt.Println(oai.String())
t.Assert(len(oai.Components.Schemas.Map()), 3)
t.Assert(len(oai.Paths), 1)
t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 8)
})
}
func TestOpenApiV3_CommonResponse_EmptyResponse(t *testing.T) {
type CommonResponse struct {
Code int `json:"code" description:"Error code"`
Message string `json:"message" description:"Error message"`
Data interface{} `json:"data" description:"Result data for certain request according API definition"`
}
type Req struct {
gmeta.Meta `method:"PUT"`
Product string `json:"product" v:"required" description:"Unique product key"`
Name string `json:"name" v:"required" description:"Instance name"`
}
type Res struct{}
f := func(ctx context.Context, req *Req) (res *Res, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
oai.Config.CommonResponse = CommonResponse{}
oai.Config.CommonResponseDataField = `Data`
err = oai.Add(goai.AddInput{
Path: "/index",
Object: f,
})
t.AssertNil(err)
// Schema asserts.
// fmt.Println(oai.String())
t.Assert(len(oai.Components.Schemas.Map()), 3)
t.Assert(len(oai.Paths), 1)
t.Assert(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Ref, `github.com.gogf.gf.v2.net.goai_test.Req`)
t.Assert(len(oai.Paths["/index"].Put.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3)
})
}
func TestOpenApiV3_CommonResponse_SubDataField(t *testing.T) {
type CommonResError struct {
Code string `description:"错误码"`
Message string `description:"错误描述"`
}
type CommonResResponse struct {
RequestId string `description:"RequestId"`
Error *CommonResError `json:",omitempty" description:"执行错误信息"`
}
type CommonRes struct {
Response CommonResResponse
}
type Req struct {
gmeta.Meta `method:"GET"`
Product string `json:"product" in:"query" v:"required" description:"Unique product key"`
Name string `json:"name" in:"query" v:"required" description:"Instance name"`
}
type Res struct {
Product string `json:"product" v:"required" description:"Unique product key"`
TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
Version string `json:"version" v:"required" description:"Workflow template version"`
TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"`
Globals string `json:"globals" description:"Globals"`
}
f := func(ctx context.Context, req *Req) (res *Res, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
oai.Config.CommonResponse = CommonRes{}
oai.Config.CommonResponseDataField = `Response.`
err = oai.Add(goai.AddInput{
Path: "/index",
Object: f,
})
t.AssertNil(err)
// Schema asserts.
// fmt.Println(oai.String())
t.Assert(len(oai.Components.Schemas.Map()), 4)
t.Assert(len(oai.Paths), 1)
t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 1)
t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Get(`Response`).Value.Properties.Map()), 7)
})
}
func TestOpenApiV3_ShortTags(t *testing.T) {
type CommonReq struct {
AppId int64 `json:"appId" v:"required" in:"path" dc:"应用Id" sm:"应用Id Summary"`
ResourceId string `json:"resourceId" in:"query" dc:"资源Id" sm:"资源Id Summary"`
}
type SetSpecInfo struct {
StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" dc:"StorageType"`
Shards int32 `dc:"shards 分片数" sm:"Shards Summary"`
Params []string `dc:"默认参数(json 串-ClickHouseParams)" sm:"Params Summary"`
}
type CreateResourceReq struct {
CommonReq
gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sm:"CreateResourceReq sum" dc:"CreateResourceReq des"`
Name string `dc:"实例名称"`
Product string `dc:"业务类型"`
Region string `v:"required" dc:"区域"`
SetMap map[string]*SetSpecInfo `v:"required" dc:"配置Map"`
SetSlice []SetSpecInfo `v:"required" dc:"配置Slice"`
}
type CreateResourceRes struct {
gmeta.Meta `dc:"Demo Response Struct"`
FlowId int64 `dc:"创建实例流程id"`
}
f := func(ctx context.Context, req *CreateResourceReq) (res *CreateResourceRes, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
err = oai.Add(goai.AddInput{
Path: "/test1/{appId}",
Method: http.MethodPut,
Object: f,
})
t.AssertNil(err)
err = oai.Add(goai.AddInput{
Path: "/test1/{appId}",
Method: http.MethodPost,
Object: f,
})
t.AssertNil(err)
// fmt.Println(oai.String())
// Schema asserts.
t.Assert(len(oai.Components.Schemas.Map()), 3)
t.Assert(oai.Paths[`/test1/{appId}`].Summary, ``)
t.Assert(oai.Paths[`/test1/{appId}`].Description, ``)
t.Assert(oai.Paths[`/test1/{appId}`].Put.Summary, `CreateResourceReq sum`)
t.Assert(oai.Paths[`/test1/{appId}`].Put.Description, `CreateResourceReq des`)
t.Assert(oai.Paths[`/test1/{appId}`].Put.Parameters[1].Value.Schema.Value.Description, `资源Id`)
t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Get(`Name`).Value.Description, `实例名称`)
})
}
func TestOpenApiV3_HtmlResponse(t *testing.T) {
type Req struct {
g.Meta `path:"/test" method:"get" summary:"展示内容详情页面" tags:"内容"`
Id uint `json:"id" v:"min:1#请选择查看的内容" dc:"内容id"`
}
type Res struct {
g.Meta `mime:"text/html" type:"string" example:"<html/>"`
}
f := func(ctx context.Context, req *Req) (res *Res, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
err = oai.Add(goai.AddInput{
Path: "/test",
Method: http.MethodGet,
Object: f,
})
t.AssertNil(err)
// fmt.Println(oai.String())
t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`).Value.Type, goai.TypeString)
})
}
func TestOpenApiV3_HtmlResponseWithCommonResponse(t *testing.T) {
type CommonResError struct {
Code string `description:"错误码"`
Message string `description:"错误描述"`
}
type CommonResResponse struct {
RequestId string `description:"RequestId"`
Error *CommonResError `json:",omitempty" description:"执行错误信息"`
}
type CommonRes struct {
Response CommonResResponse
}
type Req struct {
g.Meta `path:"/test" method:"get" summary:"展示内容详情页面" tags:"内容"`
Id uint `json:"id" v:"min:1#请选择查看的内容" dc:"内容id"`
}
type Res struct {
g.Meta `mime:"text/html" type:"string" example:"<html/>"`
}
f := func(ctx context.Context, req *Req) (res *Res, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
oai.Config.CommonResponse = CommonRes{}
oai.Config.CommonResponseDataField = `Response.`
err = oai.Add(goai.AddInput{
Path: "/test",
Method: http.MethodGet,
Object: f,
})
t.AssertNil(err)
// fmt.Println(oai.String())
t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`).Value.Type, goai.TypeString)
})
}
func Test_Required_In_Schema(t *testing.T) {
type CommonReq struct {
AppId int64 `json:"appId" v:"required" in:"cookie" description:"应用Id"`
ResourceId string `json:"resourceId" in:"query" description:"资源Id"`
}
type SetSpecInfo struct {
StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" description:"StorageType"`
Shards int32 `description:"shards 分片数"`
Params []string `description:"默认参数(json 串-ClickHouseParams)"`
}
type CreateResourceReq struct {
CommonReq
gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"`
Name string `description:"实例名称"`
Product string `description:"业务类型"`
Region string `v:"required|min:1" description:"区域"`
SetMap map[string]*SetSpecInfo `v:"required|min:1" description:"配置Map"`
SetSlice []SetSpecInfo `v:"required|min:1" description:"配置Slice"`
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
req = new(CreateResourceReq)
)
err = oai.Add(goai.AddInput{
Object: req,
})
t.AssertNil(err)
var (
schemaKey1 = `github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`
schemaKey2 = `github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`
)
t.Assert(oai.Components.Schemas.Map()[schemaKey1].Value.Required, g.Slice{
"appId",
"Region",
"SetMap",
"SetSlice",
})
t.Assert(oai.Components.Schemas.Map()[schemaKey2].Value.Required, g.Slice{
"StorageType",
})
t.Assert(oai.Components.Schemas.Map()[schemaKey2].Value.Properties.Map()["StorageType"].Value.Enum, g.Slice{
"CLOUD_PREMIUM",
"CLOUD_SSD",
"CLOUD_HSSD",
})
})
}
func Test_Properties_In_Sequence(t *testing.T) {
type ResourceCreateReq struct {
g.Meta `path:"/resource" tags:"OSS Resource" method:"put" x-sort:"1" summary:"创建实例(发货)"`
AppId uint64 `v:"required" dc:"应用Id"`
Uin string `v:"required" dc:"主用户账号,该资源隶属于的账号"`
CreateUin string `v:"required" dc:"创建实例的用户账号"`
Product string `v:"required" dc:"业务类型" eg:"tdach"`
Region string `v:"required" dc:"地域" eg:"ap-guangzhou"`
Zone string `v:"required" dc:"区域" eg:"ap-guangzhou-1"`
Tenant string `v:"required" dc:"业务自定义数据,透传到底层"`
VpcId string `dc:"业务Vpc Id, TCS场景下非必须"`
SubnetId string `dc:"业务Vpc子网Id"`
Name string `dc:"自定义实例名称默认和ResourceId一致"`
ClusterPreset string `dc:"业务自定义Cluster定义透传到底层"`
Engine string `dc:"引擎名称例如TxLightning"`
Version string `dc:"引擎版本例如10.3.213 (兼容ClickHouse 21.3.12)"`
SkipUpdateStatus bool `dc:"是否跳过状态更新继续保持creating" ed:"http://goframe.org"`
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
req = new(ResourceCreateReq)
)
err = oai.Add(goai.AddInput{
Object: req,
})
t.AssertNil(err)
fmt.Println(oai)
})
}
func TestOpenApiV3_Ignore_Parameter(t *testing.T) {
type CommonResponse struct {
Code int `json:"code" description:"Error code"`
Message string `json:"message" description:"Error message"`
Data interface{} `json:"data" description:"Result data for certain request according API definition"`
}
type ProductSearchReq struct {
gmeta.Meta `path:"/test" method:"get"`
Product string `json:"-" in:"query" v:"required|max:5" description:"Unique product key"`
Name string `json:"name" in:"query" v:"required" description:"Instance name"`
}
type ProductSearchRes struct {
ID int64 `json:"-" description:"Product ID"`
Product string `json:"product" v:"required" description:"Unique product key"`
TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
Version string `json:"version" v:"required" description:"Workflow template version"`
TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"`
Globals string `json:"globals" description:"Globals"`
}
f := func(ctx context.Context, req *ProductSearchReq) (res *ProductSearchRes, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
oai.Config.CommonResponse = CommonResponse{}
err = oai.Add(goai.AddInput{
Object: f,
})
t.AssertNil(err)
// Schema asserts.
// fmt.Println(oai.String())
t.Assert(len(oai.Components.Schemas.Map()), 3)
t.Assert(len(oai.Paths), 1)
t.Assert(len(oai.Paths["/test"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 8)
})
}
func Test_EnumOfSchemaItems(t *testing.T) {
type CreateResourceReq struct {
gmeta.Meta `path:"/CreateResourceReq" method:"POST"`
Members []string `v:"required|in:a,b,c"`
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
req = new(CreateResourceReq)
)
err = oai.Add(goai.AddInput{
Object: req,
})
t.AssertNil(err)
t.Assert(
oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.
Properties.Get(`Members`).Value.
Items.Value.Enum,
g.Slice{"a", "b", "c"},
)
})
}
func Test_AliasNameOfAttribute(t *testing.T) {
type CreateResourceReq struct {
gmeta.Meta `path:"/CreateResourceReq" method:"POST"`
Name string `p:"n"`
Age string `json:"a"`
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
req = new(CreateResourceReq)
)
err = oai.Add(goai.AddInput{
Object: req,
})
t.AssertNil(err)
t.Assert(
oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.
Properties.Get(`Name`), nil,
)
t.Assert(
oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.
Properties.Get(`Age`), nil,
)
t.AssertNE(
oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.
Properties.Get(`n`), nil,
)
t.AssertNE(
oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.
Properties.Get(`a`), nil,
)
})
}
func Test_EmbeddedStructAttribute(t *testing.T) {
type CreateResourceReq struct {
gmeta.Meta `path:"/CreateResourceReq" method:"POST"`
Name string `dc:"This is name."`
Embedded struct {
Age uint `dc:"This is embedded age."`
}
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
req = new(CreateResourceReq)
)
err = oai.Add(goai.AddInput{
Object: req,
})
t.AssertNil(err)
b, err := json.Marshal(oai)
t.AssertNil(err)
t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateResourceReq":{"properties":{"Name":{"description":"This is name.","format":"string","properties":{},"type":"string"},"Embedded":{"properties":{"Age":{"description":"This is embedded age.","format":"uint","properties":{},"type":"integer"}},"type":"object"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`)
})
}
func Test_NameFromJsonTag(t *testing.T) {
// POST
gtest.C(t, func(t *gtest.T) {
type CreateReq struct {
gmeta.Meta `path:"/CreateReq" method:"POST"`
Name string `json:"nick_name, omitempty"`
}
var (
err error
oai = goai.New()
req = new(CreateReq)
)
err = oai.Add(goai.AddInput{
Object: req,
})
t.AssertNil(err)
b, err := json.Marshal(oai)
t.AssertNil(err)
t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateReq":{"properties":{"nick_name":{"format":"string","properties":{},"type":"string"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`)
})
// GET
gtest.C(t, func(t *gtest.T) {
type CreateReq struct {
gmeta.Meta `path:"/CreateReq" method:"GET"`
Name string `json:"nick_name, omitempty" in:"header"`
}
var (
err error
oai = goai.New()
req = new(CreateReq)
)
err = oai.Add(goai.AddInput{
Object: req,
})
t.AssertNil(err)
b, err := json.Marshal(oai)
t.AssertNil(err)
fmt.Println(string(b))
t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateReq":{"properties":{"nick_name":{"format":"string","properties":{},"type":"string"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`)
})
}
func TestOpenApiV3_PathSecurity(t *testing.T) {
type CommonResponse struct {
Code int `json:"code" description:"Error code"`
Message string `json:"message" description:"Error message"`
Data interface{} `json:"data" description:"Result data for certain request according API definition"`
}
type Req struct {
gmeta.Meta `method:"PUT" security:"apiKey"` // 这里的apiKey要和openApi定义的key一致
Product string `json:"product" v:"required" description:"Unique product key"`
Name string `json:"name" v:"required" description:"Instance name"`
}
type Res struct{}
f := func(ctx context.Context, req *Req) (res *Res, err error) {
return
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
)
oai.Config.CommonResponse = CommonResponse{}
oai.Components = goai.Components{
SecuritySchemes: goai.SecuritySchemes{
"apiKey": goai.SecuritySchemeRef{
Ref: "",
Value: &goai.SecurityScheme{
// 此处type是openApi的规定详见 https://swagger.io/docs/specification/authentication/api-keys/
Type: "apiKey",
In: "header",
Name: "X-API-KEY",
},
},
},
}
err = oai.Add(goai.AddInput{
Path: "/index",
Object: f,
})
t.AssertNil(err)
// Schema asserts.
fmt.Println(oai.String())
t.Assert(len(oai.Components.Schemas.Map()), 3)
t.Assert(len(oai.Components.SecuritySchemes), 1)
t.Assert(oai.Components.SecuritySchemes["apiKey"].Value.Type, "apiKey")
t.Assert(len(oai.Paths), 1)
t.Assert(len(oai.Paths["/index"].Put.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3)
})
}
func Test_EmptyJsonNameWithOmitEmpty(t *testing.T) {
type CreateResourceReq struct {
gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"`
Name string `description:"实例名称" json:",omitempty"`
Product string `description:"业务类型" json:",omitempty"`
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
req = new(CreateResourceReq)
)
err = oai.Add(goai.AddInput{
Object: req,
})
t.AssertNil(err)
var reqKey = "github.com.gogf.gf.v2.net.goai_test.CreateResourceReq"
t.AssertNE(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Name"), nil)
t.AssertNE(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Product"), nil)
t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("None"), nil)
})
}
func Test_Enums(t *testing.T) {
type Status string
const (
StatusA Status = "a"
StatusB Status = "b"
)
type Req struct {
gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"`
Name string `dc:"实例名称" json:",omitempty"`
Status1 Status `dc:"状态1" json:",omitempty"`
Status2 *Status `dc:"状态2" json:",omitempty"`
Status3 []Status `dc:"状态2" json:",omitempty"`
Status4 []*Status `dc:"状态2" json:",omitempty"`
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
req = new(Req)
)
err = gtag.SetGlobalEnums(gjson.MustEncodeString(g.Map{
"github.com/gogf/gf/v2/net/goai_test.Status": []interface{}{StatusA, StatusB},
}))
t.AssertNil(err)
err = oai.Add(goai.AddInput{
Object: req,
})
t.AssertNil(err)
var reqKey = "github.com.gogf.gf.v2.net.goai_test.Req"
t.AssertNE(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Name"), nil)
t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status1").Value.Enum, g.Slice{"a", "b"})
t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status2").Value.Enum, g.Slice{"a", "b"})
t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status3").Value.Items.Value.Enum, g.Slice{"a", "b"})
t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status4").Value.Items.Value.Enum, g.Slice{"a", "b"})
})
}
func Test_XExtension(t *testing.T) {
type GetListReq struct {
g.Meta `path:"/user" tags:"User" method:"get" x-group:"User/Info" summary:"Get user list with basic info."`
Page int `dc:"Page number" d:"1" x-sort:"1"`
Size int `dc:"Size for per page." d:"10" x-sort:"2"`
}
gtest.C(t, func(t *gtest.T) {
var (
err error
oai = goai.New()
req = new(GetListReq)
)
err = oai.Add(goai.AddInput{
Object: req,
})
t.AssertNil(err)
t.Assert(oai.String(), `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.GetListReq":{"properties":{"Page":{"default":1,"description":"Page number","format":"int","properties":{},"type":"integer","x-sort":"1"},"Size":{"default":10,"description":"Size for per page.","format":"int","properties":{},"type":"integer","x-sort":"2"}},"type":"object","x-group":"User/Info"}}},"info":{"title":"","version":""},"paths":null}`)
})
}