github.com/gogf/gf/v2@v2.7.4/net/goai/goai_z_unit_test.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package goai_test 8 9 import ( 10 "context" 11 "fmt" 12 "net/http" 13 "testing" 14 15 "github.com/gogf/gf/v2/encoding/gjson" 16 "github.com/gogf/gf/v2/frame/g" 17 "github.com/gogf/gf/v2/internal/json" 18 "github.com/gogf/gf/v2/net/ghttp" 19 "github.com/gogf/gf/v2/net/goai" 20 "github.com/gogf/gf/v2/test/gtest" 21 "github.com/gogf/gf/v2/util/gmeta" 22 "github.com/gogf/gf/v2/util/gtag" 23 ) 24 25 func Test_Basic(t *testing.T) { 26 type CommonReq struct { 27 AppId int64 `json:"appId" v:"required" in:"cookie" description:"应用Id"` 28 ResourceId string `json:"resourceId" in:"query" description:"资源Id"` 29 } 30 type SetSpecInfo struct { 31 StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" description:"StorageType"` 32 Shards int32 `description:"shards 分片数"` 33 Params []string `description:"默认参数(json 串-ClickHouseParams)"` 34 } 35 type CreateResourceReq struct { 36 CommonReq 37 gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"` 38 Name string `description:"实例名称"` 39 Product string `description:"业务类型"` 40 Region string `v:"required" description:"区域"` 41 SetMap map[string]*SetSpecInfo `v:"required" description:"配置Map"` 42 SetSlice []SetSpecInfo `v:"required" description:"配置Slice"` 43 } 44 45 gtest.C(t, func(t *gtest.T) { 46 var ( 47 err error 48 oai = goai.New() 49 req = new(CreateResourceReq) 50 ) 51 err = oai.Add(goai.AddInput{ 52 Object: req, 53 }) 54 t.AssertNil(err) 55 // Schema asserts. 56 t.Assert(len(oai.Components.Schemas.Map()), 2) 57 t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Type, goai.TypeObject) 58 t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Map()), 7) 59 t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Get(`appId`).Value.Type, goai.TypeInteger) 60 t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Get(`resourceId`).Value.Type, goai.TypeString) 61 62 t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Map()), 3) 63 t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Get(`Params`).Value.Type, goai.TypeArray) 64 65 // Schema Required. 66 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Required, []string{"appId", "Region", "SetMap", "SetSlice"}) 67 }) 68 } 69 70 func TestOpenApiV3_Add(t *testing.T) { 71 type CommonReq struct { 72 AppId int64 `json:"appId" v:"required" in:"path" description:"应用Id"` 73 ResourceId string `json:"resourceId" in:"query" description:"资源Id"` 74 } 75 type SetSpecInfo struct { 76 StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" description:"StorageType"` 77 Shards int32 `description:"shards 分片数"` 78 Params []string `description:"默认参数(json 串-ClickHouseParams)"` 79 } 80 type CreateResourceReq struct { 81 CommonReq 82 gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"` 83 Name string `description:"实例名称"` 84 Product string `description:"业务类型"` 85 Region string `v:"required" description:"区域"` 86 SetMap map[string]*SetSpecInfo `v:"required" description:"配置Map"` 87 SetSlice []SetSpecInfo `v:"required" description:"配置Slice"` 88 } 89 90 type CreateResourceRes struct { 91 gmeta.Meta `description:"Demo Response Struct"` 92 FlowId int64 `description:"创建实例流程id"` 93 } 94 95 f := func(ctx context.Context, req *CreateResourceReq) (res *CreateResourceRes, err error) { 96 return 97 } 98 99 gtest.C(t, func(t *gtest.T) { 100 var ( 101 err error 102 oai = goai.New() 103 ) 104 err = oai.Add(goai.AddInput{ 105 Path: "/test1/{appId}", 106 Method: http.MethodPut, 107 Object: f, 108 }) 109 t.AssertNil(err) 110 111 err = oai.Add(goai.AddInput{ 112 Path: "/test1/{appId}", 113 Method: http.MethodPost, 114 Object: f, 115 }) 116 t.AssertNil(err) 117 // fmt.Println(oai.String()) 118 // Schema asserts. 119 t.Assert(len(oai.Components.Schemas.Map()), 3) 120 t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Type, goai.TypeObject) 121 122 t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Map()), 7) 123 t.Assert(len(oai.Paths["/test1/{appId}"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 5) 124 t.Assert(len(oai.Paths["/test1/{appId}"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 5) 125 126 t.Assert(oai.Paths["/test1/{appId}"].Post.Parameters[0].Value.Schema.Value.Type, goai.TypeInteger) 127 t.Assert(oai.Paths["/test1/{appId}"].Post.Parameters[1].Value.Schema.Value.Type, goai.TypeString) 128 129 t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Map()), 3) 130 t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Get(`Params`).Value.Type, goai.TypeArray) 131 132 // Schema Required. 133 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Required, []string{"appId", "Region", "SetMap", "SetSlice"}) 134 135 // Paths. 136 t.Assert(len(oai.Paths), 1) 137 t.AssertNE(oai.Paths[`/test1/{appId}`].Put, nil) 138 t.Assert(len(oai.Paths[`/test1/{appId}`].Put.Tags), 1) 139 t.Assert(len(oai.Paths[`/test1/{appId}`].Put.Parameters), 2) 140 t.AssertNE(oai.Paths[`/test1/{appId}`].Post, nil) 141 t.Assert(len(oai.Paths[`/test1/{appId}`].Post.Tags), 1) 142 t.Assert(len(oai.Paths[`/test1/{appId}`].Post.Parameters), 2) 143 }) 144 } 145 146 func TestOpenApiV3_Add_Recursive(t *testing.T) { 147 type CategoryTreeItem struct { 148 Id uint `json:"id"` 149 ParentId uint `json:"parent_id"` 150 Items []*CategoryTreeItem `json:"items,omitempty"` 151 } 152 153 type CategoryGetTreeReq struct { 154 gmeta.Meta `path:"/category-get-tree" method:"GET" tags:"default"` 155 ContentType string `in:"query"` 156 } 157 type CategoryGetTreeRes struct { 158 List []*CategoryTreeItem 159 } 160 161 f := func(ctx context.Context, req *CategoryGetTreeReq) (res *CategoryGetTreeRes, err error) { 162 return 163 } 164 165 gtest.C(t, func(t *gtest.T) { 166 var ( 167 err error 168 oai = goai.New() 169 ) 170 err = oai.Add(goai.AddInput{ 171 Path: "/tree", 172 Object: f, 173 }) 174 t.AssertNil(err) 175 // Schema asserts. 176 t.Assert(len(oai.Components.Schemas.Map()), 3) 177 t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CategoryTreeItem`).Value.Type, goai.TypeObject) 178 t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CategoryTreeItem`).Value.Properties.Map()), 3) 179 }) 180 } 181 182 func TestOpenApiV3_Add_EmptyReqAndRes(t *testing.T) { 183 type CaptchaIndexReq struct { 184 gmeta.Meta `method:"PUT" summary:"获取默认的验证码" description:"注意直接返回的是图片二进制内容" tags:"前台-验证码"` 185 } 186 type CaptchaIndexRes struct { 187 gmeta.Meta `mime:"png" description:"验证码二进制内容" ` 188 } 189 190 f := func(ctx context.Context, req *CaptchaIndexReq) (res *CaptchaIndexRes, err error) { 191 return 192 } 193 194 gtest.C(t, func(t *gtest.T) { 195 var ( 196 err error 197 oai = goai.New() 198 ) 199 err = oai.Add(goai.AddInput{ 200 Path: "/tree", 201 Object: f, 202 }) 203 t.AssertNil(err) 204 // Schema asserts. 205 fmt.Println(oai.String()) 206 }) 207 } 208 209 func TestOpenApiV3_Add_AutoDetectIn(t *testing.T) { 210 type Req struct { 211 gmeta.Meta `method:"get" tags:"default"` 212 Name string 213 Product string 214 Region string 215 } 216 217 type Res struct { 218 gmeta.Meta `description:"Demo Response Struct"` 219 } 220 221 f := func(ctx context.Context, req *Req) (res *Res, err error) { 222 return 223 } 224 225 gtest.C(t, func(t *gtest.T) { 226 var ( 227 err error 228 oai = goai.New() 229 path = `/test/{product}/{name}` 230 ) 231 err = oai.Add(goai.AddInput{ 232 Path: path, 233 Method: http.MethodGet, 234 Object: f, 235 }) 236 t.AssertNil(err) 237 238 fmt.Println(oai.String()) 239 240 t.Assert(len(oai.Components.Schemas.Map()), 2) 241 t.Assert(len(oai.Paths), 1) 242 t.AssertNE(oai.Paths[path].Get, nil) 243 t.Assert(len(oai.Paths[path].Get.Parameters), 3) 244 t.Assert(oai.Paths[path].Get.Parameters[0].Value.Name, `Name`) 245 t.Assert(oai.Paths[path].Get.Parameters[0].Value.In, goai.ParameterInPath) 246 t.Assert(oai.Paths[path].Get.Parameters[1].Value.Name, `Product`) 247 t.Assert(oai.Paths[path].Get.Parameters[1].Value.In, goai.ParameterInPath) 248 t.Assert(oai.Paths[path].Get.Parameters[2].Value.Name, `Region`) 249 t.Assert(oai.Paths[path].Get.Parameters[2].Value.In, goai.ParameterInQuery) 250 }) 251 } 252 253 func TestOpenApiV3_CommonRequest(t *testing.T) { 254 type CommonRequest struct { 255 Code int `json:"code" description:"Error code"` 256 Message string `json:"message" description:"Error message"` 257 Data interface{} `json:"data" description:"Result data for certain request according API definition"` 258 } 259 260 type Req struct { 261 gmeta.Meta `method:"PUT"` 262 Product string `json:"product" v:"required" description:"Unique product key"` 263 Name string `json:"name" v:"required" description:"Instance name"` 264 } 265 type Res struct { 266 Product string `json:"product" v:"required" description:"Unique product key"` 267 TemplateName string `json:"templateName" v:"required" description:"Workflow template name"` 268 Version string `json:"version" v:"required" description:"Workflow template version"` 269 TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"` 270 Globals string `json:"globals" description:"Globals"` 271 } 272 273 f := func(ctx context.Context, req *Req) (res *Res, err error) { 274 return 275 } 276 277 gtest.C(t, func(t *gtest.T) { 278 var ( 279 err error 280 oai = goai.New() 281 ) 282 283 oai.Config.CommonRequest = CommonRequest{} 284 oai.Config.CommonRequestDataField = `Data` 285 286 err = oai.Add(goai.AddInput{ 287 Path: "/index", 288 Object: f, 289 }) 290 t.AssertNil(err) 291 // Schema asserts. 292 t.Assert(len(oai.Components.Schemas.Map()), 3) 293 t.Assert(len(oai.Paths), 1) 294 t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3) 295 296 // Schema Required. 297 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`).Value.Required, []string{"product", "name"}) 298 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`).Value.Required, []string{"product", "templateName", "version", "txID"}) 299 }) 300 } 301 302 func TestOpenApiV3_CommonRequest_WithoutDataField_Setting(t *testing.T) { 303 type CommonRequest struct { 304 Code int `json:"code" description:"Error code"` 305 Message string `json:"message" description:"Error message"` 306 Data interface{} `json:"data" description:"Result data for certain request according API definition"` 307 } 308 309 type PutReq struct { 310 gmeta.Meta `method:"PUT"` 311 Product string `json:"product" in:"query" v:"required" description:"Unique product key"` 312 Name string `json:"name" in:"query" v:"required" description:"Instance name"` 313 } 314 315 type PostReq struct { 316 gmeta.Meta `method:"POST"` 317 Product string `json:"product" v:"required" description:"Unique product key"` 318 Name string `json:"name" v:"required" description:"Instance name"` 319 } 320 321 type Res struct { 322 Product string `json:"product" v:"required" description:"Unique product key"` 323 TemplateName string `json:"templateName" v:"required" description:"Workflow template name"` 324 Version string `json:"version" v:"required" description:"Workflow template version"` 325 TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"` 326 Globals string `json:"globals" description:"Globals"` 327 } 328 329 f := func(ctx context.Context, req *PutReq) (res *Res, err error) { 330 return 331 } 332 f2 := func(ctx context.Context, req *PostReq) (res *Res, err error) { 333 return 334 } 335 336 gtest.C(t, func(t *gtest.T) { 337 var ( 338 err error 339 oai = goai.New() 340 ) 341 342 oai.Config.CommonRequest = CommonRequest{} 343 344 err = oai.Add(goai.AddInput{ 345 Path: "/index", 346 Object: f, 347 }) 348 t.AssertNil(err) 349 350 err = oai.Add(goai.AddInput{ 351 Path: "/index", 352 Object: f2, 353 }) 354 t.AssertNil(err) 355 // Schema asserts. 356 // fmt.Println(oai.String()) 357 t.Assert(len(oai.Components.Schemas.Map()), 4) 358 t.Assert(len(oai.Paths), 1) 359 t.Assert(len(oai.Paths["/index"].Put.Parameters), 2) 360 t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3) 361 t.Assert(len(oai.Paths["/index"].Post.Parameters), 0) 362 t.Assert(len(oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 5) 363 364 // Schema Required. 365 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.PutReq`).Value.Required, []string{"product", "name"}) 366 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.PutReq`).Value.Required, []string{"product", "name"}) 367 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`).Value.Required, []string{"product", "templateName", "version", "txID"}) 368 }) 369 } 370 371 func TestOpenApiV3_CommonRequest_EmptyRequest(t *testing.T) { 372 type CommonRequest struct { 373 Code int `json:"code" description:"Error code"` 374 Message string `json:"message" description:"Error message"` 375 Data interface{} `json:"data" description:"Result data for certain request according API definition"` 376 } 377 378 type Req struct { 379 gmeta.Meta `method:"Put"` 380 Product string `json:"product" in:"query" v:"required" description:"Unique product key"` 381 Name string `json:"name" in:"query" v:"required" description:"Instance name"` 382 } 383 type Res struct{} 384 385 f := func(ctx context.Context, req *Req) (res *Res, err error) { 386 return 387 } 388 389 gtest.C(t, func(t *gtest.T) { 390 var ( 391 err error 392 oai = goai.New() 393 ) 394 395 oai.Config.CommonRequest = CommonRequest{} 396 oai.Config.CommonRequestDataField = `Data` 397 398 err = oai.Add(goai.AddInput{ 399 Path: "/index", 400 Object: f, 401 }) 402 t.AssertNil(err) 403 // Schema asserts. 404 // fmt.Println(oai.String()) 405 t.Assert(len(oai.Components.Schemas.Map()), 3) 406 t.Assert(len(oai.Paths), 1) 407 t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3) 408 409 // Schema Required. 410 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`).Value.Required, []string{"product", "name"}) 411 }) 412 } 413 414 func TestOpenApiV3_CommonRequest_SubDataField(t *testing.T) { 415 type CommonReqError struct { 416 Code string `description:"错误码"` 417 Message string `description:"错误描述"` 418 } 419 420 type CommonReqRequest struct { 421 RequestId string `description:"RequestId"` 422 Error *CommonReqError `json:",omitempty" description:"执行错误信息"` 423 } 424 425 type CommonReq struct { 426 Request CommonReqRequest 427 } 428 429 type PutReq struct { 430 gmeta.Meta `method:"Put"` 431 Product string `json:"product" in:"query" v:"required" description:"Unique product key"` 432 Name string `json:"name" in:"query" v:"required" description:"Instance name"` 433 } 434 435 type PostReq struct { 436 gmeta.Meta `method:"Post"` 437 Product string `json:"product" v:"required" description:"Unique product key"` 438 Name string `json:"name" v:"required" description:"Instance name"` 439 } 440 441 type Res struct { 442 Product string `json:"product" v:"required" description:"Unique product key"` 443 TemplateName string `json:"templateName" v:"required" description:"Workflow template name"` 444 Version string `json:"version" v:"required" description:"Workflow template version"` 445 TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"` 446 Globals string `json:"globals" description:"Globals"` 447 } 448 449 f := func(ctx context.Context, req *PutReq) (res *Res, err error) { 450 return 451 } 452 f2 := func(ctx context.Context, req *PostReq) (res *Res, err error) { 453 return 454 } 455 456 gtest.C(t, func(t *gtest.T) { 457 var ( 458 err error 459 oai = goai.New() 460 ) 461 462 oai.Config.CommonRequest = CommonReq{} 463 oai.Config.CommonRequestDataField = `Request.` 464 465 err = oai.Add(goai.AddInput{ 466 Path: "/index", 467 Object: f, 468 }) 469 t.AssertNil(err) 470 471 err = oai.Add(goai.AddInput{ 472 Path: "/index", 473 Object: f2, 474 }) 475 t.AssertNil(err) 476 477 // Schema asserts. 478 // fmt.Println(oai.String()) 479 t.Assert(len(oai.Components.Schemas.Map()), 5) 480 t.Assert(len(oai.Paths), 1) 481 t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 1) 482 t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Get(`Request`).Value.Properties.Map()), 2) 483 t.Assert(len(oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 1) 484 t.Assert(len(oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Get(`Request`).Value.Properties.Map()), 4) 485 486 // Schema Required. 487 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.PutReq`).Value.Required, []string{"product", "name"}) 488 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.PutReq`).Value.Required, []string{"product", "name"}) 489 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`).Value.Required, []string{"product", "templateName", "version", "txID"}) 490 }) 491 } 492 493 func TestOpenApiV3_CommonRequest_Files(t *testing.T) { 494 type Req struct { 495 g.Meta `path:"/upload" method:"POST" tags:"Upload" mime:"multipart/form-data" summary:"上传文件"` 496 Files []*ghttp.UploadFile `json:"files" type:"file" dc:"选择上传文件"` 497 File *ghttp.UploadFile `json:"file" type:"file" dc:"选择上传文件"` 498 } 499 type Res struct { 500 } 501 502 f := func(ctx context.Context, req *Req) (res *Res, err error) { 503 return 504 } 505 506 gtest.C(t, func(t *gtest.T) { 507 var ( 508 err error 509 oai = goai.New() 510 ) 511 err = oai.Add(goai.AddInput{ 512 Path: "/upload", 513 Method: http.MethodGet, 514 Object: f, 515 }) 516 t.AssertNil(err) 517 518 // fmt.Println(oai.String()) 519 t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`).Value.Properties.Get("files").Value.Type, goai.TypeArray) 520 t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`).Value.Properties.Get("file").Value.Type, goai.TypeFile) 521 }) 522 } 523 524 func TestOpenApiV3_CommonResponse(t *testing.T) { 525 type CommonResponse struct { 526 Code int `json:"code" description:"Error code"` 527 Message string `json:"message" description:"Error message"` 528 Data interface{} `json:"data" description:"Result data for certain request according API definition"` 529 } 530 531 type Req struct { 532 gmeta.Meta `method:"GET"` 533 Product string `json:"product" in:"query" v:"required" description:"Unique product key"` 534 Name string `json:"name" in:"query" v:"required" description:"Instance name"` 535 } 536 type Res struct { 537 Product string `json:"product" v:"required" description:"Unique product key"` 538 TemplateName string `json:"templateName" v:"required" description:"Workflow template name"` 539 Version string `json:"version" v:"required" description:"Workflow template version"` 540 TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"` 541 Globals string `json:"globals" description:"Globals"` 542 } 543 544 f := func(ctx context.Context, req *Req) (res *Res, err error) { 545 return 546 } 547 548 gtest.C(t, func(t *gtest.T) { 549 var ( 550 err error 551 oai = goai.New() 552 ) 553 554 oai.Config.CommonResponse = CommonResponse{} 555 oai.Config.CommonResponseDataField = `Data` 556 557 err = oai.Add(goai.AddInput{ 558 Path: "/index", 559 Object: f, 560 }) 561 t.AssertNil(err) 562 563 // g.Dump(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()) 564 // Schema asserts. 565 t.Assert(len(oai.Components.Schemas.Map()), 3) 566 t.Assert(len(oai.Paths), 1) 567 t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3) 568 t.Assert( 569 oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Get("data").Value.Description, 570 `Result data for certain request according API definition`, 571 ) 572 573 // Schema Required. 574 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`).Value.Required, []string{"product", "name"}) 575 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`).Value.Required, []string{"product", "templateName", "version", "txID"}) 576 }) 577 } 578 579 func TestOpenApiV3_CommonResponse_WithoutDataField_Setting(t *testing.T) { 580 type CommonResponse struct { 581 Code int `json:"code" description:"Error code"` 582 Message string `json:"message" description:"Error message"` 583 Data interface{} `json:"data" description:"Result data for certain request according API definition"` 584 } 585 586 type Req struct { 587 gmeta.Meta `method:"GET"` 588 Product string `json:"product" in:"query" v:"required" description:"Unique product key"` 589 Name string `json:"name" in:"query" v:"required" description:"Instance name"` 590 } 591 type Res struct { 592 Product string `json:"product" v:"required" description:"Unique product key"` 593 TemplateName string `json:"templateName" v:"required" description:"Workflow template name"` 594 Version string `json:"version" v:"required" description:"Workflow template version"` 595 TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"` 596 Globals string `json:"globals" description:"Globals"` 597 } 598 599 f := func(ctx context.Context, req *Req) (res *Res, err error) { 600 return 601 } 602 603 gtest.C(t, func(t *gtest.T) { 604 var ( 605 err error 606 oai = goai.New() 607 ) 608 609 oai.Config.CommonResponse = CommonResponse{} 610 611 err = oai.Add(goai.AddInput{ 612 Path: "/index", 613 Object: f, 614 }) 615 t.AssertNil(err) 616 // Schema asserts. 617 fmt.Println(oai.String()) 618 t.Assert(len(oai.Components.Schemas.Map()), 3) 619 t.Assert(len(oai.Paths), 1) 620 t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 8) 621 622 // Schema Required. 623 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`).Value.Required, []string{"product", "name"}) 624 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`).Value.Required, []string{"product", "templateName", "version", "txID"}) 625 }) 626 } 627 628 func TestOpenApiV3_CommonResponse_EmptyResponse(t *testing.T) { 629 type CommonResponse struct { 630 Code int `json:"code" description:"Error code"` 631 Message string `json:"message" description:"Error message"` 632 Data interface{} `json:"data" description:"Result data for certain request according API definition"` 633 } 634 635 type Req struct { 636 gmeta.Meta `method:"PUT"` 637 Product string `json:"product" v:"required" description:"Unique product key"` 638 Name string `json:"name" v:"required" description:"Instance name"` 639 } 640 type Res struct{} 641 642 f := func(ctx context.Context, req *Req) (res *Res, err error) { 643 return 644 } 645 646 gtest.C(t, func(t *gtest.T) { 647 var ( 648 err error 649 oai = goai.New() 650 ) 651 652 oai.Config.CommonResponse = CommonResponse{} 653 oai.Config.CommonResponseDataField = `Data` 654 655 err = oai.Add(goai.AddInput{ 656 Path: "/index", 657 Object: f, 658 }) 659 t.AssertNil(err) 660 // Schema asserts. 661 // fmt.Println(oai.String()) 662 t.Assert(len(oai.Components.Schemas.Map()), 3) 663 t.Assert(len(oai.Paths), 1) 664 t.Assert(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Ref, `github.com.gogf.gf.v2.net.goai_test.Req`) 665 t.Assert(len(oai.Paths["/index"].Put.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3) 666 667 // Schema Required. 668 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`).Value.Required, []string{"product", "name"}) 669 }) 670 } 671 672 func TestOpenApiV3_CommonResponse_SubDataField(t *testing.T) { 673 type CommonResError struct { 674 Code string `description:"错误码"` 675 Message string `description:"错误描述"` 676 } 677 678 type CommonResResponse struct { 679 RequestId string `description:"RequestId"` 680 Error *CommonResError `json:",omitempty" description:"执行错误信息"` 681 } 682 683 type CommonRes struct { 684 Response CommonResResponse 685 } 686 687 type Req struct { 688 gmeta.Meta `method:"GET"` 689 Product string `json:"product" in:"query" v:"required" description:"Unique product key"` 690 Name string `json:"name" in:"query" v:"required" description:"Instance name"` 691 } 692 693 type Res struct { 694 Product string `json:"product" v:"required" description:"Unique product key"` 695 TemplateName string `json:"templateName" v:"required" description:"Workflow template name"` 696 Version string `json:"version" v:"required" description:"Workflow template version"` 697 TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"` 698 Globals string `json:"globals" description:"Globals"` 699 } 700 701 f := func(ctx context.Context, req *Req) (res *Res, err error) { 702 return 703 } 704 705 gtest.C(t, func(t *gtest.T) { 706 var ( 707 err error 708 oai = goai.New() 709 ) 710 711 oai.Config.CommonResponse = CommonRes{} 712 oai.Config.CommonResponseDataField = `Response.` 713 714 err = oai.Add(goai.AddInput{ 715 Path: "/index", 716 Object: f, 717 }) 718 t.AssertNil(err) 719 // Schema asserts. 720 // fmt.Println(oai.String()) 721 t.Assert(len(oai.Components.Schemas.Map()), 4) 722 t.Assert(len(oai.Paths), 1) 723 t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 1) 724 t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Get(`Response`).Value.Properties.Map()), 7) 725 726 // Schema Required. 727 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`).Value.Required, []string{"product", "name"}) 728 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`).Value.Required, []string{"product", "templateName", "version", "txID"}) 729 }) 730 } 731 732 func TestOpenApiV3_ShortTags(t *testing.T) { 733 type CommonReq struct { 734 AppId int64 `json:"appId" v:"required" in:"path" dc:"应用Id" sm:"应用Id Summary"` 735 ResourceId string `json:"resourceId" in:"query" dc:"资源Id" sm:"资源Id Summary"` 736 } 737 type SetSpecInfo struct { 738 StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" dc:"StorageType"` 739 Shards int32 `dc:"shards 分片数" sm:"Shards Summary"` 740 Params []string `dc:"默认参数(json 串-ClickHouseParams)" sm:"Params Summary"` 741 } 742 type CreateResourceReq struct { 743 CommonReq 744 gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sm:"CreateResourceReq sum" dc:"CreateResourceReq des"` 745 Name string `dc:"实例名称"` 746 Product string `dc:"业务类型"` 747 Region string `v:"required" dc:"区域"` 748 SetMap map[string]*SetSpecInfo `v:"required" dc:"配置Map"` 749 SetSlice []SetSpecInfo `v:"required" dc:"配置Slice"` 750 } 751 752 type CreateResourceRes struct { 753 gmeta.Meta `dc:"Demo Response Struct"` 754 FlowId int64 `dc:"创建实例流程id"` 755 } 756 757 f := func(ctx context.Context, req *CreateResourceReq) (res *CreateResourceRes, err error) { 758 return 759 } 760 761 gtest.C(t, func(t *gtest.T) { 762 var ( 763 err error 764 oai = goai.New() 765 ) 766 err = oai.Add(goai.AddInput{ 767 Path: "/test1/{appId}", 768 Method: http.MethodPut, 769 Object: f, 770 }) 771 t.AssertNil(err) 772 773 err = oai.Add(goai.AddInput{ 774 Path: "/test1/{appId}", 775 Method: http.MethodPost, 776 Object: f, 777 }) 778 t.AssertNil(err) 779 // fmt.Println(oai.String()) 780 // Schema asserts. 781 t.Assert(len(oai.Components.Schemas.Map()), 3) 782 t.Assert(oai.Paths[`/test1/{appId}`].Summary, ``) 783 t.Assert(oai.Paths[`/test1/{appId}`].Description, ``) 784 t.Assert(oai.Paths[`/test1/{appId}`].Put.Summary, `CreateResourceReq sum`) 785 t.Assert(oai.Paths[`/test1/{appId}`].Put.Description, `CreateResourceReq des`) 786 t.Assert(oai.Paths[`/test1/{appId}`].Put.Parameters[1].Value.Schema.Value.Description, `资源Id`) 787 t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Get(`Name`).Value.Description, `实例名称`) 788 789 // Schema Required. 790 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Required, []string{"appId", "Region", "SetMap", "SetSlice"}) 791 }) 792 } 793 794 func TestOpenApiV3_HtmlResponse(t *testing.T) { 795 type Req struct { 796 g.Meta `path:"/test" method:"get" summary:"展示内容详情页面" tags:"内容"` 797 Id uint `json:"id" v:"min:1#请选择查看的内容" dc:"内容id"` 798 } 799 type Res struct { 800 g.Meta `mime:"text/html" type:"string" example:"<html/>"` 801 } 802 803 f := func(ctx context.Context, req *Req) (res *Res, err error) { 804 return 805 } 806 807 gtest.C(t, func(t *gtest.T) { 808 var ( 809 err error 810 oai = goai.New() 811 ) 812 err = oai.Add(goai.AddInput{ 813 Path: "/test", 814 Method: http.MethodGet, 815 Object: f, 816 }) 817 t.AssertNil(err) 818 819 // fmt.Println(oai.String()) 820 t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`).Value.Type, goai.TypeString) 821 }) 822 } 823 824 func TestOpenApiV3_HtmlResponseWithCommonResponse(t *testing.T) { 825 type CommonResError struct { 826 Code string `description:"错误码"` 827 Message string `description:"错误描述"` 828 } 829 830 type CommonResResponse struct { 831 RequestId string `description:"RequestId"` 832 Error *CommonResError `json:",omitempty" description:"执行错误信息"` 833 } 834 835 type CommonRes struct { 836 Response CommonResResponse 837 } 838 839 type Req struct { 840 g.Meta `path:"/test" method:"get" summary:"展示内容详情页面" tags:"内容"` 841 Id uint `json:"id" v:"min:1#请选择查看的内容" dc:"内容id"` 842 } 843 type Res struct { 844 g.Meta `mime:"text/html" type:"string" example:"<html/>"` 845 } 846 847 f := func(ctx context.Context, req *Req) (res *Res, err error) { 848 return 849 } 850 851 gtest.C(t, func(t *gtest.T) { 852 var ( 853 err error 854 oai = goai.New() 855 ) 856 oai.Config.CommonResponse = CommonRes{} 857 oai.Config.CommonResponseDataField = `Response.` 858 859 err = oai.Add(goai.AddInput{ 860 Path: "/test", 861 Method: http.MethodGet, 862 Object: f, 863 }) 864 t.AssertNil(err) 865 866 // fmt.Println(oai.String()) 867 t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`).Value.Type, goai.TypeString) 868 }) 869 } 870 871 func Test_Required_In_Schema(t *testing.T) { 872 type CommonReq struct { 873 AppId int64 `json:"appId" v:"required" in:"cookie" description:"应用Id"` 874 ResourceId string `json:"resourceId" in:"query" description:"资源Id"` 875 } 876 type SetSpecInfo struct { 877 StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" description:"StorageType"` 878 Shards int32 `description:"shards 分片数"` 879 Params []string `description:"默认参数(json 串-ClickHouseParams)"` 880 } 881 type CreateResourceReq struct { 882 CommonReq 883 gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"` 884 Name string `description:"实例名称"` 885 Product string `description:"业务类型"` 886 Region string `v:"required|min:1" description:"区域"` 887 SetMap map[string]*SetSpecInfo `v:"required|min:1" description:"配置Map"` 888 SetSlice []SetSpecInfo `v:"required|min:1" description:"配置Slice"` 889 } 890 891 gtest.C(t, func(t *gtest.T) { 892 var ( 893 err error 894 oai = goai.New() 895 req = new(CreateResourceReq) 896 ) 897 err = oai.Add(goai.AddInput{ 898 Object: req, 899 }) 900 t.AssertNil(err) 901 var ( 902 schemaKey1 = `github.com.gogf.gf.v2.net.goai_test.CreateResourceReq` 903 schemaKey2 = `github.com.gogf.gf.v2.net.goai_test.SetSpecInfo` 904 ) 905 t.Assert(oai.Components.Schemas.Map()[schemaKey1].Value.Required, g.Slice{ 906 "appId", 907 "Region", 908 "SetMap", 909 "SetSlice", 910 }) 911 t.Assert(oai.Components.Schemas.Map()[schemaKey2].Value.Required, g.Slice{ 912 "StorageType", 913 }) 914 t.Assert(oai.Components.Schemas.Map()[schemaKey2].Value.Properties.Map()["StorageType"].Value.Enum, g.Slice{ 915 "CLOUD_PREMIUM", 916 "CLOUD_SSD", 917 "CLOUD_HSSD", 918 }) 919 920 // Schema Required. 921 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Required, []string{"appId", "Region", "SetMap", "SetSlice"}) 922 }) 923 } 924 925 func Test_Properties_In_Sequence(t *testing.T) { 926 type ResourceCreateReq struct { 927 g.Meta `path:"/resource" tags:"OSS Resource" method:"put" x-sort:"1" summary:"创建实例(发货)"` 928 AppId uint64 `v:"required" dc:"应用Id"` 929 Uin string `v:"required" dc:"主用户账号,该资源隶属于的账号"` 930 CreateUin string `v:"required" dc:"创建实例的用户账号"` 931 Product string `v:"required" dc:"业务类型" eg:"tdach"` 932 Region string `v:"required" dc:"地域" eg:"ap-guangzhou"` 933 Zone string `v:"required" dc:"区域" eg:"ap-guangzhou-1"` 934 Tenant string `v:"required" dc:"业务自定义数据,透传到底层"` 935 VpcId string `dc:"业务Vpc Id, TCS场景下非必须"` 936 SubnetId string `dc:"业务Vpc子网Id"` 937 Name string `dc:"自定义实例名称,默认和ResourceId一致"` 938 ClusterPreset string `dc:"业务自定义Cluster定义,透传到底层"` 939 Engine string `dc:"引擎名称,例如:TxLightning"` 940 Version string `dc:"引擎版本,例如:10.3.213 (兼容ClickHouse 21.3.12)"` 941 SkipUpdateStatus bool `dc:"是否跳过状态更新,继续保持creating" ed:"http://goframe.org"` 942 } 943 gtest.C(t, func(t *gtest.T) { 944 var ( 945 err error 946 oai = goai.New() 947 req = new(ResourceCreateReq) 948 ) 949 err = oai.Add(goai.AddInput{ 950 Object: req, 951 }) 952 t.AssertNil(err) 953 fmt.Println(oai) 954 955 // Schema Required. 956 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.ResourceCreateReq`).Value.Required, []string{"AppId", "Uin", "CreateUin", "Product", "Region", "Zone", "Tenant"}) 957 }) 958 } 959 960 func TestOpenApiV3_Ignore_Parameter(t *testing.T) { 961 type CommonResponse struct { 962 Code int `json:"code" description:"Error code"` 963 Message string `json:"message" description:"Error message"` 964 Data interface{} `json:"data" description:"Result data for certain request according API definition"` 965 } 966 type ProductSearchReq struct { 967 gmeta.Meta `path:"/test" method:"get"` 968 Product string `json:"-" in:"query" v:"required|max:5" description:"Unique product key"` 969 Name string `json:"name" in:"query" v:"required" description:"Instance name"` 970 } 971 type ProductSearchRes struct { 972 ID int64 `json:"-" description:"Product ID"` 973 Product string `json:"product" v:"required" description:"Unique product key"` 974 TemplateName string `json:"templateName" v:"required" description:"Workflow template name"` 975 Version string `json:"version" v:"required" description:"Workflow template version"` 976 TxID string `json:"txID" v:"required" description:"Transaction ID for creating instance"` 977 Globals string `json:"globals" description:"Globals"` 978 } 979 980 f := func(ctx context.Context, req *ProductSearchReq) (res *ProductSearchRes, err error) { 981 return 982 } 983 984 gtest.C(t, func(t *gtest.T) { 985 var ( 986 err error 987 oai = goai.New() 988 ) 989 990 oai.Config.CommonResponse = CommonResponse{} 991 992 err = oai.Add(goai.AddInput{ 993 Object: f, 994 }) 995 t.AssertNil(err) 996 // Schema asserts. 997 // fmt.Println(oai.String()) 998 t.Assert(len(oai.Components.Schemas.Map()), 3) 999 t.Assert(len(oai.Paths), 1) 1000 t.Assert(len(oai.Paths["/test"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 8) 1001 }) 1002 } 1003 1004 func Test_EnumOfSchemaItems(t *testing.T) { 1005 type CreateResourceReq struct { 1006 gmeta.Meta `path:"/CreateResourceReq" method:"POST"` 1007 Members []string `v:"required|in:a,b,c"` 1008 } 1009 1010 gtest.C(t, func(t *gtest.T) { 1011 var ( 1012 err error 1013 oai = goai.New() 1014 req = new(CreateResourceReq) 1015 ) 1016 err = oai.Add(goai.AddInput{ 1017 Object: req, 1018 }) 1019 t.AssertNil(err) 1020 1021 t.Assert( 1022 oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value. 1023 Properties.Get(`Members`).Value. 1024 Items.Value.Enum, 1025 g.Slice{"a", "b", "c"}, 1026 ) 1027 1028 // Schema Required. 1029 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Required, []string{"Members"}) 1030 }) 1031 } 1032 1033 func Test_AliasNameOfAttribute(t *testing.T) { 1034 type CreateResourceReq struct { 1035 gmeta.Meta `path:"/CreateResourceReq" method:"POST"` 1036 Name string `p:"n"` 1037 Age string `json:"a"` 1038 } 1039 1040 gtest.C(t, func(t *gtest.T) { 1041 var ( 1042 err error 1043 oai = goai.New() 1044 req = new(CreateResourceReq) 1045 ) 1046 err = oai.Add(goai.AddInput{ 1047 Object: req, 1048 }) 1049 t.AssertNil(err) 1050 1051 t.Assert( 1052 oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value. 1053 Properties.Get(`Name`), nil, 1054 ) 1055 t.Assert( 1056 oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value. 1057 Properties.Get(`Age`), nil, 1058 ) 1059 t.AssertNE( 1060 oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value. 1061 Properties.Get(`n`), nil, 1062 ) 1063 t.AssertNE( 1064 oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value. 1065 Properties.Get(`a`), nil, 1066 ) 1067 }) 1068 } 1069 1070 func Test_EmbeddedStructAttribute(t *testing.T) { 1071 type CreateResourceReq struct { 1072 gmeta.Meta `path:"/CreateResourceReq" method:"POST"` 1073 Name string `dc:"This is name."` 1074 Embedded struct { 1075 Age uint `dc:"This is embedded age."` 1076 } 1077 } 1078 1079 gtest.C(t, func(t *gtest.T) { 1080 var ( 1081 err error 1082 oai = goai.New() 1083 req = new(CreateResourceReq) 1084 ) 1085 err = oai.Add(goai.AddInput{ 1086 Object: req, 1087 }) 1088 t.AssertNil(err) 1089 1090 b, err := json.Marshal(oai) 1091 t.AssertNil(err) 1092 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","type":"string"},"Embedded":{"properties":{"Age":{"description":"This is embedded age.","format":"uint","type":"integer"}},"type":"object"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`) 1093 }) 1094 } 1095 1096 func Test_NameFromJsonTag(t *testing.T) { 1097 // POST 1098 gtest.C(t, func(t *gtest.T) { 1099 type CreateReq struct { 1100 gmeta.Meta `path:"/CreateReq" method:"POST"` 1101 Name string `json:"nick_name, omitempty"` 1102 } 1103 1104 var ( 1105 err error 1106 oai = goai.New() 1107 req = new(CreateReq) 1108 ) 1109 err = oai.Add(goai.AddInput{ 1110 Object: req, 1111 }) 1112 t.AssertNil(err) 1113 1114 b, err := json.Marshal(oai) 1115 t.AssertNil(err) 1116 t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateReq":{"properties":{"nick_name":{"format":"string","type":"string"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`) 1117 }) 1118 // GET 1119 gtest.C(t, func(t *gtest.T) { 1120 type CreateReq struct { 1121 gmeta.Meta `path:"/CreateReq" method:"GET"` 1122 Name string `json:"nick_name, omitempty" in:"header"` 1123 } 1124 var ( 1125 err error 1126 oai = goai.New() 1127 req = new(CreateReq) 1128 ) 1129 err = oai.Add(goai.AddInput{ 1130 Object: req, 1131 }) 1132 t.AssertNil(err) 1133 1134 b, err := json.Marshal(oai) 1135 t.AssertNil(err) 1136 fmt.Println(string(b)) 1137 t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateReq":{"properties":{"nick_name":{"format":"string","type":"string"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`) 1138 }) 1139 } 1140 1141 func TestOpenApiV3_PathSecurity(t *testing.T) { 1142 type CommonResponse struct { 1143 Code int `json:"code" description:"Error code"` 1144 Message string `json:"message" description:"Error message"` 1145 Data interface{} `json:"data" description:"Result data for certain request according API definition"` 1146 } 1147 1148 type Req struct { 1149 gmeta.Meta `method:"PUT" security:"apiKey"` // 这里的apiKey要和openApi定义的key一致 1150 Product string `json:"product" v:"required" description:"Unique product key"` 1151 Name string `json:"name" v:"required" description:"Instance name"` 1152 } 1153 type Res struct{} 1154 1155 f := func(ctx context.Context, req *Req) (res *Res, err error) { 1156 return 1157 } 1158 1159 gtest.C(t, func(t *gtest.T) { 1160 var ( 1161 err error 1162 oai = goai.New() 1163 ) 1164 1165 oai.Config.CommonResponse = CommonResponse{} 1166 oai.Components = goai.Components{ 1167 SecuritySchemes: goai.SecuritySchemes{ 1168 "apiKey": goai.SecuritySchemeRef{ 1169 Ref: "", 1170 Value: &goai.SecurityScheme{ 1171 // 此处type是openApi的规定,详见 https://swagger.io/docs/specification/authentication/api-keys/ 1172 Type: "apiKey", 1173 In: "header", 1174 Name: "X-API-KEY", 1175 }, 1176 }, 1177 }, 1178 } 1179 err = oai.Add(goai.AddInput{ 1180 Path: "/index", 1181 Object: f, 1182 }) 1183 t.AssertNil(err) 1184 // Schema asserts. 1185 fmt.Println(oai.String()) 1186 t.Assert(len(oai.Components.Schemas.Map()), 3) 1187 t.Assert(len(oai.Components.SecuritySchemes), 1) 1188 t.Assert(oai.Components.SecuritySchemes["apiKey"].Value.Type, "apiKey") 1189 t.Assert(len(oai.Paths), 1) 1190 t.Assert(len(oai.Paths["/index"].Put.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3) 1191 1192 // Schema Required. 1193 t.AssertEQ(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Req`).Value.Required, []string{"product", "name"}) 1194 }) 1195 } 1196 1197 func Test_EmptyJsonNameWithOmitEmpty(t *testing.T) { 1198 type CreateResourceReq struct { 1199 gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"` 1200 Name string `description:"实例名称" json:",omitempty"` 1201 Product string `description:"业务类型" json:",omitempty"` 1202 } 1203 1204 gtest.C(t, func(t *gtest.T) { 1205 var ( 1206 err error 1207 oai = goai.New() 1208 req = new(CreateResourceReq) 1209 ) 1210 err = oai.Add(goai.AddInput{ 1211 Object: req, 1212 }) 1213 t.AssertNil(err) 1214 var reqKey = "github.com.gogf.gf.v2.net.goai_test.CreateResourceReq" 1215 t.AssertNE(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Name"), nil) 1216 t.AssertNE(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Product"), nil) 1217 t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("None"), nil) 1218 }) 1219 } 1220 1221 func Test_Enums(t *testing.T) { 1222 type Status string 1223 const ( 1224 StatusA Status = "a" 1225 StatusB Status = "b" 1226 ) 1227 type Req struct { 1228 gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"` 1229 Name string `dc:"实例名称" json:",omitempty"` 1230 Status1 Status `dc:"状态1" json:",omitempty"` 1231 Status2 *Status `dc:"状态2" json:",omitempty"` 1232 Status3 []Status `dc:"状态2" json:",omitempty"` 1233 Status4 []*Status `dc:"状态2" json:",omitempty"` 1234 } 1235 1236 gtest.C(t, func(t *gtest.T) { 1237 var ( 1238 err error 1239 oai = goai.New() 1240 req = new(Req) 1241 ) 1242 err = gtag.SetGlobalEnums(gjson.MustEncodeString(g.Map{ 1243 "github.com/gogf/gf/v2/net/goai_test.Status": []interface{}{StatusA, StatusB}, 1244 })) 1245 t.AssertNil(err) 1246 1247 err = oai.Add(goai.AddInput{ 1248 Object: req, 1249 }) 1250 t.AssertNil(err) 1251 var reqKey = "github.com.gogf.gf.v2.net.goai_test.Req" 1252 t.AssertNE(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Name"), nil) 1253 t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status1").Value.Enum, g.Slice{"a", "b"}) 1254 t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status2").Value.Enum, g.Slice{"a", "b"}) 1255 t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status3").Value.Items.Value.Enum, g.Slice{"a", "b"}) 1256 t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status4").Value.Items.Value.Enum, g.Slice{"a", "b"}) 1257 }) 1258 } 1259 1260 func Test_XExtension(t *testing.T) { 1261 type GetListReq struct { 1262 g.Meta `path:"/user" tags:"User" method:"get" x-group:"User/Info" summary:"Get user list with basic info."` 1263 Page int `dc:"Page number" d:"1" x-sort:"1"` 1264 Size int `dc:"Size for per page." d:"10" x-sort:"2"` 1265 } 1266 gtest.C(t, func(t *gtest.T) { 1267 var ( 1268 err error 1269 oai = goai.New() 1270 req = new(GetListReq) 1271 ) 1272 err = oai.Add(goai.AddInput{ 1273 Object: req, 1274 }) 1275 t.AssertNil(err) 1276 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","type":"integer","x-sort":"1"},"Size":{"default":10,"description":"Size for per page.","format":"int","type":"integer","x-sort":"2"}},"type":"object","x-group":"User/Info"}}},"info":{"title":"","version":""},"paths":null}`) 1277 }) 1278 }