github.com/go-swagger/go-swagger@v0.31.0/codescan/parameters_test.go (about) 1 package codescan 2 3 import ( 4 "testing" 5 6 "github.com/go-openapi/spec" 7 "github.com/stretchr/testify/assert" 8 "github.com/stretchr/testify/require" 9 ) 10 11 const ( 12 gcBadEnum = "bad_enum" 13 ) 14 15 func getParameter(sctx *scanCtx, nm string) *entityDecl { 16 for _, v := range sctx.app.Parameters { 17 param := v 18 if v.Ident.Name == nm { 19 return param 20 } 21 } 22 return nil 23 } 24 25 func TestScanFileParam(t *testing.T) { 26 sctx := loadClassificationPkgsCtx(t) 27 operations := make(map[string]*spec.Operation) 28 for _, rn := range []string{"OrderBodyParams", "MultipleOrderParams", "ComplexerOneParams", "NoParams", "NoParamsAlias", "MyFileParams", "MyFuncFileParams", "EmbeddedFileParams"} { 29 td := getParameter(sctx, rn) 30 31 prs := ¶meterBuilder{ 32 ctx: sctx, 33 decl: td, 34 } 35 require.NoError(t, prs.Build(operations)) 36 } 37 assert.Len(t, operations, 10) 38 39 of, ok := operations["myOperation"] 40 assert.True(t, ok) 41 assert.Len(t, of.Parameters, 1) 42 fileParam := of.Parameters[0] 43 assert.Equal(t, "MyFormFile desc.", fileParam.Description) 44 assert.Equal(t, "formData", fileParam.In) 45 assert.Equal(t, "file", fileParam.Type) 46 assert.False(t, fileParam.Required) 47 48 emb, ok := operations["myOtherOperation"] 49 assert.True(t, ok) 50 assert.Len(t, emb.Parameters, 2) 51 fileParam = emb.Parameters[0] 52 assert.Equal(t, "MyFormFile desc.", fileParam.Description) 53 assert.Equal(t, "formData", fileParam.In) 54 assert.Equal(t, "file", fileParam.Type) 55 assert.False(t, fileParam.Required) 56 extraParam := emb.Parameters[1] 57 assert.Equal(t, "ExtraParam desc.", extraParam.Description) 58 assert.Equal(t, "formData", extraParam.In) 59 assert.Equal(t, "integer", extraParam.Type) 60 assert.True(t, extraParam.Required) 61 62 ffp, ok := operations["myFuncOperation"] 63 assert.True(t, ok) 64 assert.Len(t, ffp.Parameters, 1) 65 fileParam = ffp.Parameters[0] 66 assert.Equal(t, "MyFormFile desc.", fileParam.Description) 67 assert.Equal(t, "formData", fileParam.In) 68 assert.Equal(t, "file", fileParam.Type) 69 assert.False(t, fileParam.Required) 70 } 71 72 func TestParamsParser(t *testing.T) { 73 sctx := loadClassificationPkgsCtx(t) 74 operations := make(map[string]*spec.Operation) 75 for _, rn := range []string{"OrderBodyParams", "MultipleOrderParams", "ComplexerOneParams", "NoParams", "NoParamsAlias", "MyFileParams", "MyFuncFileParams", "EmbeddedFileParams"} { 76 td := getParameter(sctx, rn) 77 78 prs := ¶meterBuilder{ 79 ctx: sctx, 80 decl: td, 81 } 82 require.NoError(t, prs.Build(operations)) 83 } 84 85 assert.Len(t, operations, 10) 86 cr, okParam := operations["yetAnotherOperation"] 87 assert.True(t, okParam) 88 assert.Len(t, cr.Parameters, 8) 89 for _, param := range cr.Parameters { 90 switch param.Name { 91 case "id": 92 assert.Equal(t, "integer", param.Type) 93 assert.Equal(t, "int64", param.Format) 94 case "name": 95 assert.Equal(t, "string", param.Type) 96 assert.Equal(t, "", param.Format) 97 case "age": 98 assert.Equal(t, "integer", param.Type) 99 assert.Equal(t, "int32", param.Format) 100 case "notes": 101 assert.Equal(t, "string", param.Type) 102 assert.Equal(t, "", param.Format) 103 case "extra": 104 assert.Equal(t, "string", param.Type) 105 assert.Equal(t, "", param.Format) 106 case "createdAt": 107 assert.Equal(t, "string", param.Type) 108 assert.Equal(t, "date-time", param.Format) 109 case "informity": 110 assert.Equal(t, "string", param.Type) 111 assert.Equal(t, "formData", param.In) 112 case "NoTagName": 113 assert.Equal(t, "string", param.Type) 114 assert.Equal(t, "", param.Format) 115 default: 116 assert.Fail(t, "unknown property: "+param.Name) 117 } 118 } 119 120 ob, okParam := operations["updateOrder"] 121 assert.True(t, okParam) 122 assert.Len(t, ob.Parameters, 1) 123 bodyParam := ob.Parameters[0] 124 assert.Equal(t, "The order to submit.", bodyParam.Description) 125 assert.Equal(t, "body", bodyParam.In) 126 assert.Equal(t, "#/definitions/order", bodyParam.Schema.Ref.String()) 127 assert.True(t, bodyParam.Required) 128 129 mop, okParam := operations["getOrders"] 130 assert.True(t, okParam) 131 assert.Len(t, mop.Parameters, 2) 132 ordersParam := mop.Parameters[0] 133 assert.Equal(t, "The orders", ordersParam.Description) 134 assert.True(t, ordersParam.Required) 135 assert.Equal(t, "array", ordersParam.Type) 136 otherParam := mop.Parameters[1] 137 assert.Equal(t, "And another thing", otherParam.Description) 138 139 op, okParam := operations["someOperation"] 140 assert.True(t, okParam) 141 assert.Len(t, op.Parameters, 12) 142 143 for _, param := range op.Parameters { 144 switch param.Name { 145 case "id": 146 assert.Equal(t, "ID of this no model instance.\nids in this application start at 11 and are smaller than 1000", param.Description) 147 assert.Equal(t, "path", param.In) 148 assert.Equal(t, "integer", param.Type) 149 assert.Equal(t, "int64", param.Format) 150 assert.True(t, param.Required) 151 assert.Equal(t, "ID", param.Extensions["x-go-name"]) 152 assert.EqualValues(t, 1000, *param.Maximum) 153 assert.True(t, param.ExclusiveMaximum) 154 assert.EqualValues(t, 10, *param.Minimum) 155 assert.True(t, param.ExclusiveMinimum) 156 assert.Equal(t, 1, param.Default, "%s default value is incorrect", param.Name) 157 158 case "score": 159 assert.Equal(t, "The Score of this model", param.Description) 160 assert.Equal(t, "query", param.In) 161 assert.Equal(t, "integer", param.Type) 162 assert.Equal(t, "int32", param.Format) 163 assert.True(t, param.Required) 164 assert.Equal(t, "Score", param.Extensions["x-go-name"]) 165 assert.EqualValues(t, 45, *param.Maximum) 166 assert.False(t, param.ExclusiveMaximum) 167 assert.EqualValues(t, 3, *param.Minimum) 168 assert.False(t, param.ExclusiveMinimum) 169 assert.Equal(t, 2, param.Default, "%s default value is incorrect", param.Name) 170 assert.Equal(t, 27, param.Example) 171 172 case "x-hdr-name": 173 assert.Equal(t, "Name of this no model instance", param.Description) 174 assert.Equal(t, "header", param.In) 175 assert.Equal(t, "string", param.Type) 176 assert.True(t, param.Required) 177 assert.Equal(t, "Name", param.Extensions["x-go-name"]) 178 assert.EqualValues(t, 4, *param.MinLength) 179 assert.EqualValues(t, 50, *param.MaxLength) 180 assert.Equal(t, "[A-Za-z0-9-.]*", param.Pattern) 181 182 case "created": 183 assert.Equal(t, "Created holds the time when this entry was created", param.Description) 184 assert.Equal(t, "query", param.In) 185 assert.Equal(t, "string", param.Type) 186 assert.Equal(t, "date-time", param.Format) 187 assert.False(t, param.Required) 188 assert.Equal(t, "Created", param.Extensions["x-go-name"]) 189 190 case "category_old": 191 assert.Equal(t, "The Category of this model (old enum format)", param.Description) 192 assert.Equal(t, "query", param.In) 193 assert.Equal(t, "string", param.Type) 194 assert.True(t, param.Required) 195 assert.Equal(t, "CategoryOld", param.Extensions["x-go-name"]) 196 assert.EqualValues(t, []interface{}{"foo", "bar", "none"}, param.Enum, "%s enum values are incorrect", param.Name) 197 assert.Equal(t, "bar", param.Default, "%s default value is incorrect", param.Name) 198 case "category": 199 assert.Equal(t, "The Category of this model", param.Description) 200 assert.Equal(t, "query", param.In) 201 assert.Equal(t, "string", param.Type) 202 assert.True(t, param.Required) 203 assert.Equal(t, "Category", param.Extensions["x-go-name"]) 204 assert.EqualValues(t, []interface{}{"foo", "bar", "none"}, param.Enum, "%s enum values are incorrect", param.Name) 205 assert.Equal(t, "bar", param.Default, "%s default value is incorrect", param.Name) 206 case "type_old": 207 assert.Equal(t, "Type of this model (old enum format)", param.Description) 208 assert.Equal(t, "query", param.In) 209 assert.Equal(t, "integer", param.Type) 210 assert.EqualValues(t, []interface{}{1, 3, 5}, param.Enum, "%s enum values are incorrect", param.Name) 211 case "type": 212 assert.Equal(t, "Type of this model", param.Description) 213 assert.Equal(t, "query", param.In) 214 assert.Equal(t, "integer", param.Type) 215 assert.EqualValues(t, []interface{}{1, 3, 5}, param.Enum, "%s enum values are incorrect", param.Name) 216 case gcBadEnum: 217 assert.Equal(t, "query", param.In) 218 assert.Equal(t, "integer", param.Type) 219 assert.EqualValues(t, []interface{}{1, "rsq", "qaz"}, param.Enum, "%s enum values are incorrect", param.Name) 220 case "foo_slice": 221 assert.Equal(t, "a FooSlice has foos which are strings", param.Description) 222 assert.Equal(t, "FooSlice", param.Extensions["x-go-name"]) 223 assert.Equal(t, "query", param.In) 224 assert.Equal(t, "array", param.Type) 225 assert.False(t, param.Required) 226 assert.True(t, param.UniqueItems) 227 assert.Equal(t, "pipe", param.CollectionFormat) 228 assert.EqualValues(t, 3, *param.MinItems, "'foo_slice' should have had 3 min items") 229 assert.EqualValues(t, 10, *param.MaxItems, "'foo_slice' should have had 10 max items") 230 itprop := param.Items 231 assert.EqualValues(t, 3, *itprop.MinLength, "'foo_slice.items.minLength' should have been 3") 232 assert.EqualValues(t, 10, *itprop.MaxLength, "'foo_slice.items.maxLength' should have been 10") 233 assert.EqualValues(t, "\\w+", itprop.Pattern, "'foo_slice.items.pattern' should have \\w+") 234 assert.EqualValues(t, "bar", itprop.Default, "'foo_slice.items.default' should have bar default value") 235 236 case "items": 237 assert.Equal(t, "Items", param.Extensions["x-go-name"]) 238 assert.Equal(t, "body", param.In) 239 assert.NotNil(t, param.Schema) 240 aprop := param.Schema 241 assert.Equal(t, "array", aprop.Type[0]) 242 assert.NotNil(t, aprop.Items) 243 assert.NotNil(t, aprop.Items.Schema) 244 itprop := aprop.Items.Schema 245 assert.Len(t, itprop.Properties, 4) 246 assert.Len(t, itprop.Required, 3) 247 assertProperty(t, itprop, "integer", "id", "int32", "ID") 248 iprop, ok := itprop.Properties["id"] 249 assert.True(t, ok) 250 assert.Equal(t, "ID of this no model instance.\nids in this application start at 11 and are smaller than 1000", iprop.Description) 251 assert.EqualValues(t, 1000, *iprop.Maximum) 252 assert.True(t, iprop.ExclusiveMaximum, "'id' should have had an exclusive maximum") 253 assert.NotNil(t, iprop.Minimum) 254 assert.EqualValues(t, 10, *iprop.Minimum) 255 assert.True(t, iprop.ExclusiveMinimum, "'id' should have had an exclusive minimum") 256 assert.Equal(t, 3, iprop.Default, "Items.ID default value is incorrect") 257 258 assertRef(t, itprop, "pet", "Pet", "#/definitions/pet") 259 iprop, ok = itprop.Properties["pet"] 260 assert.True(t, ok) 261 // if itprop.Ref.String() == "" { 262 // assert.Equal(t, "The Pet to add to this NoModel items bucket.\nPets can appear more than once in the bucket", iprop.Description) 263 // } 264 265 assertProperty(t, itprop, "integer", "quantity", "int16", "Quantity") 266 iprop, ok = itprop.Properties["quantity"] 267 assert.True(t, ok) 268 assert.Equal(t, "The amount of pets to add to this bucket.", iprop.Description) 269 assert.EqualValues(t, 1, *iprop.Minimum) 270 assert.EqualValues(t, 10, *iprop.Maximum) 271 272 assertProperty(t, itprop, "string", "notes", "", "Notes") 273 iprop, ok = itprop.Properties["notes"] 274 assert.True(t, ok) 275 assert.Equal(t, "Notes to add to this item.\nThis can be used to add special instructions.", iprop.Description) 276 277 case "bar_slice": 278 assert.Equal(t, "a BarSlice has bars which are strings", param.Description) 279 assert.Equal(t, "BarSlice", param.Extensions["x-go-name"]) 280 assert.Equal(t, "query", param.In) 281 assert.Equal(t, "array", param.Type) 282 assert.False(t, param.Required) 283 assert.True(t, param.UniqueItems) 284 assert.Equal(t, "pipe", param.CollectionFormat) 285 assert.NotNil(t, param.Items, "bar_slice should have had an items property") 286 assert.EqualValues(t, 3, *param.MinItems, "'bar_slice' should have had 3 min items") 287 assert.EqualValues(t, 10, *param.MaxItems, "'bar_slice' should have had 10 max items") 288 itprop := param.Items 289 if assert.NotNil(t, itprop) { 290 assert.EqualValues(t, 4, *itprop.MinItems, "'bar_slice.items.minItems' should have been 4") 291 assert.EqualValues(t, 9, *itprop.MaxItems, "'bar_slice.items.maxItems' should have been 9") 292 itprop2 := itprop.Items 293 if assert.NotNil(t, itprop2) { 294 assert.EqualValues(t, 5, *itprop2.MinItems, "'bar_slice.items.items.minItems' should have been 5") 295 assert.EqualValues(t, 8, *itprop2.MaxItems, "'bar_slice.items.items.maxItems' should have been 8") 296 itprop3 := itprop2.Items 297 if assert.NotNil(t, itprop3) { 298 assert.EqualValues(t, 3, *itprop3.MinLength, "'bar_slice.items.items.items.minLength' should have been 3") 299 assert.EqualValues(t, 10, *itprop3.MaxLength, "'bar_slice.items.items.items.maxLength' should have been 10") 300 assert.EqualValues(t, "\\w+", itprop3.Pattern, "'bar_slice.items.items.items.pattern' should have \\w+") 301 } 302 } 303 } 304 305 default: 306 assert.Fail(t, "unknown property: "+param.Name) 307 } 308 } 309 310 // assert that the order of the parameters is maintained 311 order, ok := operations["anotherOperation"] 312 assert.True(t, ok) 313 assert.Len(t, order.Parameters, 12) 314 315 for index, param := range order.Parameters { 316 switch param.Name { 317 case "id": 318 assert.Equal(t, 0, index, "%s index incorrect", param.Name) 319 case "score": 320 assert.Equal(t, 1, index, "%s index incorrect", param.Name) 321 case "x-hdr-name": 322 assert.Equal(t, 2, index, "%s index incorrect", param.Name) 323 case "created": 324 assert.Equal(t, 3, index, "%s index incorrect", param.Name) 325 case "category_old": 326 assert.Equal(t, 4, index, "%s index incorrect", param.Name) 327 case "category": 328 assert.Equal(t, 5, index, "%s index incorrect", param.Name) 329 case "type_old": 330 assert.Equal(t, 6, index, "%s index incorrect", param.Name) 331 case "type": 332 assert.Equal(t, 7, index, "%s index incorrect", param.Name) 333 case gcBadEnum: 334 assert.Equal(t, 8, index, "%s index incorrect", param.Name) 335 case "foo_slice": 336 assert.Equal(t, 9, index, "%s index incorrect", param.Name) 337 case "bar_slice": 338 assert.Equal(t, 10, index, "%s index incorrect", param.Name) 339 case "items": 340 assert.Equal(t, 11, index, "%s index incorrect", param.Name) 341 default: 342 assert.Fail(t, "unknown property: "+param.Name) 343 } 344 } 345 346 // check that aliases work correctly 347 aliasOp, ok := operations["someAliasOperation"] 348 assert.True(t, ok) 349 assert.Len(t, aliasOp.Parameters, 4) 350 for _, param := range aliasOp.Parameters { 351 switch param.Name { 352 case "intAlias": 353 assert.Equal(t, "query", param.In) 354 assert.Equal(t, "integer", param.Type) 355 assert.Equal(t, "int64", param.Format) 356 assert.True(t, param.Required) 357 assert.EqualValues(t, 10, *param.Maximum) 358 assert.EqualValues(t, 1, *param.Minimum) 359 case "stringAlias": 360 assert.Equal(t, "query", param.In) 361 assert.Equal(t, "string", param.Type) 362 case "intAliasPath": 363 assert.Equal(t, "path", param.In) 364 assert.Equal(t, "integer", param.Type) 365 assert.Equal(t, "int64", param.Format) 366 case "intAliasForm": 367 assert.Equal(t, "formData", param.In) 368 assert.Equal(t, "integer", param.Type) 369 assert.Equal(t, "int64", param.Format) 370 default: 371 assert.Fail(t, "unknown property: "+param.Name) 372 } 373 } 374 } 375 376 func TestParameterParser_Issue2007(t *testing.T) { 377 sctx := loadClassificationPkgsCtx(t) 378 operations := make(map[string]*spec.Operation) 379 td := getParameter(sctx, "SetConfiguration") 380 prs := ¶meterBuilder{ 381 ctx: sctx, 382 decl: td, 383 } 384 require.NoError(t, prs.Build(operations)) 385 386 op := operations["getConfiguration"] 387 require.NotNil(t, op) 388 require.Len(t, op.Parameters, 1) 389 sch := op.Parameters[0].Schema 390 require.NotNil(t, sch) 391 392 require.True(t, sch.Type.Contains("object")) 393 require.NotNil(t, sch.AdditionalProperties) 394 require.NotNil(t, sch.AdditionalProperties.Schema) 395 require.True(t, sch.AdditionalProperties.Schema.Type.Contains("string")) 396 } 397 398 func TestParameterParser_Issue2011(t *testing.T) { 399 sctx := loadClassificationPkgsCtx(t) 400 operations := make(map[string]*spec.Operation) 401 td := getParameter(sctx, "NumPlates") 402 prs := ¶meterBuilder{ 403 ctx: sctx, 404 decl: td, 405 } 406 require.NoError(t, prs.Build(operations)) 407 408 op := operations["putNumPlate"] 409 require.NotNil(t, op) 410 require.Len(t, op.Parameters, 1) 411 sch := op.Parameters[0].Schema 412 require.NotNil(t, sch) 413 }