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