github.com/josephspurrier/go-swagger@v0.2.1-0.20221129144919-1f672a142a00/codescan/routes_test.go (about) 1 package codescan 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/require" 7 8 "github.com/go-openapi/spec" 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestRouteExpression(t *testing.T) { 13 assert.Regexp(t, rxRoute, "swagger:route DELETE /orders/{id} deleteOrder") 14 assert.Regexp(t, rxRoute, "swagger:route GET /v1.2/something deleteOrder") 15 } 16 17 func TestRoutesParser(t *testing.T) { 18 sctx := loadClassificationPkgsCtx(t) 19 var ops spec.Paths 20 for _, apiPath := range sctx.app.Routes { 21 prs := &routesBuilder{ 22 ctx: sctx, 23 route: apiPath, 24 operations: make(map[string]*spec.Operation), 25 } 26 require.NoError(t, prs.Build(&ops)) 27 } 28 29 assert.Len(t, ops.Paths, 3) 30 31 po, ok := ops.Paths["/pets"] 32 ext := make(spec.Extensions) 33 ext.Add("x-some-flag", "true") 34 assert.True(t, ok) 35 assert.NotNil(t, po.Get) 36 assertOperation(t, 37 po.Get, 38 "listPets", 39 "Lists pets filtered by some parameters.", 40 "This will show all available pets by default.\nYou can get the pets that are out of stock", 41 []string{"pets", "users"}, 42 []string{"read", "write"}, 43 ext, 44 ) 45 assertOperation(t, 46 po.Post, 47 "createPet", 48 "Create a pet based on the parameters.", 49 "", 50 []string{"pets", "users"}, 51 []string{"read", "write"}, 52 nil, 53 ) 54 55 po, ok = ops.Paths["/orders"] 56 ext = make(spec.Extensions) 57 ext.Add("x-some-flag", "false") 58 ext.Add("x-some-list", []string{"item1", "item2", "item3"}) 59 ext.Add("x-some-object", map[string]interface{}{ 60 "key1": "value1", 61 "key2": "value2", 62 "subobject": map[string]interface{}{ 63 "subkey1": "subvalue1", 64 "subkey2": "subvalue2", 65 }, 66 "key3": "value3", 67 }) 68 assert.True(t, ok) 69 assert.NotNil(t, po.Get) 70 assertOperation(t, 71 po.Get, 72 "listOrders", 73 "lists orders filtered by some parameters.", 74 "", 75 []string{"orders"}, 76 []string{"orders:read", "https://www.googleapis.com/auth/userinfo.email"}, 77 ext, 78 ) 79 assertOperation(t, 80 po.Post, 81 "createOrder", 82 "create an order based on the parameters.", 83 "", 84 []string{"orders"}, 85 []string{"read", "write"}, 86 nil, 87 ) 88 89 po, ok = ops.Paths["/orders/{id}"] 90 assert.True(t, ok) 91 assert.NotNil(t, po.Get) 92 assertOperation(t, 93 po.Get, 94 "orderDetails", 95 "gets the details for an order.", 96 "", 97 []string{"orders"}, 98 []string{"read", "write"}, 99 nil, 100 ) 101 102 assertOperation(t, 103 po.Put, 104 "updateOrder", 105 "Update the details for an order.", 106 "When the order doesn't exist this will return an error.", 107 []string{"orders"}, 108 []string{"read", "write"}, 109 nil, 110 ) 111 112 assertOperation(t, 113 po.Delete, 114 "deleteOrder", 115 "delete a particular order.", 116 "", 117 nil, 118 []string{"read", "write"}, 119 nil, 120 ) 121 122 // additional check description tag at Responses 123 rsp, ok := po.Delete.Responses.StatusCodeResponses[202] 124 assert.True(t, ok) 125 assert.Equal(t, "Some description", rsp.Description) 126 assert.Equal(t, "", rsp.Ref.String()) 127 } 128 129 func TestRoutesParserBody(t *testing.T) { 130 sctx, err := newScanCtx(&Options{ 131 Packages: []string{ 132 "github.com/go-swagger/go-swagger/fixtures/goparsing/classification", 133 "github.com/go-swagger/go-swagger/fixtures/goparsing/classification/models", 134 "github.com/go-swagger/go-swagger/fixtures/goparsing/classification/operations", 135 "github.com/go-swagger/go-swagger/fixtures/goparsing/classification/operations_body", 136 }, 137 }) 138 require.NoError(t, err) 139 var ops spec.Paths 140 for _, apiPath := range sctx.app.Routes { 141 prs := &routesBuilder{ 142 ctx: sctx, 143 route: apiPath, 144 operations: make(map[string]*spec.Operation), 145 } 146 require.NoError(t, prs.Build(&ops)) 147 } 148 149 assert.Len(t, ops.Paths, 4) 150 151 po, ok := ops.Paths["/pets"] 152 assert.True(t, ok) 153 assert.NotNil(t, po.Get) 154 assertOperationBody(t, 155 po.Get, 156 "listPets", 157 "Lists pets filtered by some parameters.", 158 "This will show all available pets by default.\nYou can get the pets that are out of stock", 159 []string{"pets", "users"}, 160 []string{"read", "write"}, 161 ) 162 assert.NotNil(t, po.Post) 163 164 assertOperationBody(t, 165 po.Post, 166 "createPet", 167 "Create a pet based on the parameters.", 168 "", 169 []string{"pets", "users"}, 170 []string{"read", "write"}, 171 ) 172 173 po, ok = ops.Paths["/orders"] 174 assert.True(t, ok) 175 assert.NotNil(t, po.Get) 176 assertOperationBody(t, 177 po.Get, 178 "listOrders", 179 "lists orders filtered by some parameters.", 180 "", 181 []string{"orders"}, 182 []string{"orders:read", "https://www.googleapis.com/auth/userinfo.email"}, 183 ) 184 assert.NotNil(t, po.Post) 185 186 assertOperationBody(t, 187 po.Post, 188 "createOrder", 189 "create an order based on the parameters.", 190 "", 191 []string{"orders"}, 192 []string{"read", "write"}, 193 ) 194 195 po, ok = ops.Paths["/orders/{id}"] 196 assert.True(t, ok) 197 assert.NotNil(t, po.Get) 198 assertOperationBody(t, 199 po.Get, 200 "orderDetails", 201 "gets the details for an order.", 202 "", 203 []string{"orders"}, 204 []string{"read", "write"}, 205 ) 206 207 assertOperationBody(t, 208 po.Put, 209 "updateOrder", 210 "Update the details for an order.", 211 "When the order doesn't exist this will return an error.", 212 []string{"orders"}, 213 []string{"read", "write"}, 214 ) 215 216 assertOperationBody(t, 217 po.Delete, 218 "deleteOrder", 219 "delete a particular order.", 220 "", 221 nil, 222 []string{"read", "write"}, 223 ) 224 225 validateRoutesParameters(t, ops) 226 } 227 228 func validateRoutesParameters(t *testing.T, ops spec.Paths) { 229 po := ops.Paths["/pets"] 230 assert.Equal(t, 2, len(po.Post.Parameters)) 231 232 // Testing standard param properties 233 p := po.Post.Parameters[0] 234 assert.Equal(t, "request", p.Name) 235 assert.Equal(t, "body", p.In) 236 assert.Equal(t, "The request model.", p.Description) 237 238 // Testing "required" and "allowEmpty" 239 p = po.Post.Parameters[1] 240 assert.Equal(t, "id", p.Name) 241 assert.Equal(t, "The pet id", p.Description) 242 assert.Equal(t, "path", p.In) 243 assert.Equal(t, true, p.Required) 244 assert.Equal(t, false, p.AllowEmptyValue) 245 246 po = ops.Paths["/orders"] 247 assert.Equal(t, 2, len(po.Post.Parameters)) 248 249 // Testing invalid value for "in" 250 p = po.Post.Parameters[0] 251 assert.Equal(t, "id", p.Name) 252 assert.Equal(t, "The order id", p.Description) 253 assert.Equal(t, "", p.In) // Invalid value should not be set 254 assert.Equal(t, false, p.Required) 255 assert.Equal(t, true, p.AllowEmptyValue) 256 257 p = po.Post.Parameters[1] 258 assert.Equal(t, "request", p.Name) 259 assert.Equal(t, "body", p.In) 260 assert.Equal(t, "The request model.", p.Description) 261 262 po = ops.Paths["/param-test"] 263 assert.Equal(t, 6, len(po.Post.Parameters)) 264 265 // Testing number param with "max" and "min" constraints 266 p = po.Post.Parameters[0] 267 assert.Equal(t, "someNumber", p.Name) 268 assert.Equal(t, "some number", p.Description) 269 assert.Equal(t, "path", p.In) 270 assert.Equal(t, true, p.Required) 271 assert.Equal(t, "number", p.Type) 272 min, max, def := float64(10), float64(20), float64(15) 273 assert.Equal(t, &max, p.Maximum) 274 assert.Equal(t, &min, p.Minimum) 275 assert.Equal(t, def, p.Default) 276 assert.Nil(t, p.Schema) 277 278 // Testing array param provided as query string. Testing "minLength" and "maxLength" constraints for "array" types 279 p = po.Post.Parameters[1] 280 assert.Equal(t, "someQuery", p.Name) 281 assert.Equal(t, "some query values", p.Description) 282 assert.Equal(t, "query", p.In) 283 assert.Equal(t, false, p.Required) 284 assert.Equal(t, "array", p.Type) 285 minLen, maxLen := int64(5), int64(20) 286 assert.Equal(t, &maxLen, p.MaxLength) 287 assert.Equal(t, &minLen, p.MinLength) 288 assert.Nil(t, p.Schema) 289 290 // Testing boolean param with default value 291 p = po.Post.Parameters[2] 292 assert.Equal(t, "someBoolean", p.Name) 293 assert.Equal(t, "some boolean", p.Description) 294 assert.Equal(t, "path", p.In) 295 assert.Equal(t, false, p.Required) 296 assert.Equal(t, "boolean", p.Type) 297 assert.Equal(t, true, p.Default) 298 assert.Nil(t, p.Schema) 299 300 // Testing that "min", "max", "minLength" and "maxLength" constraints will only be considered if the right type is provided 301 p = po.Post.Parameters[3] 302 assert.Equal(t, "constraintsOnInvalidType", p.Name) 303 assert.Equal(t, "test constraints on invalid types", p.Description) 304 assert.Equal(t, "query", p.In) 305 assert.Equal(t, "boolean", p.Type) 306 assert.Nil(t, p.Maximum) 307 assert.Nil(t, p.Minimum) 308 assert.Nil(t, p.MaxLength) 309 assert.Nil(t, p.MinLength) 310 assert.Equal(t, "abcde", p.Format) 311 assert.Equal(t, false, p.Default) 312 assert.Nil(t, p.Schema) 313 314 // Testing that when "type" is not provided, a schema will not be created 315 p = po.Post.Parameters[4] 316 assert.Equal(t, "noType", p.Name) 317 assert.Equal(t, "test no type", p.Description) 318 assert.Equal(t, "", p.Type) 319 assert.Nil(t, p.Schema) 320 321 // Testing a request body that takes a string value defined by a list of possible values in "enum" 322 p = po.Post.Parameters[5] 323 assert.Equal(t, "request", p.Name) 324 assert.Equal(t, "The request model.", p.Description) 325 assert.Equal(t, "body", p.In) 326 assert.Equal(t, "string", p.Schema.Type[0]) 327 assert.Equal(t, "orange", p.Schema.Default) 328 assert.Equal(t, []interface{}{"apple", "orange", "pineapple", "peach", "plum"}, p.Schema.Enum) 329 assert.Empty(t, "", p.Type) 330 } 331 332 func assertOperation(t *testing.T, op *spec.Operation, id, summary, description string, tags, scopes []string, extensions spec.Extensions) { 333 assert.NotNil(t, op) 334 assert.Equal(t, summary, op.Summary) 335 assert.Equal(t, description, op.Description) 336 assert.Equal(t, id, op.ID) 337 assert.EqualValues(t, tags, op.Tags) 338 assert.EqualValues(t, []string{"application/json", "application/x-protobuf"}, op.Consumes) 339 assert.EqualValues(t, []string{"application/json", "application/x-protobuf"}, op.Produces) 340 assert.EqualValues(t, []string{"http", "https", "ws", "wss"}, op.Schemes) 341 assert.Len(t, op.Security, 2) 342 akv, ok := op.Security[0]["api_key"] 343 assert.True(t, ok) 344 // akv must be defined & not empty 345 assert.NotNil(t, akv) 346 assert.Empty(t, akv) 347 348 vv, ok := op.Security[1]["oauth"] 349 assert.True(t, ok) 350 assert.EqualValues(t, scopes, vv) 351 352 assert.NotNil(t, op.Responses.Default) 353 assert.Equal(t, "#/responses/genericError", op.Responses.Default.Ref.String()) 354 355 rsp, ok := op.Responses.StatusCodeResponses[200] 356 assert.True(t, ok) 357 assert.Equal(t, "#/responses/someResponse", rsp.Ref.String()) 358 rsp, ok = op.Responses.StatusCodeResponses[422] 359 assert.True(t, ok) 360 assert.Equal(t, "#/responses/validationError", rsp.Ref.String()) 361 362 ext := op.Extensions 363 assert.Equal(t, extensions, ext) 364 } 365 366 func assertOperationBody(t *testing.T, op *spec.Operation, id, summary, description string, tags, scopes []string) { 367 assert.NotNil(t, op) 368 assert.Equal(t, summary, op.Summary) 369 assert.Equal(t, description, op.Description) 370 assert.Equal(t, id, op.ID) 371 assert.EqualValues(t, tags, op.Tags) 372 assert.EqualValues(t, []string{"application/json", "application/x-protobuf"}, op.Consumes) 373 assert.EqualValues(t, []string{"application/json", "application/x-protobuf"}, op.Produces) 374 assert.EqualValues(t, []string{"http", "https", "ws", "wss"}, op.Schemes) 375 assert.Len(t, op.Security, 2) 376 akv, ok := op.Security[0]["api_key"] 377 assert.True(t, ok) 378 // akv must be defined & not empty 379 assert.NotNil(t, akv) 380 assert.Empty(t, akv) 381 382 vv, ok := op.Security[1]["oauth"] 383 assert.True(t, ok) 384 assert.EqualValues(t, scopes, vv) 385 386 assert.NotNil(t, op.Responses.Default) 387 assert.Equal(t, "", op.Responses.Default.Ref.String()) 388 assert.Equal(t, "#/definitions/genericError", op.Responses.Default.Schema.Ref.String()) 389 390 rsp, ok := op.Responses.StatusCodeResponses[200] 391 assert.True(t, ok) 392 assert.Equal(t, "", rsp.Ref.String()) 393 assert.Equal(t, "#/definitions/someResponse", rsp.Schema.Ref.String()) 394 rsp, ok = op.Responses.StatusCodeResponses[422] 395 assert.True(t, ok) 396 assert.Equal(t, "", rsp.Ref.String()) 397 assert.Equal(t, "#/definitions/validationError", rsp.Schema.Ref.String()) 398 }