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