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